aboutsummaryrefslogtreecommitdiffstats
path: root/main
diff options
context:
space:
mode:
authorrizzo <rizzo@f38db490-d61c-443f-a65b-d21fe96a405b>2007-07-11 16:24:35 +0000
committerrizzo <rizzo@f38db490-d61c-443f-a65b-d21fe96a405b>2007-07-11 16:24:35 +0000
commit4ea8cdb08addc2b92d5aea746c05cf13b5da92dc (patch)
treebeabed287baae21b973f865e98bf62607d524810 /main
parent13e34e0fa90fbcf6fa455a70dae7f7ea5fa0778a (diff)
add a bit of documentation on what the stun code in rtp.c does
(which is very little, at the moment). Eventually, when the functionality is extended, the changes can be merged back to 1.4. At the moment this is pointless. Note, this change is whitespace only. git-svn-id: http://svn.digium.com/svn/asterisk/trunk@74571 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'main')
-rw-r--r--main/rtp.c61
1 files changed, 60 insertions, 1 deletions
diff --git a/main/rtp.c b/main/rtp.c
index ab55a0590..01f1b078c 100644
--- a/main/rtp.c
+++ b/main/rtp.c
@@ -237,10 +237,34 @@ struct ast_rtcp {
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;
-/* XXX Maybe stun belongs in another file if it ever has use outside of RTP */
struct stun_header {
unsigned short msgtype;
unsigned short msglen;
@@ -254,6 +278,9 @@ struct stun_attr {
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;
@@ -264,6 +291,13 @@ struct stun_addr {
#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
@@ -271,6 +305,9 @@ struct stun_addr {
#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
@@ -283,6 +320,7 @@ struct stun_addr {
#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) {
@@ -302,6 +340,7 @@ static const char *stun_msg2str(int msg)
return "Non-RFC3489 Message";
}
+/*! \brief helper function to print attribute names */
static const char *stun_attr2str(int msg)
{
switch (msg) {
@@ -331,6 +370,7 @@ static const char *stun_attr2str(int msg)
return "Non-RFC3489 Attribute";
}
+/*! \brief here we store credentials extracted from a message */
struct stun_state {
const char *username;
const char *password;
@@ -356,6 +396,7 @@ static int stun_process_attr(struct stun_state *state, struct stun_attr *attr)
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);
@@ -369,6 +410,7 @@ static void append_attr_string(struct stun_attr **attr, int attrval, const char
}
}
+/*! \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;
@@ -387,12 +429,14 @@ static void append_attr_address(struct stun_attr **attr, int attrval, struct soc
}
}
+/*! \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;
@@ -405,6 +449,9 @@ size_t ast_rtp_alloc_size(void)
return sizeof(struct ast_rtp);
}
+/*! \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)
{
struct stun_header *req;
@@ -426,6 +473,13 @@ void ast_rtp_stun_request(struct ast_rtp *rtp, struct sockaddr_in *suggestion, c
stun_send(rtp->s, suggestion, req);
}
+/*! \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.
+ */
static int stun_handle_packet(int s, struct sockaddr_in *src, unsigned char *data, size_t len)
{
struct stun_header *resp, *hdr = (struct stun_header *)data;
@@ -1259,6 +1313,11 @@ struct ast_frame *ast_rtp_read(struct ast_rtp *rtp)
/* Check RTP version */
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
+ * if the request is valid.
+ */
if ((stun_handle_packet(rtp->s, &sin, rtp->rawdata + AST_FRIENDLY_OFFSET, res) == STUN_ACCEPT) &&
(!rtp->them.sin_port && !rtp->them.sin_addr.s_addr)) {
memcpy(&rtp->them, &sin, sizeof(rtp->them));