コード例 #1
0
static int
UseMediaProxy(struct sip_msg* msg, char* str1, char* str2)
{
    str sdp, sessionIP, callId, fromDomain, toDomain, userAgent, tokens[64];
    str fromAddr, toAddr, fromTag, toTag;
    char *clientIP, *ptr, *command, *result, *agent, *fromType, *toType, *info;
    int streamCount, i, port, count, portCount, cmdlen, infolen, success, type;
    StreamInfo streams[64], stream;
    Bool request;

    if (msg->first_line.type == SIP_REQUEST) {
        if (msg->first_line.u.request.method_value == METHOD_INVITE)
            type = MSG_INVITE;
        else if (msg->first_line.u.request.method_value == METHOD_ACK)
            type = MSG_ACK;
        else
            type = MSG_UNKNOWN;
    } else if (msg->first_line.type == SIP_REPLY) {
        type = MSG_REPLY;
    } else {
        type = MSG_UNKNOWN;
    }

    if (type==MSG_INVITE || type==MSG_ACK) {
        request = True;
    } else if (type==MSG_REPLY) {
        request = False;
    } else {
        return -1;
    }

    if (!getCallId(msg, &callId)) {
        LOG(L_ERR, "error: use_media_proxy(): can't get Call-Id\n");
        return -1;
    }

    success = getSDPMessage(msg, &sdp);
    if (success==0 && type==MSG_ACK) {
        return 1; // nothing to do. it's ok for ACK to not have a SDP body
    } else if (success <= 0) {
        LOG(L_ERR, "error: use_media_proxy(): failed to get the SDP message\n");
        return -1;
    }

    if (!getSessionLevelMediaIP(&sdp, &sessionIP)) {
        LOG(L_ERR, "error: use_media_proxy(): error parsing the SDP message\n");
        return -1;
    }

    streamCount = getMediaStreams(&sdp, &sessionIP, streams, 64);
    if (streamCount == -1) {
        LOG(L_ERR, "error: use_media_proxy(): can't extract media streams "
            "from the SDP message\n");
        return -1;
    }

    if (streamCount == 0) {
        // there are no media streams. we have nothing to do.
        return 1;
    }

    fromDomain = getFromDomain(&fromType, msg);
    fromAddr   = getFromAddress(msg);
    toAddr     = getToAddress(msg);
    fromTag    = getFromTag(msg);
    toTag      = getToTag(msg);
    userAgent  = getUserAgent(msg);
    if (request) {
        toDomain = getDestinationDomain(&toType, msg); // call only for requests
    } else {
        toDomain = getToDomain(&toType, msg);
    }

    clientIP = ip_addr2a(&msg->rcv.src_ip);

    infolen = fromAddr.len + toAddr.len + fromTag.len + toTag.len + 64;

    cmdlen = callId.len + strlen(clientIP) + fromDomain.len + toDomain.len +
        userAgent.len*3 + infolen + 128;

    for (i=0; i<streamCount; i++) {
        stream = streams[i];
        cmdlen += stream.ip.len + stream.port.len + stream.type.len + 4;
    }

    command = pkg_malloc(cmdlen);
    if (!command) {
        LOG(L_ERR, "error: use_media_proxy(): out of memory\n");
        return -1;
    }

    if (request)
        count = sprintf(command, "request %.*s", callId.len, callId.s);
    else
        count = sprintf(command, "lookup %.*s", callId.len, callId.s);

    for (i=0, ptr=command+count; i<streamCount; i++) {
        char c = (i==0 ? ' ' : ',');
        count = sprintf(ptr, "%c%.*s:%.*s:%.*s", c,
                        streams[i].ip.len, streams[i].ip.s,
                        streams[i].port.len, streams[i].port.s,
                        streams[i].type.len, streams[i].type.s);
        ptr += count;
    }

    agent = encodeQuopri(userAgent);
    if (!agent) {
        LOG(L_ERR, "error: use_media_proxy(): out of memory\n");
        pkg_free(command);
        return -1;
    }

    info = pkg_malloc(infolen);
    if (!info) {
        LOG(L_ERR, "error: use_media_proxy(): out of memory\n");
        pkg_free(command);
        pkg_free(agent);
        return -1;
    }

    sprintf(info, "from:%.*s,to:%.*s,fromtag:%.*s,totag:%.*s",
            fromAddr.len, fromAddr.s, toAddr.len, toAddr.s,
            fromTag.len, fromTag.s, toTag.len, toTag.s);
    if (isRTPAsymmetric(userAgent)) {
        strcat(info, ",asymmetric");
    }

    snprintf(ptr, command + cmdlen - ptr, " %s %.*s %s %.*s %s %s info=%s\n",
             clientIP, fromDomain.len, fromDomain.s, fromType,
             toDomain.len, toDomain.s, toType, agent, info);

    pkg_free(info);
    pkg_free(agent);

    result = sendMediaproxyCommand(command);

    pkg_free(command);

    if (result == NULL)
        return -1;

    count = getTokens(result, tokens, sizeof(tokens)/sizeof(str));

    if (count == 0) {
        LOG(L_ERR, "error: use_media_proxy(): empty response from mediaproxy\n");
        return -1;
    } else if (count<streamCount+1) {
        if (request) {
            LOG(L_ERR, "error: use_media_proxy(): insufficient ports returned "
                "from mediaproxy: got %d, expected %d\n", count-1, streamCount);
            return -1;
        } else {
            LOG(L_WARN, "warning: use_media_proxy(): broken client. Called UA "
                "added extra media stream(s) in the OK reply\n");
        }
    }

    if (sessionIP.s && !isAnyAddress(sessionIP)) {
        success = replaceElement(msg, &sessionIP, &tokens[0]);
        if (!success) {
            LOG(L_ERR, "error: use_media_proxy(): failed to replace "
                "session-level media IP in SDP body\n");
            return -1;
        }
    }

    portCount = min(count-1, streamCount);

    for (i=0; i<portCount; i++) {
        // check. is this really necessary?
        port = strtoint(&tokens[i+1]);
        if (port <= 0 || port > 65535) {
            LOG(L_ERR, "error: use_media_proxy(): invalid port returned "
                "by mediaproxy: %.*s\n", tokens[i+1].len, tokens[i+1].s);
            //return -1;
            continue;
        }

        if (streams[i].port.len!=1 || streams[i].port.s[0]!='0') {
            success = replaceElement(msg, &(streams[i].port), &tokens[i+1]);
            if (!success) {
                LOG(L_ERR, "error: use_media_proxy(): failed to replace "
                    "port in media stream nr. %d\n", i+1);
                return -1;
            }
        }

        if (streams[i].localIP && !isAnyAddress(streams[i].ip)) {
            success = replaceElement(msg, &(streams[i].ip), &tokens[0]);
            if (!success) {
                LOG(L_ERR, "error: use_media_proxy(): failed to replace "
                    "IP address in media stream nr. %d\n", i+1);
                return -1;
            }
        }
    }

    return 1;
}
コード例 #2
0
ファイル: mediaproxy.c プロジェクト: Drooids/openser-xmlrpc
static int
UseMediaProxy(struct sip_msg* msg, char* str1, char* str2)
{
    str sdp, sessionIP, signalingIP, callId, userAgent, tokens[64];
    str fromDomain, toDomain, fromAddr, toAddr, fromTag, toTag, domain;
    char *ptr, *command, *result, *agent, *fromType, *toType, *info;
    int streamCount, i, port, count, portCount, cmdlen, infolen, status;
    StreamInfo streams[64], stream;
    Bool request;

    if (msg->first_line.type == SIP_REQUEST) {
        request = True;
    } else if (msg->first_line.type == SIP_REPLY) {
        request = False;
    } else {
        return -1;
    }

    if (!getCallId(msg, &callId)) {
        LM_ERR("can't get Call-Id\n");
        return -1;
    }

    status = getSDPMessage(msg, &sdp);
    // status = -1 is error, -2 is missing SDP body
    if (status < 0)
        return status;

    if (!getSessionLevelMediaIP(&sdp, &sessionIP)) {
        LM_ERR("failed to parse the SDP message\n");
        return -1;
    }

    streamCount = getMediaStreams(&sdp, &sessionIP, streams, 64);
    if (streamCount == -1) {
        LM_ERR("can't extract media streams from the SDP message\n");
        return -1;
    }

    if (streamCount == 0)
        return 1; // there are no media streams. we have nothing to do.

    fromDomain = getFromDomain(msg);
    fromType   = (isFromLocal(msg, NULL, NULL)>0) ? "local" : "remote";
    fromAddr   = getFromAddress(msg);
    toAddr     = getToAddress(msg);
    fromTag    = getFromTag(msg);
    toTag      = getToTag(msg);
    userAgent  = getUserAgent(msg);
    if (request) {
        toDomain = getDestinationDomain(msg); // call only for requests
        toType = (isDestinationLocal(msg, NULL, NULL)>0) ? "local" : "remote";
    } else {
        toDomain.s = "unknown";
        toDomain.len = 7;
        toType = "unknown";
    }

    signalingIP = getSignalingIP(msg);
    domain = getMediaproxyDomain(msg);

    infolen = fromAddr.len + toAddr.len + fromTag.len + toTag.len +
        domain.len + 64;

    cmdlen = callId.len + signalingIP.len + fromDomain.len + toDomain.len +
        userAgent.len*3 + infolen + 128;

    for (i=0; i<streamCount; i++) {
        stream = streams[i];
        cmdlen += stream.ip.len + stream.port.len + stream.type.len + 4;
    }

    command = pkg_malloc(cmdlen);
    if (!command) {
        LM_ERR("out of memory\n");
        return -1;
    }

    if (request)
        count = sprintf(command, "request %.*s", callId.len, callId.s);
    else
        count = sprintf(command, "lookup %.*s", callId.len, callId.s);

    for (i=0, ptr=command+count; i<streamCount; i++) {
        char c = (i==0 ? ' ' : ',');
        count = sprintf(ptr, "%c%.*s:%.*s:%.*s", c,
                        streams[i].ip.len, streams[i].ip.s,
                        streams[i].port.len, streams[i].port.s,
                        streams[i].type.len, streams[i].type.s);
        ptr += count;
    }

    agent = encodeQuopri(userAgent);
    if (!agent) {
        LM_ERR("out of memory\n");
        pkg_free(command);
        return -1;
    }

    info = pkg_malloc(infolen);
    if (!info) {
        LM_ERR("out of memory\n");
        pkg_free(command);
        pkg_free(agent);
        return -1;
    }

    sprintf(info, "from:%.*s,to:%.*s,fromtag:%.*s,totag:%.*s",
            fromAddr.len, fromAddr.s, toAddr.len, toAddr.s,
            fromTag.len, fromTag.s, toTag.len, toTag.s);

    if (domain.len) {
        strcat(info, ",domain:");
        strncat(info, domain.s, domain.len);
    }
    if (isRTPAsymmetric(userAgent)) {
        strcat(info, ",asymmetric");
    }

    snprintf(ptr, command + cmdlen - ptr, " %.*s %.*s %s %.*s %s %s info=%s\n",
             signalingIP.len, signalingIP.s, fromDomain.len, fromDomain.s,
             fromType, toDomain.len, toDomain.s, toType, agent, info);

    pkg_free(info);
    pkg_free(agent);

    result = sendMediaproxyCommand(command);

    pkg_free(command);

    if (result == NULL)
        return -1;

    count = getTokens(result, tokens, sizeof(tokens)/sizeof(str));

    if (count == 0) {
        LM_ERR("empty response from mediaproxy\n");
        return -1;
    } else if (count<streamCount+1) {
        if (request) {
            LM_ERR("insufficient ports returned from mediaproxy: got %d, "
                   "expected %d\n", count-1, streamCount);
            return -1;
        } else {
            LM_WARN("broken client. Called UA added extra media stream(s) "
                    "in the OK reply\n");
        }
    }

    if (sessionIP.s && !isAnyAddress(sessionIP)) {
        if (!replaceElement(msg, &sessionIP, &tokens[0])) {
            LM_ERR("failed to replace session-level media IP in the SDP body\n");
            return -1;
        }
    }

    portCount = min(count-1, streamCount);

    for (i=0; i<portCount; i++) {
        // check. is this really necessary?
        port = strtoint(&tokens[i+1]);
        if (port <= 0 || port > 65535) {
            LM_ERR("invalid port returned by mediaproxy: %.*s\n",
                   tokens[i+1].len, tokens[i+1].s);
            //return -1;
            continue;
        }

        if (streams[i].port.len!=1 || streams[i].port.s[0]!='0') {
            if (!replaceElement(msg, &(streams[i].port), &tokens[i+1])) {
                LM_ERR("failed to replace port in media stream number %d\n", i+1);
                return -1;
            }
        }

        if (streams[i].localIP && !isAnyAddress(streams[i].ip)) {
            if (!replaceElement(msg, &(streams[i].ip), &tokens[0])) {
                LM_ERR("failed to replace IP address in media stream number %d\n", i+1);
                return -1;
            }
        }
    }

    return 1;
}