📄 mediaproxy.c
字号:
} uri = get_from(msg)->uri; if (uri.len == 0) return notfound; if (strncmp(uri.s, "sip:", 4)==0) { uri.s += 4; uri.len -= 4; } if ((ptr = strfind(uri.s, uri.len, ";", 1))!=NULL) { uri.len = ptr - uri.s; } return uri;}/* Get To tag */static strgetToAddress(struct sip_msg *msg){ static char buf[16] = "unknown"; // buf is here for a reason. don't static str notfound = {buf, 7}; // use the constant string directly! str uri; char *ptr; if (!msg->to) { LOG(L_ERR, "error: mediaproxy/getToAddress(): missing To: field\n"); return notfound; } uri = get_to(msg)->uri; if (uri.len == 0) return notfound; if (strncmp(uri.s, "sip:", 4)==0) { uri.s += 4; uri.len -= 4; } if ((ptr = strfind(uri.s, uri.len, ";", 1))!=NULL) { uri.len = ptr - uri.s; } return uri;}/* Get From tag */static strgetFromTag(struct sip_msg *msg){ static char buf[4] = ""; // buf is here for a reason. don't static str notfound = {buf, 0}; // use the constant string directly! str tag; if (parse_from_header(msg) == -1) { LOG(L_ERR, "error: mediaproxy/getFromTag(): error parsing From: field\n"); return notfound; } tag = get_from(msg)->tag_value; if (tag.len == 0) return notfound; return tag;}/* Get To tag */static strgetToTag(struct sip_msg *msg){ static char buf[4] = ""; // buf is here for a reason. don't static str notfound = {buf, 0}; // use the constant string directly! str tag; if (!msg->to) { LOG(L_ERR, "error: mediaproxy/getToTag(): missing To: field\n"); return notfound; } tag = get_to(msg)->tag_value; if (tag.len == 0) return notfound; return tag;}/* Extract User-Agent */static strgetUserAgent(struct sip_msg* msg){ static char buf[16] = "unknown-agent"; // buf is here for a reason. don't static str notfound = {buf, 13}; // use the constant string directly! str block, server; char *ptr; if ((parse_headers(msg, HDR_USERAGENT, 0)!=-1) && msg->user_agent && msg->user_agent->body.len>0) { return msg->user_agent->body; } // If we can't find user-agent, look after the Server: field // This is a temporary hack. Normally it should be extracted by ser // (either as the Server field, or if User-Agent is missing in place // of the User-Agent field) block.s = msg->buf; block.len = msg->len; ptr = findLineStartingWith(&block, "Server:", True); if (!ptr) return notfound; server.s = ptr + 7; server.len = findendline(server.s, block.s+block.len-server.s) - server.s; trim(&server); if (server.len == 0) return notfound; return server;}// Get URI from the Contact: field.static BoolgetContactURI(struct sip_msg* msg, struct sip_uri *uri, contact_t** _c){ if ((parse_headers(msg, HDR_CONTACT, 0) == -1) || !msg->contact) return False; if (!msg->contact->parsed && parse_contact(msg->contact) < 0) { LOG(L_ERR, "error: mediaproxy/getContactURI(): cannot parse Contact header\n"); return False; } *_c = ((contact_body_t*)msg->contact->parsed)->contacts; if (*_c == NULL) { return False; } if (parse_uri((*_c)->uri.s, (*_c)->uri.len, uri) < 0 || uri->host.len <= 0) { LOG(L_ERR, "error: mediaproxy/getContactURI(): cannot parse Contact URI\n"); return False; } return True;}// Functions to manipulate the SDP message bodystatic BoolcheckContentType(struct sip_msg *msg){ str type; if (!msg->content_type) { LOG(L_WARN, "warning: mediaproxy/checkContentType(): Content-Type " "header missing! Let's assume the content is text/plain ;-)\n"); return True; } type = msg->content_type->body; trim(&type); if (strncasecmp(type.s, "application/sdp", 15) != 0) { LOG(L_ERR, "error: mediaproxy/checkContentType(): invalid Content-Type " "for SDP message\n"); return False; } if (!(isspace((int)type.s[15]) || type.s[15] == ';' || type.s[15] == 0)) { LOG(L_ERR,"error: mediaproxy/checkContentType(): invalid character " "after Content-Type!\n"); return False; } return True;}// Get the SDP message from SIP message and check it's Content-Type// return -1 on error, 0 if empty message, 1 if message present and not emptystatic intgetSDPMessage(struct sip_msg *msg, str *sdp){ sdp->s = get_body(msg); if (sdp->s==NULL) { LOG(L_ERR, "error: mediaproxy/getSDPMessage(): cannot get the SDP body from SIP message\n"); return -1; } sdp->len = msg->buf + msg->len - sdp->s; if (sdp->len==0) { // 0 length body is ok for ACK messages if (!(msg->first_line.type == SIP_REQUEST && msg->first_line.u.request.method_value == METHOD_ACK)) { LOG(L_ERR, "error: mediaproxy/getSDPMessage(): SDP message has zero length\n"); } return 0; } if (!checkContentType(msg)) { LOG(L_ERR, "error: mediaproxy/getSDPMessage(): content type is not `application/sdp'\n"); return -1; } return 1;}// will return the ip address present in a `c=' line in the given block// returns: -1 on error, 0 if not found, 1 if foundstatic intgetMediaIPFromBlock(str *block, str *mediaip){ str tokens[3], zone; char *ptr; int count; ptr = findLineStartingWith(block, "c=", False); if (!ptr) { mediaip->s = NULL; mediaip->len = 0; return 0; } zone.s = ptr + 2; zone.len = findendline(zone.s, block->s + block->len - zone.s) - zone.s; count = getStrTokens(&zone, tokens, 3); if (count != 3) { LOG(L_ERR, "error: mediaproxy/getMediaIPFromBlock(): invalid `c=' " "line in SDP body\n"); return -1; } // can also check if tokens[1] == 'IP4' *mediaip = tokens[2]; return 1;}// Get the session-level media IP defined by the SDP messagestatic BoolgetSessionLevelMediaIP(str *sdp, str *mediaip){ str block; char *ptr; // session IP can be found from the beginning up to the first media block ptr = findLineStartingWith(sdp, "m=", False); if (ptr) { block.s = sdp->s; block.len = ptr - block.s; } else { block = *sdp; } if (getMediaIPFromBlock(&block, mediaip) == -1) { LOG(L_ERR, "error: mediaproxy/getSessionLevelMediaIP(): parse error " "while getting session-level media IP from SDP body\n"); return False; } // it's not an error to be missing. it can be locally defined // by each media stream. thus we return true even if not found return True;}// will get all media streamsstatic intgetMediaStreams(str *sdp, str *sessionIP, StreamInfo *streams, int limit){ str tokens[2], block, zone; char *ptr, *sdpEnd; int i, count, streamCount, result; sdpEnd = sdp->s + sdp->len; for (i=0, block=*sdp; i<limit; i++) { ptr = findLineStartingWith(&block, "m=", False); if (!ptr) break; zone.s = ptr + 2; zone.len = findendline(zone.s, sdpEnd - zone.s) - zone.s; count = getStrTokens(&zone, tokens, 2); if (count != 2) { LOG(L_ERR, "error: mediaproxy/getMediaStreams(): invalid `m=' " "line in SDP body\n"); return -1; } streams[i].type = tokens[0]; streams[i].port = tokens[1]; block.s = zone.s + zone.len; block.len = sdpEnd - block.s; } streamCount = i; for (i=0; i<streamCount; i++) { block.s = streams[i].port.s; if (i < streamCount-1) block.len = streams[i+1].port.s - block.s; else block.len = sdpEnd - block.s; result = getMediaIPFromBlock(&block, &(streams[i].ip)); if (result == -1) { LOG(L_ERR, "error: mediaproxy/getMediaStreams(): parse error in " "getting the contact IP for the media stream nr. %d\n", i+1); return -1; } else if (result == 0) { if (sessionIP->s == NULL) { LOG(L_ERR, "error: mediaproxy/getMediaStreams(): media stream " "doesn't define a contact IP and the session-level IP " "is missing\n"); return -1; } streams[i].ip = *sessionIP; streams[i].localIP = 0; } else { streams[i].localIP = 1; } } return streamCount;}static BoolreplaceElement(struct sip_msg *msg, str *oldElem, str *newElem){ struct lump* anchor; char *buf; if (newElem->len==oldElem->len && memcmp(newElem->s, oldElem->s, newElem->len)==0) { return True; } buf = pkg_malloc(newElem->len); if (!buf) { LOG(L_ERR, "error: mediaproxy/replaceElement(): out of memory\n"); return False; } anchor = del_lump(msg, oldElem->s - msg->buf, oldElem->len, 0); if (!anchor) { LOG(L_ERR, "error: mediaproxy/replaceElement(): failed to delete old element\n"); pkg_free(buf); return False; } memcpy(buf, newElem->s, newElem->len); if (insert_new_lump_after(anchor, buf, newElem->len, 0)==0) { LOG(L_ERR, "error: mediaproxy/replaceElement(): failed to insert new element\n"); pkg_free(buf); return False; } return True;}// Functions dealing with the external mediaproxy helperstatic inline size_tuwrite(int fd, const void *buf, size_t count){ int len; do len = write(fd, buf, count); while (len == -1 && errno == EINTR); return len;}static inline size_turead(int fd, void *buf, size_t count){ int len; do len = read(fd, buf, count); while (len == -1 && errno == EINTR); return len;}static inline size_treadall(int fd, void *buf, size_t count){ int len, total; for (len=0, total=0; count-total>0; total+=len) { len = uread(fd, (char*)buf+total, count-total); if (len == -1) { return -1; } if (len == 0) { break; } } return total;}static char*sendMediaproxyCommand(char *command){ struct sockaddr_un addr; int smpSocket, len; static char buf[1024]; memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_LOCAL; strncpy(addr.sun_path, mediaproxySocket, sizeof(addr.sun_path) - 1);#ifdef HAVE_SOCKADDR_SA_LEN addr.sun_len = strlen(addr.sun_path);#endif smpSocket = socket(AF_LOCAL, SOCK_STREAM, 0); if (smpSocket < 0) { LOG(L_ERR, "error: mediaproxy/sendMediaproxyCommand(): can't create socket\n"); return NULL; } if (connect(smpSocket, (struct sockaddr*)&addr, sizeof(addr)) < 0) { close(smpSocket); LOG(L_ERR, "error: mediaproxy/sendMediaproxyCommand(): can't connect to MediaProxy\n"); return NULL; } len = uwrite(smpSocket, command, strlen(command)); if (len <= 0) { close(smpSocket); LOG(L_ERR, "error: mediaproxy/sendMediaproxyCommand(): can't send command to MediaProxy\n"); return NULL; } len = readall(smpSocket, buf, sizeof(buf)-1); close(smpSocket); if (len < 0) { LOG(L_ERR, "error: mediaproxy/sendMediaproxyCommand(): can't read reply from MediaProxy\n"); return NULL; } buf[len] = 0; return buf;}// Miscellaneous helper functions/* Test if IP in `address' belongs to a RFC1918 network */static inline intrfc1918address(str *address){ struct in_addr inaddr; uint32_t netaddr; int i, result; char c; c = address->s[address->len]; address->s[address->len] = 0; result = inet_aton(address->s, &inaddr); address->s[address->len] = c; if (result==0) return -1; /* invalid address to test */ netaddr = ntohl(inaddr.s_addr); for (i=0; rfc1918nets[i].name!=NULL; i++) { if ((netaddr & rfc1918nets[i].mask)==rfc1918nets[i].address) { return 1; } } return 0;}#define isPrivateAddress(x) (rfc1918address(x)==1 ? 1 : 0)// test for a public address is more complex (also need to test for// address not in 0.0.0.0/8, 127.0.0.0/8, 224.0.0.0/4).// #define isPublicAddress(x) (rfc1918address(x)==0 ? 1 : 0)// Check if the requested asymmetrics file has changed and reload it if neededstatic voidcheckAsymmetricFile(AsymmetricClients *aptr){ char buf[512], errbuf[256], *which; regex_t *re, **regs; int i, size, code; Bool firstTime = False; struct stat statbuf; FILE *file; str line; if (stat(aptr->file, &statbuf) < 0) return; // ignore missing file if (statbuf.st_mtime <= aptr->timestamp) return; // not changed // now we have work to do which = (aptr == &sipAsymmetrics ? "SIP" : "RTP"); if (!aptr->clients) { // if we are here the first time allocate memory to hold the regexps
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -