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

📄 mediaproxy.c

📁 用来作为linux中SIP SERVER,完成VOIP网络电话中服务器的功能
💻 C
📖 第 1 页 / 共 3 页
字号:
/* $Id: mediaproxy.c,v 1.23.2.4 2005/07/20 05:45:10 danp Exp $ * * Copyright (C) 2004 Dan Pascu * * This file is part of ser, a free SIP server. * * ser is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version * * For a license to use the ser software under conditions * other than those described here, or to purchase support for this * software, please contact iptel.org by e-mail at the following addresses: *    info@iptel.org * * ser is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * */// TODO//// - make the asymmetric files use CFG_DIR// - find a way to install the config files with make install#include "../../sr_module.h"#include "../../dprint.h"#include "../../str.h"#include "../../error.h"#include "../../data_lump.h"#include "../../forward.h"#include "../../mem/mem.h"#include "../../resolve.h"#include "../../timer.h"#include "../../ut.h"#include "../../parser/parse_from.h"#include "../../parser/parse_to.h"#include "../../parser/parse_uri.h"#include "../../msg_translator.h"#include "../registrar/sip_msg.h"#include "../usrloc/usrloc.h"#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <ctype.h>#include <errno.h>#include <regex.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <sys/un.h>MODULE_VERSION// Although `AF_LOCAL' is mandated by POSIX.1g, `AF_UNIX' is portable to// more systems.  `AF_UNIX' was the traditional name stemming from BSD, so// even most POSIX systems support it.  It is also the name of choice in// the Unix98 specification. So if there's no AF_LOCAL fallback to AF_UNIX#ifndef AF_LOCAL# define AF_LOCAL AF_UNIX#endif#define min(x, y)         (((x) < (y)) ? (x) : (y))#define isAnyAddress(adr) ((adr).len==7 && memcmp("0.0.0.0", (adr).s, 7)==0)typedef int Bool;#define True  1#define False 0typedef int  (*CheckLocalPartyProc)(struct sip_msg* msg, char* s1, char* s2);typedef Bool (*NatTestProc)(struct sip_msg* msg);typedef enum {    NTNone=0,    NTPrivateContact=1,    NTSourceAddress=2,    NTPrivateVia=4} NatTestType;typedef enum {    STUnknown=0,    STAudio,    STVideo,    STAudioVideo} StreamType;typedef struct {    const char *name;    uint32_t address;    uint32_t mask;} NetInfo;typedef struct {    str ip;    str port;    str type;    // stream type (`audio', `video', ...)    int localIP; // true if the IP is locally defined inside this media stream} StreamInfo;typedef struct {    NatTestType test;    NatTestProc proc;} NatTest;typedef struct {    char *file;        // the file which lists the asymmetric clients    long timestamp;    // for checking if it was modified    regex_t **clients; // the asymmetric clients regular expressions    int size;          // size of array above    int count;         // how many clients are in array above} AsymmetricClients;/* Function prototypes */static int ClientNatTest(struct sip_msg *msg, char *str1, char *str2);static int FixContact(struct sip_msg *msg, char *str1, char *str2);static int UseMediaProxy(struct sip_msg *msg, char *str1, char *str2);static int EndMediaSession(struct sip_msg *msg, char *str1, char *str2);static int mod_init(void);static int fixstring2int(void **param, int param_count);static Bool testPrivateContact(struct sip_msg* msg);static Bool testSourceAddress(struct sip_msg* msg);static Bool testPrivateVia(struct sip_msg* msg);/* Local global variables */static char *mediaproxySocket = "/var/run/proxydispatcher.sock";static int natpingInterval = 60; // 60 secondsstatic usrloc_api_t userLocation;static AsymmetricClients sipAsymmetrics = {    "/etc/ser/sip-asymmetric-clients",    //CFG_DIR"/sip-asymmetric-clients",    0,    NULL,    0,    0};static AsymmetricClients rtpAsymmetrics = {    "/etc/ser/rtp-asymmetric-clients",    0,    NULL,    0,    0};static CheckLocalPartyProc isFromLocal;//static CheckLocalPartyProc isToLocal;static CheckLocalPartyProc isDestinationLocal;NetInfo rfc1918nets[] = {    {"10.0.0.0",    0x0a000000UL, 0xff000000UL},    {"172.16.0.0",  0xac100000UL, 0xfff00000UL},    {"192.168.0.0", 0xc0a80000UL, 0xffff0000UL},    {NULL,          0UL,          0UL}};NatTest natTests[] = {    {NTPrivateContact, testPrivateContact},    {NTSourceAddress,  testSourceAddress},    {NTPrivateVia,     testPrivateVia},    {NTNone,           NULL}};static cmd_export_t commands[] = {    {"fix_contact",       FixContact,      0, 0,             REQUEST_ROUTE | ONREPLY_ROUTE },    {"use_media_proxy",   UseMediaProxy,   0, 0,             REQUEST_ROUTE | ONREPLY_ROUTE },    {"end_media_session", EndMediaSession, 0, 0,             REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE },    {"client_nat_test",   ClientNatTest,   1, fixstring2int, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE },    {0, 0, 0, 0, 0}};static param_export_t parameters[] = {    {"mediaproxy_socket", STR_PARAM, &mediaproxySocket},    {"sip_asymmetrics",   STR_PARAM, &(sipAsymmetrics.file)},    {"rtp_asymmetrics",   STR_PARAM, &(rtpAsymmetrics.file)},    {"natping_interval",  INT_PARAM, &natpingInterval},    {0, 0, 0}};struct module_exports exports = {    "mediaproxy", // module name    commands,     // module exported functions    parameters,   // module exported parameters    mod_init,     // module init (before any kid is created. kids will inherit)    NULL,         // reply processing    NULL,         // destroy function    NULL,         // on_break    NULL          // child_init};/* Helper functions */// Functions dealing with strings/* * strfind() finds the start of the first occurrence of the substring needle * of length nlen in the memory area haystack of length len. */static void*strfind(const void *haystack, size_t len, const void *needle, size_t nlen){    char *sp;    /* Sanity check */    if(!(haystack && needle && nlen && len>=nlen))        return NULL;    for (sp = (char*)haystack; sp <= (char*)haystack + len - nlen; sp++) {        if (*sp == *(char*)needle && memcmp(sp, needle, nlen)==0) {            return sp;        }    }    return NULL;}/* * strcasefind() finds the start of the first occurrence of the substring * needle of length nlen in the memory area haystack of length len by doing * a case insensitive search */static void*strcasefind(const char *haystack, size_t len, const char *needle, size_t nlen){    char *sp;    /* Sanity check */    if(!(haystack && needle && nlen && len>=nlen))        return NULL;    for (sp = (char*)haystack; sp <= (char*)haystack + len - nlen; sp++) {        if (tolower(*sp) == tolower(*(char*)needle) &&            strncasecmp(sp, needle, nlen)==0) {            return sp;        }    }    return NULL;}/* returns string with whitespace trimmed from left end */static inline voidltrim(str *string){    while (string->len>0 && isspace((int)*(string->s))) {        string->len--;        string->s++;    }}/* returns string with whitespace trimmed from right end */static inline voidrtrim(str *string){    char *ptr;    ptr = string->s + string->len - 1;    while (string->len>0 && (*ptr==0 || isspace((int)*ptr))) {        string->len--;        ptr--;    }}/* returns string with whitespace trimmed from both ends */static inline voidtrim(str *string){    ltrim(string);    rtrim(string);}/* returns a pointer to first CR or LF char found or the end of string */static char*findendline(char *string, int len){    char *ptr = string;    while(ptr - string < len && *ptr != '\n' && *ptr != '\r')        ptr++;    return ptr;}static intstrtoint(str *data){    long int result;    char c;    // hack to avoid copying the string    c = data->s[data->len];    data->s[data->len] = 0;    result = strtol(data->s, NULL, 10);    data->s[data->len] = c;    return (int)result;}/* Free the returned string with pkg_free() after you've done with it */static char*encodeQuopri(str buf){    char *result;    int i, j;    char c;    result = pkg_malloc(buf.len*3+1);    if (!result) {        LOG(L_ERR, "error: mediaproxy/encodeQuopri(): out of memory\n");        return NULL;    }    for (i=0, j=0; i<buf.len; i++) {        c = buf.s[i];        if ((c>0x20 && c<0x7f && c!='=') || c=='\n' || c=='\r') {            result[j++] = c;        } else {            result[j++] = '=';            sprintf(&result[j], "%02X", (c & 0xff));            j += 2;        }    }    result[j] = 0;    return result;}/* Find a line in str `block' that starts with `start'. */static char*findLineStartingWith(str *block, char *start, int ignoreCase){    char *ptr, *bend;    str zone;    int tlen;    bend = block->s + block->len;    tlen = strlen(start);    ptr = NULL;    for (zone = *block; zone.len > 0; zone.len = bend - zone.s) {        if (ignoreCase)            ptr = strcasefind(zone.s, zone.len, start, tlen);        else            ptr = strfind(zone.s, zone.len, start, tlen);        if (!ptr || ptr==zone.s || ptr[-1]=='\n' || ptr[-1]=='\r')            break;        zone.s = ptr + tlen;    }    return ptr;}/* get up to `limit' whitespace separated tokens from `char *string' */static intgetTokens(char *string, str *tokens, int limit){    int i, len, size;    char *ptr;    if (!string) {        return 0;    }    len  = strlen(string);    for (ptr=string, i=0; i<limit && len>0; i++) {        size = strspn(ptr, " \t\n\r");        ptr += size;        len -= size;        if (len <= 0)            break;        size = strcspn(ptr, " \t\n\r");        if (size==0)            break;        tokens[i].s = ptr;        tokens[i].len = size;        ptr += size;        len -= size;    }    return i;}/* get up to `limit' whitespace separated tokens from `str *string' */static intgetStrTokens(str *string, str *tokens, int limit){    int count;    char c;    if (!string || !string->s) {        return 0;    }    c = string->s[string->len];    string->s[string->len] = 0;    count = getTokens(string->s, tokens, limit);    string->s[string->len] = c;    return count;}/* Functions to extract the info we need from the SIP/SDP message *//* Extract Call-ID value. */static BoolgetCallId(struct sip_msg* msg, str *cid){    if (msg->callid == NULL) {        if (parse_headers(msg, HDR_CALLID, 0) == -1) {            return False;        }        if (msg->callid == NULL) {            return False;        }    }    *cid = msg->callid->body;    trim(cid);    return True;}/* Get caller domain */static strgetFromDomain(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!    static struct sip_uri puri;    str uri;    if (parse_from_header(msg) < 0) {        LOG(L_ERR, "error: mediaproxy/getFromDomain(): error parsing `From' header\n");        return notfound;    }    uri = get_from(msg)->uri;    if (parse_uri(uri.s, uri.len, &puri) < 0) {        LOG(L_ERR, "error: mediaproxy/getFromDomain(): error parsing `From' URI\n");        return notfound;    } else if (puri.host.len == 0) {        return notfound;    }    return puri.host;}/* Get called domain */static strgetToDomain(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!    static struct sip_uri puri;    str uri;    uri = get_to(msg)->uri;    if (parse_uri(uri.s, uri.len, &puri) < 0) {        LOG(L_ERR, "error: mediaproxy/getToDomain(): error parsing `To' URI\n");        return notfound;    } else if (puri.host.len == 0) {        return notfound;    }    return puri.host;}/* Get destination domain */// This function only works when called for a request although it's more// reliable than the getToDomain function.static strgetDestinationDomain(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!    if (parse_sip_msg_uri(msg) < 0) {        LOG(L_ERR, "error: mediaproxy/getDestinationDomain(): error parsing destination URI\n");        return notfound;    } else if (msg->parsed_uri.host.len==0) {        return notfound;    }    return msg->parsed_uri.host;}/* Get From tag */static strgetFromAddress(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 (parse_from_header(msg) == -1) {        LOG(L_ERR, "error: mediaproxy/getFromAddress(): error parsing From: field\n");        return notfound;

⌨️ 快捷键说明

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