diff --git a/apps/dsm/mods/mod_dlg/ModDlg.h b/apps/dsm/mods/mod_dlg/ModDlg.h index 23cb104b..098f7722 100644 --- a/apps/dsm/mods/mod_dlg/ModDlg.h +++ b/apps/dsm/mods/mod_dlg/ModDlg.h @@ -52,6 +52,7 @@ DEF_ACTION_1P(DLGGetOtherIdAction); DEF_ACTION_1P(DLGGetRtpRelayModeAction); DEF_ACTION_2P(DLGReferAction); +DEF_ACTION_2P(DLGInfoAction); DEF_ACTION_2P(DLGB2BRelayErrorAction); DEF_ACTION_2P(DLGAddReplyBodyPartAction); diff --git a/apps/dsm/mods/mod_regex/ModRegex.cpp b/apps/dsm/mods/mod_regex/ModRegex.cpp index e0a3b7a2..642bb5d8 100644 --- a/apps/dsm/mods/mod_regex/ModRegex.cpp +++ b/apps/dsm/mods/mod_regex/ModRegex.cpp @@ -74,7 +74,7 @@ int MOD_CLS_NAME::preload() { } int MOD_CLS_NAME::add_regex(const string& r_name, const string& r_reg) { - if (regexes[r_name].regcomp(r_reg.c_str(), REG_NOSUB | REG_EXTENDED)) { + if (regexes[r_name].regcomp(r_reg.c_str(), /* REG_NOSUB | */ REG_EXTENDED)) { ERROR("compiling '%s' for regex '%s'\n", r_reg.c_str(), r_name.c_str()); regexes.erase(r_name); return -1; @@ -97,8 +97,18 @@ MATCH_CONDITION_START(SCExecRegexCondition) { return false; } - int res = it->second.regexec(val.c_str(), 1, NULL, 0); + regmatch_t matches[it->second.get_nsub()+1]; + int res = it->second.regexec(val.c_str(), it->second.get_nsub(), matches, 0); // res==0 -> match + + if (!res) { + for (size_t i=1;isecond.get_nsub()+1;i++) { + if (matches[i].rm_so < 0) continue; + sc_sess->var["regex.match["+int2str((unsigned int)i)+"]"] = + val.substr(matches[i].rm_so, matches[i].rm_eo - matches[i].rm_so); + } + } + DBG("regex did %smatch\n", res==0?"":"not "); if (inv) { return res != 0; @@ -131,7 +141,17 @@ EXEC_ACTION_START(SCExecRegexAction) { EXEC_ACTION_STOP; } - int res = it->second.regexec(val.c_str(), 1, NULL, 0); + regmatch_t matches[it->second.get_nsub()+1]; + int res = it->second.regexec(val.c_str(), it->second.get_nsub()+1, matches, 0); + + if (!res) { + for (size_t i=1;isecond.get_nsub()+1;i++) { + if (matches[i].rm_so < 0) continue; + sc_sess->var["regex.match["+int2str((unsigned int)i)+"]"] = + val.substr(matches[i].rm_so, matches[i].rm_eo - matches[i].rm_so); + } + } + if (!res) { // yeah side effects sc_sess->var["regex.match"] = "1"; @@ -179,3 +199,7 @@ int TsRegex::regexec(const char *_string, size_t nmatch, m.unlock(); return res; } + +size_t TsRegex::get_nsub() { + return i ? reg.re_nsub : 0; +} diff --git a/apps/dsm/mods/mod_regex/ModRegex.h b/apps/dsm/mods/mod_regex/ModRegex.h index f553389c..216b31a1 100644 --- a/apps/dsm/mods/mod_regex/ModRegex.h +++ b/apps/dsm/mods/mod_regex/ModRegex.h @@ -46,7 +46,7 @@ class TsRegex { ~TsRegex(); int regcomp(const char *regex, int cflags); int regexec(const char *_string, size_t nmatch, regmatch_t pmatch[], int eflags); - + size_t get_nsub(); }; DECLARE_MODULE_BEGIN(MOD_CLS_NAME); diff --git a/apps/dsm/mods/mod_sbc/ModSbc.cpp b/apps/dsm/mods/mod_sbc/ModSbc.cpp index a2f3a9b0..945d263d 100644 --- a/apps/dsm/mods/mod_sbc/ModSbc.cpp +++ b/apps/dsm/mods/mod_sbc/ModSbc.cpp @@ -210,6 +210,7 @@ CONST_ACTION_2P(MODSBCActionProfileSet, ',', false); EXEC_ACTION_START(MODSBCActionProfileSet) { string profile_param = resolveVars(par1, sess, sc_sess, event_params); string value = resolveVars(par2, sess, sc_sess, event_params); + FilterEntry mf; ACTION_GET_PROFILE; @@ -268,7 +269,6 @@ EXEC_ACTION_START(MODSBCActionProfileSet) { SET_TO_CALL_PROFILE("aleg_next_hop", aleg_next_hop); - // TODO: message_filter // TODO: header_filter // TODO: sdp_filter @@ -312,6 +312,22 @@ EXEC_ACTION_START(MODSBCActionProfileSet) { EXEC_ACTION_STOP; } + if (profile_param == "message_filter") { + mf.filter_type = String2FilterType(value.c_str()); + DBG("message_filter set to '%s'\n", value.c_str()); + EXEC_ACTION_STOP; + } + + if (profile_param == "message_list") { + vector elems = explode(value, ","); + for (vector::iterator it=elems.begin(); it != elems.end(); it++) + mf.filter_list.insert(*it); + profile->messagefilter.push_back(mf); + mf.filter_type = Undefined; + DBG("message_list set to '%s'\n", value.c_str()); + EXEC_ACTION_STOP; + } + } // TODO: Transcoder Settings diff --git a/apps/jsonrpc/JsonRPCServer.cpp b/apps/jsonrpc/JsonRPCServer.cpp index b48524ee..c5143212 100644 --- a/apps/jsonrpc/JsonRPCServer.cpp +++ b/apps/jsonrpc/JsonRPCServer.cpp @@ -173,14 +173,14 @@ int JsonRpcServer::processMessage(char* msgbuf, unsigned int* msg_size, } string id; + bool id_is_int = false; if (rpc_params.hasMember("id")) { - if (isArgCStr(rpc_params["id"])) + if (isArgCStr(rpc_params["id"])) { id = rpc_params["id"].asCStr(); - else if (isArgInt(rpc_params["id"])) + } else if (isArgInt(rpc_params["id"])) { id = int2str(rpc_params["id"].asInt()); - else if (isArgBool(rpc_params["id"])) - id = rpc_params["id"].asBool() ? "True":"False"; - else { + id_is_int = true; + } else { ERROR("incorrect type for jsonrpc id <%s>\n", AmArg::print(rpc_params["id"]).c_str()); } @@ -237,11 +237,18 @@ int JsonRpcServer::processMessage(char* msgbuf, unsigned int* msg_size, } AmArg rpc_res; + int int_id; execRpc(rpc_params, rpc_res); - // rpc_res["error"] = AmArg(); // Undef/null - // rpc_res["id"] = rpc_params["id"]; + if (!id.empty()) { + if (id_is_int) { + str2int(id, int_id); + rpc_res["id"] = int_id; + } else { + rpc_res["id"] = id; + } + } string res_s = arg2json(rpc_res); if (res_s.length() > MAX_RPC_MSG_SIZE) { @@ -287,7 +294,6 @@ void JsonRpcServer::execRpc(const string& method, const string& id, const AmArg& if (factory == "core") { runCoreMethod(fact_meth, params, rpc_res["result"]); rpc_res["id"] = id; - rpc_res["error"] = AmArg(); // Undef/null rpc_res["jsonrpc"] = "2.0"; return; } @@ -344,10 +350,9 @@ void JsonRpcServer::execRpc(const string& method, const string& id, const AmArg& // todo: notification! rpc_res["id"] = id; rpc_res["jsonrpc"] = "2.0"; + rpc_res.erase("result"); return; } - - rpc_res["error"] = AmArg(); // Undef/null } void JsonRpcServer::runCoreMethod(const string& method, const AmArg& params, AmArg& res) { diff --git a/core/AmAppTimer.cpp b/core/AmAppTimer.cpp index 921c6ff6..323c2834 100644 --- a/core/AmAppTimer.cpp +++ b/core/AmAppTimer.cpp @@ -25,7 +25,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "AmEventDispatcher.h" +#include "AmSessionContainer.h" #include "AmAppTimer.h" #include "log.h" @@ -88,8 +88,8 @@ void _AmAppTimer::app_timer_cb(app_timer* at) user_timers[at->get_q_id()][at->get_id()] = at_local; } else { DBG("timer fired: %d for '%s'\n", at->get_id(), at->get_q_id().c_str()); - AmEventDispatcher::instance()->post(at->get_q_id(), - new AmTimeoutEvent(at->get_id())); + AmSessionContainer::instance()->postEvent(at->get_q_id(), + new AmTimeoutEvent(at->get_id())); delete at; } diff --git a/core/AmB2BMedia.cpp b/core/AmB2BMedia.cpp index 94af7e5b..b83d5aa4 100644 --- a/core/AmB2BMedia.cpp +++ b/core/AmB2BMedia.cpp @@ -585,12 +585,13 @@ void AmB2BMedia::changeSessionUnsafe(bool a_leg, AmB2BSession *new_session) for (RelayStreamIterator j = relay_streams.begin(); j != relay_streams.end(); ++j) { AmRtpStream &a = (*j)->a; - AmRtpStream &b = (*j)->a; + AmRtpStream &b = (*j)->b; // FIXME: is stop & resume receiving needed here? - a.changeSession(new_session); - b.changeSession(new_session); - + if (a_leg) + a.changeSession(new_session); + else + b.changeSession(new_session); } if (needs_processing) { diff --git a/core/AmBasicSipDialog.cpp b/core/AmBasicSipDialog.cpp index 8a95c66f..f0aeef49 100644 --- a/core/AmBasicSipDialog.cpp +++ b/core/AmBasicSipDialog.cpp @@ -99,9 +99,15 @@ const char* AmBasicSipDialog::getStatusStr() return getStatusStr(status); } -string AmBasicSipDialog::getContactHdr() +string AmBasicSipDialog::getContactHdr() { + return + SIP_HDR_COLSP(SIP_HDR_CONTACT) "<"+ getContactUri() += ">" CRLF; +} + + +string AmBasicSipDialog::getContactUri() { - string contact_uri = SIP_HDR_COLSP(SIP_HDR_CONTACT) "advertized_rate = pl.advertised_clock_rate; DBG("fmt.advertized_rate = %d", this->advertized_rate); this->frame_size = 20*this->rate/1000; + DBG("fmt.sdp_format_parameters = %s", this->sdp_format_parameters.c_str()); if (this->codec != NULL) { destroyCodec(); } @@ -333,6 +334,8 @@ int AmRtpAudio::init(const AmSdp& local, } fmt_p->setCurrentPayload(payloads[pl_it->second.index]); fmt.reset(fmt_p); + amci_codec_t* codec = fmt->getCodec(); + use_default_plc = ((codec==NULL) || (codec->plc == NULL)); fec.reset(new LowcFE(getSampleRate())); @@ -371,7 +374,13 @@ int AmRtpAudio::setCurrentPayload(int payload) } this->payload = payload; - return ((AmAudioRtpFormat*)fmt.get())->setCurrentPayload(payloads[index]); + int res = ((AmAudioRtpFormat*)fmt.get())->setCurrentPayload(payloads[index]); + + amci_codec_t* codec = fmt->getCodec(); + use_default_plc = ((codec==NULL) || (codec->plc == NULL)); + + return res; + } else { return 0; diff --git a/core/AmSdp.cpp b/core/AmSdp.cpp index 1097c9a3..5689a34d 100644 --- a/core/AmSdp.cpp +++ b/core/AmSdp.cpp @@ -33,14 +33,19 @@ using std::map; #include "strings.h" #endif +#define CR '\r' +#define LF '\n' +#define CRLF "\r\n" + static void parse_session_attr(AmSdp* sdp_msg, char* s, char** next); static bool parse_sdp_line_ex(AmSdp* sdp_msg, char*& s); -static void parse_sdp_connection(AmSdp* sdp_msg, char* s, char t); +static char* parse_sdp_connection(AmSdp* sdp_msg, char* s, char t); static void parse_sdp_media(AmSdp* sdp_msg, char* s); -static void parse_sdp_attr(AmSdp* sdp_msg, char* s); +static char* parse_sdp_attr(AmSdp* sdp_msg, char* s); static void parse_sdp_origin(AmSdp* sdp_masg, char* s); inline char* get_next_line(char* s); +inline char* skip_till_next_line(char* s, size_t& line_len); static char* is_eql_next(char* s); static char* parse_until(char* s, char end); static char* parse_until(char* s, char* end, char c); @@ -555,7 +560,7 @@ static bool parse_sdp_line_ex(AmSdp* sdp_msg, char*& s) { if (!s) return true; // SDP can't be empty, return error (true really used for failure?) - char* next=0; + char* next=0; size_t line_len = 0; register parse_st state; //default state state=SDP_DESCR; @@ -568,11 +573,13 @@ static bool parse_sdp_line_ex(AmSdp* sdp_msg, char*& s) case 'v': { s = is_eql_next(s); - next = get_next_line(s); - if (int(next-s)-2 >= 0) { - string version(s, int(next-s)-2); + next = skip_till_next_line(s, line_len); + if (line_len) { + string version(s, line_len); str2i(version, sdp_msg->version); - //DBG("parse_sdp_line_ex: found version\n"); + // DBG("parse_sdp_line_ex: found version '%s'\n", version.c_str()); + } else { + sdp_msg->version = 0; } s = next; state = SDP_DESCR; @@ -588,23 +595,24 @@ static bool parse_sdp_line_ex(AmSdp* sdp_msg, char*& s) break; case 's': { - //DBG("parse_sdp_line_ex: found session\n"); s = is_eql_next(s); - next = get_next_line(s); - if (int(next-s)-2 >= 0) { - string sessionName(s, int(next-s)-2); - sdp_msg->sessionName = sessionName; + next = skip_till_next_line(s, line_len); + if (line_len) { + sdp_msg->sessionName = string(s, line_len); + } else { + sdp_msg->sessionName.clear(); } s = next; break; } case 'u': { - //DBG("parse_sdp_line_ex: found uri\n"); s = is_eql_next(s); - next = get_next_line(s); - if (int(next-s)-2 >= 0) { - sdp_msg->uri = string(s, int(next-s)-2); + next = skip_till_next_line(s, line_len); + if (line_len) { + sdp_msg->uri = string(s, line_len); + } else { + sdp_msg->uri.clear(); } s = next; } break; @@ -615,14 +623,11 @@ static bool parse_sdp_line_ex(AmSdp* sdp_msg, char*& s) case 'b': case 't': case 'k': - //DBG("parse_sdp_line_ex: found unknown line '%c'\n", *s); s = is_eql_next(s); - next = get_next_line(s); - s = next; + s = skip_till_next_line(s, line_len); state = SDP_DESCR; break; case 'a': - //DBG("parse_sdp_line_ex: found attributes\n"); s = is_eql_next(s); parse_session_attr(sdp_msg, s, &next); // next = get_next_line(s); @@ -631,11 +636,9 @@ static bool parse_sdp_line_ex(AmSdp* sdp_msg, char*& s) state = SDP_DESCR; break; case 'c': - //DBG("parse_sdp_line_ex: found connection\n"); s = is_eql_next(s); - parse_sdp_connection(sdp_msg, s, 'd'); - s = get_next_line(s); - state = SDP_DESCR; + s = parse_sdp_connection(sdp_msg, s, 'd'); + state = SDP_DESCR; break; case 'm': //DBG("parse_sdp_line_ex: found media\n"); @@ -644,11 +647,17 @@ static bool parse_sdp_line_ex(AmSdp* sdp_msg, char*& s) default: { - next = get_next_line(s); - if (int(next-s)-2 >= 0) { - string line(s, int(next-s)-2); + next = skip_till_next_line(s, line_len); + if (line_len) { + sdp_msg->uri = string(s, line_len); + } else { + sdp_msg->uri.clear(); + } + + next = skip_till_next_line(s, line_len); + if (line_len) { DBG("parse_sdp_line: skipping unknown Session description %s=\n", - (char*)line.c_str()); + string(s, line_len).c_str()); } s = next; break; @@ -661,45 +670,42 @@ static bool parse_sdp_line_ex(AmSdp* sdp_msg, char*& s) case 'm': s = is_eql_next(s); parse_sdp_media(sdp_msg, s); - s = get_next_line(s); + s = skip_till_next_line(s, line_len); state = SDP_MEDIA; break; case 'i': s = is_eql_next(s); - s = get_next_line(s); + s = skip_till_next_line(s, line_len); state = SDP_MEDIA; break; case 'c': s = is_eql_next(s); //DBG("parse_sdp_line: found media connection\n"); - parse_sdp_connection(sdp_msg, s, 'm'); - s = get_next_line(s); + s = parse_sdp_connection(sdp_msg, s, 'm'); state = SDP_MEDIA; break; case 'b': s = is_eql_next(s); - s = get_next_line(s); + s = skip_till_next_line(s, line_len); state = SDP_MEDIA; break; case 'k': s = is_eql_next(s); - s = get_next_line(s); + s = skip_till_next_line(s, line_len); state = SDP_MEDIA; break; case 'a': s = is_eql_next(s); - parse_sdp_attr(sdp_msg, s); - s = get_next_line(s); + s = parse_sdp_attr(sdp_msg, s); state = SDP_MEDIA; break; default : { - next = get_next_line(s); - if (int(next-s)-2 >= 0) { - string line(s, int(next-s)-2); - DBG("parse_sdp_line: skipping unknown Media description '%s'\n", - (char*)line.c_str()); + next = skip_till_next_line(s, line_len); + if (line_len) { + DBG("parse_sdp_line: skipping unknown Media description '%.*s'\n", + (int)line_len, s); } s = next; break; @@ -713,17 +719,23 @@ static bool parse_sdp_line_ex(AmSdp* sdp_msg, char*& s) } -static void parse_sdp_connection(AmSdp* sdp_msg, char* s, char t) +static char* parse_sdp_connection(AmSdp* sdp_msg, char* s, char t) { char* connection_line=s; char* next=0; - char* line_end=0; + char* next_line=0; + size_t line_len = 0; int parsing=1; SdpConnection c; - line_end = get_next_line(s); + next_line = skip_till_next_line(s, line_len); + if (line_len <= 7) { // should be at least c=IN IP4 ... + DBG("short connection line '%.*s'\n", (int)line_len, s); + return next_line; + } + register sdp_connection_st state; state = NET_TYPE; @@ -732,34 +744,35 @@ static void parse_sdp_connection(AmSdp* sdp_msg, char* s, char t) while(parsing){ switch(state){ case NET_TYPE: - //Ignore NET_TYPE since it is always IN - connection_line +=3; + //Ignore NET_TYPE since it is always IN, fixme + c.network = NT_IN; // fixme + connection_line +=3; // fixme state = ADDR_TYPE; break; case ADDR_TYPE: { string addr_type(connection_line,3); - connection_line +=4; + connection_line +=4; // fixme if(addr_type == "IP4"){ - c.addrType = 1; + c.addrType = AT_V4; state = IP4; }else if(addr_type == "IP6"){ - c.addrType = 2; + c.addrType = AT_V6; state = IP6; }else{ - ERROR("parse_sdp_connection: Unknown addr_type in c=\n"); - c.addrType = 0; - parsing = 0; + DBG("parse_sdp_connection: Unknown addr_type in c-line: '%s'\n", addr_type.c_str()); + c.addrType = AT_NONE; + parsing = 0; // ??? } break; } case IP4: { - if(contains(connection_line, line_end, '/')){ + if(contains(connection_line, next_line, '/')){ next = parse_until(s, '/'); c.address = string(connection_line,int(next-connection_line)-2); }else{ - c.address = string(connection_line, int(line_end-connection_line)-2); + c.address = string(connection_line, line_len-7); } parsing = 0; break; @@ -767,11 +780,11 @@ static void parse_sdp_connection(AmSdp* sdp_msg, char* s, char t) case IP6: { - if(contains(connection_line, line_end, '/')){ + if(contains(connection_line, next_line, '/')){ next = parse_until(s, '/'); c.address = string(connection_line, int(next-connection_line)-2); }else{ - c.address = string(connection_line, int(line_end-connection_line)-2); + c.address = string(connection_line, line_len-7); } parsing = 0; break; @@ -788,7 +801,7 @@ static void parse_sdp_connection(AmSdp* sdp_msg, char* s, char t) } //DBG("parse_sdp_line_ex: parse_sdp_connection: done parsing sdp connection\n"); - return; + return next_line; } @@ -930,7 +943,8 @@ static void parse_sdp_media(AmSdp* sdp_msg, char* s) // session level attribute static void parse_session_attr(AmSdp* sdp_msg, char* s, char** next) { - *next = get_next_line(s); + size_t line_len = 0; + *next = skip_till_next_line(s, line_len); if (*next == s) { WARN("premature end of SDP in session attr\n"); while (**next != '\0') (*next)++; @@ -938,7 +952,7 @@ static void parse_session_attr(AmSdp* sdp_msg, char* s, char** next) { } char* attr_end = *next-1; while (attr_end >= s && - ((*attr_end == 10) || (*attr_end == 13))) + ((*attr_end == LF) || (*attr_end == CR))) attr_end--; if (*attr_end == ':') { @@ -959,15 +973,14 @@ static void parse_session_attr(AmSdp* sdp_msg, char* s, char** next) { string(col, attr_end-col+1))); // DBG("got session attribute '%.*s:%.*s'\n", (int)(col-s-1), s, (int)(attr_end-col+1), col); } - } // media level attribute -static void parse_sdp_attr(AmSdp* sdp_msg, char* s) +static char* parse_sdp_attr(AmSdp* sdp_msg, char* s) { if(sdp_msg->media.empty()){ ERROR("While parsing media options: no actual media !\n"); - return; + return s; } SdpMedia& media = sdp_msg->media.back(); @@ -981,20 +994,16 @@ static void parse_sdp_attr(AmSdp* sdp_msg, char* s) char* attr_line=s; char* next=0; char* line_end=0; + size_t line_len = 0; int parsing = 1; - line_end = get_next_line(attr_line); + line_end = skip_till_next_line(attr_line, line_len); unsigned int payload_type, clock_rate, encoding_param = 0; string encoding_name, params; string attr; if (!contains(attr_line, line_end, ':')) { - next = parse_until(attr_line, '\r'); - if (next >= line_end) { - DBG("found attribute line '%s', which is not followed by cr\n", attr_line); - next = line_end; - } - attr = string(attr_line, int(next-attr_line)-1); + attr = string(attr_line, line_len); attr_check(attr); parsing = 0; } else { @@ -1089,10 +1098,10 @@ static void parse_sdp_attr(AmSdp* sdp_msg, char* s) } else if(attr == "fmtp"){ while(parsing){ - switch(fmtp_st){ + switch(fmtp_st){ // fixme case FORMAT: { - next = parse_until(attr_line, ' '); + next = parse_until(attr_line, line_end, ' '); string fmtp_format(attr_line, int(next-attr_line)-1); str2i(fmtp_format, payload_type); attr_line = next; @@ -1100,12 +1109,12 @@ static void parse_sdp_attr(AmSdp* sdp_msg, char* s) break; } case FORMAT_PARAM: - { - line_end--; - while (is_wsp(*line_end)) - line_end--; + { + char* param_end = line_end-1; + while (is_wsp(*param_end)) + param_end--; - params = string(attr_line, line_end-attr_line+1); + params = string(attr_line, param_end-attr_line+1); parsing = 0; } break; @@ -1127,21 +1136,20 @@ static void parse_sdp_attr(AmSdp* sdp_msg, char* s) } else if (attr == "direction") { if (parsing) { - next = parse_until(attr_line, '\r'); - if(next < line_end){ - string value(attr_line, int(next-attr_line)-1); - if (value == "active") { - media.dir=SdpMedia::DirActive; - // DBG("found media attr 'direction' value '%s'\n", (char*)value.c_str()); - } else if (value == "passive") { - media.dir=SdpMedia::DirPassive; - //DBG("found media attr 'direction' value '%s'\n", (char*)value.c_str()); - } else if (attr == "both") { - media.dir=SdpMedia::DirBoth; - //DBG("found media attr 'direction' value '%s'\n", (char*)value.c_str()); - } + size_t dir_len = 0; + next = skip_till_next_line(attr_line, dir_len); + string value(attr_line, dir_len); + if (value == "active") { + media.dir=SdpMedia::DirActive; + // DBG("found media attr 'direction' value '%s'\n", (char*)value.c_str()); + } else if (value == "passive") { + media.dir=SdpMedia::DirPassive; + //DBG("found media attr 'direction' value '%s'\n", (char*)value.c_str()); + } else if (attr == "both") { + media.dir=SdpMedia::DirBoth; + //DBG("found media attr 'direction' value '%s'\n", (char*)value.c_str()); } else { - DBG("found media attribute 'direction', but value is not followed by cr\n"); + DBG("found unknown value for media attribute 'direction'\n"); } } else { DBG("ignoring direction attribute without value\n"); @@ -1162,12 +1170,9 @@ static void parse_sdp_attr(AmSdp* sdp_msg, char* s) attr_check(attr); string value; if (parsing) { - next = parse_until(attr_line, '\r'); - if(next >= line_end){ - DBG("found media attribute '%s', but value is not followed by cr\n", - (char *)attr.c_str()); - } - value = string (attr_line, int(next-attr_line)-1); + size_t attr_len = 0; + next = skip_till_next_line(attr_line, attr_len); + value = string (attr_line, attr_len); } // if (value.empty()) { @@ -1177,6 +1182,7 @@ static void parse_sdp_attr(AmSdp* sdp_msg, char* s) // } media.attributes.push_back(SdpAttribute(attr, value)); } + return line_end; } static void parse_sdp_origin(AmSdp* sdp_msg, char* s) @@ -1184,7 +1190,8 @@ static void parse_sdp_origin(AmSdp* sdp_msg, char* s) char* origin_line = s; char* next=0; char* line_end=0; - line_end = get_next_line(s); + size_t line_len=0; + line_end = skip_till_next_line(s, line_len); register sdp_origin_st origin_st; origin_st = USER; @@ -1248,6 +1255,7 @@ static void parse_sdp_origin(AmSdp* sdp_msg, char* s) break; } string net_type(origin_line, int(next-origin_line)-1); + origin.conn.network = NT_IN; // fixme origin_line = next; origin_st = ADDR; break; @@ -1260,7 +1268,17 @@ static void parse_sdp_origin(AmSdp* sdp_msg, char* s) origin_st = UNICAST_ADDR; break; } + string addr_type(origin_line, int(next-origin_line)-1); + if(addr_type == "IP4"){ + origin.conn.addrType = AT_V4; + }else if(addr_type == "IP6"){ + origin.conn.addrType = AT_V6; + }else{ + DBG("parse_sdp_connection: Unknown addr_type in o line: '%s'\n", addr_type.c_str()); + origin.conn.addrType = AT_NONE; + } + origin_line = next; origin_st = UNICAST_ADDR; break; @@ -1268,12 +1286,18 @@ static void parse_sdp_origin(AmSdp* sdp_msg, char* s) case UNICAST_ADDR: { next = parse_until(origin_line, ' '); - //check if line contains more values than allowed - if(next > line_end){ - origin.conn.address = string(origin_line, int(line_end-origin_line)-2); - }else{ - DBG("parse_sdp_origin: 'o=' contains more values than allowed; these values will be ignored\n"); - origin.conn.address = string(origin_line, int(next-origin_line)-1); + if (next != origin_line) { + //check if line contains more values than allowed + if(next > line_end){ + size_t addr_len = 0; + skip_till_next_line(origin_line, addr_len); + origin.conn.address = string(origin_line, addr_len); + }else{ + DBG("parse_sdp_origin: 'o=' contains more values than allowed; these values will be ignored\n"); + origin.conn.address = string(origin_line, int(next-origin_line)-1); + } + } else { + origin.conn.address = ""; } parsing = 0; break; @@ -1328,6 +1352,28 @@ static char* parse_until(char* s, char* end, char c) return line; } +static size_t len_till_eol(char* s, char* end) +{ + size_t res=0; + char* line=s; + while(line +#include +#include +#include +/** + * @file plug-in/opus/opus.c + * OPUS support + * This plug-in imports the OPUS Codec. + * + * See http://www.opus-codec.org/ . + * Features:
    + *
  • OPUS codec/payload/subtype + *
  • OPUS file format + *
+ * + */ + +#include + +#define _OPUS_APPLICATION_ OPUS_APPLICATION_VOIP +/* Allowed values: +OPUS_APPLICATION_VOIP Process signal for improved speech intelligibility. +OPUS_APPLICATION_AUDIO Favor faithfulness to the original input. +OPUS_APPLICATION_RESTRICTED_LOWDELAY Configure the minimum possible coding delay by disabling certain modes of operation.*/ + +#define _OPUS_MAX_BANDWIDTH_ OPUS_BANDWIDTH_FULLBAND +/* Allowed values: +OPUS_BANDWIDTH_NARROWBAND - 4 kHz passband +OPUS_BANDWIDTH_MEDIUMBAND - 6 kHz passband +OPUS_BANDWIDTH_WIDEBAND - 8 kHz passband +OPUS_BANDWIDTH_SUPERWIDEBAND - 12 kHz passband +OPUS_BANDWIDTH_FULLBAND - 20 kHz passband */ + +#define _OPUS_PKT_LOSS_PCT_ 5 +/* Allowed values: 0 - 100 */ + +#define _OPUS_COMPLEXITY_ 10 +/* Allowed values: 0 - 10, where 10 is highest computational complexity */ + +#define _OPUS_INBAND_FEC_ 1 +/* Forward error correction. +Allowed values: 0 - 1 */ + +#define _OPUS_DTX_ 0 +/* Discontinued transmission +Allowed values: 0 - 1 */ + +static int opus_2_pcm16( unsigned char* out_buf, unsigned char* in_buf, unsigned int size, + unsigned int channels, unsigned int rate, long h_codec ); + +static int opus_plc( unsigned char* out_buf, unsigned int size, + unsigned int channels, unsigned int rate, long h_codec ); + +static int pcm16_2_opus( unsigned char* out_buf, unsigned char* in_buf, unsigned int size, + unsigned int channels, unsigned int rate, long h_codec ); +static long opus_create(const char* format_parameters, amci_codec_fmt_info_t* format_description); +static void opus_destroy(long h_inst); + +#if SYSTEM_SAMPLECLOCK_RATE >= 48000 +#define _OPUS_RATE 48000 +#elif SYSTEM_SAMPLECLOCK_RATE >= 24000 +#define _OPUS_RATE 24000 +#elif SYSTEM_SAMPLECLOCK_RATE >= 12000 +#define _OPUS_RATE 12000 +#elif SYSTEM_SAMPLECLOCK_RATE >= 8000 +#define _OPUS_RATE 8000 +#else +#error Minimal sample rate for OPUS codec is 8000. +#endif + +BEGIN_EXPORTS( "opus" , AMCI_NO_MODULEINIT, AMCI_NO_MODULEDESTROY ) + + BEGIN_CODECS + CODEC( CODEC_OPUS, pcm16_2_opus, opus_2_pcm16, opus_plc, + opus_create, + opus_destroy, + NULL, NULL ) + END_CODECS + + BEGIN_PAYLOADS + PAYLOAD( -1, "opus", _OPUS_RATE, 48000, 1, CODEC_OPUS, AMCI_PT_AUDIO_FRAME ) + END_PAYLOADS + + BEGIN_FILE_FORMATS + END_FILE_FORMATS + +END_EXPORTS + +typedef struct { + OpusEncoder* opus_enc; + OpusDecoder* opus_dec; +} opus_state_t; + +long opus_create(const char* format_parameters, amci_codec_fmt_info_t* format_description) { + opus_state_t* codec_inst; + int error; + + if (format_parameters) { + DBG("OPUS params: >>%s<<.\n", format_parameters); + } + + format_description[0].id = AMCI_FMT_FRAME_LENGTH ; + format_description[0].value = 20; + format_description[1].id = AMCI_FMT_FRAME_SIZE; + format_description[1].value = 20 * _OPUS_RATE / 1000; + format_description[2].id = 0; + + codec_inst = (opus_state_t*)malloc(sizeof(opus_state_t)); + + if (!codec_inst) + return -1; + + codec_inst->opus_enc = opus_encoder_create(_OPUS_RATE,1,_OPUS_APPLICATION_,&error); + if (error) { + DBG("OPUS: error %d while creating encoder state.\n", error); + return -1; + } + + opus_encoder_ctl(codec_inst->opus_enc, OPUS_SET_FORCE_CHANNELS(1)); + opus_encoder_ctl(codec_inst->opus_enc, OPUS_SET_MAX_BANDWIDTH(_OPUS_MAX_BANDWIDTH_)); + opus_encoder_ctl(codec_inst->opus_enc, OPUS_SET_PACKET_LOSS_PERC(_OPUS_PKT_LOSS_PCT_)); + opus_encoder_ctl(codec_inst->opus_enc, OPUS_SET_COMPLEXITY(_OPUS_COMPLEXITY_)); + opus_encoder_ctl(codec_inst->opus_enc, OPUS_SET_INBAND_FEC(_OPUS_INBAND_FEC_)); + opus_encoder_ctl(codec_inst->opus_enc, OPUS_SET_DTX(_OPUS_DTX_)); + + codec_inst->opus_dec = opus_decoder_create(_OPUS_RATE,1,&error); + if (error) { + DBG("OPUS: error %d while creating decoder state.\n", error); + opus_encoder_destroy(codec_inst->opus_enc); + return -1; + } + + return (long)codec_inst; +} + +void opus_destroy(long h_inst) { + opus_state_t* codec_inst; + + if (h_inst) { + codec_inst = (opus_state_t*)h_inst; + opus_encoder_destroy(codec_inst->opus_enc); + opus_decoder_destroy(codec_inst->opus_dec); + free(codec_inst); + } +} + +int pcm16_2_opus( unsigned char* out_buf, unsigned char* in_buf, unsigned int size, + unsigned int channels, unsigned int rate, long h_codec ) +{ + opus_state_t* codec_inst; + int res; + + if (!h_codec){ + ERROR("opus codec not initialized.\n"); + return 0; + } + codec_inst = (opus_state_t*)h_codec; + + res = opus_encode(codec_inst->opus_enc, (opus_int16*)in_buf, size/2/channels, out_buf, AUDIO_BUFFER_SIZE); + /* returns bytes in encoded frame */ + + /* DBG ("OPUS encode: size: %d, chan: %d, rate: %d, result %d.\n", size, channels, rate, res); */ + return res; +} + +static int opus_2_pcm16( unsigned char* out_buf, unsigned char* in_buf, unsigned int size, + unsigned int channels, unsigned int rate, long h_codec ) +{ + opus_state_t* codec_inst; + int res; + + if (!h_codec){ + ERROR("opus codec not initialized.\n"); + return 0; + } + codec_inst = (opus_state_t*)h_codec; + + if (0<(res = opus_decode(codec_inst->opus_dec, in_buf, size, (opus_int16*)out_buf, AUDIO_BUFFER_SIZE/2, 0))) { + /* returns samples in encoded frame */ + res*=2; + } + + /* DBG ("OPUS decode: size: %d, chan: %d, rate: %d, result %d.\n", size, channels, rate, res); */ + + return res; + +} + +static int opus_plc( unsigned char* out_buf, unsigned int size, + unsigned int channels, unsigned int rate, long h_codec ) +{ + opus_state_t* codec_inst; + int res; + + if (!h_codec){ + ERROR("opus codec not initialized.\n"); + return 0; + } + codec_inst = (opus_state_t*)h_codec; + + if (size/channels > AUDIO_BUFFER_SIZE) { + /* DBG("OPUS plc: size %d, chan %d exceeds buffer size %d.\n", size, channels, AUDIO_BUFFER_SIZE); */ + return 0; + } + + if (0<(res = opus_decode(codec_inst->opus_dec, NULL, 0, (opus_int16*)out_buf, size/2/channels, 0))) { + /* returns samples in encoded frame */ + res*=2; + } + + /* DBG ("OPUS plc: size: %d, chan: %d, rate: %d, result %d.\n", size, channels, rate, res); */ + + return res; +} + diff --git a/core/plug-in/session_timer/SessionTimer.cpp b/core/plug-in/session_timer/SessionTimer.cpp index e416bd10..e3170c07 100644 --- a/core/plug-in/session_timer/SessionTimer.cpp +++ b/core/plug-in/session_timer/SessionTimer.cpp @@ -58,6 +58,11 @@ SessionTimer::SessionTimer(AmSession* s) { } +SessionTimer::~SessionTimer(){ + if (NULL != s) + removeTimers(s); +} + bool SessionTimer::process(AmEvent* ev) { assert(ev); diff --git a/core/plug-in/session_timer/SessionTimer.h b/core/plug-in/session_timer/SessionTimer.h index 4d6713da..1789df3c 100644 --- a/core/plug-in/session_timer/SessionTimer.h +++ b/core/plug-in/session_timer/SessionTimer.h @@ -156,7 +156,7 @@ protected: public: SessionTimer(AmSession*); - virtual ~SessionTimer(){} + virtual ~SessionTimer(); /* @see AmSessionEventHandler */ virtual int configure(AmConfigReader& conf); diff --git a/core/plug-in/stats/StatsUDPServer.cpp b/core/plug-in/stats/StatsUDPServer.cpp index 25b5df7a..b5c79092 100644 --- a/core/plug-in/stats/StatsUDPServer.cpp +++ b/core/plug-in/stats/StatsUDPServer.cpp @@ -36,6 +36,8 @@ #include "AmPlugIn.h" #include "AmApi.h" +#include "sip/trans_table.h" + #include using std::string; @@ -289,6 +291,7 @@ int StatsUDPServer::execute(char* msg_buf, string& reply, reply = "calls - number of active calls (Session Container size)\n" "which - print available commands\n" + "version - return SEMS version\n" "set_loglevel - set log level\n" "get_loglevel - get log level\n" "set_cpslimit - set maximum allowed CPS\n" @@ -300,12 +303,21 @@ int StatsUDPServer::execute(char* msg_buf, string& reply, "get_cpsavg - get calls per second (5 sec average)\n" "get_cpsmax - get maximum of CPS since the last query\n" + "dump_transactions - dump transaction table to log (loglevel debug)\n" + "DI ()* - invoke DI command\n" "\n" "When in shutdown mode, SEMS will answer with the configured 5xx errorcode to\n" "new INVITE and OPTIONS requests.\n" ; } + else if (cmd_str == "version") { + reply = SEMS_VERSION; + } + else if (cmd_str == "dump_transactions") { + dumps_transactions(); + reply = "200 OK"; + } else if (cmd_str.length() > 4 && cmd_str.substr(0, 4) == "set_") { // setters if (cmd_str.substr(4, 8) == "loglevel") { diff --git a/core/plug-in/uac_auth/UACAuth.cpp b/core/plug-in/uac_auth/UACAuth.cpp index f44ee537..c3225065 100644 --- a/core/plug-in/uac_auth/UACAuth.cpp +++ b/core/plug-in/uac_auth/UACAuth.cpp @@ -226,10 +226,16 @@ bool UACAuth::onSipReply(const AmSipRequest& req, const AmSipReply& reply, } + int flags = SIP_FLAGS_VERBATIM | SIP_FLAGS_NOAUTH; + size_t skip = 0, pos1, pos2, hdr_start; + if (findHeader(hdrs, SIP_HDR_CONTACT, skip, pos1, pos2, hdr_start) || + findHeader(hdrs, "m", skip, pos1, pos2, hdr_start)) + flags |= SIP_FLAGS_NOCONTACT; + // resend request if (dlg->sendRequest(ri->second.method, &(ri->second.body), - hdrs, SIP_FLAGS_VERBATIM | SIP_FLAGS_NOAUTH) == 0) { + hdrs, flags) == 0) { processed = true; DBG("authenticated request successfully sent.\n"); // undo SIP dialog status change diff --git a/core/sip/sip_trans.cpp b/core/sip/sip_trans.cpp index 6deec587..ef961927 100644 --- a/core/sip/sip_trans.cpp +++ b/core/sip/sip_trans.cpp @@ -280,9 +280,12 @@ const char* sip_trans::state_str() const void sip_trans::dump() const { DBG("type=%s (0x%x); msg=%p; to_tag=%.*s;" - " reply_status=%i; state=%s (%i); retr_buf=%p\n", + " reply_status=%i; state=%s (%i); retr_buf=%p; timers [%s,%s,%s]\n", type_str(),type,msg,to_tag.len,to_tag.s, - reply_status,state_str(),state,retr_buf); + reply_status,state_str(),state,retr_buf, + timers[0]==NULL?"none":timer_name(timers[0]->type), + timers[1]==NULL?"none":timer_name(timers[1]->type), + timers[2]==NULL?"none":timer_name(timers[2]->type)); } /** EMACS ** diff --git a/core/sip/trans_layer.cpp b/core/sip/trans_layer.cpp index 003f6383..024d13ec 100644 --- a/core/sip/trans_layer.cpp +++ b/core/sip/trans_layer.cpp @@ -1406,8 +1406,8 @@ int _trans_layer::cancel(trans_ticket* tt, const cstring& dialog_id, } if(!t){ - DBG("No transaction to cancel: wrong key or finally replied\n"); bucket->unlock(); + DBG("No transaction to cancel: wrong key or finally replied\n"); return 0; } @@ -1416,8 +1416,10 @@ int _trans_layer::cancel(trans_ticket* tt, const cstring& dialog_id, // RFC 3261 says: SHOULD NOT be sent for other request // than INVITE. if(req->u.request->method != sip_request::INVITE){ + t->dump(); bucket->unlock(); - ERROR("Trying to cancel a non-INVITE request (we SHOULD NOT do that)\n"); + ERROR("Trying to cancel a non-INVITE request (we SHOULD NOT do that); inv_cseq: %u, i:%.*s\n", + inv_cseq, dialog_id.len,dialog_id.s); return -1; } @@ -1439,8 +1441,10 @@ int _trans_layer::cancel(trans_ticket* tt, const cstring& dialog_id, } case TS_COMPLETED: + ERROR("Trying to cancel a request while in TS_COMPLETED state; inv_cseq: %u, i:%.*s\n", + inv_cseq, dialog_id.len,dialog_id.s); + t->dump(); bucket->unlock(); - ERROR("Trying to cancel a request while in TS_COMPLETED state\n"); return -1; case TS_PROCEEDING: @@ -1449,8 +1453,10 @@ int _trans_layer::cancel(trans_ticket* tt, const cstring& dialog_id, break; default: + ERROR("Trying to cancel a request while in %s state; inv_cseq: %u, i:%.*s\n", + t->state_str(), inv_cseq, dialog_id.len,dialog_id.s); + t->dump(); bucket->unlock(); - ERROR("Trying to cancel a request while in unknown state\n"); return -1; } @@ -1836,13 +1842,24 @@ int _trans_layer::update_uac_reply(trans_bucket* bucket, sip_trans* t, sip_msg* if(reply_code >= 300){ - if(reply_code == 503) { - if(default_bl_ttl) { + bool forget_reply = false; + if(reply_code == 503 && + (t->state == TS_CALLING || + t->state == TS_PROCEEDING)) { + + if(!(t->flags & TR_FLAG_DISABLE_BL)) { tr_blacklist::instance()->insert(&t->msg->remote_ip, default_bl_ttl,"503"); } - if(!try_next_ip(bucket,t,false)) - goto end; + + if(msg->local_socket) { // remote reply + if(!try_next_ip(bucket,t,true)) + forget_reply = true; + } + else { // local reply + if(!try_next_ip(bucket,t,false)) + goto end; + } } // Final error reply @@ -1860,6 +1877,9 @@ int _trans_layer::update_uac_reply(trans_bucket* bucket, sip_trans* t, sip_msg* send_non_200_ack(msg,t); t->reset_timer(STIMER_D, D_TIMER, bucket->get_id()); + if(forget_reply) + goto end; + goto pass_reply; case TS_ABANDONED: @@ -2488,7 +2508,11 @@ void _trans_layer::timer_expired(trans_timer* t, trans_bucket* bucket, } break; case STIMER_M: { - try_next_ip(bucket,tr,true); + if(!try_next_ip(bucket,tr,true)) { + // Abandon old transaction + tr->clear_timer(STIMER_A); + tr->state = TS_ABANDONED; + } } break; case STIMER_BL: @@ -2654,10 +2678,6 @@ int _trans_layer::try_next_ip(trans_bucket* bucket, sip_trans* tr, tmp_msg.release(); n_tr->msg = p_msg; - // Abandon old transaction - tr->clear_timer(STIMER_A); - tr->state = TS_ABANDONED; - // take over target set n_tr->targets = tr->targets; tr->targets = NULL; diff --git a/core/tests/sems_tests.cpp b/core/tests/sems_tests.cpp index f3044bff..5e7498ef 100644 --- a/core/tests/sems_tests.cpp +++ b/core/tests/sems_tests.cpp @@ -22,6 +22,7 @@ FCT_BGN() { log_stderr=true; log_level=3; + FCTMF_SUITE_CALL(test_sdp); FCTMF_SUITE_CALL(test_auth); FCTMF_SUITE_CALL(test_headers); FCTMF_SUITE_CALL(test_uriparser); diff --git a/core/tests/test_sdp.cpp b/core/tests/test_sdp.cpp new file mode 100644 index 00000000..ffd040c5 --- /dev/null +++ b/core/tests/test_sdp.cpp @@ -0,0 +1,90 @@ +#include "fct.h" + +#include "log.h" + +#include "AmSdp.h" + +#define CRLF "\r\n" +#define LF "\n" + +FCTMF_SUITE_BGN(test_sdp) { + + FCT_TEST_BGN(normal_sdp_ok) { + AmSdp s; + string sdp = + "v=0" CRLF + "o=- 3615077380 3615077398 IN IP4 178.66.14.5" CRLF + "s=-" CRLF + "c=IN IP4 178.66.14.5" CRLF + "t=0 0" CRLF + "m=audio 21964 RTP/AVP 0 101" CRLF + "a=sendrecv" CRLF + "a=ptime:20" CRLF + "a=rtpmap:0 PCMU/8000" CRLF + "a=rtpmap:101 telephone-event/8000" CRLF + "a=fmtp:101 0-15" CRLF ; + + fct_chk(!s.parse(sdp.c_str())); + fct_chk(s.version==0); + fct_chk(s.origin.user == "-"); + fct_chk(s.origin.sessId == 3615077380); + fct_chk(s.origin.sessV == 3615077398); + fct_chk(s.origin.conn.address == "178.66.14.5"); + fct_chk(s.origin.conn.network == NT_IN); + fct_chk(s.origin.conn.addrType == AT_V4); + + fct_chk(s.conn.address == "178.66.14.5"); + fct_chk(s.conn.network == NT_IN); + fct_chk(s.conn.addrType == AT_V4); + + fct_chk(s.media.size() == 1); + fct_chk(s.media[0].type == MT_AUDIO); + fct_chk(s.media[0].port == 21964); + fct_chk(s.media[0].transport == TP_RTPAVP); + fct_chk(s.media[0].payloads.size()==2); + fct_chk(s.media[0].payloads[0].payload_type==0); + fct_chk(s.media[0].payloads[1].payload_type==101); + fct_chk(s.media[0].payloads[0].encoding_name=="PCMU"); + fct_chk(s.media[0].payloads[1].encoding_name=="telephone-event"); + } FCT_TEST_END(); + + FCT_TEST_BGN(sdp_LF_no_CRLF) { + AmSdp s; + string sdp = + "v=0" LF + "o=- 3615077380 3615077398 IN IP4 178.66.14.5" LF + "s=-" LF + "c=IN IP4 178.66.14.5" LF + "t=0 0" LF + "m=audio 21964 RTP/AVP 0 101" LF + "a=sendrecv" LF + "a=ptime:20" LF + "a=rtpmap:0 PCMU/8000" LF + "a=rtpmap:101 telephone-event/8000" LF + "a=fmtp:101 0-15" LF ; + + fct_chk(!s.parse(sdp.c_str())); + fct_chk(s.version==0); + fct_chk(s.origin.user == "-"); + fct_chk(s.origin.sessId == 3615077380); + fct_chk(s.origin.sessV == 3615077398); + fct_chk(s.origin.conn.address == "178.66.14.5"); + fct_chk(s.origin.conn.network == NT_IN); + fct_chk(s.origin.conn.addrType == AT_V4); + + fct_chk(s.conn.address == "178.66.14.5"); + fct_chk(s.conn.network == NT_IN); + fct_chk(s.conn.addrType == AT_V4); + + fct_chk(s.media.size() == 1); + fct_chk(s.media[0].type == MT_AUDIO); + fct_chk(s.media[0].port == 21964); + fct_chk(s.media[0].transport == TP_RTPAVP); + fct_chk(s.media[0].payloads.size()==2); + fct_chk(s.media[0].payloads[0].payload_type==0); + fct_chk(s.media[0].payloads[1].payload_type==101); + fct_chk(s.media[0].payloads[0].encoding_name=="PCMU"); + fct_chk(s.media[0].payloads[1].encoding_name=="telephone-event"); + } FCT_TEST_END(); + +} FCTMF_SUITE_END(); diff --git a/core/tests/test_sdp.h b/core/tests/test_sdp.h new file mode 100644 index 00000000..8d1c8b69 --- /dev/null +++ b/core/tests/test_sdp.h @@ -0,0 +1 @@ + diff --git a/debian/ngcp-sems.postinst b/debian/ngcp-sems.postinst index 443ad147..73acc76d 100644 --- a/debian/ngcp-sems.postinst +++ b/debian/ngcp-sems.postinst @@ -5,9 +5,11 @@ set -e dpkg-maintscript-helper rm_conffile /etc/default/sems -- "$@" dpkg-maintscript-helper rm_conffile /etc/init.d/sems -- "$@" -# don't do anything when called with other argument than configure case "$1" in configure) + # add sems user + adduser --quiet --system --group --disabled-password --shell /bin/false \ + --gecos "SIP Express Media Server" --home /var/run/ngcp-sems sems || true ;; abort-upgrade|abort-remove|abort-deconfigure) exit 0 @@ -18,54 +20,6 @@ case "$1" in ;; esac -restart_handler() { - if [ -x "/etc/init.d/ngcp-sems" ]; then - if [ -x "$(which invoke-rc.d 2>/dev/null)" ]; then - invoke-rc.d ngcp-sems restart || exit $? - else - /etc/init.d/ngcp-sems restart || exit $? - fi - fi -} - -initscript_handler() { - if [ -x "/etc/init.d/ngcp-sems" ]; then - update-rc.d ngcp-sems defaults >/dev/null - invoke-rc.d ngcp-sems start || exit $? - fi -} - -init_handler() { - # just invoke init script wrappers on ce systems since - # they do not provide ngcp-check_active and we don't - # have to handle inactive nodes - if ! [ -x "$(which ngcp-check_active 2>/dev/null)" ]; then - restart_handler - initscript_handler - else # do not restart daemon on inactive node in pro systems - if ngcp-check_active ; then - echo "Active node detected, restarting ngcp-sems" - restart_handler - else - echo "Inactive node detected, ignoring request to restart ngcp-sems" - fi - fi -} - -# add sems user -adduser --quiet --system --group --disabled-password --shell /bin/false \ ---gecos "SIP Express Media Server" --home /var/run/ngcp-sems sems || true - -init_handler - -echo "" -echo "***" -echo "Configuration of ngcp-sems has finished." -echo "" -echo "To restart it when configuration has changed use '/etc/init.d/ngcp-sems restart'" -echo "" -echo "To change it's configuration use 'dpkg-reconfigure ngcp-sems'" -echo "***" -echo "" +#DEBHELPER# exit 0 diff --git a/debian/ngcp-sems.postrm b/debian/ngcp-sems.postrm deleted file mode 100644 index 29fbd00b..00000000 --- a/debian/ngcp-sems.postrm +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh -# postrm script for ngcp-sems - -set -e - -removal_wrapper() { - # remove the init script only on ce systems, as the - # the pro system handle it inside the monitoring/HA setup - if ! [ -x "$(which ngcp-check_active 2>/dev/null)" ]; then - update-rc.d ngcp-sems remove >/dev/null - fi -} - -if [ "$1" = "purge" ] ; then - removal_wrapper -fi - -exit 0 diff --git a/debian/patches/series b/debian/patches/series index 315b18eb..fdf53e22 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1,4 +1,3 @@ sipwise/sw_vcs.patch -upstream/0001-dsm-mod_dlg-q-f-make-compilable.patch no_config.patch py_sems_path.patch diff --git a/debian/patches/upstream/0001-dsm-mod_dlg-q-f-make-compilable.patch b/debian/patches/upstream/0001-dsm-mod_dlg-q-f-make-compilable.patch deleted file mode 100644 index 29b57ccc..00000000 --- a/debian/patches/upstream/0001-dsm-mod_dlg-q-f-make-compilable.patch +++ /dev/null @@ -1,24 +0,0 @@ -From c008d587acc92faa62afb622ce15e85a72d54c38 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?V=C3=A1clav=20Kubart?= -Date: Fri, 16 May 2014 16:19:55 +0200 -Subject: [PATCH] dsm mod_dlg q/f: make compilable - ---- - apps/dsm/mods/mod_dlg/ModDlg.h | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/apps/dsm/mods/mod_dlg/ModDlg.h b/apps/dsm/mods/mod_dlg/ModDlg.h -index 23cb104..098f772 100644 ---- a/apps/dsm/mods/mod_dlg/ModDlg.h -+++ b/apps/dsm/mods/mod_dlg/ModDlg.h -@@ -52,6 +52,7 @@ DEF_ACTION_1P(DLGGetOtherIdAction); - DEF_ACTION_1P(DLGGetRtpRelayModeAction); - - DEF_ACTION_2P(DLGReferAction); -+DEF_ACTION_2P(DLGInfoAction); - DEF_ACTION_2P(DLGB2BRelayErrorAction); - - DEF_ACTION_2P(DLGAddReplyBodyPartAction); --- -2.0.0.rc0 - diff --git a/debian/source/include-binaries b/debian/source/include-binaries new file mode 100644 index 00000000..bf8d67d5 --- /dev/null +++ b/debian/source/include-binaries @@ -0,0 +1,2 @@ +core/compat/getarch +core/compat/getos diff --git a/doc/Readme.jsonrpc b/doc/Readme.jsonrpc new file mode 100644 index 00000000..28cefe31 --- /dev/null +++ b/doc/Readme.jsonrpc @@ -0,0 +1,7 @@ +This plugin implements JSON-RPC protocol version 2.0 +(http://www.jsonrpc.org/specification) operating over TCP/Netstrings. +Each request and response is of form : where + tells the number of bytes in . + +Configuration file jsonrpc.conf can contain parameters jsonrpc_port +(default 7080) and server_threads (default 5). diff --git a/doc/dsm/dsm_sbc_syntax.txt b/doc/dsm/dsm_sbc_syntax.txt index cc0c3125..be00a927 100644 --- a/doc/dsm/dsm_sbc_syntax.txt +++ b/doc/dsm/dsm_sbc_syntax.txt @@ -154,19 +154,20 @@ sbc.isDisconnected() / sbc.isNoReply() / sbc.isRinging() / sbc.isConnected() / s Actions ------- sbc.profileSet(profile_variable, value) - set SBC profile options - *** only meaningful in 'start' event (later, most profile options are not used any more) *** - profile_variables: To, RURI, FROM, Call-ID, next_hop, RURI_host, refuse_with, - outbound_proxy, force_outbound_proxy = "yes" | "no, + *** only meaningful in 'start' event (later, most profile options + are not used any more) *** + profile_variables: To, RURI, FROM, Call-ID, next_hop, RURI_host, + refuse_with, outbound_proxy, force_outbound_proxy = "yes" | "no, aleg_outbound_proxy, aleg_force_outbound_proxy = "yes" | "no, - next_hop_1st_req = "yes" | "no, patch_ruri_next_hop = "yes" | "no, - aleg_next_hop, - append_headers, append_headers_req, - rtprelay_enabled = "yes" | "no, - force_symmetric_rtp = "yes" | "no, aleg_force_symmetric_rtp = "yes" | "no, - msgflags_symmetric_rtp = "yes" | "no, - rtprelay_transparent_seqno = "yes" | "no, rtprelay_transparent_ssrc = "yes" | "no, - rtprelay_interface, aleg_rtprelay_interface, - rtprelay_dtmf_detection = "yes" | "no, rtprelay_dtmf_filtering = "yes" | "no + next_hop_1st_req = "yes" | "no, patch_ruri_next_hop = "yes" | "no, + aleg_next_hop, append_headers, append_headers_req, + rtprelay_enabled = "yes" | "no, force_symmetric_rtp = "yes" | "no, + aleg_force_symmetric_rtp = "yes" | "no, msgflags_symmetric_rtp = + "yes" | "no, rtprelay_transparent_seqno = "yes" | "no, + rtprelay_transparent_ssrc = "yes" | "no, + rtprelay_interface, aleg_rtprelay_interface, + rtprelay_dtmf_detection = "yes" | "no, rtprelay_dtmf_filtering = + "yes" | "no, message_filter, message_list sbc.stopCall(string cause) - stop both call legs diff --git a/doc/dsm/mods/Readme.mod_regex.txt b/doc/dsm/mods/Readme.mod_regex.txt index bf740685..af7cabae 100644 --- a/doc/dsm/mods/Readme.mod_regex.txt +++ b/doc/dsm/mods/Readme.mod_regex.txt @@ -15,6 +15,8 @@ regex.compile(name, reg_ex) regex.match(name, match_string) Match match_string on regex referenced by name. $regex.match is set to 1 if matched, 0 if not matched. + $regex.match[n] is set to nth substring match, starting with 1 + ($regex.match[1] is set to first substring match...) regex.clear(name) Clear the regex referenced by name. @@ -22,9 +24,8 @@ regex.clear(name) Conditions: regex.match(name, match_string) Match match_string on regex referenced by name. - - + $regex.match[n] is set to nth substring match, starting with 1 + ($regex.match[1] is set to first substring match...) TODO: - - implement substring adressing - find a better way for $regex.match side-effect diff --git a/pkg/deb/debian/rules b/pkg/deb/debian/rules index 6f856b61..5ac115ae 100755 --- a/pkg/deb/debian/rules +++ b/pkg/deb/debian/rules @@ -40,3 +40,10 @@ override_dh_auto_install: override_dh_strip: dh_strip --dbg-package=sems-dbg + # those binaries aren't automatically stripped + test -r $(CURDIR)/debian/libsems1-dev/usr/include/sems/compat/getarch && \ + strip --remove-section=.comment --remove-section=.note --strip-unneeded \ + $(CURDIR)/debian/libsems1-dev/usr/include/sems/compat/getarch + test -r $(CURDIR)/debian/libsems1-dev/usr/include/sems/compat/getos && \ + strip --remove-section=.comment --remove-section=.note --strip-unneeded \ + $(CURDIR)/debian/libsems1-dev/usr/include/sems/compat/getos diff --git a/pkg/deb/jessie/rules b/pkg/deb/jessie/rules index 6f856b61..5ac115ae 100755 --- a/pkg/deb/jessie/rules +++ b/pkg/deb/jessie/rules @@ -40,3 +40,10 @@ override_dh_auto_install: override_dh_strip: dh_strip --dbg-package=sems-dbg + # those binaries aren't automatically stripped + test -r $(CURDIR)/debian/libsems1-dev/usr/include/sems/compat/getarch && \ + strip --remove-section=.comment --remove-section=.note --strip-unneeded \ + $(CURDIR)/debian/libsems1-dev/usr/include/sems/compat/getarch + test -r $(CURDIR)/debian/libsems1-dev/usr/include/sems/compat/getos && \ + strip --remove-section=.comment --remove-section=.note --strip-unneeded \ + $(CURDIR)/debian/libsems1-dev/usr/include/sems/compat/getos diff --git a/pkg/deb/precise/rules b/pkg/deb/precise/rules index 6f856b61..5ac115ae 100755 --- a/pkg/deb/precise/rules +++ b/pkg/deb/precise/rules @@ -40,3 +40,10 @@ override_dh_auto_install: override_dh_strip: dh_strip --dbg-package=sems-dbg + # those binaries aren't automatically stripped + test -r $(CURDIR)/debian/libsems1-dev/usr/include/sems/compat/getarch && \ + strip --remove-section=.comment --remove-section=.note --strip-unneeded \ + $(CURDIR)/debian/libsems1-dev/usr/include/sems/compat/getarch + test -r $(CURDIR)/debian/libsems1-dev/usr/include/sems/compat/getos && \ + strip --remove-section=.comment --remove-section=.note --strip-unneeded \ + $(CURDIR)/debian/libsems1-dev/usr/include/sems/compat/getos diff --git a/pkg/deb/trusty/changelog b/pkg/deb/trusty/changelog new file mode 100644 index 00000000..40221b26 --- /dev/null +++ b/pkg/deb/trusty/changelog @@ -0,0 +1,112 @@ +sems (1.6.0~dev) unstable; urgency=medium + + * Devel version + + -- Victor Seva Thu, 03 Apr 2014 17:52:53 +0200 + +sems (1.5.0) maverick; urgency=low + + * Core + - configurable SIP timers (global) + - timer C support (mainly for SBC) + - SUBSCRIBE/NOTIFY support + - multi-mime bodies + - wideband / multiple sample frequency support + - multiple destinations (faked SRV record) + - DNS SRV: support for 503 replies + - multi-threaded RTP receiver + - complete rework of offer/answer mechanisms + + * Codecs: + - iSAC + - SILK + - SPEEX 16kHz, 32kHz + - G722 + - L16 + + * SBC + - audio & dtmf transcoder + - call-control modules + - lots of small improvements + + * Monitoring + - munin plugin + + * DSM + - mod_xml: XML handling + - mod_curl: HTTP requests + - mod_subscription: SUBSCRIBE/NOTIFY + - mod_regex: regular expressions + - lots of small improvements + + * App Plug-ins + - db_reg_agent: register SIP accounts from a DB + - rtmp: RTMP gateway + + -- Raphael Coeffic Tue, 03 Jul 2012 15:06:08 +0200 + +sems (1.4.0) maverick; urgency=low + + * SEMS 1.4.0 release + + -- Stefan Sayer Tue, 15 Mar 2011 11:13:05 +0100 + +sems (1.3.0) unstable; urgency=low + + * 100rel (PRACK) support + * DNS cache, lb on SRV records + * B2B with Session Timer + * json-rpc v2 module + * SIP stack moved into core + * optimizations, especially for signaling + * many DSM improvements + + -- Stefan Sayer Sun, 26 Sep 2010 17:35:22 -0400 + +sems (1.2.0) unstable; urgency=low + + * SEMS 1.2.0 release + + -- Stefan Sayer Tue, 30 Mar 2010 21:46:39 +0200 + +sems (1.1.1) unstable; urgency=low + + * SEMS 1.1.1 bugfix release - fixed Via HF missing the port number + in ACK to 200 reply - do not try to scale too short RTP packets - + fixed initialization of SSL - caused random crashing of xmlrpc + server - fix size() for AmArg struct type - authenticate on both + 401 and 407 reply in click2dial - fixed ssl build dependency for + DIAMETER client in deb + + -- Stefan Sayer Tue, 07 Jul 2009 15:13:24 +0200 + +sems (1.1.0-1) unstable; urgency=low + + * DSM state machine scripting (it's cool!) + * an (experimental) ISDN gateway module + * binrpc: MT (SER->) and connection pool (->SER) + * MT xmlrpc server + * controlled server shutdown + * improved logging + * g722 in 8khz compat mode + * out of dialog request handling for modules & dialogs without + sessions + * audio file autorewind, AmAudio mixing + * SIP and media IP separately configurable + * UID/DID support for voicemail/-box/annrecorder + * and quite some bugs and mem leaks fixed, documentation, etc. + + -- Stefan Sayer Tue, 20 Jan 2009 18:11:25 +0100 + +sems (1.1.0-0rc1) unstable; urgency=low + + * Debian Release Candidate 1 for 1.1. + + -- Stefan Sayer Mon, 8 Dec 2008 23:01:40 +0200 + +sems (1.0.0-0pre1-r856M) unstable; urgency=low + + * Debian Release Candidate 1 for 1.0. + + -- Stefan Sayer Sun, 2 Mar 2002 23:41:31 +0200 + diff --git a/pkg/deb/trusty/compat b/pkg/deb/trusty/compat new file mode 100644 index 00000000..ec635144 --- /dev/null +++ b/pkg/deb/trusty/compat @@ -0,0 +1 @@ +9 diff --git a/pkg/deb/trusty/control b/pkg/deb/trusty/control new file mode 100644 index 00000000..3544dbbb --- /dev/null +++ b/pkg/deb/trusty/control @@ -0,0 +1,54 @@ +Source: sems +Section: net +Priority: optional +Maintainer: Debian VoIP Team +Uploaders: Victor Seva +Build-Depends: debhelper (>= 9~), + flite-dev, + libcurl4-openssl-dev | libcurl4-gnutls-dev, + libev-dev, + libevent-dev (>= 2.0.0), + libhiredis-dev, + libmysql++-dev, + libspandsp-dev, + libspeex-dev, + libssl-dev, + libxml2-dev, + openssl, + python-dev, + python-sip-dev +Standards-Version: 3.9.5 + +Package: sems +Architecture: any +Depends: adduser, python, ${misc:Depends}, ${shlibs:Depends} +Description: SIP Express Media Server, very fast and flexible SIP media server + SEMS, the SIP Express Media Server, is a free, high performance, + extensible media server and SBC for SIP (RFC3261) based VoIP services. It + features voicemail, conferencing, announcements, pre-call announcements, + prepaid service, calling card service etc. + +Package: sems-dbg +Architecture: any +Section: debug +Priority: extra +Depends: sems (= ${binary:Version}), ${misc:Depends} +Description: Debugging symbols for Sems SIP Express Media Server + SEMS, the SIP Express Media Server, is a free, high performance, + extensible media server and SBC for SIP (RFC3261) based VoIP services. It + features voicemail, conferencing, announcements, pre-call announcements, + prepaid service, calling card service etc. + . + This package contains the debugging sysmbols. + +Package: libsems1-dev +Architecture: any +Section: libdevel +Depends: ${misc:Depends} +Description: development files for SIP Express Media Server + SEMS, the SIP Express Media Server, is a free, high performance, + extensible media server and SBC for SIP (RFC3261) based VoIP services. It + features voicemail, conferencing, announcements, pre-call announcements, + prepaid service, calling card service etc. + . + This package contains the files needed to compile sems applications. diff --git a/pkg/deb/trusty/copyright b/pkg/deb/trusty/copyright new file mode 100644 index 00000000..77797779 --- /dev/null +++ b/pkg/deb/trusty/copyright @@ -0,0 +1,34 @@ +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: SEMS +Upstream-Contact: semsdev@lists.iptel.org +Source: http://www.iptel.org/sems + +Files: * +Copyright: + 2005-2014 Raphael Coeffic + 2010-2014 FRAFOS GmbH + 2005-2014 Stefan Sayer + 2002-2005 FhG Fokus + 2006-2010 iptelorg GmbH + 2007-2009 IPTEGO GmbH + 2007-2013 Juha Heinanen + 2007 Andreas Granig + 2009-2010 TelTech Systems Inc. + 2006-2007 Maxim Sobolev + 2010 Anton Zagorskiy amberovsky@gmail.com + 2011-2012 Peter Lemenkov + Various others (see README file) +License: GPL-2.0+ OpenSSL exception + On Debian systems, the full text of the GNU General Public + License version 2 can be found in the file `/usr/share/common-licenses/GPL-2'. + * Exception: permission to copy, modify, propagate, and distribute a work + * formed by combining OpenSSL toolkit software and the code in this file, + * such as linking with software components and libraries released under + * OpenSSL project license. + +Files: debian/* +Copyright: 2014 Victor Seva + 2008-2014, Stefan Sayer +License: GPL-2+ + On Debian systems, the full text of the GNU General Public + License version 2 can be found in the file `/usr/share/common-licenses/GPL-2'. diff --git a/pkg/deb/trusty/libsems1-dev.install b/pkg/deb/trusty/libsems1-dev.install new file mode 100644 index 00000000..1f77c7cc --- /dev/null +++ b/pkg/deb/trusty/libsems1-dev.install @@ -0,0 +1,13 @@ +Makefile.defs usr/include/sems/ +core/*.h usr/include/sems/ +core/SampleArray.cc usr/include/sems/ +core/amci usr/include/sems/ +core/ampi usr/include/sems/ +core/compat/*.c usr/include/sems/compat/ +core/compat/*.h usr/include/sems/compat/ +core/compat/getarch usr/include/sems/compat/ +core/compat/getos usr/include/sems/compat/ +core/plug-in/Makefile.app_module usr/include/sems/plug-in/ +core/plug-in/Makefile.audio_module usr/include/sems/plug-in/ +core/rtp usr/include/sems/ +core/sip/*.h usr/include/sems/sip/ diff --git a/pkg/deb/trusty/rules b/pkg/deb/trusty/rules new file mode 100755 index 00000000..5ac115ae --- /dev/null +++ b/pkg/deb/trusty/rules @@ -0,0 +1,49 @@ +#!/usr/bin/make -f +# -*- makefile -*- + +# Uncomment this to turn on verbose mode. +export DH_VERBOSE=1 + +PYTHON_MODULES=ivr conf_auth mailbox pin_collect + +EXCLUDED_MODULES=gateway examples mp3 twit + +EXCLUDED_DSM_MODULES=mod_aws +EXCLUDED_DSM_PY_MODULES=mod_aws mod_py + +CPPFLAGS += -DHAVE_XMLRPCPP_SSL + +export USE_SPANDSP=yes LONG_DEBUG_MESSAGE=yes CPPFLAGS="$(CPPFLAGS)" + +%: + dh $@ + +override_dh_auto_build: + $(MAKE) \ + cfg-target=/etc/sems/ prefix=/usr \ + exclude_app_modules="$(EXCLUDED_MODULES)" \ + exclude_dsm_modules="$(EXCLUDED_DSM_MODULES)" \ + DESTDIR=$(CURDIR)/debian/sems + +override_dh_auto_install: + $(MAKE) -C core/ install \ + DESTDIR=$(CURDIR)/debian/sems \ + prefix=/usr \ + cfg-target=/etc/sems/ + + $(MAKE) -C apps/ install \ + exclude_app_modules="$(EXCLUDED_MODULES) $(PYTHON_MODULES)" \ + exclude_dsm_modules="$(EXCLUDED_DSM_PY_MODULES)" \ + DESTDIR=$(CURDIR)/debian/sems \ + prefix=/usr \ + cfg-target=/etc/sems/ + +override_dh_strip: + dh_strip --dbg-package=sems-dbg + # those binaries aren't automatically stripped + test -r $(CURDIR)/debian/libsems1-dev/usr/include/sems/compat/getarch && \ + strip --remove-section=.comment --remove-section=.note --strip-unneeded \ + $(CURDIR)/debian/libsems1-dev/usr/include/sems/compat/getarch + test -r $(CURDIR)/debian/libsems1-dev/usr/include/sems/compat/getos && \ + strip --remove-section=.comment --remove-section=.note --strip-unneeded \ + $(CURDIR)/debian/libsems1-dev/usr/include/sems/compat/getos diff --git a/pkg/deb/trusty/sems.default b/pkg/deb/trusty/sems.default new file mode 100644 index 00000000..c2774ef2 --- /dev/null +++ b/pkg/deb/trusty/sems.default @@ -0,0 +1,25 @@ +# configuration for SEMS - SIP Express Media Server +# +# this file is sourced by SEMS init script /etc/init.d/sems + +# Don't start with default config as we need to deploy the ngcp-templates first +SEMS_RUN="no" + +# ser configuration file +SEMS_CFG_FILE="/etc/sems/sems.conf" + +# user to run SEMS as +SEMS_USER="sems" + +# group to run SEMS as +SEMS_GROUP="sems" + +SEMS_RUNDIR="/var/run/sems" + +# sems pidfile +SEMS_PIDFILE="$SEMS_RUNDIR/sems.pid" + +# set if you want to create core files +SEMS_CREATE_CORE="yes" + +SEMS_COREDIR="/var/cores" diff --git a/pkg/deb/trusty/sems.init b/pkg/deb/trusty/sems.init new file mode 100644 index 00000000..d855e2b0 --- /dev/null +++ b/pkg/deb/trusty/sems.init @@ -0,0 +1,108 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides: sems +# Required-Start: $local_fs $remote_fs $network $syslog +# Required-Stop: $local_fs $remote_fs $network $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Start/stop SEMS Application Server +### END INIT INFO + +. /lib/lsb/init-functions + +# read configuration from /etc/default/sems file +if test -f /etc/default/sems ; then + . /etc/default/sems +fi + + +if test "$SEMS_RUN" = "no" ; then + log_failure_msg "Sems start disabled by default file" + exit 0 +fi + +PATH=/sbin:/bin:/usr/sbin:/usr/bin +DAEMON=/usr/sbin/sems +NAME=sems +DESC=sems + +PARAMS="" + +if ! test -d $SEMS_RUNDIR ; then + mkdir $SEMS_RUNDIR +fi +chown $SEMS_USER:$SEMS_GROUP $SEMS_RUNDIR + +if test "$SEMS_PIDFILE" ; then + PARAMS="$PARAMS -P $SEMS_PIDFILE" +fi + +if test "$SEMS_USER" ; then + PARAMS="$PARAMS -u $SEMS_USER" +fi + +if test "$SEMS_GROUP" ; then + PARAMS="$PARAMS -g $SEMS_GROUP" +fi + +if test "$SEMS_CFG_FILE" ; then + PARAMS="$PARAMS -f $SEMS_CFG_FILE" + CFGPARAMS="-f $SEMS_CFG_FILE" +fi + +if test "$SEMS_CREATE_CORE" = "yes" ; then + # directory for the core dump files + [ -d $SEMS_COREDIR ] || mkdir $SEMS_COREDIR + chmod 777 $SEMS_COREDIR + echo "$SEMS_COREDIR/core.%e.sig%s.%p" > /proc/sys/kernel/core_pattern + echo 2 > /proc/sys/fs/suid_dumpable + ulimit -c unlimited +fi + +# raise file descriptors limit - call hold consumes two fds for RTP ports and one for moh file +ulimit -n 100000 + +if ! test -f $DAEMON ; then + log_failure_msg "Error: cannot find $DAEMON" + exit 1 +fi + +LD_LIBRARY_PATH=/usr/lib/sems +export LD_LIBRARY_PATH + +set -e + +case "$1" in + start) + log_daemon_msg "Starting $DESC: $NAME " + start-stop-daemon --start --quiet --oknodo --pidfile $SEMS_PIDFILE \ + --exec $DAEMON -- $PARAMS + log_end_msg $? + ;; + stop) + log_daemon_msg "Stopping $DESC: $NAME " + start-stop-daemon --oknodo --stop --quiet --pidfile $SEMS_PIDFILE \ + --exec $DAEMON + log_end_msg $? + ;; + restart|force-reload) + log_daemon_msg "Restarting $DESC: $NAME " + start-stop-daemon --oknodo --stop --quiet --pidfile \ + $SEMS_PIDFILE --exec $DAEMON + sleep 5 + start-stop-daemon --start --quiet --pidfile \ + $SEMS_PIDFILE --exec $DAEMON -- $PARAMS + echo "." + ;; + status) + status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? + ;; + *) + N=/etc/init.d/$NAME + echo "Usage: $N {start|stop|restart|force-reload|status}" >&2 + exit 1 + ;; +esac + +exit 0 + diff --git a/pkg/deb/trusty/sems.lintian-overrides b/pkg/deb/trusty/sems.lintian-overrides new file mode 100644 index 00000000..7ed54d41 --- /dev/null +++ b/pkg/deb/trusty/sems.lintian-overrides @@ -0,0 +1 @@ +sems: possible-gpl-code-linked-with-openssl diff --git a/pkg/deb/trusty/sems.postinst b/pkg/deb/trusty/sems.postinst new file mode 100644 index 00000000..e81a1745 --- /dev/null +++ b/pkg/deb/trusty/sems.postinst @@ -0,0 +1,25 @@ +#!/bin/sh + +set -e + +# don't do anything when called with other argument than configure +case "$1" in + configure) + ;; + abort-upgrade|abort-remove|abort-deconfigure) + exit 0 + ;; + *) + echo "postinst called with unknown argument \$1'" >&2 + exit 1 + ;; +esac + +# add sems user +adduser --quiet --system --group --disabled-password --shell /bin/false \ +--gecos "SIP Express Media Server" --home /var/run/sems sems || true + +#DEBHELPER# + +exit 0 + diff --git a/pkg/deb/trusty/sems.postrm b/pkg/deb/trusty/sems.postrm new file mode 100644 index 00000000..ccfdb382 --- /dev/null +++ b/pkg/deb/trusty/sems.postrm @@ -0,0 +1,18 @@ +#!/bin/sh + +set -e + +#DEBHELPER# + +if [ "$1" = "purge" ] ; then + # remove user/group on purge + if [ -x "$(command -v deluser)" ]; then + deluser --quiet --remove-home sems >/dev/null 2>&1 || true + else + echo >&2 "not removing sems system account because deluser command was not found" + fi + # remove /etc/sems if empty + rmdir /etc/sems || true +fi + +exit 0 diff --git a/pkg/deb/trusty/shlibs.local b/pkg/deb/trusty/shlibs.local new file mode 100644 index 00000000..e69de29b diff --git a/pkg/deb/trusty/source/format b/pkg/deb/trusty/source/format new file mode 100644 index 00000000..89ae9db8 --- /dev/null +++ b/pkg/deb/trusty/source/format @@ -0,0 +1 @@ +3.0 (native) diff --git a/pkg/deb/wheezy/rules b/pkg/deb/wheezy/rules index 6f856b61..5ac115ae 100755 --- a/pkg/deb/wheezy/rules +++ b/pkg/deb/wheezy/rules @@ -40,3 +40,10 @@ override_dh_auto_install: override_dh_strip: dh_strip --dbg-package=sems-dbg + # those binaries aren't automatically stripped + test -r $(CURDIR)/debian/libsems1-dev/usr/include/sems/compat/getarch && \ + strip --remove-section=.comment --remove-section=.note --strip-unneeded \ + $(CURDIR)/debian/libsems1-dev/usr/include/sems/compat/getarch + test -r $(CURDIR)/debian/libsems1-dev/usr/include/sems/compat/getos && \ + strip --remove-section=.comment --remove-section=.note --strip-unneeded \ + $(CURDIR)/debian/libsems1-dev/usr/include/sems/compat/getos diff --git a/pkg/deb/wheezy/sems.init b/pkg/deb/wheezy/sems.init index d855e2b0..a4d19787 100644 --- a/pkg/deb/wheezy/sems.init +++ b/pkg/deb/wheezy/sems.init @@ -85,6 +85,24 @@ case "$1" in --exec $DAEMON log_end_msg $? ;; + restart-graceful) + log_daemon_msg "Activating shutdown mode: " + /usr/sbin/sems-stats -c "set_shutdownmode 1" + CALLS=`/usr/sbin/sems-stats | grep 'Active calls' | awk -F' ' '{print $3}'` + while [ $CALLS -ne "0" ] + do + echo "Current calls $CALLS, waiting..." + sleep 5 + CALLS=`/usr/sbin/sems-stats | grep 'Active calls' | awk -F' ' '{print $3}'` + done + log_daemon_msg "Restarting $DESC: $NAME " + start-stop-daemon --oknodo --stop --quiet --pidfile \ + $SEMS_PIDFILE --exec $DAEMON + sleep 5 + start-stop-daemon --start --quiet --pidfile \ + $SEMS_PIDFILE --exec $DAEMON -- $PARAMS + echo "." + ;; restart|force-reload) log_daemon_msg "Restarting $DESC: $NAME " start-stop-daemon --oknodo --stop --quiet --pidfile \ @@ -99,7 +117,7 @@ case "$1" in ;; *) N=/etc/init.d/$NAME - echo "Usage: $N {start|stop|restart|force-reload|status}" >&2 + echo "Usage: $N {start|stop|restart|restart-graceful|force-reload|status}" >&2 exit 1 ;; esac