[asterisk-commits] file: branch file/rtp_engine r124371 - /team/file/rtp_engine/main/rtp.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Jun 20 15:44:56 CDT 2008


Author: file
Date: Fri Jun 20 15:44:56 2008
New Revision: 124371

URL: http://svn.digium.com/view/asterisk?view=rev&rev=124371
Log:
Goodbye STUN.

Modified:
    team/file/rtp_engine/main/rtp.c

Modified: team/file/rtp_engine/main/rtp.c
URL: http://svn.digium.com/view/asterisk/team/file/rtp_engine/main/rtp.c?view=diff&rev=124371&r1=124370&r2=124371
==============================================================================
--- team/file/rtp_engine/main/rtp.c (original)
+++ team/file/rtp_engine/main/rtp.c Fri Jun 20 15:44:56 2008
@@ -36,6 +36,7 @@
 #include <math.h> 
 
 #include "asterisk/rtp.h"
+#include "asterisk/stun.h"
 #include "asterisk/pbx.h"
 #include "asterisk/frame.h"
 #include "asterisk/channel.h"
@@ -74,7 +75,6 @@
 static int rtcpdebug;			/*!< Are we debugging RTCP? */
 static int rtcpstats;			/*!< Are we debugging RTCP? */
 static int rtcpinterval = RTCP_DEFAULT_INTERVALMS; /*!< Time between rtcp reports in millisecs */
-static int stundebug;			/*!< Are we debugging stun? */
 static struct sockaddr_in rtpdebugaddr;	/*!< Debug packets to/from this host */
 static struct sockaddr_in rtcpdebugaddr;	/*!< Debug RTCP packets to/from this host */
 #ifdef SO_NO_CHECK
@@ -286,422 +286,9 @@
 	int sendfur;
 };
 
-/*!
- * \brief STUN support code
- *
- * This code provides some support for doing STUN transactions.
- * Eventually it should be moved elsewhere as other protocols
- * than RTP can benefit from it - e.g. SIP.
- * STUN is described in RFC3489 and it is based on the exchange
- * of UDP packets between a client and one or more servers to
- * determine the externally visible address (and port) of the client
- * once it has gone through the NAT boxes that connect it to the
- * outside.
- * The simplest request packet is just the header defined in
- * struct stun_header, and from the response we may just look at
- * one attribute, STUN_MAPPED_ADDRESS, that we find in the response.
- * By doing more transactions with different server addresses we
- * may determine more about the behaviour of the NAT boxes, of
- * course - the details are in the RFC.
- *
- * All STUN packets start with a simple header made of a type,
- * length (excluding the header) and a 16-byte random transaction id.
- * Following the header we may have zero or more attributes, each
- * structured as a type, length and a value (whose format depends
- * on the type, but often contains addresses).
- * Of course all fields are in network format.
- */
-
-typedef struct { unsigned int id[4]; } __attribute__((packed)) stun_trans_id;
-
-struct stun_header {
-	unsigned short msgtype;
-	unsigned short msglen;
-	stun_trans_id  id;
-	unsigned char ies[0];
-} __attribute__((packed));
-
-struct stun_attr {
-	unsigned short attr;
-	unsigned short len;
-	unsigned char value[0];
-} __attribute__((packed));
-
-/*
- * The format normally used for addresses carried by STUN messages.
- */
-struct stun_addr {
-	unsigned char unused;
-	unsigned char family;
-	unsigned short port;
-	unsigned int addr;
-} __attribute__((packed));
-
-#define STUN_IGNORE		(0)
-#define STUN_ACCEPT		(1)
-
-/*! \brief STUN message types
- * 'BIND' refers to transactions used to determine the externally
- * visible addresses. 'SEC' refers to transactions used to establish
- * a session key for subsequent requests.
- * 'SEC' functionality is not supported here.
- */
- 
-#define STUN_BINDREQ	0x0001
-#define STUN_BINDRESP	0x0101
-#define STUN_BINDERR	0x0111
-#define STUN_SECREQ	0x0002
-#define STUN_SECRESP	0x0102
-#define STUN_SECERR	0x0112
-
-/*! \brief Basic attribute types in stun messages.
- * Messages can also contain custom attributes (codes above 0x7fff)
- */
-#define STUN_MAPPED_ADDRESS	0x0001
-#define STUN_RESPONSE_ADDRESS	0x0002
-#define STUN_CHANGE_REQUEST	0x0003
-#define STUN_SOURCE_ADDRESS	0x0004
-#define STUN_CHANGED_ADDRESS	0x0005
-#define STUN_USERNAME		0x0006
-#define STUN_PASSWORD		0x0007
-#define STUN_MESSAGE_INTEGRITY	0x0008
-#define STUN_ERROR_CODE		0x0009
-#define STUN_UNKNOWN_ATTRIBUTES	0x000a
-#define STUN_REFLECTED_FROM	0x000b
-
-/*! \brief helper function to print message names */
-static const char *stun_msg2str(int msg)
-{
-	switch (msg) {
-	case STUN_BINDREQ:
-		return "Binding Request";
-	case STUN_BINDRESP:
-		return "Binding Response";
-	case STUN_BINDERR:
-		return "Binding Error Response";
-	case STUN_SECREQ:
-		return "Shared Secret Request";
-	case STUN_SECRESP:
-		return "Shared Secret Response";
-	case STUN_SECERR:
-		return "Shared Secret Error Response";
-	}
-	return "Non-RFC3489 Message";
-}
-
-/*! \brief helper function to print attribute names */
-static const char *stun_attr2str(int msg)
-{
-	switch (msg) {
-	case STUN_MAPPED_ADDRESS:
-		return "Mapped Address";
-	case STUN_RESPONSE_ADDRESS:
-		return "Response Address";
-	case STUN_CHANGE_REQUEST:
-		return "Change Request";
-	case STUN_SOURCE_ADDRESS:
-		return "Source Address";
-	case STUN_CHANGED_ADDRESS:
-		return "Changed Address";
-	case STUN_USERNAME:
-		return "Username";
-	case STUN_PASSWORD:
-		return "Password";
-	case STUN_MESSAGE_INTEGRITY:
-		return "Message Integrity";
-	case STUN_ERROR_CODE:
-		return "Error Code";
-	case STUN_UNKNOWN_ATTRIBUTES:
-		return "Unknown Attributes";
-	case STUN_REFLECTED_FROM:
-		return "Reflected From";
-	}
-	return "Non-RFC3489 Attribute";
-}
-
-/*! \brief here we store credentials extracted from a message */
-struct stun_state {
-	const char *username;
-	const char *password;
-};
-
-static int stun_process_attr(struct stun_state *state, struct stun_attr *attr)
-{
-	if (stundebug)
-		ast_verbose("Found STUN Attribute %s (%04x), length %d\n",
-			    stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len));
-	switch (ntohs(attr->attr)) {
-	case STUN_USERNAME:
-		state->username = (const char *) (attr->value);
-		break;
-	case STUN_PASSWORD:
-		state->password = (const char *) (attr->value);
-		break;
-	default:
-		if (stundebug)
-			ast_verbose("Ignoring STUN attribute %s (%04x), length %d\n", 
-				    stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len));
-	}
-	return 0;
-}
-
-/*! \brief append a string to an STUN message */
-static void append_attr_string(struct stun_attr **attr, int attrval, const char *s, int *len, int *left)
-{
-	int size = sizeof(**attr) + strlen(s);
-	if (*left > size) {
-		(*attr)->attr = htons(attrval);
-		(*attr)->len = htons(strlen(s));
-		memcpy((*attr)->value, s, strlen(s));
-		(*attr) = (struct stun_attr *)((*attr)->value + strlen(s));
-		*len += size;
-		*left -= size;
-	}
-}
-
-/*! \brief append an address to an STUN message */
-static void append_attr_address(struct stun_attr **attr, int attrval, struct sockaddr_in *sin, int *len, int *left)
-{
-	int size = sizeof(**attr) + 8;
-	struct stun_addr *addr;
-	if (*left > size) {
-		(*attr)->attr = htons(attrval);
-		(*attr)->len = htons(8);
-		addr = (struct stun_addr *)((*attr)->value);
-		addr->unused = 0;
-		addr->family = 0x01;
-		addr->port = sin->sin_port;
-		addr->addr = sin->sin_addr.s_addr;
-		(*attr) = (struct stun_attr *)((*attr)->value + 8);
-		*len += size;
-		*left -= size;
-	}
-}
-
-/*! \brief wrapper to send an STUN message */
-static int stun_send(int s, struct sockaddr_in *dst, struct stun_header *resp)
-{
-	return sendto(s, resp, ntohs(resp->msglen) + sizeof(*resp), 0,
-		      (struct sockaddr *)dst, sizeof(*dst));
-}
-
-/*! \brief helper function to generate a random request id */
-static void stun_req_id(struct stun_header *req)
-{
-	int x;
-	for (x = 0; x < 4; x++)
-		req->id.id[x] = ast_random();
-}
-
 size_t ast_rtp_alloc_size(void)
 {
 	return sizeof(struct ast_rtp);
-}
-
-/*! \brief callback type to be invoked on stun responses. */
-typedef int (stun_cb_f)(struct stun_attr *attr, void *arg);
-
-/*! \brief handle an incoming STUN message.
- *
- * Do some basic sanity checks on packet size and content,
- * try to extract a bit of information, and possibly reply.
- * At the moment this only processes BIND requests, and returns
- * the externally visible address of the request.
- * If a callback is specified, invoke it with the attribute.
- */
-static int stun_handle_packet(int s, struct sockaddr_in *src,
-	unsigned char *data, size_t len, stun_cb_f *stun_cb, void *arg)
-{
-	struct stun_header *hdr = (struct stun_header *)data;
-	struct stun_attr *attr;
-	struct stun_state st;
-	int ret = STUN_IGNORE;	
-	int x;
-
-	/* On entry, 'len' is the length of the udp payload. After the
-	 * initial checks it becomes the size of unprocessed options,
-	 * while 'data' is advanced accordingly.
-	 */
-	if (len < sizeof(struct stun_header)) {
-		ast_debug(1, "Runt STUN packet (only %d, wanting at least %d)\n", (int) len, (int) sizeof(struct stun_header));
-		return -1;
-	}
-	len -= sizeof(struct stun_header);
-	data += sizeof(struct stun_header);
-	x = ntohs(hdr->msglen);	/* len as advertised in the message */
-	if (stundebug)
-		ast_verbose("STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), ntohs(hdr->msgtype), x);
-	if (x > len) {
-		ast_debug(1, "Scrambled STUN packet length (got %d, expecting %d)\n", x, (int)len);
-	} else
-		len = x;
-	memset(&st, 0, sizeof(st));
-	while (len) {
-		if (len < sizeof(struct stun_attr)) {
-			ast_debug(1, "Runt Attribute (got %d, expecting %d)\n", (int)len, (int) sizeof(struct stun_attr));
-			break;
-		}
-		attr = (struct stun_attr *)data;
-		/* compute total attribute length */
-		x = ntohs(attr->len) + sizeof(struct stun_attr);
-		if (x > len) {
-			ast_debug(1, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", x, (int)len);
-			break;
-		}
-		if (stun_cb)
-			stun_cb(attr, arg);
-		if (stun_process_attr(&st, attr)) {
-			ast_debug(1, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr));
-			break;
-		}
-		/* Clear attribute id: in case previous entry was a string,
-		 * this will act as the terminator for the string.
-		 */
-		attr->attr = 0;
-		data += x;
-		len -= x;
-	}
-	/* Null terminate any string.
-	 * XXX NOTE, we write past the size of the buffer passed by the
-	 * caller, so this is potentially dangerous. The only thing that
-	 * saves us is that usually we read the incoming message in a
-	 * much larger buffer in the struct ast_rtp
-	 */
-	*data = '\0';
-
-	/* Now prepare to generate a reply, which at the moment is done
-	 * only for properly formed (len == 0) STUN_BINDREQ messages.
-	 */
-	if (len == 0) {
-		unsigned char respdata[1024];
-		struct stun_header *resp = (struct stun_header *)respdata;
-		int resplen = 0;	/* len excluding header */
-		int respleft = sizeof(respdata) - sizeof(struct stun_header);
-
-		resp->id = hdr->id;
-		resp->msgtype = 0;
-		resp->msglen = 0;
-		attr = (struct stun_attr *)resp->ies;
-		switch (ntohs(hdr->msgtype)) {
-		case STUN_BINDREQ:
-			if (stundebug)
-				ast_verbose("STUN Bind Request, username: %s\n", 
-					    st.username ? st.username : "<none>");
-			if (st.username)
-				append_attr_string(&attr, STUN_USERNAME, st.username, &resplen, &respleft);
-			append_attr_address(&attr, STUN_MAPPED_ADDRESS, src, &resplen, &respleft);
-			resp->msglen = htons(resplen);
-			resp->msgtype = htons(STUN_BINDRESP);
-			stun_send(s, src, resp);
-			ret = STUN_ACCEPT;
-			break;
-		default:
-			if (stundebug)
-				ast_verbose("Dunno what to do with STUN message %04x (%s)\n", ntohs(hdr->msgtype), stun_msg2str(ntohs(hdr->msgtype)));
-		}
-	}
-	return ret;
-}
-
-/*! \brief Extract the STUN_MAPPED_ADDRESS from the stun response.
- * This is used as a callback for stun_handle_response
- * when called from ast_stun_request.
- */
-static int stun_get_mapped(struct stun_attr *attr, void *arg)
-{
-	struct stun_addr *addr = (struct stun_addr *)(attr + 1);
-	struct sockaddr_in *sa = (struct sockaddr_in *)arg;
-
-	if (ntohs(attr->attr) != STUN_MAPPED_ADDRESS || ntohs(attr->len) != 8)
-		return 1;	/* not us. */
-	sa->sin_port = addr->port;
-	sa->sin_addr.s_addr = addr->addr;
-	return 0;
-}
-
-/*! \brief Generic STUN request
- * Send a generic stun request to the server specified,
- * possibly waiting for a reply and filling the 'reply' field with
- * the externally visible address. Note that in this case the request
- * will be blocking.
- * (Note, the interface may change slightly in the future).
- *
- * \param s the socket used to send the request
- * \param dst the address of the STUN server
- * \param username if non null, add the username in the request
- * \param answer if non null, the function waits for a response and
- *    puts here the externally visible address.
- * \return 0 on success, other values on error.
- */
-int ast_stun_request(int s, struct sockaddr_in *dst,
-	const char *username, struct sockaddr_in *answer)
-{
-	struct stun_header *req;
-	unsigned char reqdata[1024];
-	int reqlen, reqleft;
-	struct stun_attr *attr;
-	int res = 0;
-	int retry;
-	
-	req = (struct stun_header *)reqdata;
-	stun_req_id(req);
-	reqlen = 0;
-	reqleft = sizeof(reqdata) - sizeof(struct stun_header);
-	req->msgtype = 0;
-	req->msglen = 0;
-	attr = (struct stun_attr *)req->ies;
-	if (username)
-		append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft);
-	req->msglen = htons(reqlen);
-	req->msgtype = htons(STUN_BINDREQ);
-	for (retry = 0; retry < 3; retry++) {	/* XXX make retries configurable */
-		/* send request, possibly wait for reply */
-		unsigned char reply_buf[1024];
-		fd_set rfds;
-		struct timeval to = { 3, 0 };	/* timeout, make it configurable */
-		struct sockaddr_in src;
-		socklen_t srclen;
-
-		res = stun_send(s, dst, req);
-		if (res < 0) {
-			ast_log(LOG_WARNING, "ast_stun_request send #%d failed error %d, retry\n",
-				retry, res);
-			continue;
-		}
-		if (answer == NULL)
-			break;
-		FD_ZERO(&rfds);
-		FD_SET(s, &rfds);
-		res = ast_select(s + 1, &rfds, NULL, NULL, &to);
-		if (res <= 0)	/* timeout or error */
-			continue;
-		bzero(&src, sizeof(src));
-		srclen = sizeof(src);
-		/* XXX pass -1 in the size, because stun_handle_packet might
-		 * write past the end of the buffer.
-		 */
-		res = recvfrom(s, reply_buf, sizeof(reply_buf) - 1,
-			0, (struct sockaddr *)&src, &srclen);
-		if (res < 0) {
-			ast_log(LOG_WARNING, "ast_stun_request recvfrom #%d failed error %d, retry\n",
-				retry, res);
-			continue;
-		}
-		bzero(answer, sizeof(struct sockaddr_in));
-		stun_handle_packet(s, &src, reply_buf, res,
-			stun_get_mapped, answer);
-		res = 0; /* signal regular exit */
-		break;
-	}
-	return res;
-}
-
-/*! \brief send a STUN BIND request to the given destination.
- * Optionally, add a username if specified.
- */
-void ast_rtp_stun_request(struct ast_rtp *rtp, struct sockaddr_in *suggestion, const char *username)
-{
-	ast_stun_request(rtp->s, suggestion, username, NULL);
 }
 
 /*! \brief List of current sessions */
@@ -1586,11 +1173,11 @@
 	version = (seqno & 0xC0000000) >> 30;
 	if (!version) {
 		/* If the two high bits are 0, this might be a
-		 * STUN message, so process it. stun_handle_packet()
-		 * answers to requests, and it returns STUN_ACCEPT
+		 * STUN message, so process it. ast_stun_handle_packet()
+		 * answers to requests, and it returns AST_STUN_ACCEPT
 		 * if the request is valid.
 		 */
-		if ((stun_handle_packet(rtp->s, &sin, rtp->rawdata + AST_FRIENDLY_OFFSET, res, NULL, NULL) == STUN_ACCEPT) &&
+		if ((ast_stun_handle_packet(rtp->s, &sin, rtp->rawdata + AST_FRIENDLY_OFFSET, res, NULL, NULL) == AST_STUN_ACCEPT) &&
 			(!rtp->them.sin_port && !rtp->them.sin_addr.s_addr)) {
 			memcpy(&rtp->them, &sin, sizeof(rtp->them));
 		}
@@ -4585,68 +4172,14 @@
 	return CLI_SUCCESS;
 }
 
-static char *handle_cli_stun_debug_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
-	switch (cmd) {
-	case CLI_INIT:
-		e->command = "stun debug [off]";
-		e->usage =
-			"Usage: stun debug [off]\n"
-			"       Enable/Disable STUN (Simple Traversal of UDP through NATs)\n"
-			"       debugging\n";
-		return NULL;
-	case CLI_GENERATE:
-		return NULL;
-	}
-
-	if (a->argc < 2 || a->argc > 3)
-		return CLI_SHOWUSAGE;
-	if (a->argc == 3 && strncasecmp(a->argv[2], "off", 3))
-		return CLI_SHOWUSAGE;
-
-	stundebug = (a->argc == 3) ? 0 : 1;
-	ast_cli(a->fd, "STUN Debugging %s\n", stundebug ? "Enabled" : "Disabled");
-	return CLI_SUCCESS;
-}
-
-static char *handle_cli_stun_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
-	switch (cmd) {
-	case CLI_INIT:
-		e->command = "stun set debug {on|off}";
-		e->usage =
-			"Usage: stun set debug {on|off}\n"
-			"       Enable/Disable STUN (Simple Traversal of UDP through NATs)\n"
-			"       debugging\n";
-		return NULL;
-	case CLI_GENERATE:
-		return NULL;
-	}
-
-	if (a->argc != e->args)
-		return CLI_SHOWUSAGE;
-
-	if (!strncasecmp(a->argv[e->args-1], "on", 2))
-		stundebug = 1;
-	else if (!strncasecmp(a->argv[e->args-1], "off", 3))
-		stundebug = 0;
-	else
-		return CLI_SHOWUSAGE;
-
-	ast_cli(a->fd, "STUN Debugging %s\n", stundebug ? "Enabled" : "Disabled");
-	return CLI_SUCCESS;
-}
-
 static struct ast_cli_entry cli_rtp_debug_deprecated = AST_CLI_DEFINE(handle_cli_rtp_debug_deprecated,  "Enable/Disable RTP debugging");
 static struct ast_cli_entry cli_rtcp_debug_deprecated = AST_CLI_DEFINE(handle_cli_rtcp_debug_deprecated, "Enable/Disable RTCP debugging");
 static struct ast_cli_entry cli_rtcp_stats_deprecated = AST_CLI_DEFINE(handle_cli_rtcp_stats_deprecated, "Enable/Disable RTCP stats");
-static struct ast_cli_entry cli_stun_debug_deprecated = AST_CLI_DEFINE(handle_cli_stun_debug_deprecated, "Enable/Disable STUN debugging");
 
 static struct ast_cli_entry cli_rtp[] = {
 	AST_CLI_DEFINE(handle_cli_rtp_set_debug,  "Enable/Disable RTP debugging", .deprecate_cmd = &cli_rtp_debug_deprecated),
 	AST_CLI_DEFINE(handle_cli_rtcp_set_debug, "Enable/Disable RTCP debugging", .deprecate_cmd = &cli_rtcp_debug_deprecated),
 	AST_CLI_DEFINE(handle_cli_rtcp_set_stats, "Enable/Disable RTCP stats", .deprecate_cmd = &cli_rtcp_stats_deprecated),
-	AST_CLI_DEFINE(handle_cli_stun_set_debug, "Enable/Disable STUN debugging", .deprecate_cmd = &cli_stun_debug_deprecated),
 };
 
 static int __ast_rtp_reload(int reload)




More information about the asterisk-commits mailing list