[Serdev] Video NAT traversal
Rodrigo Frez
rodrigo at frez.cl
Fri Jan 23 13:52:25 UTC 2004
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