[Serdev] Video NAT traversal
Adrian Georgescu
ag at ag-projects.com
Fri Jan 23 13:56:54 UTC 2004
Sounds good!
Is this officially accepted by Maxim? Will this be committed to CVS
main tree?
On 23 Jan 2004, at 14:52, Rodrigo Frez wrote:
> The patch from gbernard works very well with two messenger clients
> behind nat
>
> #################################################################
>
> --- nathelper.c.org Sun Jan 18 22:36:30 2004
> +++ nathelper.c Mon Jan 19 14:23:32 2004
> @@ -49,6 +49,10 @@
> * proxied and ignores sessions with such flag.
> * o Added run-time check for version of command protocol
> * supported by the RTP proxy.
> + * 2004-01-19 o Added support for a second RTP flow (ie VIDEO)
> + * o Added support for RTCP (not tested)
> + * (G. Bernard IPDirections)
> + *
> */
>
> #include "nhelpr_funcs.h"
> @@ -106,7 +110,7 @@
> static int fix_nated_contact_f(struct sip_msg *, char *, char *);
> static int fix_nated_sdp_f(struct sip_msg *, char *, char *);
> static int extract_mediaip(str *, str *);
> -static int extract_mediaport(str *, str *);
> +static int extract_mediaport(str *, str *, str *, char *);
> static int alter_mediaip(struct sip_msg *, str *, str *, str *, int);
> static int alter_mediaport(struct sip_msg *, str *, str *, str *,
> int);
> static char *send_rtpp_command(const struct iovec *, int, int);
> @@ -574,35 +578,59 @@
> }
>
> static int
> -extract_mediaport(str *body, str *mediaport)
> +extract_mediaport(str *body, str *mediaport, str *mediactl, char
> *type)
> {
> char *cp, *cp1;
> int len;
>
> - cp1 = NULL;
> - for (cp = body->s; (len = body->s + body->len - cp) > 0;) {
> - cp1 = ser_memmem(cp, "m=", len, 2);
> - if (cp1 == NULL || cp1[-1] == '\n' || cp1[-1] == '\r')
> - break;
> - cp = cp1 + 2;
> - }
> + cp1 = body->s;
> if (cp1 == NULL) {
> - LOG(L_ERR, "ERROR: extract_mediaport: no `m=' in
> SDP\n");
> + LOG(L_ERR, "ERROR: extract_mediaport: no body\n");
> return -1;
> }
> - mediaport->s = cp1 + 2;
> - mediaport->len = eat_line(mediaport->s, body->s + body->len -
> - mediaport->s) - mediaport->s;
> - trim_len(mediaport->len, mediaport->s, *mediaport);
> -
> - if (mediaport->len < 7 || memcmp(mediaport->s, "audio", 5) != 0
> ||
> - !isspace((int)mediaport->s[5])) {
> - LOG(L_ERR, "ERROR: extract_mediaport: can't parse `m='
> in SDP\n");
> - return -1;
> + while (cp1) {
> + for (cp = cp1; (len = body->s + body->len - cp) > 0;) {
> + cp1 = ser_memmem(cp, "m=", len, 2);
> + if (cp1 == NULL || cp1[-1] == '\n' || cp1[-1]
> ==
> '\r')
> + break;
> + cp = cp1 + 2;
> + }
> + if (cp1 == NULL) {
> + LOG(L_ERR,
> + "ERROR: extract_mediaport: no `m=%s' in
> SDP\n",
> + type);
> + return -1;
> + }
> + cp1 += 2;
> + mediaport->s = cp1;
> + mediaport->len = eat_line(mediaport->s, body->s +
> body->len -
> + mediaport->s) - mediaport->s;
> + trim_len(mediaport->len, mediaport->s, *mediaport);
> +
> + if (!(mediaport->len < 7 || memcmp(mediaport->s, type,
> 5) != 0
> + || !isspace((int)mediaport->s[5]))) break;
> }
> cp = eat_space_end(mediaport->s + 5, mediaport->s +
> mediaport->len);
> mediaport->len = eat_token_end(cp, mediaport->s +
> mediaport->len) - cp;
> mediaport->s = cp;
> + mediactl->len = -1;
> + if (cp1 == NULL) {
> + LOG(L_ERR, "ERROR: extract_mediaport: no rctp port
> found\n");
> + return 1;
> + }
> + for (cp = cp1; (len = body->s + body->len - cp) > 0;) {
> + cp1 = ser_memmem(cp, "a=rtcp:", len, 7);
> + if (cp1 == NULL || cp1[-1] == '\n' || cp1[-1] == '\r')
> + break;
> + cp = cp1 + 7;
> + }
> + if (cp1 != NULL) {
> + cp1 += 7;
> + mediactl->s = cp1;
> + mediactl->len = eat_line(mediactl->s, body->s +
> body->len -
> + mediactl->s) - mediactl->s;
> + trim_len(mediactl->len, mediactl->s, *mediactl);
> + }
> return 1;
> }
>
> @@ -774,7 +802,7 @@
> static int
> unforce_rtp_proxy_f(struct sip_msg* msg, char* str1, char* str2)
> {
> - str callid, from_tag, to_tag;
> + str callid, from_tag, to_tag, tag;
> struct iovec v[4 + 3] = {{"D", 1}, {" ", 1}, {NULL, 0}, {" ",
> 1}, {NULL, 0}, {" ", 1}, {NULL, 0}};
> /* 0 */ /* 1 */ /* 2 */ /* 3 */
> /* 4 */ /* 5 */ /* 6 */
>
> @@ -795,10 +823,26 @@
> LOG(L_ERR, "ERROR: unforce_rtp_proxy: can't get From
> tag\n");
> return -1;
> }
> - STR2IOVEC(callid, v[2]);
> + tag.s = pkg_malloc(callid.len + 6);
> + if (tag.s == NULL) {
> + LOG(L_ERR, "ERROR: type_tag: out of memory\n");
> + return -1;
> + }
> + strcpy(tag.s, "audio-");
> + strncat(tag.s, callid.s, callid.len);
> + tag.len = callid.len + 6;
> + tag.s[tag.len] = (char)0;
> + STR2IOVEC(tag, v[2]);
> STR2IOVEC(from_tag, v[4]);
> STR2IOVEC(to_tag, v[6]);
> send_rtpp_command(v, (to_tag.len > 0) ? 7 : 5, 0);
> + strcpy(tag.s, "video-");
> + strncat(tag.s, callid.s, callid.len);
> + tag.len = callid.len + 6;
> + tag.s[tag.len] = (char)0;
> + STR2IOVEC(tag, v[2]);
> + send_rtpp_command(v, (to_tag.len > 0) ? 7 : 5, 0);
> + pkg_free(tag.s);
>
> return 1;
> }
> @@ -806,10 +850,12 @@
> static int
> force_rtp_proxy_f(struct sip_msg* msg, char* str1, char* str2)
> {
> - str body, body1, oldport, oldip, oldip1, newport, newip;
> - str callid, from_tag, to_tag;
> - int create, port, len;
> + str body, body1, oldport, oldctl, oldvport, oldvctl, oldip,
> oldip1;
> + str newvport, newport, newip;
> + str callid, from_tag, to_tag, tag;
> + int create, port, portv=0, len;
> char buf[16];
> + char fub[16];
> char *cp, *cp1;
> struct lump* anchor;
> struct iovec v[6 + 5] = {{"U", 1}, {" ", 1}, {NULL, 0}, {" ",
> 1}, {NULL, 7}, {" ", 1}, {NULL, 1}, {" ", 1}, {NULL, 0}, {" ", 1},
> {NULL, 0}};
> @@ -868,29 +914,80 @@
> if (extract_mediaip(&body1, &oldip1) == -1) {
> oldip1.len = 0;
> }
> - if (extract_mediaport(&body, &oldport) == -1) {
> - LOG(L_ERR, "ERROR: force_rtp_proxy: can't extract media
> port "
> + if (extract_mediaport(&body, &oldport, &oldctl, "audio") == -1)
> {
> + LOG(L_ERR, "ERROR: force_rtp_proxy: can't extract audio
> port "
> "from the message\n");
> return -1;
> }
> + if (oldctl.len > 0)
> + LOG(L_DBG, "DEBUG: Found Audio RTP/RTCP ports\n");
> + else
> + LOG(L_DBG, "DEBUG: Found Audio RTP port\n");
> + if (extract_mediaport(&body, &oldvport, &oldvctl, "video") ==
> -1) {
> + LOG(L_ERR, "ERROR: force_rtp_proxy: can't extract video
> port "
> + "from the message\n");
> + oldvport.len = oldvctl.len = -1;
> + }
> + if (oldvctl.len > 0)
> + LOG(L_DBG, "DEBUG: Found Video RTP/RTCP ports\n");
> + else if (oldvport.len > 0)
> + LOG(L_DBG, "DEBUG: Found Video RTP port\n");
> newip.s = ip_addr2a(&msg->rcv.src_ip);
> newip.len = strlen(newip.s);
> if (create == 0)
> v[0].iov_base = "L";
> - STR2IOVEC(callid, v[2]);
> + tag.s = pkg_malloc(callid.len + 6);
> + if (tag.s == NULL) {
> + LOG(L_ERR, "ERROR: force_rtpproxy: out of memory\n");
> + return -1;
> + }
> + strcpy(tag.s, "audio-");
> + strncat(tag.s, callid.s, callid.len);
> + tag.len = callid.len + 6;
> + tag.s[tag.len] = (char)0;
> + STR2IOVEC(tag, v[2]);
> STR2IOVEC(newip, v[4]);
> STR2IOVEC(oldport, v[6]);
> STR2IOVEC(from_tag, v[8]);
> STR2IOVEC(to_tag, v[10]);
> + LOG(L_DBG, "DEBUG: Call-ID set to: %s\n", tag.s);
> cp = send_rtpp_command(v, (to_tag.len > 0) ? 11 : 9, 1);
> + pkg_free(tag.s);
> if (cp == NULL)
> return -1;
> + LOG(L_DBG, "DEBUG: New audio port is %s", cp);
> port = atoi(cp);
> - if (port <= 0 || port > 65535)
> + if (port <= 0 || port > 65534)
> return -1;
>
> newport.s = buf;
> newport.len = sprintf(buf, "%d", port);
> +
> + if (oldvport.len > 0) {
> + tag.s = pkg_malloc(callid.len + 6);
> + if (tag.s == NULL) {
> + LOG(L_ERR, "ERROR: force_rtpproxy: out of
> memory\n");
> + return -1;
> + }
> + strcpy(tag.s, "video-");
> + strncat(tag.s, callid.s, callid.len);
> + tag.len = callid.len + 6;
> + tag.s[tag.len] = (char)0;
> + STR2IOVEC(tag, v[2]);
> + STR2IOVEC(oldvport, v[6]);
> + LOG(L_DBG, "DEBUG: Call-ID set to: %s\n", tag.s);
> + cp = send_rtpp_command(v, (to_tag.len > 0) ? 11 : 9,
> 1);
> + pkg_free(tag.s);
> + if (cp == NULL)
> + return -1;
> + LOG(L_DBG, "DEBUG: New video port is %s", cp);
> + portv = atoi(cp);
> + if (portv <= 0 || portv > 65534)
> + return -1;
> + newvport.s = fub;
> + newvport.len = sprintf(fub, "%d", portv);
> + }
> +
> newip.s = ip_addr2a(&msg->rcv.dst_ip);
> newip.len = strlen(newip.s);
>
> @@ -901,6 +998,21 @@
> return -1;
> if (alter_mediaport(msg, &body, &oldport, &newport, 0) == -1)
> return -1;
> + port++;
> + newport.s = buf;
> + newport.len = sprintf(buf, "%d", port);
> + if (oldctl.len > 0 &&
> + alter_mediaport(msg, &body, &oldctl, &newport, 0) ==
> -1)
> + return -1;
> + if (oldvport.len > 0 &&
> + alter_mediaport(msg, &body, &oldvport, &newvport, 0) ==
> -1)
> + return -1;
> + portv++;
> + newvport.s = fub;
> + newvport.len = sprintf(fub, "%d", portv);
> + if (oldvport.len > 0 && oldvctl.len > 0 &&
> + alter_mediaport(msg, &body, &oldvctl, &newvport, 0) ==
> -1)
> + return -1;
>
> cp = pkg_malloc(ANORTPPROXY_LEN * sizeof(char));
> if (cp == NULL) {
>
> #################################################################
> -----Original Message-----
> From: Adrian Georgescu [mailto:ag at ag-projects.com]
> Sent: Viernes, 23 de Enero de 2004 10:43
> To: serdev at lists.iptel.org
> Subject: [Serdev] Video NAT traversal
>
>
> If nobody is bussy with this I am prepared to allocated resources for
> this project.
>
> I will check personally with Maxim but any feed back is appreciated.
>
> ---
> Adrian
>
> _______________________________________________
> Serdev mailing list
> serdev at lists.iptel.org
> http://lists.iptel.org/mailman/listinfo/serdev
>
>
More information about the Serdev
mailing list