diff --git a/.gitreview b/.gitreview new file mode 100644 index 000000000..90ab7e1d1 --- /dev/null +++ b/.gitreview @@ -0,0 +1,4 @@ +[gerrit] +host=gerrit.mgm.sipwise.com +port=29418 +project=rtpengine diff --git a/daemon/call.c b/daemon/call.c index ceb1258bf..34255e1d9 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -146,6 +146,7 @@ const char * get_tag_type_text(enum tag_type t) { } static void determine_handler(struct packet_stream *in, const struct packet_stream *out); +static void __call_media_state_machine(struct call_media *m); static int __k_null(struct rtpengine_srtp *s, struct packet_stream *); static int __k_srtp_encrypt(struct rtpengine_srtp *s, struct packet_stream *); @@ -645,7 +646,7 @@ static int stream_packet(struct stream_fd *sfd, str *s, struct sockaddr_in6 *fsi if (!stun_ret) goto unlock_out; if (stun_ret == 1) { - call_stream_state_machine(stream); + __call_media_state_machine(media); mutex_lock(&stream->in_lock); /* for the jump */ goto kernel_check; } @@ -885,7 +886,7 @@ forward: ret = sendmsg(sink->sfd->fd.fd, &mh, 0); if (ret == -1) { - ret = -errno; + ret = 0; /* temp for address family mismatches */ ilog(LOG_DEBUG,"Error when sending message. Error: %s",strerror(errno)); atomic64_inc(&stream->stats.errors); atomic64_inc(&cm->statsps.errors); @@ -1863,15 +1864,21 @@ static int __num_media_streams(struct call_media *media, unsigned int num_ports) return ret; } -static void __fill_stream(struct packet_stream *ps, const struct endpoint *ep, unsigned int port_off) { - ps->endpoint = *ep; - ps->endpoint.port += port_off; +static void __fill_stream(struct packet_stream *ps, const struct endpoint *epp, unsigned int port_off) { + struct endpoint ep; + + ep = *epp; + ep.port += port_off; + + /* if the endpoint hasn't changed, we do nothing */ + if (PS_ISSET(ps, FILLED) && !memcmp(&ps->advertised_endpoint, &ep, sizeof(ep))) + return; + + ps->endpoint = ep; + ps->advertised_endpoint = ep; /* we reset crypto params whenever the endpoint changes */ - if (PS_ISSET(ps, FILLED) && memcmp(&ps->advertised_endpoint, &ps->endpoint, sizeof(ps->endpoint))) { - crypto_reset(&ps->crypto); - dtls_shutdown(ps); - } - ps->advertised_endpoint = ps->endpoint; + crypto_reset(&ps->crypto); + dtls_shutdown(ps); PS_SET(ps, FILLED); } @@ -1898,6 +1905,13 @@ enum call_stream_state call_stream_state_machine(struct packet_stream *ps) { return CSS_RUNNING; } +static void __call_media_state_machine(struct call_media *m) { + GList *l; + + for (l = m->streams.head; l; l = l->next) + call_stream_state_machine(l->data); +} + static int __init_stream(struct packet_stream *ps) { struct call_media *media = ps->media; struct call *call = ps->call; @@ -2434,11 +2448,14 @@ int monologue_offer_answer(struct call_monologue *other_ml, GQueue *streams, * but also lets endpoints re-negotiate. */ media->protocol = NULL; } + /* default is to leave the protocol unchanged */ + if (!media->protocol) + media->protocol = other_media->protocol; /* allow override of outgoing protocol even if we know it already */ - if (flags && flags->transport_protocol) + /* but only if this is an RTP-based protocol */ + if (flags && flags->transport_protocol + && other_media->protocol && other_media->protocol->rtp) media->protocol = flags->transport_protocol; - else if (!media->protocol) - media->protocol = other_media->protocol; /* copy parameters advertised by the sender of this message */ bf_copy_same(&other_media->media_flags, &sp->sp_flags, @@ -2463,7 +2480,6 @@ int monologue_offer_answer(struct call_monologue *other_ml, GQueue *streams, /* control rtcp-mux */ __rtcp_mux_logic(flags, media, other_media); - /* XXX update ICE if rtcp-mux changes */ /* SDES and DTLS */ __generate_crypto(flags, media, other_media); @@ -2539,6 +2555,7 @@ init: /* we are now ready to fire up ICE if so desired and requested */ ice_update(other_media->ice_agent, sp); + ice_update(media->ice_agent, NULL); /* this is in case rtcp-mux has changed */ } return 0; @@ -3476,7 +3493,15 @@ struct local_interface *get_local_interface(struct callmaster *m, const str *nam if (!name || !name->s) { GQueue *q; q = __interface_list_for_family(m, family); - return q->head ? q->head->data : NULL; + if (q->head) + return q->head->data; + q = __interface_list_for_family(m, AF_INET); + if (q->head) + return q->head->data; + q = __interface_list_for_family(m, AF_INET6); + if (q->head) + return q->head->data; + return NULL; } d.name = *name; diff --git a/daemon/ice.c b/daemon/ice.c index dd5c09495..9ab3404c6 100644 --- a/daemon/ice.c +++ b/daemon/ice.c @@ -317,8 +317,9 @@ void ice_update(struct ice_agent *ag, struct stream_params *sp) { int recalc = 0; unsigned int comps; struct packet_stream *components[MAX_COMPONENTS], *ps; + GQueue *candidates; - if (!ag || !sp) + if (!ag) return; media = ag->media; @@ -326,19 +327,25 @@ void ice_update(struct ice_agent *ag, struct stream_params *sp) { __role_change(ag, MEDIA_ISSET(media, ICE_CONTROLLING)); - /* check for ICE restarts */ - if (ag->ufrag[0].s && sp->ice_ufrag.s && str_cmp_str(&ag->ufrag[0], &sp->ice_ufrag)) - __ice_restart(ag); - else if (ag->pwd[0].s && sp->ice_pwd.s && str_cmp_str(&ag->pwd[0], &sp->ice_pwd)) - __ice_restart(ag); - else if (ag->local_interface != media->interface) - __ice_restart(ag); - - /* update remote info */ - if (sp->ice_ufrag.s) - call_str_cpy(call, &ag->ufrag[0], &sp->ice_ufrag); - if (sp->ice_pwd.s) - call_str_cpy(call, &ag->pwd[0], &sp->ice_pwd); + if (sp) { + /* check for ICE restarts */ + if (ag->ufrag[0].s && sp->ice_ufrag.s && str_cmp_str(&ag->ufrag[0], &sp->ice_ufrag)) + __ice_restart(ag); + else if (ag->pwd[0].s && sp->ice_pwd.s && str_cmp_str(&ag->pwd[0], &sp->ice_pwd)) + __ice_restart(ag); + else if (ag->local_interface != media->interface) + __ice_restart(ag); + + /* update remote info */ + if (sp->ice_ufrag.s) + call_str_cpy(call, &ag->ufrag[0], &sp->ice_ufrag); + if (sp->ice_pwd.s) + call_str_cpy(call, &ag->pwd[0], &sp->ice_pwd); + + candidates = &sp->ice_candidates; + } + else /* this is a dummy update in case rtcp-mux has changed */ + candidates = &ag->remote_candidates; /* get our component streams */ ZERO(components); @@ -349,7 +356,7 @@ void ice_update(struct ice_agent *ag, struct stream_params *sp) { components[1] = NULL; comps = 0; - for (l = sp->ice_candidates.head; l; l = l->next) { + for (l = candidates->head; l; l = l->next) { if (ag->remote_candidates.length >= MAX_ICE_CANDIDATES) { ilog(LOG_WARNING, "Maxmimum number of ICE candidates exceeded"); break; @@ -360,15 +367,16 @@ void ice_update(struct ice_agent *ag, struct stream_params *sp) { /* skip invalid */ if (!cand->component_id || cand->component_id > G_N_ELEMENTS(components)) continue; - /* skip if we don't have a candidate of our own */ ps = components[cand->component_id - 1]; - if (!ps) - continue; - comps = MAX(comps, cand->component_id); + if (ps) /* only count active components */ + comps = MAX(comps, cand->component_id); - /* check for duplicates */ dup = g_hash_table_lookup(ag->candidate_hash, cand); + if (!sp && dup) /* this isn't a real update, so only check pairings */ + goto pair; + + /* check for duplicates */ if (dup) { /* if this is peer reflexive, we've learned it through STUN. * otherwise it's simply one we've seen before. */ @@ -410,6 +418,9 @@ void ice_update(struct ice_agent *ag, struct stream_params *sp) { g_hash_table_insert(ag->foundation_hash, dup, dup); +pair: + if (!ps) + continue; for (k = ag->local_interface->list.head; k; k = k->next) { /* skip duplicates here also */ if (__pair_lookup(ag, dup, k->data)) @@ -559,6 +570,7 @@ void ice_init(void) { static void __fail_pair(struct ice_candidate_pair *pair) { ilog(LOG_DEBUG, "Setting ICE candidate pair "PAIR_FORMAT" as failed", PAIR_FMT(pair)); PAIR_SET(pair, FAILED); + PAIR_CLEAR(pair, IN_PROGRESS); } /* agent must NOT be locked, but call must be locked in R */ @@ -869,7 +881,9 @@ static void __trigger_check(struct ice_candidate_pair *pair) { ilog(LOG_DEBUG, "Triggering check for "PAIR_FORMAT, PAIR_FMT(pair)); mutex_lock(&ag->lock); - PAIR_CLEAR(pair, FAILED); + pair->retransmits = 0; + if (PAIR_CLEAR(pair, FAILED)) + PAIR_CLEAR(pair, IN_PROGRESS); if (ag->triggered.length < 4 * MAX_ICE_CANDIDATES && !PAIR_SET(pair, TRIGGERED)) g_queue_push_tail(&ag->triggered, pair); mutex_unlock(&ag->lock); @@ -1078,17 +1092,17 @@ int ice_request(struct packet_stream *ps, struct sockaddr_in6 *src, struct in6_a ret = 0; - if (attrs->use) { + if (attrs->use && !PAIR_SET(pair, NOMINATED)) { ilog(LOG_DEBUG, "ICE pair "PAIR_FORMAT" has been nominated by peer", PAIR_FMT(pair)); - PAIR_SET(pair, NOMINATED); - mutex_lock(&ag->lock); g_tree_insert(ag->nominated_pairs, pair, pair); - if (PAIR_ISSET(pair, SUCCEEDED)) + if (PAIR_ISSET(pair, SUCCEEDED)) { + PAIR_SET(pair, VALID); g_tree_insert(ag->valid_pairs, pair, pair); + } if (!AGENT_ISSET(ag, CONTROLLING)) ret = __check_valid(ag); @@ -1128,7 +1142,7 @@ static int __check_succeeded_complete(struct ice_agent *ag) { int ice_response(struct packet_stream *ps, struct sockaddr_in6 *src, struct in6_addr *dst, struct stun_attrs *attrs, u_int32_t transaction[3]) { - struct ice_candidate_pair *pair; + struct ice_candidate_pair *pair, *opair; struct ice_agent *ag; struct call_media *media = ps->media; const char *err; @@ -1221,20 +1235,21 @@ int ice_response(struct packet_stream *ps, struct sockaddr_in6 *src, struct in6_ cand = __foundation_lookup(ag, &pair->remote_candidate->foundation, component); if (!cand) continue; - pair = __pair_lookup(ag, cand, ifa); - if (!pair) + opair = __pair_lookup(ag, cand, ifa); + if (!opair) continue; - if (PAIR_ISSET(pair, FAILED)) + if (PAIR_ISSET(opair, FAILED)) continue; - if (!PAIR_CLEAR(pair, FROZEN)) + if (!PAIR_CLEAR(opair, FROZEN)) continue; - ilog(LOG_DEBUG, "Unfreezing related ICE pair "PAIR_FORMAT, PAIR_FMT(pair)); + ilog(LOG_DEBUG, "Unfreezing related ICE pair "PAIR_FORMAT, PAIR_FMT(opair)); } /* if this was previously nominated by the peer, it's now valid */ if (PAIR_ISSET(pair, NOMINATED)) { + PAIR_SET(pair, VALID); g_tree_insert(ag->valid_pairs, pair, pair); if (!AGENT_ISSET(ag, CONTROLLING)) diff --git a/debian/changelog b/debian/changelog index 2983b8e55..ffa836f4b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,93 @@ +ngcp-rtpengine (3.3.0.0+0~mr4.0.0.0) unstable; urgency=low + + [ Sergey Lavrov ] + * [bb14eba] Fix %post/%preun directives. + * [fe5e129] Added rtpengine-ctl and dependency to spec file. + + [ Richard Fuchs ] + * [a0068f4] relax sdes key lifetime validation check + * [caba5be] MT#10583 remember the "created from" address in raw format + * [6e32379] MT#10583 support ipv6 control connection in simulator + * [02d27d5] MT#10583 support b2bua callback to sip proxy address + * [43cd3f5] reset other side's crypto params only in passthru mode + * [2af682b] use SSL_CTX_set_read_ahead to fix for openssl 1.0.1k + * [e24253a] move parse_ip(6)_port into aux.h + * [a81588e] provide convenience function get_log_level() + * [37d98ad] dump DTLS cert and keys + * [57c0a84] add locking to totalstats + * [f544471] fix compiler warnings + * [36c7141] change control_ng_stats into a hash and use locking and atomic ops + * [c0b2f3d] fix graphite code not to leak fds in error cases + * [965d989] static'ize graphite global vars + * [7175a26] decrease sleep time of graphite loop + * [3882285] decrease calls to time() in graphite code + * [de37ac0] use TLS buffer array for temporary strings + * [ee4f2d2] convert ilog() into macro + * [411a888] use atomic ops for stats + * [28c6db9] fix references and locking in CLI + * [20fd255] use UINT64F instead of %llu where appropriate + * [3bc1672] more atomic stats, and fix average length calc + * [fedaadd] remove superfluous \n from log messages + * [1e3f06a] split some perl SRTP stuff into module and add debug script + * [deba231] rename an old MP_ variable to RE_ + * [fb9ed6e] use trial & error approach to guess ROC in case of SRTP auth failures + * [f6dee07] fix initial seqnum in simulator + * [787d90f] rename atomic_uint64 to atomic64 for brevity + * [49328cd] implement atomic64 for non-64-bit platforms + * [da6b6a1] fix compiler warning on 32bit + * [ca149e6] "long" can be 32 bits only and may truncate math + * [b023d6c] update redis mod version to 7 + * [adeb0b3] the log rate limiter must take the prefix into account + * [fb667a8] turn tag and termination texts into array lookups + * [d79c68f] remove some unnecessary memsets + * [a5f7315] string handling fixes and improvements + * [037c6aa] shorter locking in stats loop + * [f7a1594] more descriptive warning for failed kernelizing + * [5fa9902] atomic vars should be volatile + * [c21193a] fix byte stats in kernel module + * [c2ff5c3] MT#9935 understand, learn, remember and report RTP payload types (codecs) + * [b586fa7] fix memory leak + * [65b3f66] use atomic64_t for kernel stats + * [4a97bb1] attempt to work around trickle ice + * [b44bb28] segfault fix + * [015b2a9] legacy tcp protocol fix + * [016f8b3] Rework logging a bit (primarily in NG) + * [91a85e6] fix for skewed stats + * [6173a7a] implement atomic bitfield ops + * [1f7c8a2] remove obsolete HAS_HANDLER flag + * [f224bab] segfault fix if no rtpmap attribute is present + * [26ca844] drop support for glib versions older than 2.30 + * [b83e80c] add makefile dependency to itself + * [956d07d] fix erroneously reported 0.0.0.0 address when bridging from ipv6 + * [f99d6d4] implement full ICE support + * [98e0b6d] update for redis plugin + * [0e4e6f2] revamp and move timeval functions + * [26137d2] move thread loop functions out of main.c + * [5fca71d] fix segfault when parsing server reflexive ICE candidates + * [3520617] remove ice-lite mention from readme + * [9593519] Leave unsupported (non-RTP) protocols alone when translation is requested + + [ Eric Tamme ] + * [b8b17bf] clear crypto for BOTH legs when in passthrough mode + * [506076b] add raddr and rport on all non host type candidates per rfc5245 section-15.1 + + [ Carsten Bock ] + * [9a2da87] Fix randomness source for key generation. + + [ Frederic-Philippe Metz ] + * [2ae0e35] Added functionality to report statistics to graphite + * [7446822] Forgot the files .. + * [61a72b1] Added some more statistics. + * [0ccb11a] Added statistics on control ng interface. + * [794709f] Changed retry behaviour for connecting to graphite server. + + [ Michael Prokop ] + * [fca4500] MT#9127 Bump Standards-Version to 3.9.6 + + [ Sipwise Jenkins Builder ] + + -- Sipwise Jenkins Builder Wed, 18 Mar 2015 14:15:06 +0100 + ngcp-rtpengine (3.3.0.0+0~mr3.8.0.0) unstable; urgency=low [ Richard Fuchs ] diff --git a/el/rtpengine.init b/el/rtpengine.init index 48b2c215c..3ae663dea 100644 --- a/el/rtpengine.init +++ b/el/rtpengine.init @@ -39,7 +39,7 @@ MODULE=0 build_opts() { shopt -s nocasematch - RPMS=`rpm -qa | grep ngcp-rtpengine-kernel` + RPMS=`rpm -qa | grep rtpengine-kernel` if [[ "$KERNEL" == "yes" && -n "$TABLE" && -n "$RPMS" ]] then MODULE=1 diff --git a/el/rtpengine.spec b/el/rtpengine.spec index dba62c65b..493f6a038 100644 --- a/el/rtpengine.spec +++ b/el/rtpengine.spec @@ -1,4 +1,4 @@ -Name: ngcp-rtpengine +Name: rtpengine Version: 2.3.6 Release: 0%{?dist} Summary: The Sipwise NGCP rtpengine @@ -6,14 +6,15 @@ Summary: The Sipwise NGCP rtpengine Group: System Environment/Daemons License: GPLv3 URL: https://github.com/sipwise/rtpengine -Source0: https://github.com/sipwise/rtpengine/archive/%{version}/%{name}-%{version}.tar.gz -Conflicts: %{name}-kernel < %{version} -BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) +Source0: https://github.com/sipwise/rtpengine/archive/mr%{version}/%{name}-%{version}.tar.gz +Conflicts: %{name}-kernel < %{version}-%{release} BuildRequires: gcc make pkgconfig redhat-rpm-config BuildRequires: glib2-devel libcurl-devel openssl-devel pcre-devel BuildRequires: xmlrpc-c-devel zlib-devel -Requires: glibc libcurl openssl pcre xmlrpc-c nmap-ncat +Requires: nc +# Remain compat with other installations +Provides: ngcp-rtpengine = %{version}-%{release} %description @@ -26,11 +27,12 @@ drop-in replacement for any of the other available RTP and media proxies. Summary: NGCP rtpengine in-kernel packet forwarding Group: System Environment/Daemons BuildRequires: gcc make redhat-rpm-config iptables-devel -Requires: iptables iptables-ipv6 ngcp-rtpengine = %{version} -Requires: ngcp-rtpengine-dkms = %{version} +Requires: iptables iptables-ipv6 +Requires: %{name}%{?_isa} = %{version}-%{release} +Requires: %{name}-dkms%{?_isa} = %{version}-%{release} %description kernel -NGCP rtpengine in-kernel packet forwarding +%{summary}. %package dkms @@ -43,7 +45,7 @@ Requires(post): epel-release dkms Requires(preun): epel-release dkms %description dkms -Kernel module for rtpengine in-kernel packet forwarding +%{summary}. %prep @@ -60,16 +62,16 @@ cd .. %install # Install the userspace daemon -install -D -p -m755 daemon/rtpengine %{buildroot}/%{_sbindir}/rtpengine +install -D -p -m755 daemon/%{name} %{buildroot}%{_sbindir}/%{name} # Install CLI (command line interface) -install -D -p -m755 utils/rtpengine-ctl %{buildroot}/%{_sbindir}/rtpengine-ctl +install -D -p -m755 utils/%{name}-ctl %{buildroot}%{_sbindir}/%{name}-ctl ## Install the init.d script and configuration file -install -D -p -m755 el/rtpengine.init \ - %{buildroot}/%{_sysconfdir}/rc.d/init.d/rtpengine -install -D -p -m644 el/rtpengine.sysconfig \ - %{buildroot}/%{_sysconfdir}/sysconfig/rtpengine -mkdir -p %{buildroot}/%{_sharedstatedir}/rtpengine +install -D -p -m755 el/%{name}.init \ + %{buildroot}%{_initrddir}/%{name} +install -D -p -m644 el/%{name}.sysconfig \ + %{buildroot}%{_sysconfdir}/sysconfig/%{name} +mkdir -p %{buildroot}%{_sharedstatedir}/%{name} # Install the iptables plugin install -D -p -m755 iptables-extension/libxt_RTPENGINE.so \ @@ -77,29 +79,24 @@ install -D -p -m755 iptables-extension/libxt_RTPENGINE.so \ ## DKMS module source install install -D -p -m644 kernel-module/Makefile \ - %{buildroot}/%{_usrsrc}/%{name}-%{version}-%{release}/Makefile + %{buildroot}%{_usrsrc}/%{name}-%{version}-%{release}/Makefile install -D -p -m644 kernel-module/xt_RTPENGINE.c \ - %{buildroot}/%{_usrsrc}/%{name}-%{version}-%{release}/xt_RTPENGINE.c + %{buildroot}%{_usrsrc}/%{name}-%{version}-%{release}/xt_RTPENGINE.c install -D -p -m644 kernel-module/xt_RTPENGINE.h \ - %{buildroot}/%{_usrsrc}/%{name}-%{version}-%{release}/xt_RTPENGINE.h -sed "s/__VERSION__/%{version}-%{release}/g" debian/dkms.conf.in > \ - %{buildroot}/%{_usrsrc}/%{name}-%{version}-%{release}/dkms.conf - - -%clean -rm -rf %{buildroot} + %{buildroot}%{_usrsrc}/%{name}-%{version}-%{release}/xt_RTPENGINE.h +sed -i -e "s/__VERSION__/%{version}-%{release}/g;s/ngcp-rtpengine/rtpengine/g" debian/dkms.conf.in +install -D -p -m644 debian/dkms.conf.in %{buildroot}%{_usrsrc}/%{name}-%{version}-%{release}/dkms.conf %pre -/usr/sbin/groupadd -r rtpengine 2> /dev/null || : -/usr/sbin/useradd -r -g rtpengine -s /sbin/nologin -c "rtpengine daemon" \ - -d %{_sharedstatedir}/rtpengine rtpengine \ - 2> /dev/null || : +getent group %{name} >/dev/null || /usr/sbin/groupadd -r %{name} +getent passwd %{name} >/dev/null || /usr/sbin/useradd -r -g %{name} \ + -s /sbin/nologin -c "%{name} daemon" -d %{_sharedstatedir}/%{name} %{name} %post if [ $1 -eq 1 ]; then - /sbin/chkconfig --add rtpengine || : + /sbin/chkconfig --add %{name} || : fi @@ -113,8 +110,8 @@ true %preun if [ $1 = 0 ] ; then - /sbin/service rtpengine stop >/dev/null 2>&1 - /sbin/chkconfig --del rtpengine + /sbin/service %{name} stop >/dev/null 2>&1 + /sbin/chkconfig --del %{name} fi @@ -126,14 +123,14 @@ true %files # Userspace daemon -%{_sbindir}/rtpengine +%{_sbindir}/%{name} # CLI (command line interface) -%{_sbindir}/rtpengine-ctl +%{_sbindir}/%{name}-ctl # init.d script and configuration file -%{_sysconfdir}/rc.d/init.d/rtpengine -%config(noreplace) %{_sysconfdir}/sysconfig/rtpengine -%dir %{_sharedstatedir}/rtpengine +%{_initrddir}/%{name} +%config(noreplace) %{_sysconfdir}/sysconfig/%{name} +%attr(0750,%{name},%{name}) %dir %{_sharedstatedir}/%{name} # Documentation %doc LICENSE README.md el/README.el.md debian/changelog debian/copyright @@ -144,7 +141,7 @@ true %files dkms -%attr(0755,root,root) %{_usrsrc}/%{name}-%{version}-%{release}/ +%{_usrsrc}/%{name}-%{version}-%{release}/ %changelog