⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mediaproxy.c

📁 用来作为linux中SIP SERVER,完成VOIP网络电话中服务器的功能
💻 C
📖 第 1 页 / 共 3 页
字号:
        // initial size of array        // (hopefully not reached so we won't need to realloc)        size = 32;        aptr->clients = (regex_t**)pkg_malloc(size*sizeof(regex_t**));        if (!aptr->clients) {            LOG(L_WARN, "warning: mediaproxy/checkAsymmetricFile() cannot "                "allocate memory for the %s asymmetric client list. "                "%s asymmetric clients will not be handled properly.\n",                which, which);            return; // ignore as it is not fatal        }        aptr->size  = size;        aptr->count = 0;        firstTime = True;    } else {        // else clean old stuff        for (i=0; i<aptr->count; i++) {            regfree(aptr->clients[i]);            pkg_free(aptr->clients[i]);            aptr->clients[i] = NULL;        }        aptr->count = 0;    }    // read new    file = fopen(aptr->file, "r");    i = 0; // this will count on which line are we in the file    while (!feof(file)) {        if (!fgets(buf, 512, file))            break;        i++;        line.s = buf;        line.len = strlen(buf);        trim(&line);        if (line.len == 0 || line.s[0] == '#')            continue; // comment or empty line. ignore        line.s[line.len] = 0;        re = (regex_t*)pkg_malloc(sizeof(regex_t));        if (!re) {            LOG(L_WARN, "warning: mediaproxy/checkAsymmetricFile(): "                "cannot allocate memory for all the %s asymmetric "                "clients listed in file. Some of them will not be "                "handled properly.\n", which);            break;        }        code = regcomp(re, line.s, REG_EXTENDED|REG_ICASE|REG_NOSUB);        if (code == 0) {            if (aptr->count+1 > aptr->size) {                size = aptr->size * 2;                regs = aptr->clients;                regs = (regex_t**)pkg_realloc(regs, size*sizeof(regex_t**));                if (!regs) {                    LOG(L_WARN, "warning: mediaproxy/checkAsymmetricFile(): "                        "cannot allocate memory for all the %s asymmetric "                        "clients listed in file. Some of them will not be "                        "handled properly.\n", which);                    break;                }                aptr->clients = regs;                aptr->size = size;            }            aptr->clients[aptr->count] = re;            aptr->count++;        } else {            regerror(code, re, errbuf, 256);            LOG(L_WARN, "warning: mediaproxy/checkAsymmetricFile(): cannot "                "compile line %d of the %s asymmetric clients file into a "                "regular expression (will be ignored): %s", i, which, errbuf);            pkg_free(re);        }    }    aptr->timestamp = statbuf.st_mtime;    LOG(L_INFO, "info: mediaproxy: %sloaded %s asymmetric clients file "        "containing %d entr%s.\n", firstTime ? "" : "re",        which, aptr->count, aptr->count==1 ? "y" : "ies");}//// This is a hack. Until a I find a better way to allow all children to update// the asymmetric client list when the files change on disk, it stays as it is// A timer registered from mod_init() only runs in one of the ser processes// and the others will always see the file that was read at startup.//#include <time.h>#define CHECK_INTERVAL 5static voidperiodicAsymmetricsCheck(void){    static time_t last = 0;    time_t now;    // this is not guaranteed to run at every CHECK_INTERVAL.    // it is only guaranteed that the files won't be checked more often.    now = time(NULL);    if (now > last + CHECK_INTERVAL) {        checkAsymmetricFile(&sipAsymmetrics);        checkAsymmetricFile(&rtpAsymmetrics);        last = now;    }}static BoolisSIPAsymmetric(str userAgent){    int i, code;    char c;    periodicAsymmetricsCheck();    if (!sipAsymmetrics.clients || sipAsymmetrics.count==0)        return False;    c = userAgent.s[userAgent.len];    userAgent.s[userAgent.len] = 0;    for (i=0; i<sipAsymmetrics.count; i++) {        code = regexec(sipAsymmetrics.clients[i], userAgent.s, 0, NULL, 0);        if (code == 0) {            userAgent.s[userAgent.len] = c;            return True;        } else if (code != REG_NOMATCH) {            char errbuf[256];            regerror(code, sipAsymmetrics.clients[i], errbuf, 256);            LOG(L_WARN, "warning: mediaproxy/isSIPAsymmetric() failed to "                "match regexp: %s\n", errbuf);        }    }    userAgent.s[userAgent.len] = c;    return False;}static BoolisRTPAsymmetric(str userAgent){    int i, code;    char c;    periodicAsymmetricsCheck();    if (!rtpAsymmetrics.clients || rtpAsymmetrics.count==0)        return False;    c = userAgent.s[userAgent.len];    userAgent.s[userAgent.len] = 0;    for (i=0; i<rtpAsymmetrics.count; i++) {        code = regexec(rtpAsymmetrics.clients[i], userAgent.s, 0, NULL, 0);        if (code == 0) {            userAgent.s[userAgent.len] = c;            return True;        } else if (code != REG_NOMATCH) {            char errbuf[256];            regerror(code, rtpAsymmetrics.clients[i], errbuf, 256);            LOG(L_WARN, "warning: mediaproxy/isRTPAsymmetric() failed to "                "match regexp: %s\n", errbuf);        }    }    userAgent.s[userAgent.len] = c;    return False;}// NAT tests/* tests if address of signaling is different from address in 1st Via field */static BooltestSourceAddress(struct sip_msg* msg){    Bool diffIP, diffPort;    int via1Port;    diffIP = received_test(msg);    if (isSIPAsymmetric(getUserAgent(msg))) {        // ignore port test for asymmetric clients (it's always different)        diffPort = False;    } else {        via1Port = (msg->via1->port ? msg->via1->port : SIP_PORT);        diffPort = (msg->rcv.src_port != via1Port);    }    return (diffIP || diffPort);}/* tests if Contact field contains a private IP address as defined in RFC1918 */static BooltestPrivateContact(struct sip_msg* msg){    struct sip_uri uri;    contact_t* contact;    if (!getContactURI(msg, &uri, &contact))        return False;    return isPrivateAddress(&(uri.host));}/* tests if top Via field contains a private IP address as defined in RFC1918 */static BooltestPrivateVia(struct sip_msg* msg){    return isPrivateAddress(&(msg->via1->host));}#include "functions.h"/* The public functions that are exported by this module */static intClientNatTest(struct sip_msg* msg, char* str1, char* str2){    int tests, i;    tests = (int)(long)str1;    for (i=0; natTests[i].test!=NTNone; i++) {        if ((tests & natTests[i].test)!=0 && natTests[i].proc(msg)) {            return 1;        }    }    return -1; // all failed}static intEndMediaSession(struct sip_msg* msg, char* str1, char* str2){    char *command, *result;    str callId;    if (!getCallId(msg, &callId)) {        LOG(L_ERR, "error: end_media_session(): can't get Call-Id\n");        return -1;    }    command = pkg_malloc(callId.len + 20);    if (command == NULL) {        LOG(L_ERR, "error: end_media_session(): out of memory\n");        return -1;    }    sprintf(command, "delete %.*s info=\n", callId.len, callId.s);    result = sendMediaproxyCommand(command);    pkg_free(command);    return result==NULL ? -1 : 1;}#define MSG_UNKNOWN 0#define MSG_INVITE  1#define MSG_ACK     2#define MSG_REPLY   3static intUseMediaProxy(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(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 = getToDomain(msg);        toType = "unknown"; //there's no function to check if To domain is local    }    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;}/* Module management: initialization/destroy/function-parameter-fixing/... */static intmod_init(void){    bind_usrloc_t ul_bind_usrloc;    isFromLocal = (CheckLocalPartyProc)find_export("is_from_local", 0, 0);    isDestinationLocal = (CheckLocalPartyProc)find_export("is_uri_host_local", 0, 0);    if (!isFromLocal || !isDestinationLocal) {        LOG(L_ERR, "error: mediaproxy/mod_init(): can't find is_from_local "            "and/or is_uri_host_local functions. Check if domain.so is loaded\n");        return -1;    }    if (natpingInterval > 0) {        ul_bind_usrloc = (bind_usrloc_t)find_export("ul_bind_usrloc", 1, 0);        if (!ul_bind_usrloc) {            LOG(L_ERR, "error: mediaproxy/mod_init(): can't find the usrloc "                "module. Check if usrloc.so is loaded.\n");            return -1;        }        if (ul_bind_usrloc(&userLocation) < 0) {            LOG(L_ERR, "error: mediaproxy/mod_init(): can't access the usrloc module.\n");            return -1;        }        register_timer(pingClients, NULL, natpingInterval);    }    checkAsymmetricFile(&sipAsymmetrics);    checkAsymmetricFile(&rtpAsymmetrics);    // children won't benefit from this. figure another way    //register_timer(checkAsymmetricFiles, NULL, 5);    return 0;}// convert string parameter to integer for functions that expect an integerstatic intfixstring2int(void **param, int param_count){    unsigned long number;    int err;    if (param_count == 1) {        number = str2s(*param, strlen(*param), &err);        if (err == 0) {            pkg_free(*param);            *param = (void*)number;            return 0;        } else {            LOG(L_ERR, "error: mediaproxy/fixstring2int(): bad number `%s'\n",                (char*)(*param));            return E_CFG;        }    }    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -