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; }
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; }