Browse Source

Merge branch 'rfuchs/1und1-patches'

pull/60/head
Richard Fuchs 11 years ago
parent
commit
922211d44c
20 changed files with 824 additions and 33 deletions
  1. +15
    -0
      README.md
  2. +1
    -1
      daemon/Makefile
  3. +208
    -14
      daemon/call.c
  4. +41
    -2
      daemon/call.h
  5. +32
    -8
      daemon/call_interfaces.c
  6. +2
    -2
      daemon/call_interfaces.h
  7. +366
    -0
      daemon/cli.c
  8. +18
    -0
      daemon/cli.h
  9. +1
    -1
      daemon/control_ng.c
  10. +1
    -1
      daemon/control_udp.c
  11. +8
    -0
      daemon/log.c
  12. +2
    -4
      daemon/log.h
  13. +33
    -0
      daemon/main.c
  14. +1
    -0
      debian/control
  15. +3
    -0
      debian/ngcp-rtpengine-daemon.default
  16. +3
    -0
      debian/ngcp-rtpengine-daemon.init
  17. +1
    -0
      debian/ngcp-rtpengine-daemon.install
  18. +15
    -0
      el/rtpengine.init
  19. +3
    -0
      el/rtpengine.sysconfig
  20. +70
    -0
      utils/rtpengine-ctl

+ 15
- 0
README.md View File

@ -162,6 +162,7 @@ option and which are reproduced below:
-F, --no-fallback Only start when kernel module is available
-i, --interface=[NAME/]IP[!IP] Local interface for RTP
-l, --listen-tcp=[IP:]PORT TCP port to listen on
-c, --listen-cli=[IP46:]PORT TCP port to listen on, CLI (command line interface)
-u, --listen-udp=[IP46:]PORT UDP port to listen on
-n, --listen-ng=[IP46:]PORT UDP port to listen on, NG protocol
-T, --tos=INT TOS value to set on streams
@ -176,9 +177,11 @@ option and which are reproduced below:
-b, --b2b-url=STRING XMLRPC URL of B2B UA
-L, --log-level=INT Mask log priorities above this level
--log-facility=daemon|local0|... Syslog facility to use for logging
--log-facility-cdr=local0|... Syslog facility to use for logging CDRs
-E, --log-stderr Log on stderr instead of syslog
-x, --xmlrpc-format=INT XMLRPC timeout request format to use. 0: SEMS DI, 1: call-id only
--num-threads=INT Number of worker threads to create
-d, --delete-delay Delay for deleting a session from memory.
--sip-source Use SIP source address by default
--dtls-passive Always prefer DTLS passive role
@ -266,6 +269,10 @@ The options are described in more detail below.
It is recommended to specify not only a local port number, but also 127.0.0.1 as interface to bind to.
* -c, --listen-cli
TCP ip and port to listen for the CLI (command line interface).
* -t, --tos
Takes an integer as argument and if given, specifies the TOS value that should be set in outgoing
@ -309,6 +316,10 @@ The options are described in more detail below.
The syslog facilty to use when sending log messages to the syslog daemon. Defaults to `daemon`.
* --log-facilty-cdr=daemon|local0|...|local7|...
Same as --log-facility with the difference that only CDRs are written to this log facility.
* -E, --log-stderr
Log to stderr instead of syslog. Only useful in combination with `--foreground`.
@ -335,6 +346,10 @@ The options are described in more detail below.
Enabled the `DTLS=passive` flag for all calls unconditionally.
* -d, --delete-delay
Delete the call from memory after the specified delay from memory.
* -r, --redis, -R, --redis-db, -b, --b2b-url
NGCP-specific options


+ 1
- 1
daemon/Makefile View File

@ -62,7 +62,7 @@ endif
SRCS= main.c kernel.c poller.c aux.c control_tcp.c streambuf.c call.c control_udp.c redis.c \
bencode.c cookie_cache.c udp_listener.c control_ng.c sdp.c str.c stun.c rtcp.c \
crypto.c rtp.c call_interfaces.c dtls.c log.c
crypto.c rtp.c call_interfaces.c dtls.c log.c cli.c
OBJS= $(SRCS:.c=.o)


+ 208
- 14
daemon/call.c View File

@ -14,6 +14,8 @@
#include <time.h>
#include <xmlrpc_client.h>
#include <sys/wait.h>
#include <time.h>
#include <sys/time.h>
#include "poller.h"
#include "aux.h"
@ -34,10 +36,6 @@
#ifndef DELETE_DELAY
#define DELETE_DELAY 30
#endif
#ifndef PORT_RANDOM_MIN
#define PORT_RANDOM_MIN 6
#define PORT_RANDOM_MAX 20
@ -122,8 +120,23 @@ const struct transport_protocol transport_protocols[] = {
};
const int num_transport_protocols = G_N_ELEMENTS(transport_protocols);
const char * get_term_reason_text(char *buf, enum termination_reason t) {
if (t==TIMEOUT) { buf = "TIMEOUT"; return buf; }
if (t==REGULAR) { buf = "REGULAR"; return buf; }
if (t==FORCED) { buf = "FORCED"; return buf; }
if (t==SILENT_TIMEOUT) { buf = "SILENT_TIMEOUT"; return buf; }
buf = "UNKNOWN";
return buf;
}
const char * get_tag_type_text(char *buf, enum tag_type t) {
if (t==FROM_TAG) { buf = "FROM_TAG"; return buf; }
if (t==TO_TAG) { buf = "TO_TAG"; return buf; }
buf = "UNKNOWN";
return buf;
}
static void determine_handler(struct packet_stream *in, const struct packet_stream *out);
@ -425,7 +438,7 @@ void kernelize(struct packet_stream *stream) {
PS_SET(stream, KERNELIZED);
return;
no_kernel_warn:
ilog(LOG_WARNING, "No support for kernel packet forwarding available");
no_kernel:
@ -831,6 +844,7 @@ forward:
if (ret == -1) {
ret = -errno;
ilog(LOG_DEBUG,"Error when sending message. Error: %s",strerror(errno));
stream->stats.errors++;
mutex_lock(&cm->statspslock);
cm->statsps.errors++;
@ -980,6 +994,7 @@ static int call_timer_delete_monologues(struct call *c) {
}
__monologue_destroy(ml);
ml->deleted = 0;
if (!g_hash_table_size(c->tags)) {
@ -1014,10 +1029,15 @@ static void call_timer_iterator(void *key, void *val, void *ptr) {
int good = 0;
struct packet_stream *ps;
struct stream_fd *sfd;
int tmp_t_reason=0;
struct call_monologue *ml;
GSList *i;
rwlock_lock_r(&c->master_lock);
log_info_call(c);
cm = c->callmaster;
if (c->deleted && poller_now >= c->deleted
&& c->last_signal <= c->deleted)
goto delete;
@ -1030,8 +1050,6 @@ static void call_timer_iterator(void *key, void *val, void *ptr) {
if (!c->streams)
goto drop;
cm = c->callmaster;
for (it = c->streams; it; it = it->next) {
ps = it->data;
mutex_lock(&ps->in_lock);
@ -1055,8 +1073,11 @@ no_sfd:
goto next;
check = cm->conf.timeout;
if (!MEDIA_ISSET(ps->media, RECV) || !sfd)
tmp_t_reason = 1;
if (!MEDIA_ISSET(ps->media, RECV) || !sfd) {
check = cm->conf.silent_timeout;
tmp_t_reason = 2;
}
if (poller_now - ps->last_packet < check)
good = 1;
@ -1068,6 +1089,22 @@ next:
if (good)
goto out;
if (c->ml_deleted)
goto out;
for (i = c->monologues; i; i = i->next) {
ml = i->data;
memset(&ml->terminated,0,sizeof(struct timeval));
gettimeofday(&(ml->terminated),NULL);
if (tmp_t_reason==1) {
ml->term_reason = TIMEOUT;
} else if (tmp_t_reason==2) {
ml->term_reason = SILENT_TIMEOUT;
} else {
ml->term_reason = UNKNOWN;
}
}
ilog(LOG_INFO, "Closing call due to timeout");
drop:
@ -2299,10 +2336,38 @@ static void unkernelize(struct packet_stream *p) {
PS_CLEAR(p, KERNELIZED);
}
void timeval_subtract (struct timeval *result, const struct timeval *a, const struct timeval *b) {
long microseconds=0;
microseconds = ((long)a->tv_sec - (long)b->tv_sec) * 1000000 + ((long)a->tv_usec - (long)b->tv_usec);
result->tv_sec = microseconds/(long)1000000;
result->tv_usec = microseconds%(long)1000000;
}
void timeval_multiply(struct timeval *result, const struct timeval *a, const long multiplier) {
long microseconds=0;
microseconds = (((long)a->tv_sec * 1000000) + (long)a->tv_usec) * multiplier;
result->tv_sec = microseconds/(long)1000000;
result->tv_usec = microseconds%(long)1000000;
}
void timeval_devide(struct timeval *result, const struct timeval *a, const long devisor) {
long microseconds=0;
microseconds = (((long)a->tv_sec * 1000000) + (long)a->tv_usec) / devisor;
result->tv_sec = microseconds/(long)1000000;
result->tv_usec = microseconds%(long)1000000;
}
void timeval_add(struct timeval *result, const struct timeval *a, const struct timeval *b) {
long microseconds=0;
microseconds = ((long)a->tv_sec + (long)b->tv_sec) * (long)1000000 + ((long)a->tv_usec + (long)b->tv_usec);
result->tv_sec = microseconds/(long)1000000;
result->tv_usec = microseconds%(long)1000000;
}
/* called lock-free, but must hold a reference to the call */
void call_destroy(struct call *c) {
struct callmaster *m = c->callmaster;
struct packet_stream *ps;
struct packet_stream *ps=0, *ps2=0;
struct stream_fd *sfd;
struct poller *p = m->poller;
GSList *l;
@ -2311,6 +2376,15 @@ void call_destroy(struct call *c) {
struct call_media *md;
GList *k, *o;
char buf[64];
struct timeval tim_result_duration;
static const int CDRBUFLENGTH = 4096*2;
char reasonbuf[16]; memset(&reasonbuf,0,16);
char tagtypebuf[16]; memset(&tagtypebuf,0,16);
char cdrbuffer[CDRBUFLENGTH]; memset(&cdrbuffer,0,CDRBUFLENGTH);
char* cdrbufcur = cdrbuffer;
int cdrlinecnt = 0;
int found = 0;
//char tmpstreampairstatus[2]; memset(&tmpstreampairstatus,0,2);
rwlock_lock_w(&m->hashlock);
ret = g_hash_table_remove(m->callhash, &c->callid);
@ -2328,8 +2402,30 @@ void call_destroy(struct call *c) {
ilog(LOG_INFO, "Final packet stats:");
/* CDRs and statistics */
cdrbufcur += sprintf(cdrbufcur,"ci=%s, ",c->callid.s);
cdrbufcur += sprintf(cdrbufcur,"created_from=%s, ", c->created_from);
for (l = c->monologues; l; l = l->next) {
ml = l->data;
if (_log_facility_cdr) {
memset(&tim_result_duration,0,sizeof(struct timeval));
timeval_subtract(&tim_result_duration,&ml->terminated,&ml->started);
cdrbufcur += sprintf(cdrbufcur, "ml%i_start_time=%ld.%06lu, "
"ml%i_end_time=%ld.%06ld, "
"ml%i_duration=%ld.%06ld, "
"ml%i_termination=%s, "
"ml%i_local_tag=%s, "
"ml%i_local_tag_type=%s, "
"ml%i_remote_tag=%s, ",
cdrlinecnt, ml->started.tv_sec, ml->started.tv_usec,
cdrlinecnt, ml->terminated.tv_sec, ml->terminated.tv_usec,
cdrlinecnt, tim_result_duration.tv_sec, tim_result_duration.tv_usec,
cdrlinecnt, get_term_reason_text(reasonbuf,ml->term_reason),
cdrlinecnt, ml->tag.s,
cdrlinecnt, get_tag_type_text(tagtypebuf,ml->tagtype),
cdrlinecnt, ml->active_dialogue ? ml->active_dialogue->tag.s : "(none)");
}
ilog(LOG_INFO, "--- Tag '"STR_FORMAT"', created "
"%u:%02u ago, in dialogue with '"STR_FORMAT"'",
STR_FMT(&ml->tag),
@ -2348,6 +2444,24 @@ void call_destroy(struct call *c) {
continue;
smart_ntop_p(buf, &ps->endpoint.ip46, sizeof(buf));
if (_log_facility_cdr) {
const char* protocol = (!PS_ISSET(ps, RTP) && PS_ISSET(ps, RTCP)) ? "rtcp" : "rtp";
cdrbufcur += sprintf(cdrbufcur,
"ml%i_midx%u_%s_endpoint_ip=%s, "
"ml%i_midx%u_%s_endpoint_port=%u, "
"ml%i_midx%u_%s_local_relay_port=%u, "
"ml%i_midx%u_%s_relayed_packets=%llu, "
"ml%i_midx%u_%s_relayed_bytes=%llu, "
"ml%i_midx%u_%s_relayed_errors=%llu, ",
cdrlinecnt, md->index, protocol, buf,
cdrlinecnt, md->index, protocol, ps->endpoint.port,
cdrlinecnt, md->index, protocol, (unsigned int) (ps->sfd ? ps->sfd->fd.localport : 0),
cdrlinecnt, md->index, protocol, (unsigned long long) ps->stats.packets,
cdrlinecnt, md->index, protocol, (unsigned long long) ps->stats.bytes,
cdrlinecnt, md->index, protocol, (unsigned long long) ps->stats.errors);
}
ilog(LOG_INFO, "------ Media #%u, port %5u <> %15s:%-5hu%s, "
"%llu p, %llu b, %llu e",
md->index,
@ -2357,10 +2471,82 @@ void call_destroy(struct call *c) {
(unsigned long long) ps->stats.packets,
(unsigned long long) ps->stats.bytes,
(unsigned long long) ps->stats.errors);
m->totalstats.total_relayed_packets += (unsigned long long) ps->stats.packets;
m->totalstats.total_relayed_errors += (unsigned long long) ps->stats.errors;
}
}
if (_log_facility_cdr)
++cdrlinecnt;
}
// --- for statistics getting one way stream or no relay at all
m->totalstats.total_nopacket_relayed_sess *= 2;
for (l = c->monologues; l; l = l->next) {
ml = l->data;
// --- go through partner ml and search the RTP
for (k = ml->medias.head; k; k = k->next) {
md = k->data;
for (o = md->streams.head; o; o = o->next) {
ps = o->data;
if ((PS_ISSET(ps, RTP) && !PS_ISSET(ps, RTCP))) {
// --- only RTP is interesting
found = 1;
break;
}
}
if (found) { break; }
}
found = 0;
if (ml->active_dialogue) {
// --- go through partner ml and search the RTP
for (k = ml->active_dialogue->medias.head; k; k = k->next) {
md = k->data;
for (o = md->streams.head; o; o = o->next) {
ps2 = o->data;
if ((PS_ISSET(ps2, RTP) && !PS_ISSET(ps2, RTCP))) {
// --- only RTP is interesting
found = 1;
break;
}
}
if (found) { break; }
}
}
if (ps && ps2 && ps->stats.packets!=0 && ps2->stats.packets==0)
m->totalstats.total_oneway_stream_sess++;
if (ps && ps2 && ps->stats.packets==0 && ps2->stats.packets==0)
m->totalstats.total_nopacket_relayed_sess++;
}
m->totalstats.total_nopacket_relayed_sess /= 2;
m->totalstats.total_managed_sess += 1;
ml = c->monologues->data;
if (ml->term_reason==TIMEOUT) {
m->totalstats.total_timeout_sess++;
} else if (ml->term_reason==SILENT_TIMEOUT) {
m->totalstats.total_silent_timeout_sess++;
} else if (ml->term_reason==REGULAR) {
m->totalstats.total_regular_term_sess++;
} else if (ml->term_reason==FORCED) {
m->totalstats.total_forced_term_sess++;
}
timeval_multiply(&m->totalstats.total_average_call_dur,&m->totalstats.total_average_call_dur,m->totalstats.total_managed_sess-1);
timeval_add(&m->totalstats.total_average_call_dur,&m->totalstats.total_average_call_dur,&tim_result_duration);
timeval_devide(&m->totalstats.total_average_call_dur,&m->totalstats.total_average_call_dur,m->totalstats.total_managed_sess);
if (_log_facility_cdr)
/* log it */
cdrlog(cdrbuffer);
for (l = c->streams; l; l = l->next) {
ps = l->data;
@ -2557,7 +2743,7 @@ restart:
}
/* returns call with master_lock held in W, or NULL if not found */
static struct call *call_get(const str *callid, struct callmaster *m) {
struct call *call_get(const str *callid, struct callmaster *m) {
struct call *ret;
rwlock_lock_r(&m->hashlock);
@ -2757,6 +2943,7 @@ int call_delete_branch(struct callmaster *m, const str *callid, const str *branc
struct call_monologue *ml;
int ret;
const str *match_tag;
GSList *i;
c = call_get(callid, m);
if (!c) {
@ -2764,6 +2951,13 @@ int call_delete_branch(struct callmaster *m, const str *callid, const str *branc
goto err;
}
for (i = c->monologues; i; i = i->next) {
ml = i->data;
memset(&ml->terminated,0,sizeof(struct timeval));
gettimeofday(&(ml->terminated), NULL);
ml->term_reason = REGULAR;
}
if (!fromtag || !fromtag->s || !fromtag->len)
goto del_all;
@ -2795,15 +2989,15 @@ int call_delete_branch(struct callmaster *m, const str *callid, const str *branc
*/
ilog(LOG_INFO, "Scheduling deletion of call branch '"STR_FORMAT"' in %d seconds",
STR_FMT(&ml->tag), DELETE_DELAY);
ml->deleted = poller_now + 30;
STR_FMT(&ml->tag), m->conf.delete_delay);
ml->deleted = poller_now + m->conf.delete_delay;
if (!c->ml_deleted || c->ml_deleted > ml->deleted)
c->ml_deleted = ml->deleted;
goto success_unlock;
del_all:
ilog(LOG_INFO, "Scheduling deletion of entire call in %d seconds", DELETE_DELAY);
c->deleted = poller_now + DELETE_DELAY;
ilog(LOG_INFO, "Scheduling deletion of entire call in %d seconds", m->conf.delete_delay);
c->deleted = poller_now + m->conf.delete_delay;
rwlock_unlock_w(&c->master_lock);
goto success;


+ 41
- 2
daemon/call.h View File

@ -7,12 +7,25 @@
#include <sys/types.h>
#include <glib.h>
#include <time.h>
#include <sys/time.h>
#include <pcre.h>
#include <openssl/x509.h>
#include "compat.h"
enum termination_reason {
UNKNOWN=0,
REGULAR=1,
FORCED=2,
TIMEOUT=3,
SILENT_TIMEOUT=4
};
enum tag_type {
UNKNOWN_TAG=0,
FROM_TAG=1,
TO_TAG=2
};
enum stream_address_format {
SAF_TCP,
@ -179,6 +192,20 @@ struct stats {
u_int64_t errors;
};
struct totalstats {
time_t started;
u_int64_t total_managed_sess;
u_int64_t total_timeout_sess;
u_int64_t total_silent_timeout_sess;
u_int64_t total_regular_term_sess;
u_int64_t total_forced_term_sess;
u_int64_t total_relayed_packets;
u_int64_t total_relayed_errors;
u_int64_t total_nopacket_relayed_sess;
u_int64_t total_oneway_stream_sess;
struct timeval total_average_call_dur;
};
struct udp_fd {
int fd;
u_int16_t localport;
@ -296,9 +323,13 @@ struct call_media {
struct call_monologue {
struct call *call; /* RO */
str tag;
str tag;
enum tag_type tagtype;
time_t created; /* RO */
time_t deleted;
struct timeval started; /* for CDR */
struct timeval terminated; /* for CDR */
enum termination_reason term_reason;
GHashTable *other_tags;
struct call_monologue *active_dialogue;
@ -328,6 +359,7 @@ struct call {
time_t deleted;
time_t ml_deleted;
unsigned char tos;
char *created_from;
};
struct local_interface {
@ -352,6 +384,7 @@ struct callmaster_config {
int port_max;
unsigned int timeout;
unsigned int silent_timeout;
unsigned int delete_delay;
struct redis *redis;
char *b2b_url;
unsigned char default_tos;
@ -376,6 +409,7 @@ struct callmaster {
struct stats statsps; /* per second stats, running timer */
mutex_t statslock;
struct stats stats; /* copied from statsps once a second */
struct totalstats totalstats;
struct poller *poller;
pcre *info_re;
@ -410,6 +444,7 @@ struct packet_stream *__packet_stream_new(struct call *call);
struct call *call_get_or_create(const str *callid, struct callmaster *m);
struct call *call_get_opmode(const str *callid, struct callmaster *m, enum call_opmode opmode);
struct call_monologue *call_get_mono_dialogue(struct call *call, const str *fromtag, const str *totag);
struct call *call_get(const str *callid, struct callmaster *m);
int monologue_offer_answer(struct call_monologue *monologue, GQueue *streams, const struct sdp_ng_flags *flags);
int call_delete_branch(struct callmaster *m, const str *callid, const str *branch,
const str *fromtag, const str *totag, bencode_item_t *output);
@ -426,7 +461,10 @@ struct interface_address *get_interface_from_address(struct local_interface *lif
const struct transport_protocol *transport_protocol(const str *s);
void timeval_subtract (struct timeval *result, const struct timeval *a, const struct timeval *b);
void timeval_multiply(struct timeval *result, const struct timeval *a, const long multiplier);
void timeval_devide(struct timeval *result, const struct timeval *a, const long devisor);
void timeval_add(struct timeval *result, const struct timeval *a, const struct timeval *b);
INLINE void *call_malloc(struct call *c, size_t l) {
@ -490,5 +528,6 @@ INLINE struct packet_stream *packet_stream_sink(struct packet_stream *ps) {
return ret;
}
const char * get_tag_type_text(char *buf, enum tag_type t);
#endif

+ 32
- 8
daemon/call_interfaces.c View File

@ -134,7 +134,7 @@ fail:
return -1;
}
static str *call_update_lookup_udp(char **out, struct callmaster *m, enum call_opmode opmode) {
static str *call_update_lookup_udp(char **out, struct callmaster *m, enum call_opmode opmode, const char* addr) {
struct call *c;
struct call_monologue *monologue;
GQueue q = G_QUEUE_INIT;
@ -154,10 +154,21 @@ static str *call_update_lookup_udp(char **out, struct callmaster *m, enum call_o
STR_FMT(&callid));
return str_sprintf("%s 0 0.0.0.0\n", out[RE_UDP_COOKIE]);
}
if (addr) {
c->created_from = call_strdup(c, addr);
}
monologue = call_get_mono_dialogue(c, &fromtag, &totag);
if (!monologue)
goto ml_fail;
if (!totag.s || totag.len==0) {
monologue->tagtype = FROM_TAG;
} else {
monologue->tagtype = TO_TAG;
}
if (addr_parse_udp(&sp, out))
goto addr_fail;
@ -174,6 +185,8 @@ static str *call_update_lookup_udp(char **out, struct callmaster *m, enum call_o
redis_update(c, m->conf.redis);
gettimeofday(&(monologue->started), NULL);
ilog(LOG_INFO, "Returning to SIP proxy: "STR_FORMAT"", STR_FMT(ret));
goto out;
@ -194,11 +207,11 @@ out:
return ret;
}
str *call_update_udp(char **out, struct callmaster *m) {
return call_update_lookup_udp(out, m, OP_OFFER);
str *call_update_udp(char **out, struct callmaster *m, const char* addr) {
return call_update_lookup_udp(out, m, OP_OFFER, addr);
}
str *call_lookup_udp(char **out, struct callmaster *m) {
return call_update_lookup_udp(out, m, OP_ANSWER);
return call_update_lookup_udp(out, m, OP_ANSWER, NULL);
}
@ -579,7 +592,7 @@ static void call_ng_process_flags(struct sdp_ng_flags *out, bencode_item_t *inpu
}
static const char *call_offer_answer_ng(bencode_item_t *input, struct callmaster *m,
bencode_item_t *output, enum call_opmode opmode)
bencode_item_t *output, enum call_opmode opmode, const char* addr)
{
str sdp, fromtag, totag = STR_NULL, callid;
char *errstr;
@ -618,6 +631,9 @@ static const char *call_offer_answer_ng(bencode_item_t *input, struct callmaster
if (!call)
goto out;
if (addr) {
call->created_from = call_strdup(call, addr);
}
/* At least the random ICE strings are contained within the call struct, so we
* need to hold a ref until we're done sending the reply */
call_bencode_hold_ref(call, output);
@ -630,6 +646,12 @@ static const char *call_offer_answer_ng(bencode_item_t *input, struct callmaster
goto out;
}
if (!totag.s || totag.len==0) {
monologue->tagtype = FROM_TAG;
} else {
monologue->tagtype = TO_TAG;
}
chopper = sdp_chopper_new(&sdp);
bencode_buffer_destroy_add(output->buffer, (free_func_t) sdp_chopper_destroy, chopper);
ret = monologue_offer_answer(monologue, &streams, &flags);
@ -640,6 +662,8 @@ static const char *call_offer_answer_ng(bencode_item_t *input, struct callmaster
redis_update(call, m->conf.redis);
obj_put(call);
gettimeofday(&(monologue->started), NULL);
errstr = "Error rewriting SDP";
if (ret)
goto out;
@ -656,12 +680,12 @@ out:
return errstr;
}
const char *call_offer_ng(bencode_item_t *input, struct callmaster *m, bencode_item_t *output) {
return call_offer_answer_ng(input, m, output, OP_OFFER);
const char *call_offer_ng(bencode_item_t *input, struct callmaster *m, bencode_item_t *output, const char* addr) {
return call_offer_answer_ng(input, m, output, OP_OFFER, addr);
}
const char *call_answer_ng(bencode_item_t *input, struct callmaster *m, bencode_item_t *output) {
return call_offer_answer_ng(input, m, output, OP_ANSWER);
return call_offer_answer_ng(input, m, output, OP_ANSWER, NULL);
}
const char *call_delete_ng(bencode_item_t *input, struct callmaster *m, bencode_item_t *output) {


+ 2
- 2
daemon/call_interfaces.h View File

@ -24,12 +24,12 @@ str *call_lookup_tcp(char **, struct callmaster *);
void call_delete_tcp(char **, struct callmaster *);
void calls_status_tcp(struct callmaster *, struct control_stream *);
str *call_update_udp(char **, struct callmaster *);
str *call_update_udp(char **, struct callmaster *, const char*);
str *call_lookup_udp(char **, struct callmaster *);
str *call_delete_udp(char **, struct callmaster *);
str *call_query_udp(char **, struct callmaster *);
const char *call_offer_ng(bencode_item_t *, struct callmaster *, bencode_item_t *);
const char *call_offer_ng(bencode_item_t *, struct callmaster *, bencode_item_t *, const char*);
const char *call_answer_ng(bencode_item_t *, struct callmaster *, bencode_item_t *);
const char *call_delete_ng(bencode_item_t *, struct callmaster *, bencode_item_t *);
const char *call_query_ng(bencode_item_t *, struct callmaster *, bencode_item_t *);


+ 366
- 0
daemon/cli.c View File

@ -0,0 +1,366 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <netinet/in.h>
#include <errno.h>
#include <glib.h>
#include "poller.h"
#include "aux.h"
#include "log.h"
#include "call.h"
#include "cli.h"
static const char* TRUNCATED = " ... Output truncated. Increase Output Buffer ...\n";
#define truncate_output(x) do { x -= strlen(TRUNCATED)+1; x += sprintf(x,"%s",TRUNCATED); } while (0);
#define ADJUSTLEN(printlen,outbuflen,replybuffer) do { if (printlen>=(outbufend-replybuffer)) \
truncate_output(replybuffer); \
replybuffer += (printlen>=outbufend-replybuffer)?outbufend-replybuffer:printlen; } while (0);
static void cli_incoming_list_totals(char* buffer, int len, struct callmaster* m, char* replybuffer, const char* outbufend) {
int printlen=0;
printlen = snprintf(replybuffer,(outbufend-replybuffer), "\nTotal statistics (does not include current running sessions):\n\n");
ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), " Uptime of rtpengine :%llu seconds\n", (unsigned long long)time(NULL)-m->totalstats.started);
ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), " Total managed sessions :%llu\n", (unsigned long long)m->totalstats.total_managed_sess);
ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), " Total timed-out sessions via TIMEOUT :%llu\n",(unsigned long long)m->totalstats.total_timeout_sess);
ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), " Total timed-out sessions via SILENT_TIMEOUT :%llu\n",(unsigned long long)m->totalstats.total_silent_timeout_sess);
ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), " Total regular terminated sessions :%llu\n",(unsigned long long)m->totalstats.total_regular_term_sess);
ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), " Total forced terminated sessions :%llu\n",(unsigned long long)m->totalstats.total_forced_term_sess);
ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), " Total relayed packets :%llu\n",(unsigned long long)m->totalstats.total_relayed_packets);
ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), " Total relayed packet errors :%llu\n",(unsigned long long)m->totalstats.total_relayed_errors);
ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), " Total number of streams with no relayed packets :%llu\n", (unsigned long long)m->totalstats.total_nopacket_relayed_sess);
ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), " Total number of 1-way streams :%llu\n",(unsigned long long)m->totalstats.total_oneway_stream_sess);
ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), " Average call duration :%ld.%06ld\n\n",m->totalstats.total_average_call_dur.tv_sec,m->totalstats.total_average_call_dur.tv_usec);
ADJUSTLEN(printlen,outbufend,replybuffer);
}
static void cli_incoming_list_callid(char* buffer, int len, struct callmaster* m, char* replybuffer, const char* outbufend) {
str callid;
struct call* c=0;
struct call_monologue *ml;
struct call_media *md;
struct packet_stream *ps;
GSList *l;
GList *k, *o;
char buf[64];
int printlen=0;
char tagtypebuf[16]; memset(&tagtypebuf,0,16);
struct timeval tim_result_duration; memset(&tim_result_duration,0,sizeof(struct timeval));
struct timeval now; memset(&now,0,sizeof(struct timeval));
if (len<=1) {
printlen = snprintf(replybuffer,(outbufend-replybuffer), "%s\n", "More parameters required.");
ADJUSTLEN(printlen,outbufend,replybuffer);
return;
}
++buffer; --len; // one space
str_init_len(&callid,buffer,len);
c = call_get(&callid, m);
if (!c) {
printlen = snprintf(replybuffer,(outbufend-replybuffer), "\nCall Id not found (%s).\n\n",callid.s);
ADJUSTLEN(printlen,outbufend,replybuffer);
return;
}
printlen = snprintf (replybuffer,(outbufend-replybuffer), "\ncallid: %30s | deletionmark:%4s | created:%12i | proxy:%s\n\n", c->callid.s , c->ml_deleted?"yes":"no", (int)c->created, c->created_from);
ADJUSTLEN(printlen,outbufend,replybuffer);
for (l = c->monologues; l; l = l->next) {
ml = l->data;
if (!ml->terminated.tv_sec) {
gettimeofday(&now, NULL);
} else {
now = ml->terminated;
}
timeval_subtract(&tim_result_duration,&now,&ml->started);
printlen = snprintf(replybuffer,(outbufend-replybuffer), "--- Tag '"STR_FORMAT"' type: %s, callduration "
"%ld.%06ld , in dialogue with '"STR_FORMAT"'\n",
STR_FMT(&ml->tag), get_tag_type_text(tagtypebuf,ml->tagtype),
tim_result_duration.tv_sec,
tim_result_duration.tv_usec,
ml->active_dialogue ? ml->active_dialogue->tag.len : 6,
ml->active_dialogue ? ml->active_dialogue->tag.s : "(none)");
ADJUSTLEN(printlen,outbufend,replybuffer);
for (k = ml->medias.head; k; k = k->next) {
md = k->data;
for (o = md->streams.head; o; o = o->next) {
ps = o->data;
if (PS_ISSET(ps, FALLBACK_RTCP))
continue;
smart_ntop_p(buf, &ps->endpoint.ip46, sizeof(buf));
printlen = snprintf(replybuffer,(outbufend-replybuffer), "------ Media #%u, port %5u <> %15s:%-5hu%s, "
"%llu p, %llu b, %llu e\n",
md->index,
(unsigned int) (ps->sfd ? ps->sfd->fd.localport : 0),
buf, ps->endpoint.port,
(!PS_ISSET(ps, RTP) && PS_ISSET(ps, RTCP)) ? " (RTCP)" : "",
(unsigned long long) ps->stats.packets,
(unsigned long long) ps->stats.bytes,
(unsigned long long) ps->stats.errors);
ADJUSTLEN(printlen,outbufend,replybuffer);
}
}
}
printlen = snprintf(replybuffer,(outbufend-replybuffer), "\n");
ADJUSTLEN(printlen,outbufend,replybuffer);
rwlock_unlock_w(&c->master_lock); // because of call_get(..)
}
static void cli_incoming_list(char* buffer, int len, struct callmaster* m, char* replybuffer, const char* outbufend) {
GHashTableIter iter;
gpointer key, value;
str *ptrkey;
struct call *call;
int printlen=0;
static const char* LIST_NUMSESSIONS = "numsessions";
static const char* LIST_SESSIONS = "sessions";
static const char* LIST_SESSION = "session";
static const char* LIST_TOTALS = "totals";
if (len<=1) {
printlen = snprintf(replybuffer, outbufend-replybuffer, "%s\n", "More parameters required.");
ADJUSTLEN(printlen,outbufend,replybuffer);
return;
}
++buffer; --len; // one space
if (len>=strlen(LIST_NUMSESSIONS) && strncmp(buffer,LIST_NUMSESSIONS,strlen(LIST_NUMSESSIONS)) == 0) {
rwlock_lock_r(&m->hashlock);
printlen = snprintf(replybuffer, outbufend-replybuffer, "Current Sessions on rtpengine:%i\n", g_hash_table_size(m->callhash));
ADJUSTLEN(printlen,outbufend,replybuffer);
rwlock_unlock_r(&m->hashlock);
} else if (len>=strlen(LIST_SESSIONS) && strncmp(buffer,LIST_SESSIONS,strlen(LIST_SESSIONS)) == 0) {
rwlock_lock_r(&m->hashlock);
if (g_hash_table_size(m->callhash)==0) {
printlen = snprintf(replybuffer, outbufend-replybuffer, "No sessions on this media relay.\n");
ADJUSTLEN(printlen,outbufend,replybuffer);
rwlock_unlock_r(&m->hashlock);
return;
}
g_hash_table_iter_init (&iter, m->callhash);
while (g_hash_table_iter_next (&iter, &key, &value)) {
ptrkey = (str*)key;
call = (struct call*)value;
printlen = snprintf(replybuffer, outbufend-replybuffer, "callid: %30s | deletionmark:%4s | created:%12i | proxy:%s\n", ptrkey->s, call->ml_deleted?"yes":"no", (int)call->created, call->created_from);
ADJUSTLEN(printlen,outbufend,replybuffer);
}
rwlock_unlock_r(&m->hashlock);
} else if (len>=strlen(LIST_SESSION) && strncmp(buffer,LIST_SESSION,strlen(LIST_SESSION)) == 0) {
cli_incoming_list_callid(buffer+strlen(LIST_SESSION), len-strlen(LIST_SESSION), m, replybuffer, outbufend);
} else if (len>=strlen(LIST_TOTALS) && strncmp(buffer,LIST_TOTALS,strlen(LIST_TOTALS)) == 0) {
cli_incoming_list_totals(buffer+strlen(LIST_TOTALS), len-strlen(LIST_TOTALS), m, replybuffer, outbufend);
} else {
printlen = snprintf(replybuffer, outbufend-replybuffer, "%s:%s\n", "Unknown 'list' command", buffer);
ADJUSTLEN(printlen,outbufend,replybuffer);
}
}
static void cli_incoming_terminate(char* buffer, int len, struct callmaster* m, char* replybuffer, const char* outbufend) {
str termparam;
struct call* c=0;
int printlen=0;
GHashTableIter iter;
gpointer key, value;
struct call_monologue *ml;
GSList *i;
if (len<=1) {
printlen = snprintf(replybuffer, outbufend-replybuffer, "%s\n", "More parameters required.");
ADJUSTLEN(printlen,outbufend,replybuffer);
return;
}
++buffer; --len; // one space
str_init_len(&termparam,buffer,len);
// --- terminate all calls
if (!str_memcmp(&termparam,"all")) {
while (g_hash_table_size(m->callhash)) {
g_hash_table_iter_init (&iter, m->callhash);
g_hash_table_iter_next (&iter, &key, &value);
c = (struct call*)value;
if (!c) continue;
if (!c->ml_deleted) {
for (i = c->monologues; i; i = i->next) {
ml = i->data;
memset(&ml->terminated,0,sizeof(struct timeval));
gettimeofday(&(ml->terminated), NULL);
ml->term_reason = FORCED;
}
}
call_destroy(c);
}
ilog(LOG_INFO,"All calls terminated by operator.");
printlen = snprintf(replybuffer, outbufend-replybuffer, "%s\n", "All calls terminated by operator.");
ADJUSTLEN(printlen,outbufend,replybuffer);
return;
}
// --- terminate a dedicated call id
c = call_get(&termparam, m);
if (!c) {
printlen = snprintf(replybuffer, outbufend-replybuffer, "\nCall Id not found (%s).\n\n",termparam.s);
ADJUSTLEN(printlen,outbufend,replybuffer);
return;
}
if (!c->ml_deleted) {
for (i = c->monologues; i; i = i->next) {
ml = i->data;
memset(&ml->terminated,0,sizeof(struct timeval));
gettimeofday(&(ml->terminated), NULL);
ml->term_reason = FORCED;
}
}
call_destroy(c);
printlen = snprintf(replybuffer, outbufend-replybuffer, "\nCall Id (%s) successfully terminated by operator.\n\n",termparam.s);
ADJUSTLEN(printlen,outbufend,replybuffer);
ilog(LOG_WARN, "Call Id (%s) successfully terminated by operator.",termparam.s);
rwlock_unlock_w(&c->master_lock);
}
static void cli_incoming(int fd, void *p, uintptr_t u) {
int nfd;
struct sockaddr_in sin;
struct cli *cli = (void *) p;
socklen_t sinl;
static const int BUFLENGTH = 4096*1024;
char replybuffer[BUFLENGTH]; memset(&replybuffer,0,BUFLENGTH);
char* outbuf = replybuffer;
const char* outbufend = replybuffer+BUFLENGTH;
static const int MAXINPUT = 1024;
char inbuf[MAXINPUT]; memset(&inbuf,0,MAXINPUT);
int inlen = 0, readbytes = 0;
int rc=0;
mutex_lock(&cli->lock);
next:
sinl = sizeof(sin);
nfd = accept(fd, (struct sockaddr *) &sin, &sinl);
if (nfd == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
sprintf(replybuffer, "Could currently not accept CLI commands. Reason:%s\n", strerror(errno));
goto cleanup;
}
ilog(LOG_INFO, "Accept error:%s\n", strerror(errno));
goto next;
}
ilog(LOG_INFO, "New cli connection from " DF, DP(sin));
do {
readbytes = read(nfd, inbuf+inlen, MAXINPUT);
if (readbytes == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
ilog(LOG_INFO, "Could currently not read CLI commands. Reason:%s\n", strerror(errno));
goto cleanup;
}
ilog(LOG_INFO, "Could currently not read CLI commands. Reason:%s\n", strerror(errno));
}
inlen += readbytes;
} while (readbytes > 0);
ilog(LOG_INFO, "Got CLI command:%s\n",inbuf);
static const char* LIST = "list";
static const char* TERMINATE = "terminate";
if (inlen>=strlen(LIST) && strncmp(inbuf,LIST,strlen(LIST)) == 0) {
cli_incoming_list(inbuf+strlen(LIST), inlen-strlen(LIST), cli->callmaster, outbuf, outbufend);
} else if (inlen>=strlen(TERMINATE) && strncmp(inbuf,TERMINATE,strlen(TERMINATE)) == 0) {
cli_incoming_terminate(inbuf+strlen(TERMINATE), inlen-strlen(TERMINATE), cli->callmaster, outbuf, outbufend);
} else {
sprintf(replybuffer, "%s:%s\n", "Unknown or incomplete command:", inbuf);
}
do {
rc += write( nfd, (char *)&replybuffer, strlen(replybuffer) );
} while (rc < strlen(replybuffer));
cleanup:
close(nfd);
mutex_unlock(&cli->lock);
}
static void control_closed(int fd, void *p, uintptr_t u) {
abort();
}
struct cli *cli_new(struct poller *p, u_int32_t ip, u_int16_t port, struct callmaster *m) {
struct cli *c;
int fd;
struct sockaddr_in sin;
struct poller_item i;
if (!p || !m)
return NULL;
fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd == -1)
return NULL;
nonblock(fd);
reuseaddr(fd);
ZERO(sin);
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = ip;
sin.sin_port = htons(port);
if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)))
goto fail;
if (listen(fd, 5))
goto fail;
c = obj_alloc0("cli_udp", sizeof(*c), NULL);
c->fd = fd;
c->poller = p;
c->callmaster = m;
mutex_init(&c->lock);
ZERO(i);
i.fd = fd;
i.closed = control_closed;
i.readable = cli_incoming;
i.obj = &c->obj;
if (poller_add_item(p, &i))
goto fail2;
obj_put(c);
return c;
fail2:
obj_put(c);
fail:
close(fd);
return NULL;
}

+ 18
- 0
daemon/cli.h View File

@ -0,0 +1,18 @@
#ifndef CLI_UDP_H_
#define CLI_UDP_H_
#include <netinet/in.h>
struct cli {
struct obj obj;
struct callmaster *callmaster;
int fd;
struct poller *poller;
mutex_t lock;
};
struct cli *cli_new(struct poller *p, u_int32_t ip, u_int16_t port, struct callmaster *m);
#endif /* CLI_UDP_H_ */

+ 1
- 1
daemon/control_ng.c View File

@ -111,7 +111,7 @@ static void control_ng_incoming(struct obj *obj, str *buf, struct sockaddr_in6 *
if (!str_cmp(&cmd, "ping"))
bencode_dictionary_add_string(resp, "result", "pong");
else if (!str_cmp(&cmd, "offer"))
errstr = call_offer_ng(dict, c->callmaster, resp);
errstr = call_offer_ng(dict, c->callmaster, resp, addr);
else if (!str_cmp(&cmd, "answer"))
errstr = call_answer_ng(dict, c->callmaster, resp);
else if (!str_cmp(&cmd, "delete"))


+ 1
- 1
daemon/control_udp.c View File

@ -83,7 +83,7 @@ static void control_udp_incoming(struct obj *obj, str *buf, struct sockaddr_in6
}
if (chrtoupper(out[RE_UDP_UL_CMD][0]) == 'U')
reply = call_update_udp(out, u->callmaster);
reply = call_update_udp(out, u->callmaster, addr);
else if (chrtoupper(out[RE_UDP_UL_CMD][0]) == 'L')
reply = call_lookup_udp(out, u->callmaster);
else if (chrtoupper(out[RE_UDP_DQ_CMD][0]) == 'D')


+ 8
- 0
daemon/log.c View File

@ -57,6 +57,7 @@ static const char* const prio_str[] = {
gboolean _log_stderr = 0;
int _log_facility = LOG_DAEMON;
int _log_facility_cdr = 0;
static GHashTable *__log_limiter;
@ -167,6 +168,13 @@ out:
free(msg);
}
void cdrlog(const char* cdrbuffer) {
int previous;
int mask = LOG_MASK (LOG_INFO);
previous = setlogmask(mask);
syslog(LOG_INFO | _log_facility_cdr, "%s", cdrbuffer);
setlogmask(previous);
}
void log_init() {
mutex_init(&__log_limiter_lock);


+ 2
- 4
daemon/log.h View File

@ -22,6 +22,7 @@ struct log_info {
extern gboolean _log_stderr;
extern int _log_facility;
extern int _log_facility_cdr;
typedef struct _fac_code {
@ -46,14 +47,11 @@ extern unsigned int max_log_line_length;
void log_init(void);
void ilog(int prio, const char *fmt, ...)__attribute__ ((format (printf, 2, 3)));
void cdrlog(const char* cdrbuffer);
#include "obj.h"
INLINE void log_info_clear() {
switch (log_info.e) {
case LOG_INFO_NONE:


+ 33
- 0
daemon/main.c View File

@ -25,6 +25,7 @@
#include "sdp.h"
#include "dtls.h"
#include "call_interfaces.h"
#include "cli.h"
@ -91,6 +92,8 @@ static struct in6_addr udp_listenp;
static u_int16_t udp_listenport;
static struct in6_addr ng_listenp;
static u_int16_t ng_listenport;
static u_int32_t cli_listenp;
static u_int16_t cli_listenport;
static int tos;
static int table = -1;
static int no_fallback;
@ -104,6 +107,7 @@ static int redis_db = -1;
static char *b2b_url;
static enum xmlrpc_format xmlrpc_fmt = XF_SEMS;
static int num_threads;
static int delete_delay = 30;
static void sighandler(gpointer x) {
@ -309,8 +313,10 @@ static void options(int *argc, char ***argv) {
char *listenps = NULL;
char *listenudps = NULL;
char *listenngs = NULL;
char *listencli = NULL;
char *redisps = NULL;
char *log_facility_s = NULL;
char *log_facility_cdr_s = NULL;
int version = 0;
int sip_source = 0;
@ -322,6 +328,7 @@ static void options(int *argc, char ***argv) {
{ "listen-tcp", 'l', 0, G_OPTION_ARG_STRING, &listenps, "TCP port to listen on", "[IP:]PORT" },
{ "listen-udp", 'u', 0, G_OPTION_ARG_STRING, &listenudps, "UDP port to listen on", "[IP46:]PORT" },
{ "listen-ng", 'n', 0, G_OPTION_ARG_STRING, &listenngs, "UDP port to listen on, NG protocol", "[IP46:]PORT" },
{ "listen-cli", 'c', 0, G_OPTION_ARG_STRING, &listencli, "UDP port to listen on, CLI", "[IP46:]PORT" },
{ "tos", 'T', 0, G_OPTION_ARG_INT, &tos, "Default TOS value to set on streams", "INT" },
{ "timeout", 'o', 0, G_OPTION_ARG_INT, &timeout, "RTP timeout", "SECS" },
{ "silent-timeout",'s',0,G_OPTION_ARG_INT, &silent_timeout,"RTP timeout for muted", "SECS" },
@ -334,9 +341,11 @@ static void options(int *argc, char ***argv) {
{ "b2b-url", 'b', 0, G_OPTION_ARG_STRING, &b2b_url, "XMLRPC URL of B2B UA" , "STRING" },
{ "log-level", 'L', 0, G_OPTION_ARG_INT, (void *)&log_level,"Mask log priorities above this level","INT" },
{ "log-facility",0, 0, G_OPTION_ARG_STRING, &log_facility_s, "Syslog facility to use for logging", "daemon|local0|...|local7"},
{ "log-facility-cdr",0, 0, G_OPTION_ARG_STRING, &log_facility_cdr_s, "Syslog facility to use for logging CDRs", "daemon|local0|...|local7"},
{ "log-stderr", 'E', 0, G_OPTION_ARG_NONE, &_log_stderr, "Log on stderr instead of syslog", NULL },
{ "xmlrpc-format",'x', 0, G_OPTION_ARG_INT, &xmlrpc_fmt, "XMLRPC timeout request format to use. 0: SEMS DI, 1: call-id only", "INT" },
{ "num-threads", 0, 0, G_OPTION_ARG_INT, &num_threads, "Number of worker threads to create", "INT" },
{ "delete-delay", 'd', 0, G_OPTION_ARG_INT, &delete_delay, "Delay for deleting a session from memory.", "INT" },
{ "sip-source", 0, 0, G_OPTION_ARG_NONE, &sip_source, "Use SIP source address by default", NULL },
{ "dtls-passive", 0, 0, G_OPTION_ARG_NONE, &dtls_passive_def,"Always prefer DTLS passive role", NULL },
{ NULL, }
@ -378,6 +387,10 @@ static void options(int *argc, char ***argv) {
die("Invalid IP or port (--listen-ng)");
}
if (listencli) {if (parse_ip_port(&cli_listenp, &cli_listenport, listencli))
die("Invalid IP or port (--listen-cli)");
}
if (tos < 0 || tos > 255)
die("Invalid TOS value");
@ -407,6 +420,13 @@ static void options(int *argc, char ***argv) {
}
}
if (log_facility_cdr_s) {
if (!parse_log_facility(log_facility_cdr_s, &_log_facility_cdr)) {
print_available_log_facilities();
die ("Invalid log facility for CDR '%s' (--log-facility-cdr)\n", log_facility_cdr_s);
}
}
if (_log_stderr) {
write_log = log_to_stderr;
max_log_line_length = 0;
@ -548,6 +568,7 @@ void create_everything(struct main_context *ctx) {
struct control_tcp *ct;
struct control_udp *cu;
struct control_ng *cn;
struct cli *cl;
int kfd = -1;
void *dlh;
const char **strp;
@ -589,6 +610,7 @@ no_kernel:
mc.port_max = port_max;
mc.timeout = timeout;
mc.silent_timeout = silent_timeout;
mc.delete_delay = delete_delay;
mc.default_tos = tos;
mc.b2b_url = b2b_url;
mc.fmt = xmlrpc_fmt;
@ -616,6 +638,14 @@ no_kernel:
die("Failed to open UDP control connection port");
}
cl = NULL;
if (cli_listenport) {
callmaster_exclude_port(ctx->m, cli_listenport);
cl = cli_new(ctx->p, cli_listenp, cli_listenport, ctx->m);
if (!cl)
die("Failed to open UDP CLI connection port");
}
if (redis_ip) {
dlh = dlopen(MP_PLUGIN_DIR "/rtpengine-redis.so", RTLD_NOW | RTLD_GLOBAL);
if (!dlh && !g_file_test(MP_PLUGIN_DIR "/rtpengine-redis.so", G_FILE_TEST_IS_REGULAR)
@ -635,6 +665,9 @@ no_kernel:
ctx->m->conf = mc;
callmaster_config_init(ctx->m);
ZERO(ctx->m->totalstats);
ctx->m->totalstats.started = time(NULL);
if (!foreground)
daemonize();
wpidfile();


+ 1
- 0
debian/control View File

@ -22,6 +22,7 @@ Depends: ${misc:Depends},
${shlibs:Depends}
Conflicts: ngcp-mediaproxy-ng-daemon
Replaces: ngcp-mediaproxy-ng-daemon
Recommends: netcat-openbsd | netcat
Description: Proxy for RTP and media streams used in NGCP, userspace part.
This daemon handles the first stages of proxying media streams and talks to
the kernel part of the proxy for eventual high-performance packet forwarding.


+ 3
- 0
debian/ngcp-rtpengine-daemon.default View File

@ -2,6 +2,7 @@ RUN_RTPENGINE=no
LISTEN_TCP=25060
LISTEN_UDP=12222
LISTEN_NG=22222
LISTEN_CLI=9900
# INTERFACES="123.234.345.456"
# INTERFACES="internal/12.23.34.45 external/23.34.45.54"
# INTERFACES="12.23.34.45!23.34.45.56"
@ -19,4 +20,6 @@ TABLE=0
# B2B_URL=http://127.0.0.1:8090/
# LOG_LEVEL=6
# LOG_FACILITY=daemon
# LOG_FACILITY_CDR=daemon
# NUM_THREADS=5
# DELETE_DELAY=30

+ 3
- 0
debian/ngcp-rtpengine-daemon.init View File

@ -55,6 +55,7 @@ fi
[ -z "$LISTEN_TCP" ] || OPTIONS="$OPTIONS --listen-tcp=$LISTEN_TCP"
[ -z "$LISTEN_UDP" ] || OPTIONS="$OPTIONS --listen-udp=$LISTEN_UDP"
[ -z "$LISTEN_NG" ] || OPTIONS="$OPTIONS --listen-ng=$LISTEN_NG"
[ -z "$LISTEN_CLI" ] || OPTIONS="$OPTIONS --listen-cli=$LISTEN_CLI"
[ -z "$TIMEOUT" ] || OPTIONS="$OPTIONS --timeout=$TIMEOUT"
[ -z "$SILENT_TIMEOUT" ] || OPTIONS="$OPTIONS --silent-timeout=$SILENT_TIMEOUT"
[ -z "$PIDFILE" ] || OPTIONS="$OPTIONS --pidfile=$PIDFILE"
@ -68,7 +69,9 @@ fi
OPTIONS="$OPTIONS --table=$TABLE"
[ -z "$LOG_LEVEL" ] || OPTIONS="$OPTIONS --log-level=$LOG_LEVEL"
[ -z "$LOG_FACILITY" ] || OPTIONS="$OPTIONS --log-facility=$LOG_FACILITY"
[ -z "$LOG_FACILITY_CDR" ] || OPTIONS="$OPTIONS --log-facility-cdr=$LOG_FACILITY_CDR"
[ -z "$NUM_THREADS" ] || OPTIONS="$OPTIONS --num-threads=$NUM_THREADS"
[ -z "$DELETE_DELAY" ] || OPTIONS="$OPTIONS --delete-delay=$DELETE_DELAY"
if test "$FORK" = "no" ; then
OPTIONS="$OPTIONS --foreground"
fi


+ 1
- 0
debian/ngcp-rtpengine-daemon.install View File

@ -1 +1,2 @@
daemon/rtpengine /usr/sbin/
utils/rtpengine-ctl /usr/sbin/

+ 15
- 0
el/rtpengine.init View File

@ -78,6 +78,11 @@ build_opts() {
OPTS+=" --listen-ng=$LISTEN_NG"
fi
if [[ -n "$LISTEN_CLI" ]]
then
OPTS+=" --listen-cli=$LISTEN_CLI"
fi
if [[ -n "$TOS" ]]
then
OPTS+=" --tos=$TOS"
@ -132,6 +137,16 @@ build_opts() {
then
OPTS+=" --num-threads=$NUM_THREADS"
fi
if [[ -n "$DELETE_DELAY" ]]
then
OPTS+=" --delete-delay=$DELETE_DELAY"
fi
if [[ -n "$LOG_FACILITY_CDR" ]]
then
OPTS+=" --log-facility-cdr=$LOG_FACILITY_CDR"
fi
}
start() {


+ 3
- 0
el/rtpengine.sysconfig View File

@ -17,6 +17,7 @@ LISTEN_UDP=127.0.0.1:2222 # IP address and port combination for UDP
# control
#LISTEN_NG=127.0.0.1:2223 # IP address and port combination for NG (UDP)
# control
#LISTEN_CLI=127.0.0.1:9900
#
#TOS=184 # (o) TOS value to use in outgoing packets
#TIMEOUT=60 # (o) Number of seconds after which a media stream is
@ -31,7 +32,9 @@ LISTEN_UDP=127.0.0.1:2222 # IP address and port combination for UDP
#
#LOG_LEVEL=6 # Log level to use
#LOG_FACILITY=daemon # Syslog facility to use
#LOG_FACILITY_CDR=daemon # Syslog facility to write CDRs
#NUM_THREADS=5 # How many worker threads to launch
#DELETE_DELAY=30 # Delay to delete session from memory
# The following items are for use with NGCP
#REDIS=127.0.0.1:6379


+ 70
- 0
utils/rtpengine-ctl View File

@ -0,0 +1,70 @@
#!/bin/bash
#
host=127.0.0.1
port=9900
error_rc=255
prgname=${0##*/}
prgdir=${0%$prgname}
showusage() {
echo ""
echo " $0 [ -ip <ipaddress> -port <port> ] <command>"
echo ""
echo " Supported commands are:"
echo ""
echo " list [ numsessions | sessions | session <callid> ]"
echo " numsessions : prints the number of sessions"
echo " sessions : print one-liner session information"
echo " session <callid> : print detail about one session"
echo " totals : print total statistics (does not include current sessions)"
echo ""
echo " terminate [ all | <callid> ]"
echo " all : terminates all current sessions"
echo " <callid> : session is immediately terminated"
echo ""
echo ""
echo " Return Value:"
echo " 0 on success with ouput from server side, other values for failure."
echo ""
exit 0
}
if [ $# -eq 0 ]; then showusage; fi
command -v nc 2>&1 >/dev/null
if [ $? -ne 0 ]; then
echo "Error: $0 requires netcat to be installed."
exit 0
fi
while [ $# -gt 0 ]; do
case $1 in
"-?"|"-help"|"-h")
showusage
;;
"-ip")
shift
if [ $# -gt 0 ]; then
host=$1
else
echo "Missing parameter for option '-ip'" >&2
fi
;;
"-port")
shift
if [ $# -gt 0 ]; then
port=$1
else
echo "Missing parameter for option '-port'" >&2
fi
;;
*)
varargs="$varargs $1"
esac
shift
done
echo -n ${varargs} | nc ${host} ${port}

Loading…
Cancel
Save