📄 driver.cpp
字号:
// Copyright (C) 2005 Open Source Telecom Corp.// // This program 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.// // This program 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.#include "driver.h"#ifdef WIN32#define CONFIG_FILES "C:/Program Files/GNU Telephony/Bayonne Config"#define strdup ost::strdup#else#include <private.h>#endifnamespace sipdriver {using namespace ost;using namespace std;static Keydata::Define driver[] = { {"type", "proto"}, {"proto", "sip"}, {"driver", "exosip2"}, {"stack", "0"}, {"events", "128"}, {"priority", "0"}, {"encoding", "mulaw"}, {"framing", "20"}, {"timer", "50"}, {"payload", "0"}, {"dtmf", "101"}, {"inband", "false"}, {"silence", "500"}, {"duration", "10m"}, {"invite", "60000"}, {"pickup", "2000"}, {"hangup", "250"}, {"accept", "320"}, {"audio", "60"}, {"jitter", "2"}, {"filler", "false"}, {"urlprefix", "sip:"}, {"peering", "friend"}, // default registration type#ifdef WIN32 // use localhost default if not in conf for w32 {"interface", "127.0.0.1:5070"},#endif {NULL, NULL}};#ifdef WIN32#define KEYS "/bayonne/sip"#else#define KEYS "/bayonne/driver/sip"#endifDriver Driver::sip;bool Registry::isActive(void){ if(!proxy) return active; if(!active) return false; if(getTimer() > 0) return true; return false;}void Registry::add(ScriptImage *img){ Registry *first = (Registry *)img->getPointer("_sip_registry_"); next = first; img->setPointer("_sip_registry_", this);}Driver::Driver() :BayonneDriver(driver, KEYS, "sip", false),Thread(atoi(getLast("priority")), atoi(getLast("stack")) * 1024){ const char *cp, *p; char buf[1024];#ifdef WIN32 const char *env = Process::getEnv("DRIVERCONFIG"); if(env) loadFile(env, "sip");#else if(Bayonne::provision_system) load("/bayonne/provision/sip"); else if(Bayonne::provision_user) load("~bayonne/sip");#endif sip_port = 5060; cp = getLast("ack"); if(!cp) cp = getLast("acktimer"); if(!cp) cp = getLast("pickup"); if(cp) pickup_timer = atol(cp); if(pickup_timer < 10) pickup_timer *= 1000; cp = getLast("hangup"); if(cp) hangup_timer = atol(cp); cp = getLast("bind"); if(!cp) cp = getLast("interface"); if(!cp) { gethostname(buf, sizeof(buf) - 1); InetAddress host(buf); snprintf(buf, sizeof(buf), "%s:5060", inet_ntoa(host.getAddress())); setValue("interface", buf); cp = getLast("interface"); } else setValue("interface", cp); p = strchr(cp, ':'); if(p) sip_port = atoi(++p); else sip_port = atoi(cp); rtp_port = sip_port + 2; cp = getLast("rtp"); if(cp) rtp_port = atoi(cp); silence = atoi(getLast("silence")); cp = getLast("inband"); dtmf_inband = true; switch(*cp) { case 'n': case 'N': case 'f': case 'F': case '0': case 0: dtmf_inband = false; break; } cp = getLast("filler"); data_filler = true; switch(*cp) { case 'n': case 'N': case 'f': case 'F': case '0': case 0: data_filler = false; break; } audio_timer = atol(getLast("audio")); hangup_timer -= audio_timer; accept_timer = atol(getLast("accept")); jitter = atoi(getLast("jitter")); data_negotiate = atoi(getLast("payload")); dtmf_negotiate = 0; cp = getLast("dtmf"); if(cp) dtmf_negotiate = atoi(cp); if(cp && !stricmp(cp, "info")) info_negotiate = true; if(cp && !stricmp(cp, "sipinfo")) info_negotiate = true; memset(&info, 0, sizeof(info)); cp = getLast("encoding"); info.encoding = getEncoding(cp); info.rate = rate8khz; cp = getLast("rate"); if(cp) info.rate = atol(cp); if(peer_encoding != Audio::unknownEncoding) { if(peer_encoding != Audio::pcm16Mono) info.encoding = peer_encoding; info.setFraming(peer_framing); } else info.setFraming(atol(getLast("framing"))); registry = false; server->setValue("sip.conf", CONFIG_FILES "/sip.conf");}unsigned Driver::getRegistration(regauth_t *data, unsigned count){ unsigned idx = 0; ScriptImage *img = useImage(); Registry *reg = (Registry *)img->getPointer("_sip_registry_"); while(idx < count && reg) { if(!strnicmp(reg->proxy, "sip:", 4)) data[idx].remote = reg->proxy + 4; else data[idx].remote = reg->proxy; data[idx].userid = reg->userid; data[idx].type = reg->type; if(!reg->proxy || !reg->userid) data[idx].status = "invalid"; else if(!reg->active) data[idx].status = "failed"; else if(reg->getTimer() > 0) data[idx].status = "active"; else data[idx].status = "expired"; ++idx; reg = reg->next; } endImage(img); return idx;}bool Driver::getAuthentication(Session *s){ char buf[256]; ScriptImage *img = s->getImage(); const char *cp = s->getSymbol("session.registry"); char *p; Registry *reg; bool rtn = false; if(!cp) goto done; reg = (Registry *)img->getPointer(buf); if(!reg) goto done; if(!reg->userid) goto done; setString(buf, sizeof(buf), reg->userid); p = strchr(buf, '@'); if(p) *(p++) = 0; eXosip_lock(); if(eXosip_add_authentication_info(buf, buf, reg->secret, NULL, reg->realm)) slog.error("sip: authentication failed; host=%s", reg->proxy); else { rtn = true; slog.debug("sip: authenticating to %s using %s", reg->proxy, reg->userid); } eXosip_unlock();done: return rtn;}void Driver::setAuthentication(Registry *reg){ char uname[65]; char *p; setString(uname, sizeof(uname), reg->userid); p = strchr(uname, '@'); if(p) *p = 0; eXosip_lock(); eXosip_add_authentication_info(uname, uname, reg->secret, NULL, reg->realm); eXosip_unlock();} void Driver::startDriver(void){ char cbuf[65]; unsigned tries = 0; char *p; const char *cp; unsigned max_count = ts_limit; cp = server->getLast("slots.sip"); int rtn; exiting = false; timeslot = ts_used; msgport = new BayonneMsgport(this); if(cp) max_count = atoi(cp); while(ts_used < ts_limit && max_count--) new Session(ts_used); count = ts_used - timeslot; if(!count) return; eXosip_init(); for(;;) { cp = getLast("transport"); if(!cp) cp = "udp"; if(!stricmp(cp, "tcp")) rtn = eXosip_listen_addr(IPPROTO_TCP, NULL, sip_port, AF_INET, 0); else if(!stricmp(cp, "tls")) rtn = eXosip_listen_addr(IPPROTO_TCP, NULL, sip_port, AF_INET, 1); else rtn = eXosip_listen_addr(IPPROTO_UDP, NULL, sip_port, AF_INET, 0); if(!rtn) break; slog.error("sip: failed to bind %d", sip_port); if(tries++ > 3) { eXosip_quit(); return; } sip_port += 10; if(!getLast("rtp")) rtp_port += 10; } cp = getLast("interface"); if(!cp) cp = "all"; setString(cbuf, sizeof(cbuf) - 8, getLast("interface")); p = strrchr(cbuf, ':'); snprintf(p + 1, 8, "%d", sip_port); setValue("interface", cbuf); *p = 0; setValue("localip", cbuf); osip_trace_initialize_syslog(TRACE_LEVEL0, "bayonne");/* osip_trace_enable_level(TRACE_LEVEL1); osip_trace_enable_level(TRACE_LEVEL2); osip_trace_enable_level(TRACE_LEVEL3); osip_trace_enable_level(TRACE_LEVEL4); osip_trace_enable_level(TRACE_LEVEL5); osip_trace_enable_level(TRACE_LEVEL6); osip_trace_enable_level(TRACE_LEVEL7);*/ switch(info.encoding) { case mulawAudio: if(!data_negotiate) setValue("payload", "0"); snprintf(cbuf, sizeof(cbuf), "%d PCMU/%ld", data_negotiate, info.rate); break; case alawAudio: if(!data_negotiate) { data_negotiate = 8; setValue("payload", "8"); } snprintf(cbuf, sizeof(cbuf), "%d PCMA/%ld", data_negotiate, info.rate); break; case pcm16Mono: snprintf(cbuf, sizeof(cbuf), "%d L16/%ld", data_negotiate, info.rate); break; case pcm16Stereo: snprintf(cbuf, sizeof(cbuf), "%d L16_2CH/%ld", data_negotiate, info.rate); break; case speexVoice: if(!data_negotiate) { data_negotiate = 97; setValue("payload", "97"); } snprintf(cbuf, sizeof(cbuf), "%d SPEEX/%ld", data_negotiate, info.rate); break; case gsmVoice: if(!data_negotiate) { data_negotiate = 3; setValue("payload", "3"); } snprintf(cbuf, sizeof(cbuf), "%d GSM/%ld", data_negotiate, info.rate); break; default: slog.error("sip: unsupported sdp audio encoding"); return; } slog.debug("sip: adding sdp encoding %s", cbuf); info.annotation = strdup(cbuf); eXosip_set_user_agent("GNU Bayonne"); slog.debug("sip: bound to port %d", sip_port); msgport->start(); Thread::start(); Thread::sleep(100); BayonneDriver::startDriver(); }void Driver::stopDriver(void){ if(running) { exiting = true; __eXosip_wakeup_event(); terminate(); eXosip_quit(); BayonneDriver::stopDriver(); }}const char *Driver::assignScript(ScriptImage *img, Line *line){ Name *scr = img->getCurrent(); char buffer[1024]; char cbuf[65]; char uname[65]; char rname[76]; unsigned idx = 0; const char *cp; char *ep, *contact; Registry *reg; const char *host, *port; for(;;) { cp = line->args[idx++]; if(!cp && idx > 1) break; reg = (Registry *)img->getMemory(sizeof(Registry)); reg->add(img); reg->proxy = NULL; reg->active = true; reg->protocol = "sip"; reg->iface = "none"; reg->uri = cp; reg->hostid = "none"; reg->userid = "none"; reg->realm = NULL; reg->type = "none"; reg->dtmf = NULL; reg->scr = scr; reg->secret = NULL; reg->line = line; reg->duration = 0; setString(cbuf, sizeof(cbuf), scr->name); ep = strchr(cbuf, ':'); if(ep) { *(ep++) = 0; *ep = '.'; } else ep = ""; host = strchr(cp, '@'); if(host) { ++host; ep = strrchr((char *)host, ':'); if(ep) *ep = 0; reg->address = host; setString(uname, sizeof(uname), cp); ep = strchr(uname, '@'); if(ep) *ep = 0; } else if(cp) { reg->address = NULL; setString(uname, sizeof(uname), cp); } else { reg->address = NULL; snprintf(uname, sizeof(uname), "%s%s", cbuf, ep); } snprintf(rname, sizeof(rname), "uri.%s", uname); host = getLast("interface"); if(reg->address) { port = strrchr(host, ':'); host = reg->address; } else port = ""; snprintf(buffer, sizeof(buffer), "sip:%s@%s%s", uname, host, port); ep = strrchr(buffer, ':'); if(ep && !stricmp(ep, ":5060")) *ep = 0; contact = (char *)img->getMemory(strlen(buffer) + 1); strcpy(contact, buffer); reg->contact = (const char *)contact; if(!reg->uri) reg->uri = reg->contact; reg->localid = (char *)img->getMemory(strlen(uname) + 1); strcpy((char *)reg->localid, uname); slog.debug("sip: assigning %s to %s", scr->name, buffer); img->setPointer(rname, reg); if(!cp) break; } return "";}const char *Driver::registerScript(ScriptImage *img, Line *line){ Name *scr = img->getCurrent(); Registry *reg = (Registry *)img->getMemory(sizeof(Registry)); const char *cp = ScriptChecks::findKeyword(line, "timeout"); const char *lcp; char buf[1024]; unsigned len, pos;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -