From f81ce844a9997fad8ce9987ce9046cb7440e9d3d Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Mon, 17 Oct 2011 14:48:57 +0200 Subject: [PATCH 01/27] b/f: on receiving re-INVITE without SDP, reply 488 and continue call --- core/AmSession.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/AmSession.cpp b/core/AmSession.cpp index 2b3718a4..df012505 100644 --- a/core/AmSession.cpp +++ b/core/AmSession.cpp @@ -266,7 +266,7 @@ void AmSession::negotiate(const string& sdp_body, throw AmSession::Exception(400,"session description parsing failed"); if(sdp.media.empty()) - throw AmSession::Exception(400,"no media line found in SDP message"); + throw AmSession::Exception(488,"no media line found in SDP message"); m_payloads = sdp.getCompatiblePayloads(getPayloadProvider(), MT_AUDIO, r_host, r_port); @@ -1028,7 +1028,8 @@ void AmSession::onInvite(const AmSipRequest& req) }catch(const AmSession::Exception& e){ ERROR("%i %s\n",e.code,e.reason.c_str()); - setStopped(); + if (dlg.getStatus() < AmSipDialog::Connected) + setStopped(); dlg.reply(req,e.code,e.reason); } } From 0fbb1f9efeccf675340321a0d6af34946c1b9422 Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Mon, 31 Oct 2011 18:39:57 +0100 Subject: [PATCH 02/27] b/f: remember passive_mode for keeping symmetric RTP in a session If NAT flag (P-MsgFlags: 2) is passed only in the initial INVITE, re-INVITE will set up the RTP stream to the private address, but not enable symmetric RTP (comedia style send-to-where-i-get-rtp-from) again. this fix remembers passive_mode for the call. --- core/AmSession.cpp | 2 +- core/AmSession.h | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/core/AmSession.cpp b/core/AmSession.cpp index df012505..7721216b 100644 --- a/core/AmSession.cpp +++ b/core/AmSession.cpp @@ -79,6 +79,7 @@ AmSession::AmSession() m_dtmfDetector(this), m_dtmfEventQueue(&m_dtmfDetector), m_dtmfDetectionEnabled(true), accept_early_session(false), + passive_mode(false), rtp_interface(-1), refresh_method(REFRESH_UPDATE_FB_REINV), processing_status(SESSION_PROCESSING_EVENTS), @@ -287,7 +288,6 @@ void AmSession::negotiate(const string& sdp_body, DBG("remote party doesn't support telephone events\n"); } - bool passive_mode = false; if( sdp.remote_active || force_symmetric_rtp) { DBG("The other UA is NATed: switched to passive mode.\n"); DBG("remote_active = %i; force_symmetric_rtp = %i\n", diff --git a/core/AmSession.h b/core/AmSession.h index ca60b2a5..218259bb 100644 --- a/core/AmSession.h +++ b/core/AmSession.h @@ -157,6 +157,9 @@ private: auto_ptr _rtp_str; + /** set up RTP stream as passive? (comedia style NAT aware) */ + bool passive_mode; + AmDynInvoke* user_timer_ref; void getUserTimerInstance(); From e78fe72fb69989317d61771b661bded8fac350dc Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Mon, 31 Oct 2011 23:46:22 +0100 Subject: [PATCH 03/27] b/f: support compact Supported header (k:) --- core/AmSipDialog.cpp | 4 ++-- core/AmSipHeaders.h | 1 + core/plug-in/session_timer/SessionTimer.cpp | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/core/AmSipDialog.cpp b/core/AmSipDialog.cpp index 5a37e87d..d31357a4 100644 --- a/core/AmSipDialog.cpp +++ b/core/AmSipDialog.cpp @@ -172,7 +172,7 @@ int AmSipDialog::rel100OnRequestIn(const AmSipRequest& req) if (req.method == SIP_METH_INVITE) { switch(reliable_1xx) { case REL100_SUPPORTED: /* if support is on, enforce if asked by UAC */ - if (key_in_list(getHeader(req.hdrs, SIP_HDR_SUPPORTED), + if (key_in_list(getHeader(req.hdrs, SIP_HDR_SUPPORTED, SIP_HDR_SUPPORTED_COMPACT), SIP_EXT_100REL) || key_in_list(getHeader(req.hdrs, SIP_HDR_REQUIRE), SIP_EXT_100REL)) { @@ -182,7 +182,7 @@ int AmSipDialog::rel100OnRequestIn(const AmSipRequest& req) break; case REL100_REQUIRE: /* if support is required, reject if UAC doesn't */ - if (! (key_in_list(getHeader(req.hdrs,SIP_HDR_SUPPORTED), + if (! (key_in_list(getHeader(req.hdrs,SIP_HDR_SUPPORTED, SIP_HDR_SUPPORTED_COMPACT), SIP_EXT_100REL) || key_in_list(getHeader(req.hdrs, SIP_HDR_REQUIRE), SIP_EXT_100REL))) { diff --git a/core/AmSipHeaders.h b/core/AmSipHeaders.h index fea90af3..00b14703 100644 --- a/core/AmSipHeaders.h +++ b/core/AmSipHeaders.h @@ -45,6 +45,7 @@ #define SIP_EXT_100REL "100rel" #define SIP_HDR_SESSION_EXPIRES_COMPACT "x" +#define SIP_HDR_SUPPORTED_COMPACT "k" #define SIP_IS_200_CLASS(code) ((code >= 200) && (code < 300)) diff --git a/core/plug-in/session_timer/SessionTimer.cpp b/core/plug-in/session_timer/SessionTimer.cpp index b9778b88..a91668cc 100644 --- a/core/plug-in/session_timer/SessionTimer.cpp +++ b/core/plug-in/session_timer/SessionTimer.cpp @@ -270,7 +270,8 @@ void SessionTimer::updateTimer(AmSession* s, const AmSipRequest& req) { if((req.method == SIP_METH_INVITE)||(req.method == SIP_METH_UPDATE)){ remote_timer_aware = - key_in_list(getHeader(req.hdrs, SIP_HDR_SUPPORTED), TIMER_OPTION_TAG, true); + key_in_list(getHeader(req.hdrs, SIP_HDR_SUPPORTED, SIP_HDR_SUPPORTED_COMPACT), + TIMER_OPTION_TAG, true); // determine session interval string sess_expires_hdr = getHeader(req.hdrs, SIP_HDR_SESSION_EXPIRES, From a03278d09f744008d115ff9379be7139263466c3 Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Fri, 4 Nov 2011 17:14:54 +0100 Subject: [PATCH 04/27] b/f: in bye() don't do send_200_ack while iterating over uac_trans send_200_ack erases the transaction, which may lead to fault when iterating is continued --- core/AmSipDialog.cpp | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/core/AmSipDialog.cpp b/core/AmSipDialog.cpp index d31357a4..935a1f5b 100644 --- a/core/AmSipDialog.cpp +++ b/core/AmSipDialog.cpp @@ -792,19 +792,26 @@ int AmSipDialog::bye(const string& hdrs, int flags) switch(status){ case Disconnecting: - case Connected: - for (TransMap::iterator it=uac_trans.begin(); - it != uac_trans.end(); it++) { - if (it->second.method == "INVITE"){ - // finish any UAC transaction before sending BYE - send_200_ack(it->second); - } + case Connected: { + // collect INVITE UAC transactions + vector ack_trans; + for (TransMap::iterator it=uac_trans.begin(); it != uac_trans.end(); it++) { + if (it->second.method == "INVITE"){ + ack_trans.push_back(it->second); } - if (AmConfig::WaitForByeTransaction) - status = Disconnecting; - else - status = Disconnected; - return sendRequest("BYE", "", "", hdrs, flags); + } + // finish any UAC transaction before sending BYE + for (vector::iterator it= + ack_trans.begin(); it != ack_trans.end(); it++) { + send_200_ack(*it); + } + + if (AmConfig::WaitForByeTransaction) + status = Disconnecting; + else + status = Disconnected; + return sendRequest("BYE", "", "", hdrs, flags); + } case Pending: status = Disconnecting; From f755fac491982ddeca84e5cab03b64a02e5251a5 Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Mon, 21 Nov 2011 13:36:31 +0100 Subject: [PATCH 05/27] introduce timeout for sems-stats management utility based on a patch by T Searle closes #66 Conflicts: core/plug-in/stats/query_stats.cxx --- core/plug-in/stats/query_stats.cxx | 32 ++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/core/plug-in/stats/query_stats.cxx b/core/plug-in/stats/query_stats.cxx index 674f16cd..f226be5c 100644 --- a/core/plug-in/stats/query_stats.cxx +++ b/core/plug-in/stats/query_stats.cxx @@ -127,17 +127,33 @@ int main(int argc, char** argv) if(err == -1){ fprintf(stderr,"sendto: %s\n",strerror(errno)); - } - else { - int msg_size = recv(sd,rcv_buf,MSG_BUF_SIZE,0); - if(msg_size == -1) - fprintf(stderr,"recv: %s\n",strerror(errno)); - else - printf("received:\n%.*s",msg_size-1,rcv_buf); + } else { + err = 0; + struct timeval timeout = {5,0}; + fd_set rcv_fd; + FD_ZERO(&rcv_fd); + FD_SET(sd, &rcv_fd); + + int select_result = select(sd+1, &rcv_fd, NULL, NULL, &timeout); + if(select_result == -1) { + fprintf(stderr,"select: %s\n",strerror(errno)); + err = 1; + } else if(select_result == 0) { + fprintf(stderr,"read timeout!\n"); + err = 1; + } else { + int msg_size = recv(sd,rcv_buf,MSG_BUF_SIZE,0); + if(msg_size == -1) { + fprintf(stderr,"recv: %s\n",strerror(errno)); + err = 2; + } else { + printf("received:\n%.*s\n",msg_size-1,rcv_buf); + } + } } close(sd); - return 0; + return err; } From 97f3dcc3eab7806c3ea7aef6655671d9e731357c Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Mon, 21 Nov 2011 14:07:31 +0100 Subject: [PATCH 06/27] b/f: xmlrpc2di - detect unsuccessful bind on startup --- apps/xmlrpc2di/XMLRPC2DI.cpp | 16 +++++++++++++--- apps/xmlrpc2di/XMLRPC2DI.h | 3 +++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/apps/xmlrpc2di/XMLRPC2DI.cpp b/apps/xmlrpc2di/XMLRPC2DI.cpp index 5364ebab..16722559 100644 --- a/apps/xmlrpc2di/XMLRPC2DI.cpp +++ b/apps/xmlrpc2di/XMLRPC2DI.cpp @@ -158,6 +158,10 @@ int XMLRPC2DI::load() { server = new XMLRPC2DIServer(XMLRPCPort, bind_ip, export_di, direct_export, s); + if (!server->initialize()) { + return -1; + } + server->start(); return 0; } @@ -431,11 +435,17 @@ void XMLRPC2DIServer::registerMethods(const std::string& iface) { iface.c_str()); } } - -void XMLRPC2DIServer::run() { +bool XMLRPC2DIServer::initialize() { DBG("Binding XMLRPC2DIServer to port %u \n", port); - s->bindAndListen(port, bind_ip); + if (!s->bindAndListen(port, bind_ip)) { + ERROR("Binding XMLRPC2DIServer to %s:%u\n", bind_ip.c_str(), port); + return false; + } + return true; +} + +void XMLRPC2DIServer::run() { // register us as SIP event receiver for MOD_NAME AmEventDispatcher::instance()->addEventQueue(MOD_NAME, this); diff --git a/apps/xmlrpc2di/XMLRPC2DI.h b/apps/xmlrpc2di/XMLRPC2DI.h index a3fef2d7..fdc03b84 100644 --- a/apps/xmlrpc2di/XMLRPC2DI.h +++ b/apps/xmlrpc2di/XMLRPC2DI.h @@ -126,6 +126,9 @@ class XMLRPC2DIServer bool di_export, string direct_export, XmlRpcServer* s); + + bool initialize(); + void run(); void on_stop(); From 7c87e3c238e4be09a8fe0d5246d5a51df5bd52eb Mon Sep 17 00:00:00 2001 From: Peter Lemenkov Date: Thu, 24 Nov 2011 00:11:14 +0400 Subject: [PATCH 07/27] Fix unresolved symbol in sbc module when compiled with cmake Signed-off-by: Peter Lemenkov --- apps/sbc/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/sbc/CMakeLists.txt b/apps/sbc/CMakeLists.txt index f9083b8c..72018949 100644 --- a/apps/sbc/CMakeLists.txt +++ b/apps/sbc/CMakeLists.txt @@ -1,6 +1,7 @@ set (sbc_SRCS HeaderFilter.cpp ParamReplacer.cpp +RTPParameters.cpp RegexMapper.cpp SBC.cpp SBCCallProfile.cpp From 44889f80bb840e90308af40a94d2cae995ff4400 Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Wed, 30 Nov 2011 16:31:57 +0100 Subject: [PATCH 08/27] b/f: reset RTP-received timestamp when (re)starting process RTP stream patch by Robert Szokovacs --- core/AmMediaProcessor.cpp | 1 + core/AmRtpStream.cpp | 4 ++++ core/AmRtpStream.h | 5 +++++ 3 files changed, 10 insertions(+) diff --git a/core/AmMediaProcessor.cpp b/core/AmMediaProcessor.cpp index a52129b8..b881d81d 100644 --- a/core/AmMediaProcessor.cpp +++ b/core/AmMediaProcessor.cpp @@ -395,6 +395,7 @@ void AmMediaProcessorThread::process(AmEvent* e) case AmMediaProcessor::InsertSession: DBG("Session inserted to the scheduler\n"); sessions.insert(sr->s); + sr->s->RTPStream()->clearRTPTimeout(); break; case AmMediaProcessor::RemoveSession:{ diff --git a/core/AmRtpStream.cpp b/core/AmRtpStream.cpp index 651d19ff..bb2b0a4f 100644 --- a/core/AmRtpStream.cpp +++ b/core/AmRtpStream.cpp @@ -678,6 +678,10 @@ void AmRtpStream::clearRTPTimeout(struct timeval* recv_time) { memcpy(&last_recv_time, recv_time, sizeof(struct timeval)); } +void AmRtpStream::clearRTPTimeout() { + gettimeofday(&last_recv_time,NULL); +} + unsigned int AmRtpStream::bytes2samples(unsigned int) const { ERROR("bytes2samples called on AmRtpStream\n"); return 0; diff --git a/core/AmRtpStream.h b/core/AmRtpStream.h index 497a6213..7e839e58 100644 --- a/core/AmRtpStream.h +++ b/core/AmRtpStream.h @@ -308,6 +308,11 @@ public: */ void clearRTPTimeout(struct timeval* recv_time); + /* + * clear RTP timeout to current time + */ + void clearRTPTimeout(); + virtual unsigned int bytes2samples(unsigned int) const; /** set relay stream for RTP relaying */ From 5139d4cb19d58643341c46d770f2b08369d162fc Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Wed, 7 Dec 2011 18:08:00 +0100 Subject: [PATCH 09/27] b/f: use proper failure return value patch by Andrey Samusenko --- core/AmSessionContainer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/AmSessionContainer.cpp b/core/AmSessionContainer.cpp index bff01ed9..a981f8e8 100644 --- a/core/AmSessionContainer.cpp +++ b/core/AmSessionContainer.cpp @@ -247,7 +247,7 @@ string AmSessionContainer::startSessionUAC(AmSipRequest& req, AmArg* session_par ERROR("INVITE could not be sent: error code = %d.\n", err); AmEventDispatcher::instance()->delEventQueue(req.from_tag); MONITORING_MARK_FINISHED(req.from_tag.c_str()); - return NULL; + return ""; } if (AmConfig::LogSessions) { From 49d90444fec9f6ef64d45122af95d9d5181716a7 Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Wed, 7 Dec 2011 18:08:54 +0100 Subject: [PATCH 10/27] b/f: use proper empty string value patch by Andrey Samusenko --- apps/click2dial/Click2Dial.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/click2dial/Click2Dial.cpp b/apps/click2dial/Click2Dial.cpp index fb06d47d..51e65684 100644 --- a/apps/click2dial/Click2Dial.cpp +++ b/apps/click2dial/Click2Dial.cpp @@ -182,7 +182,7 @@ AmSession* Click2DialFactory::onInvite(const AmSipRequest& req, AmArg& session_p AmSession* Click2DialFactory::onInvite(const AmSipRequest& req) { - return new C2DCallerDialog(req, getAnnounceFile(req), NULL, NULL); + return new C2DCallerDialog(req, getAnnounceFile(req), "", NULL); } From 620f03ba84e7526f5a2a82e9be09050d0ebfe96b Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Wed, 7 Dec 2011 18:18:07 +0100 Subject: [PATCH 11/27] b/f: click2dial: save content_type, cseq to connect callee --- apps/click2dial/Click2Dial.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/click2dial/Click2Dial.cpp b/apps/click2dial/Click2Dial.cpp index 51e65684..111023ae 100644 --- a/apps/click2dial/Click2Dial.cpp +++ b/apps/click2dial/Click2Dial.cpp @@ -200,6 +200,8 @@ void C2DCallerDialog::onSessionStart(const AmSipReply& rep) { setReceiving(false); invite_req.body = rep.body; + invite_req.content_type = rep.content_type; + invite_req.cseq = rep.cseq; if(wav_file.open(filename,AmAudioFile::Read)) throw string("AnnouncementDialog::onSessionStart: Cannot open file\n"); From 4e023507b6207ff84dcf30ed1c4d5c4a3f3825b1 Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Wed, 7 Dec 2011 18:20:10 +0100 Subject: [PATCH 12/27] add Retry-After: 0 to NOTIFY 500 response on low CSeq this may prevent some peers to drop the subscription dialog usage when receiving a 500 reply to NOTIFY for more details see https://lists.cs.columbia.edu/pipermail/sip-implementors/2011-November/027955.html --- core/AmSipDialog.cpp | 11 +++++++++-- core/AmSipHeaders.h | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/core/AmSipDialog.cpp b/core/AmSipDialog.cpp index 935a1f5b..896868bf 100644 --- a/core/AmSipDialog.cpp +++ b/core/AmSipDialog.cpp @@ -112,7 +112,14 @@ void AmSipDialog::updateStatus(const AmSipRequest& req) if (r_cseq_i && req.cseq <= r_cseq){ INFO("remote cseq lower than previous ones - refusing request\n"); // see 12.2.2 - reply_error(req, 500, SIP_REPLY_SERVER_INTERNAL_ERROR, "", + string hdrs; + if (req.method == "NOTIFY") { + // clever trick to not break subscription dialog usage + // for implementations which follow 3265 instead of 5057 + hdrs = SIP_HDR_COLSP(SIP_HDR_RETRY_AFTER) "0" CRLF; + } + + reply_error(req, 500, SIP_REPLY_SERVER_INTERNAL_ERROR, hdrs, next_hop_for_replies ? next_hop_ip : "", next_hop_for_replies ? next_hop_port : 0); return; @@ -121,7 +128,7 @@ void AmSipDialog::updateStatus(const AmSipRequest& req) if (req.method == "INVITE") { if (pending_invites) { reply_error(req,500, SIP_REPLY_SERVER_INTERNAL_ERROR, - "Retry-After: " + int2str(get_random() % 10) + CRLF, + SIP_HDR_COLSP(SIP_HDR_RETRY_AFTER) + int2str(get_random() % 10) + CRLF, next_hop_for_replies ? next_hop_ip : "", next_hop_for_replies ? next_hop_port : 0); return; diff --git a/core/AmSipHeaders.h b/core/AmSipHeaders.h index 00b14703..39e59743 100644 --- a/core/AmSipHeaders.h +++ b/core/AmSipHeaders.h @@ -34,6 +34,7 @@ #define SIP_HDR_PROXY_AUTHENTICATE "Proxy-Authenticate" #define SIP_HDR_WWW_AUTHENTICATE "WWW-Authenticate" #define SIP_HDR_ALLOW "Allow" +#define SIP_HDR_RETRY_AFTER "Retry-After" #define SIP_HDR_COL(_hdr) _hdr ":" #define SIP_HDR_COLSP(_hdr) SIP_HDR_COL(_hdr) " " From 8dac2df1b8f22acf98d5b16df961edc3582d1969 Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Thu, 8 Dec 2011 00:34:33 +0100 Subject: [PATCH 13/27] b/f: fix SBC SDP filter with connection per media only --- core/AmSdp.cpp | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/core/AmSdp.cpp b/core/AmSdp.cpp index fca56313..20c7f5d7 100644 --- a/core/AmSdp.cpp +++ b/core/AmSdp.cpp @@ -175,12 +175,24 @@ SdpPayload* AmSdp::telephoneEventPayload() const { void AmSdp::print(string& body) const { - string out_buf = - "v="+int2str(version)+"\r\n" - "o="+origin.user+" "+int2str(origin.sessId)+" "+int2str(origin.sessV)+" IN IP4 "+conn.address+"\r\n" - "s="+sessionName+"\r\n" - "c=IN IP4 "+conn.address+"\r\n" - "t=0 0\r\n"; + string out_buf = "v="+int2str(version)+"\r\n" + "o="+origin.user+" "+int2str(origin.sessId)+" "+ + int2str(origin.sessV)+" IN IP4 "; + if (!origin.conn.address.empty()) + out_buf += origin.conn.address+"\r\n"; + else if (!conn.address.empty()) + out_buf += conn.address+"\r\n"; + else if (media.size() && !media[0].conn.address.empty()) + out_buf += media[0].conn.address+"\r\n"; + else + out_buf += "0.0.0.0\r\n"; + + out_buf += + "s="+sessionName+"\r\n"; + if (!conn.address.empty()) + out_buf += "c=IN IP4 "+conn.address+"\r\n"; + + out_buf += "t=0 0\r\n"; // add attributes (session level) for (std::vector::const_iterator a_it= @@ -199,6 +211,9 @@ void AmSdp::print(string& body) const out_buf += " " + int2str(pl_it->payload_type); + if (!media_it->conn.address.empty()) + options += "c=IN IP4 "+media_it->conn.address+"\r\n"; + if (pl_it->encoding_name.empty()) // don't add rtpmap if no encoding name given continue; @@ -1172,10 +1187,10 @@ static void parse_sdp_origin(AmSdp* sdp_msg, char* s) next = parse_until(origin_line, ' '); //check if line contains more values than allowed if(next > line_end){ - string unicast_addr(origin_line, int(line_end-origin_line)-1); + origin.conn.address = string(origin_line, int(line_end-origin_line)-1); }else{ DBG("parse_sdp_origin: 'o=' contains more values than allowed; these values will be ignored\n"); - string unicast_addr(origin_line, int(next-origin_line)-1); + origin.conn.address = string(origin_line, int(next-origin_line)-1); } parsing = 0; break; From 32461b9a6ee112e1c557f9eee8a7198c135d2df1 Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Wed, 14 Dec 2011 16:44:50 +0100 Subject: [PATCH 14/27] b/f: fixing b6d5f726 (fix SBC SDP filter) --- core/AmSdp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/AmSdp.cpp b/core/AmSdp.cpp index 20c7f5d7..b23a98e4 100644 --- a/core/AmSdp.cpp +++ b/core/AmSdp.cpp @@ -1187,7 +1187,7 @@ static void parse_sdp_origin(AmSdp* sdp_msg, char* s) 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)-1); + 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); From dde27343e5376751ddb544c85f086e0dc95e40f1 Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Fri, 6 Jan 2012 12:59:10 +0100 Subject: [PATCH 15/27] b/f: B2BUA: fixed replies for error handling part of 1042b0fc backported --- core/AmB2BSession.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/core/AmB2BSession.cpp b/core/AmB2BSession.cpp index 6a78e67f..90172713 100644 --- a/core/AmB2BSession.cpp +++ b/core/AmB2BSession.cpp @@ -124,6 +124,7 @@ void AmB2BSession::onB2BEvent(B2BEvent* ev) n_reply.code = 491; n_reply.reason = "Request Pending"; n_reply.cseq = req_ev->req.cseq; + n_reply.local_tag = dlg.local_tag; relayEvent(new B2BSipReplyEvent(n_reply, true, SIP_METH_INVITE)); return; } From c49cc6bd175c3b5cc7e2d5688095c5ab8f09c29c Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Mon, 30 Jan 2012 19:36:01 +0100 Subject: [PATCH 16/27] b/f: make listRooms return only non-expired rooms --- apps/webconference/WebConference.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/webconference/WebConference.cpp b/apps/webconference/WebConference.cpp index a9e54542..4ea69c48 100644 --- a/apps/webconference/WebConference.cpp +++ b/apps/webconference/WebConference.cpp @@ -884,7 +884,9 @@ void WebConferenceFactory::listRooms(const AmArg& args, AmArg& ret) { rooms_mut.lock(); for (map::iterator it = rooms.begin(); it != rooms.end(); it++) { - room_list.push(it->first.c_str()); + if (!it->second.expired()) { + room_list.push(it->first.c_str()); + } } rooms_mut.unlock(); From a7516d000029195706c198e5f3373cee16729249 Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Mon, 12 Mar 2012 16:48:22 +0100 Subject: [PATCH 17/27] b/f: on RTP timeout, end dialog with sending BYE --- core/AmSession.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/AmSession.cpp b/core/AmSession.cpp index 7721216b..5f45a577 100644 --- a/core/AmSession.cpp +++ b/core/AmSession.cpp @@ -1106,7 +1106,8 @@ void AmSession::onSendReply(const AmSipRequest& req, unsigned int code, void AmSession::onRtpTimeout() { - DBG("stopping Session.\n"); + DBG("RTP timeout, stopping Session\n"); + dlg.bye(); setStopped(); } From bed6c2545a14b62adb746bb08a3d5554e40cded1 Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Mon, 12 Mar 2012 16:48:43 +0100 Subject: [PATCH 18/27] b/f: in webconference app, handle session timer timeout and RTP timeout by leaving the conference --- apps/webconference/WebConferenceDialog.cpp | 12 ++++++++++++ apps/webconference/WebConferenceDialog.h | 3 +++ 2 files changed, 15 insertions(+) diff --git a/apps/webconference/WebConferenceDialog.cpp b/apps/webconference/WebConferenceDialog.cpp index 7622cc3f..7e73bb36 100644 --- a/apps/webconference/WebConferenceDialog.cpp +++ b/apps/webconference/WebConferenceDialog.cpp @@ -248,6 +248,18 @@ void WebConferenceDialog::onBye(const AmSipRequest& req) disconnectConference(); } +void WebConferenceDialog::onRtpTimeout() { + DBG("RTP timeout, removing from conference\n"); + disconnectConference(); + AmSession::onRtpTimeout(); +} + +void WebConferenceDialog::onSessionTimeout() { + DBG("Session Timer: Timeout, removing from conference.\n"); + disconnectConference(); + AmSession::onSessionTimeout(); +} + void WebConferenceDialog::disconnectConference() { play_list.close(); setInOut(NULL,NULL); diff --git a/apps/webconference/WebConferenceDialog.h b/apps/webconference/WebConferenceDialog.h index 4923792b..0185b11b 100644 --- a/apps/webconference/WebConferenceDialog.h +++ b/apps/webconference/WebConferenceDialog.h @@ -105,6 +105,9 @@ public: void onDtmf(int event, int duration); void onBye(const AmSipRequest& req); + void onSessionTimeout(); + void onRtpTimeout(); + UACAuthCred* getCredentials() { return cred; } }; From c096050398a9ada71407a942359d659227dcd521 Mon Sep 17 00:00:00 2001 From: Peter Lemenkov Date: Thu, 24 Nov 2011 23:51:59 +0400 Subject: [PATCH 19/27] Drop privileges for SEMS process SEMS shoud drop privileges from superiuser to its own user (e.g. sems). Signed-off-by: Peter Lemenkov --- pkg/rpm/sems.init | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/rpm/sems.init b/pkg/rpm/sems.init index 9e6080f6..15e98479 100755 --- a/pkg/rpm/sems.init +++ b/pkg/rpm/sems.init @@ -53,7 +53,7 @@ start() { return 0 fi - daemon $sems -P $pidfile -f $conffile $OPTIONS + daemon $sems -P $pidfile -u sems -g sems -f $conffile $OPTIONS RETVAL=$? echo [ $RETVAL = 0 ] && touch $lockfile From ff94051b845fabed3b81b96e96a2d15f11084cb3 Mon Sep 17 00:00:00 2001 From: Peter Lemenkov Date: Thu, 5 Apr 2012 15:11:18 +0400 Subject: [PATCH 20/27] Missing include for close(FILE *) This will affects only gcc 4.7.0+ users. Others won't see any difference. Signed-off-by: Peter Lemenkov --- core/plug-in/stats/query_stats.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/core/plug-in/stats/query_stats.cxx b/core/plug-in/stats/query_stats.cxx index f226be5c..6bb1444c 100644 --- a/core/plug-in/stats/query_stats.cxx +++ b/core/plug-in/stats/query_stats.cxx @@ -7,6 +7,7 @@ #include #include #include +#include #include #include From b74432b69f925b1502631b168320cc7f6dc18cbc Mon Sep 17 00:00:00 2001 From: Peter Lemenkov Date: Thu, 5 Apr 2012 16:58:28 +0400 Subject: [PATCH 21/27] Fix c/p typo in cmake-files Signed-off-by: Peter Lemenkov --- cmake/FindLibev.cmake | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmake/FindLibev.cmake b/cmake/FindLibev.cmake index fd90af63..5bf3504f 100644 --- a/cmake/FindLibev.cmake +++ b/cmake/FindLibev.cmake @@ -6,12 +6,12 @@ IF(LIBEV_INCLUDE_DIR AND LIBEV_LIBRARIES) ENDIF(LIBEV_INCLUDE_DIR AND LIBEV_LIBRARIES) IF(LIBEV_FOUND) - IF (NOT Speex_FIND_QUIETLY) + IF (NOT Libev_FIND_QUIETLY) MESSAGE(STATUS "Found libev includes: ${LIBEV_INCLUDE_DIR}/libev/ev.h") MESSAGE(STATUS "Found libev library: ${LIBEV_LIBRARIES}") - ENDIF (NOT Speex_FIND_QUIETLY) + ENDIF (NOT Libev_FIND_QUIETLY) ELSE(LIBEV_FOUND) - IF (Speex_FIND_REQUIRED) + IF (Libev_FIND_REQUIRED) MESSAGE(FATAL_ERROR "Could NOT find libev development files") - ENDIF (Speex_FIND_REQUIRED) + ENDIF (Libev_FIND_REQUIRED) ENDIF(LIBEV_FOUND) From 13c6e3f26d43edfca3fc16b0f61387e67750552c Mon Sep 17 00:00:00 2001 From: Peter Lemenkov Date: Thu, 5 Apr 2012 17:06:18 +0400 Subject: [PATCH 22/27] Add libzrtp support to the CMakeFile Signed-off-by: Peter Lemenkov --- CMakeLists.txt | 4 +--- cmake/FindLibzrtp.cmake | 17 +++++++++++++++++ core/CMakeLists.txt | 8 ++++++-- 3 files changed, 24 insertions(+), 5 deletions(-) create mode 100644 cmake/FindLibzrtp.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 7998e33d..8f83c5d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -108,12 +108,10 @@ ENDIF(SEMS_USE_LIBSAMPLERATE) # ZRTP support? (see zfoneproject.com) IF(SEMS_USE_ZRTP) - # TODO - SET(ZRTP_FOUND TRUE) + FIND_PACKAGE(Libzrtp REQUIRED) MESSAGE(STATUS "Using libzrtp: YES") ADD_DEFINITIONS(-DWITH_ZRTP -DBUILD_ZRTP_MUTEXES -DBUILD_DEFAULT_CACHE -DBUILD_DEFAULT_TIMER -DUNIX -DBUILD_ZRTP_MUTEXES) ELSE(SEMS_USE_ZRTP) - SET(ZRTP_FOUND FALSE) MESSAGE(STATUS "Using libzrtp: NO (default)") ENDIF(SEMS_USE_ZRTP) diff --git a/cmake/FindLibzrtp.cmake b/cmake/FindLibzrtp.cmake new file mode 100644 index 00000000..967c9d48 --- /dev/null +++ b/cmake/FindLibzrtp.cmake @@ -0,0 +1,17 @@ +FIND_PATH(LIBZRTP_INCLUDE_DIR zrtp.h HINTS /usr/include/zrtp ) +FIND_LIBRARY(LIBZRTP_LIBRARIES NAMES zrtp) + +IF(LIBZRTP_INCLUDE_DIR AND LIBZRTP_LIBRARIES) + SET(LIBZRTP_FOUND TRUE) +ENDIF(LIBZRTP_INCLUDE_DIR AND LIBZRTP_LIBRARIES) + +IF(LIBZRTP_FOUND) + IF (NOT Libzrtp_FIND_QUIETLY) + MESSAGE(STATUS "Found libzrtp includes: ${LIBZRTP_INCLUDE_DIR}/zrtp/zrtp.h") + MESSAGE(STATUS "Found libzrtp library: ${LIBZRTP_LIBRARIES}") + ENDIF (NOT Libzrtp_FIND_QUIETLY) +ELSE(LIBZRTP_FOUND) + IF (Libzrtp_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could NOT find libzrtp development files") + ENDIF (Libzrtp_FIND_REQUIRED) +ENDIF(LIBZRTP_FOUND) diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index e1eb469c..bd107c85 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -27,6 +27,10 @@ IF(LIBSAMPLERATE_FOUND) TARGET_LINK_LIBRARIES(sems ${CMAKE_DL_LIBS} samplerate) ENDIF(LIBSAMPLERATE_FOUND) +IF(LIBZRTP_FOUND) + TARGET_LINK_LIBRARIES(sems ${CMAKE_DL_LIBS} zrtp) +ENDIF(LIBZRTP_FOUND) + ADD_SUBDIRECTORY(plug-in) # Create config-file from template @@ -39,9 +43,9 @@ INSTALL(TARGETS sems RUNTIME DESTINATION ${SEMS_EXEC_PREFIX}/sbin) # Installation of config-files INSTALL(FILES ./etc/sems.conf DESTINATION ${SEMS_CFG_PREFIX}/etc/sems/) INSTALL(FILES ./etc/app_mapping.conf DESTINATION ${SEMS_CFG_PREFIX}/etc/sems/etc/) -IF(ZRTP_FOUND) +IF(LIBZRTP_FOUND) INSTALL(FILES ./etc/zrtp.conf DESTINATION ${SEMS_CFG_PREFIX}/etc/sems/etc/) -ENDIF(ZRTP_FOUND) +ENDIF(LIBZRTP_FOUND) INCLUDE(${CMAKE_SOURCE_DIR}/cmake/doc.rules.txt) From 78126830bfa36f67fb3e7495093fe4f363bd8520 Mon Sep 17 00:00:00 2001 From: Peter Lemenkov Date: Wed, 18 Apr 2012 21:51:48 +0400 Subject: [PATCH 23/27] Add systemd-related files to the pkg/rpm dir Signed-off-by: Peter Lemenkov --- pkg/rpm/sems.systemd.service | 11 +++++++++++ pkg/rpm/sems.systemd.tmpfiles.d.conf | 1 + 2 files changed, 12 insertions(+) create mode 100644 pkg/rpm/sems.systemd.service create mode 100644 pkg/rpm/sems.systemd.tmpfiles.d.conf diff --git a/pkg/rpm/sems.systemd.service b/pkg/rpm/sems.systemd.service new file mode 100644 index 00000000..ffe2a606 --- /dev/null +++ b/pkg/rpm/sems.systemd.service @@ -0,0 +1,11 @@ +[Unit] +Description=SIP Media Server +After=network.target + +[Service] +Type=simple +User=sems +Group=sems +EnvironmentFile=-/etc/sysconfig/sems +PIDFile=/var/run/sems/sems.pid +ExecStart=/usr/sbin/sems -E -u sems -g sems -P /var/run/sems/sems.pid $OPTIONS diff --git a/pkg/rpm/sems.systemd.tmpfiles.d.conf b/pkg/rpm/sems.systemd.tmpfiles.d.conf new file mode 100644 index 00000000..d1428ea7 --- /dev/null +++ b/pkg/rpm/sems.systemd.tmpfiles.d.conf @@ -0,0 +1 @@ +d /var/run/sems 0755 sems sems From 1d86e099d358733e2ef123caef58cdafd67bc78f Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Thu, 19 Apr 2012 16:46:10 +0200 Subject: [PATCH 24/27] click2dial: b/f: fix crash when using without credentials --- apps/click2dial/Click2Dial.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/click2dial/Click2Dial.cpp b/apps/click2dial/Click2Dial.cpp index 111023ae..cdc79b40 100644 --- a/apps/click2dial/Click2Dial.cpp +++ b/apps/click2dial/Click2Dial.cpp @@ -233,8 +233,13 @@ void C2DCallerDialog::process(AmEvent* event) void C2DCallerDialog::createCalleeSession() { - UACAuthCred* c = new UACAuthCred(cred.get()->realm, - cred.get()->user, cred.get()->pwd); + + UACAuthCred* c; + if (cred.get()){ + c = new UACAuthCred(cred->realm, cred->user, cred->pwd); + } else { + c = new UACAuthCred(); + } AmB2BCalleeSession* callee_session = new C2DCalleeDialog(this, c); AmSipDialog& callee_dlg = callee_session->dlg; From 8c10653865e5f0b446f8783a30b67b062f897dcb Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Tue, 24 Apr 2012 11:27:40 +0200 Subject: [PATCH 25/27] b/f: T38 streams in SBC/B2B (udptl transport); proper media direction passthrough Conflicts: core/AmSdp.cpp --- core/AmSdp.cpp | 154 +++++++++++++++++++++++++++++-------------------- core/AmSdp.h | 10 ++-- 2 files changed, 97 insertions(+), 67 deletions(-) diff --git a/core/AmSdp.cpp b/core/AmSdp.cpp index b23a98e4..1d58a2d7 100644 --- a/core/AmSdp.cpp +++ b/core/AmSdp.cpp @@ -23,6 +23,9 @@ using std::string; using std::map; +#include +#include + // Not on Solaris! #if !defined (__SVR4) && !defined (__sun) #include "strings.h" @@ -42,8 +45,8 @@ static char* parse_until(char* s, char* end, char c); static bool contains(char* s, char* next_line, char c); static bool is_wsp(char s); -static int media_type(std::string media); -static int transport_type(std::string transport); +static MediaType media_type(std::string media); +static TransProt transport_type(std::string transport); static bool attr_check(std::string attr); enum parse_st {SDP_DESCR, SDP_MEDIA}; @@ -81,6 +84,7 @@ inline string media_t_2_str(int mt) case MT_APPLICATION: return "application"; case MT_TEXT: return "text"; case MT_MESSAGE: return "message"; + case MT_IMAGE: return "image"; default: return ""; } } @@ -91,6 +95,7 @@ inline string transport_p_2_str(int tp) case TP_RTPAVP: return "RTP/AVP"; case TP_UDP: return "udp"; case TP_RTPSAVP: return "RTP/SAVP"; + case TP_UDPTL: return "udptl"; default: return ""; } } @@ -205,9 +210,10 @@ void AmSdp::print(string& body) const out_buf += "m=" + media_t_2_str(media_it->type) + " " + int2str(media_it->port) + " " + transport_p_2_str(media_it->transport); - string options; - for(std::vector::const_iterator pl_it = media_it->payloads.begin(); - pl_it != media_it->payloads.end(); pl_it++) { + if (media_it->transport == TP_RTPAVP || media_it->transport == TP_RTPSAVP) { + string options; + for(std::vector::const_iterator pl_it = media_it->payloads.begin(); + pl_it != media_it->payloads.end(); pl_it++) { out_buf += " " + int2str(pl_it->payload_type); @@ -215,30 +221,32 @@ void AmSdp::print(string& body) const options += "c=IN IP4 "+media_it->conn.address+"\r\n"; if (pl_it->encoding_name.empty()) // don't add rtpmap if no encoding name given - continue; + continue; // "a=rtpmap:" line options += "a=rtpmap:" + int2str(pl_it->payload_type) + " " - + pl_it->encoding_name + "/" + int2str(pl_it->clock_rate); + + pl_it->encoding_name + "/" + int2str(pl_it->clock_rate); if(pl_it->encoding_param > 0){ - options += "/" + int2str(pl_it->encoding_param); + options += "/" + int2str(pl_it->encoding_param); } options += "\r\n"; // "a=fmtp:" line if(pl_it->sdp_format_parameters.size()){ - options += "a=fmtp:" + int2str(pl_it->payload_type) + " " - + pl_it->sdp_format_parameters + "\r\n"; + options += "a=fmtp:" + int2str(pl_it->payload_type) + " " + + pl_it->sdp_format_parameters + "\r\n"; } - } + } - out_buf += "\r\n" + options; + out_buf += "\r\n" + options; - if(remote_active /* dir == SdpMedia::DirActive */) - out_buf += "a=direction:passive\r\n"; + } else { + // for other transports (UDP/UDPTL) just print out fmt + out_buf += " " + media_it->fmt + "\r\n"; + } // add attributes (media level) for (std::vector::const_iterator a_it= @@ -246,6 +254,12 @@ void AmSdp::print(string& body) const out_buf += a_it->print(); } + switch (media_it->dir) { + case SdpMedia::DirActive: out_buf += "a=direction:active\r\n"; break; + case SdpMedia::DirPassive: out_buf += "a=direction:passive\r\n"; break; + case SdpMedia::DirBoth: out_buf += "a=direction:both\r\n"; break; + case SdpMedia::DirUndefined: break; + } } body = out_buf; @@ -742,7 +756,6 @@ static void parse_sdp_media(AmSdp* sdp_msg, char* s) SdpPayload payload; unsigned int payload_type; DBG("parse_sdp_line_ex: parse_sdp_media: parsing media description...\n"); - m.dir = SdpMedia::DirBoth; while(parsing){ switch(state){ @@ -753,7 +766,7 @@ static void parse_sdp_media(AmSdp* sdp_msg, char* s) if (next > media_line) media = string(media_line, int(next-media_line)-1); m.type = media_type(media); - if(m.type < 0) { + if(m.type == MT_NONE) { ERROR("parse_sdp_media: Unknown media type\n"); } media_line = next; @@ -802,7 +815,7 @@ static void parse_sdp_media(AmSdp* sdp_msg, char* s) // break; // } m.transport = transport_type(proto); - if(m.transport < 0){ + if(m.transport == TP_NONE){ DBG("Unknown transport protocol: %s\n",proto.c_str()); } media_line = next; @@ -811,41 +824,49 @@ static void parse_sdp_media(AmSdp* sdp_msg, char* s) } case FMT: { - if (contains(media_line, line_end, ' ')) { - next = parse_until(media_line, ' '); - string value; - if (next > media_line) - value = string(media_line, int(next-media_line)-1); - - if (!value.empty()) { - payload.type = m.type; - str2i(value, payload_type); - payload.payload_type = payload_type; - m.payloads.push_back(payload); - } - - media_line = next; - state = FMT; - } else { - string last_value; - if (line_end>media_line) { - if (*line_end == '\0') { - // last line in message - last_value = string(media_line, int(line_end-media_line)); - } else { - last_value = string(media_line, int(line_end-media_line)-1); + if (m.transport == TP_RTPAVP || m.transport == TP_RTPSAVP) { + if (contains(media_line, line_end, ' ')) { + next = parse_until(media_line, ' '); + string value; + if (next > media_line) + value = string(media_line, int(next-media_line)-1); + + if (!value.empty()) { + payload.type = m.type; + str2i(value, payload_type); + payload.payload_type = payload_type; + m.payloads.push_back(payload); } + media_line = next; + } else { + string last_value; + if (line_end>media_line) { + if (*line_end == '\0') { + // last line in message + last_value = string(media_line, int(line_end-media_line)); + } else { + last_value = string(media_line, int(line_end-media_line)-1); + } + } + if (!last_value.empty()) { + payload.type = m.type; + str2i(last_value, payload_type); + payload.payload_type = payload_type; + m.payloads.push_back(payload); + } + parsing = 0; } - if (!last_value.empty()) { - payload.type = m.type; - str2i(last_value, payload_type); - payload.payload_type = payload_type; - m.payloads.push_back(payload); - } + } else { + line_end--; + while (line_end > media_line && + (*line_end == '\r' || *line_end == '\n')) + line_end--; + if (line_end>media_line) + m.fmt = string(media_line, line_end-media_line+1); + DBG("set media fmt to '%s'\n", m.fmt.c_str()); parsing = 0; } - break; - } + } break; } } sdp_msg->media.push_back(m); @@ -1278,32 +1299,39 @@ inline char* get_next_line(char* s) /* *Check if known media type is used */ -static int media_type(std::string media) +static MediaType media_type(std::string media) { if(media == "audio") - return 1; + return MT_AUDIO; else if(media == "video") - return 2; + return MT_VIDEO; else if(media == "application") - return 3; + return MT_APPLICATION; else if(media == "text") - return 4; + return MT_TEXT; else if(media == "message") - return 5; + return MT_MESSAGE; + else if(media == "image") + return MT_IMAGE; else - return -1; + return MT_NONE; } -static int transport_type(std::string transport) +static TransProt transport_type(string transport) { - if(transport == "RTP/AVP") - return 1; - else if(transport == "UDP") - return 2; - else if(transport == "RTP/SAVP") - return 3; + string transport_uc = transport; + std::transform(transport_uc.begin(), transport_uc.end(), transport_uc.begin(), toupper); + + if(transport_uc == "RTP/AVP") + return TP_RTPAVP; + else if(transport_uc == "UDP") + return TP_UDP; + else if(transport_uc == "RTP/SAVP") + return TP_RTPSAVP; + else if(transport_uc == "UDPTL") + return TP_UDPTL; else - return -1; + return TP_NONE; } /* diff --git a/core/AmSdp.h b/core/AmSdp.h index 91205390..ee89f8a7 100644 --- a/core/AmSdp.h +++ b/core/AmSdp.h @@ -53,9 +53,9 @@ enum NetworkType { NT_OTHER=0, NT_IN }; /** address type */ enum AddressType { AT_NONE=0, AT_V4, AT_V6 }; /** media type */ -enum MediaType { MT_NONE=0, MT_AUDIO, MT_VIDEO, MT_APPLICATION, MT_TEXT, MT_MESSAGE }; +enum MediaType { MT_NONE=0, MT_AUDIO, MT_VIDEO, MT_APPLICATION, MT_TEXT, MT_MESSAGE, MT_IMAGE }; /** transport protocol */ -enum TransProt { TP_NONE=0, TP_RTPAVP, TP_UDP, TP_RTPSAVP }; +enum TransProt { TP_NONE=0, TP_RTPAVP, TP_UDP, TP_RTPSAVP, TP_UDPTL }; /** \brief c=... line in SDP*/ struct SdpConnection @@ -131,7 +131,8 @@ struct SdpMedia enum Direction { DirBoth=0, DirActive=1, - DirPassive=2 + DirPassive=2, + DirUndefined=3 }; int type; @@ -140,12 +141,13 @@ struct SdpMedia int transport; SdpConnection conn; // c= Direction dir; // a=direction + string fmt; // format in case proto != RTP/AVP or RTP/SAVP std::vector payloads; std::vector attributes; // unknown attributes - SdpMedia() : conn() {} + SdpMedia() : conn(), dir(DirUndefined), type(MT_NONE), transport(TP_NONE) {} }; /** From ddb20bd27800c9a9badb02bf0ee44461f7db827b Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Mon, 23 Apr 2012 18:10:46 +0200 Subject: [PATCH 26/27] b/f: support values at end of SDP without CR (master 8ec8a910a2) --- core/AmSdp.cpp | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/core/AmSdp.cpp b/core/AmSdp.cpp index 1d58a2d7..86fb8780 100644 --- a/core/AmSdp.cpp +++ b/core/AmSdp.cpp @@ -1089,32 +1089,28 @@ static void parse_sdp_attr(AmSdp* sdp_msg, char* s) }else{ attr_check(attr); next = parse_until(attr_line, '\r'); - if(next < line_end){ - string value(attr_line, int(next-attr_line)-1); - DBG("found media attr '%s' value '%s'\n", - (char*)attr.c_str(), (char*)value.c_str()); - media.attributes.push_back(SdpAttribute(attr, value)); - } else { + if(next >= line_end){ DBG("found media attr '%s', but value is not followed by cr\n", (char *)attr.c_str()); } + string value(attr_line, int(next-attr_line)-1); + DBG("found media attr '%s' value '%s'\n", + (char*)attr.c_str(), (char*)value.c_str()); + media.attributes.push_back(SdpAttribute(attr, value)); } } else { next = parse_until(attr_line, '\r'); - if(next < line_end){ - string attr(attr_line, int(next-attr_line)-1); - attr_check(attr); - DBG("found media attr '%s'\n", (char*)attr.c_str()); - media.attributes.push_back(SdpAttribute(attr)); - } else { + if(next >= line_end){ DBG("found media attr line '%s', which is not followed by cr\n", attr_line); } + string attr(attr_line, int(next-attr_line)-1); + attr_check(attr); + DBG("found media attr '%s'\n", (char*)attr.c_str()); + media.attributes.push_back(SdpAttribute(attr)); } - - return; } static void parse_sdp_origin(AmSdp* sdp_msg, char* s) @@ -1379,7 +1375,7 @@ static bool attr_check(std::string attr) return true; else { - DBG("sdp_parse_attr: Unknown attribute name used:%s, plz see RFC4566\n", + DBG("sdp_parse_attr: Unknown attribute name used: %s, plz see RFC4566\n", (char*)attr.c_str()); return false; } From 427a5a77295ae31b4b8694e330f1eb4c1c661612 Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Tue, 24 Apr 2012 12:02:11 +0200 Subject: [PATCH 27/27] b/f: getHeader: find correct hdr also if it's substring of another hdr reported by Andrew Pogrebennyk --- core/AmSipMsg.cpp | 12 ++++++++++-- core/tests/test_headers.cpp | 23 +++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/core/AmSipMsg.cpp b/core/AmSipMsg.cpp index 1626e373..94a4abb9 100644 --- a/core/AmSipMsg.cpp +++ b/core/AmSipMsg.cpp @@ -66,8 +66,16 @@ bool findHeader(const string& hdrs,const string& hdr_name, const size_t skip, hdrs_c++; } - if(hdr_c == hdr_end) - break; + if(hdr_c == hdr_end) { + // matched whole of needle. + // ...all of current header? + const char* srccol = hdrs_c; + while (*srccol==' ' || *srccol=='\t') + srccol++; + if (*srccol == ':') + break; // was end of current hdr + // current hdr just starts with hdr, continue search + } while((hdrs_c != hdrs_end) && (*hdrs_c != '\n')) hdrs_c++; diff --git a/core/tests/test_headers.cpp b/core/tests/test_headers.cpp index 5805534a..e1790eee 100644 --- a/core/tests/test_headers.cpp +++ b/core/tests/test_headers.cpp @@ -59,6 +59,29 @@ FCTMF_SUITE_BGN(test_headers) { fct_chk(get_header_keyvalue("u=sayer;d=iptel.org;p=abcdef", "d") == "iptel.org"); } FCT_TEST_END(); + + FCT_TEST_BGN(getHeader_allow) { + fct_chk(getHeader("Subject: Performance Test\n" + "Allow: INVITE,ACK,OPTIONS,CANCEL,BYE,UPDATE,PRACK,INFO,SUBSCRIBE,NOTIFY,REFER,MESSAGE,PUBLISH", "Allow") == "INVITE,ACK,OPTIONS,CANCEL,BYE,UPDATE,PRACK,INFO,SUBSCRIBE,NOTIFY,REFER,MESSAGE,PUBLISH"); + } FCT_TEST_END(); + + FCT_TEST_BGN(getHeader_allow_substr) { + fct_chk(getHeader("Subject: Performance Test\n" + "Allow-Events: telephone-event,refer\n" + "Allow: INVITE,ACK,OPTIONS,CANCEL,BYE,UPDATE,PRACK,INFO,SUBSCRIBE,NOTIFY,REFER,MESSAGE,PUBLISH", "Allow") == "INVITE,ACK,OPTIONS,CANCEL,BYE,UPDATE,PRACK,INFO,SUBSCRIBE,NOTIFY,REFER,MESSAGE,PUBLISH"); + } FCT_TEST_END(); + + FCT_TEST_BGN(getHeader_allow3) { + fct_chk(getHeader("Subject: Performance Test\n" + "Allow : INVITE,ACK,OPTIONS,CANCEL,BYE,UPDATE,PRACK,INFO,SUBSCRIBE,NOTIFY,REFER,MESSAGE,PUBLISH", "Allow") == "INVITE,ACK,OPTIONS,CANCEL,BYE,UPDATE,PRACK,INFO,SUBSCRIBE,NOTIFY,REFER,MESSAGE,PUBLISH"); + } FCT_TEST_END(); + + FCT_TEST_BGN(getHeader_allow4) { + fct_chk(getHeader("Subject: Performance Test\n" + "Allow-Events : telephone-event,refer\n" + "Allow : INVITE,ACK,OPTIONS,CANCEL,BYE,UPDATE,PRACK,INFO,SUBSCRIBE,NOTIFY,REFER,MESSAGE,PUBLISH", "Allow") == "INVITE,ACK,OPTIONS,CANCEL,BYE,UPDATE,PRACK,INFO,SUBSCRIBE,NOTIFY,REFER,MESSAGE,PUBLISH"); + } FCT_TEST_END(); + FCT_TEST_BGN(addOptionTag) { string hdrs = "Supported: timer" CRLF