Merge remote-tracking branch 'remotes/origin/1.4' into sayer/1.4-spce2.4

* remotes/origin/1.4: (27 commits)
  b/f: getHeader: find correct hdr also if it's substring of another hdr
  b/f: support values at end of SDP without CR (master 8ec8a910a2)
  b/f: T38 streams in SBC/B2B (udptl transport); proper media direction passthrough
  click2dial: b/f: fix crash when using without credentials
  Add systemd-related files to the pkg/rpm dir
  Add libzrtp support to the CMakeFile
  Fix c/p typo in cmake-files
  Missing include for close(FILE *)
  Drop privileges for SEMS process
  b/f: in webconference app, handle session timer timeout and RTP timeout
  b/f: on RTP timeout, end dialog with sending BYE
  b/f: make listRooms return only non-expired rooms
  b/f: B2BUA: fixed replies for error handling
  b/f: fixing b6d5f726 (fix SBC SDP filter)
  b/f: fix SBC SDP filter with connection per media only
  add Retry-After: 0 to NOTIFY 500 response on low CSeq
  b/f: click2dial: save content_type, cseq to connect callee
  b/f: use proper empty string value
  b/f: use proper failure return value
  b/f: reset RTP-received timestamp when (re)starting process RTP stream
  ...
sayer/1.4-spce2.6
Stefan Sayer 14 years ago
commit 3e2a0b0764

@ -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)

@ -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);
}
@ -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");
@ -231,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;

@ -884,7 +884,9 @@ void WebConferenceFactory::listRooms(const AmArg& args, AmArg& ret) {
rooms_mut.lock();
for (map<string, ConferenceRoom>::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();

@ -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);

@ -105,6 +105,9 @@ public:
void onDtmf(int event, int duration);
void onBye(const AmSipRequest& req);
void onSessionTimeout();
void onRtpTimeout();
UACAuthCred* getCredentials() { return cred; }
};

@ -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)

@ -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)

@ -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;
}

@ -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:{

@ -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;

@ -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 */

@ -23,6 +23,9 @@
using std::string;
using std::map;
#include <cctype>
#include <algorithm>
// 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 "<unknown media type>";
}
}
@ -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 "<unknown media type>";
}
}
@ -175,12 +180,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<SdpAttribute>::const_iterator a_it=
@ -193,37 +210,43 @@ 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<SdpPayload>::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<SdpPayload>::const_iterator pl_it = media_it->payloads.begin();
pl_it != media_it->payloads.end(); pl_it++) {
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;
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<SdpAttribute>::const_iterator a_it=
@ -231,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;
@ -727,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){
@ -738,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;
@ -787,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;
@ -796,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);
@ -1053,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)
@ -1172,10 +1204,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)-2);
}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;
@ -1263,32 +1295,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;
}
/*
@ -1336,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;
}

@ -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<SdpPayload> payloads;
std::vector<SdpAttribute> attributes; // unknown attributes
SdpMedia() : conn() {}
SdpMedia() : conn(), dir(DirUndefined), type(MT_NONE), transport(TP_NONE) {}
};
/**

@ -1111,7 +1111,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();
}

@ -248,7 +248,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) {

@ -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;

@ -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) " "

@ -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++;

@ -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)

@ -7,6 +7,7 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <map>
#include <string>

@ -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

@ -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

@ -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

@ -0,0 +1 @@
d /var/run/sems 0755 sems sems
Loading…
Cancel
Save