Main Page | Modules | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

STUN code
[Core Library]


Data Structures

struct  switch_stun_packet_header_t
struct  switch_stun_packet_attribute_t
struct  switch_stun_packet_t
struct  switch_stun_ip_t

Defines

#define SWITCH_STUN_DEFAULT_PORT   3478
#define SWITCH_STUN_PACKET_MIN_LEN   20
#define SWITCH_STUN_ATTRIBUTE_MIN_LEN   8
#define switch_stun_attribute_padded_length(attribute)   ((uint16_t)(attribute->length + (sizeof(uint32_t)-1)) & ~sizeof(uint32_t))
 Obtain the padded length of an attribute's value.
#define switch_stun_packet_first_attribute(packet, attribute)   attribute = (switch_stun_packet_attribute_t *)(&packet->first_attribute);
 set a switch_stun_packet_attribute_t pointer to point at the first attribute in a packet
#define switch_stun_packet_next_attribute(attribute, end)   (attribute && (attribute = (switch_stun_packet_attribute_t *) (attribute->value + switch_stun_attribute_padded_length(attribute))) && ((void *)attribute < end) && attribute->length && ((void *)(attribute + switch_stun_attribute_padded_length(attribute)) < end))
 Increment an attribute pointer to the next attribute in it's packet.
#define switch_stun_packet_length(packet)   ntohs(packet->header.length) + (sizeof(switch_stun_packet_header_t))
 Obtain the correct length in bytes of a stun packet.

Enumerations

enum  switch_stun_message_t {
  SWITCH_STUN_BINDING_REQUEST = 0x0001, SWITCH_STUN_BINDING_RESPONSE = 0x0101, SWITCH_STUN_BINDING_ERROR_RESPONSE = 0x0111, SWITCH_STUN_SHARED_SECRET_REQUEST = 0x0002,
  SWITCH_STUN_SHARED_SECRET_RESPONSE = 0x0102, SWITCH_STUN_SHARED_SECRET_ERROR_RESPONSE = 0x0112, SWITCH_STUN_ALLOCATE_REQUEST = 0x0003, SWITCH_STUN_ALLOCATE_RESPONSE = 0x0103,
  SWITCH_STUN_ALLOCATE_ERROR_RESPONSE = 0x0113, SWITCH_STUN_SEND_REQUEST = 0x0004, SWITCH_STUN_SEND_RESPONSE = 0x0104, SWITCH_STUN_SEND_ERROR_RESPONSE = 0x0114,
  SWITCH_STUN_DATA_INDICATION = 0x0115
}
enum  switch_stun_attribute_t {
  SWITCH_STUN_ATTR_MAPPED_ADDRESS = 0x0001, SWITCH_STUN_ATTR_RESPONSE_ADDRESS = 0x0002, SWITCH_STUN_ATTR_CHANGE_REQUEST = 0x0003, SWITCH_STUN_ATTR_SOURCE_ADDRESS = 0x0004,
  SWITCH_STUN_ATTR_CHANGED_ADDRESS = 0x0005, SWITCH_STUN_ATTR_USERNAME = 0x0006, SWITCH_STUN_ATTR_PASSWORD = 0x0007, SWITCH_STUN_ATTR_MESSAGE_INTEGRITY = 0x0008,
  SWITCH_STUN_ATTR_ERROR_CODE = 0x0009, SWITCH_STUN_ATTR_UNKNOWN_ATTRIBUTES = 0x000a, SWITCH_STUN_ATTR_REFLECTED_FROM = 0x000b, SWITCH_STUN_ATTR_TRANSPORT_PREFERENCES = 0x000c,
  SWITCH_STUN_ATTR_LIFETIME = 0x000d, SWITCH_STUN_ATTR_ALTERNATE_SERVER = 0x000e, SWITCH_STUN_ATTR_MAGIC_COOKIE = 0x000f, SWITCH_STUN_ATTR_BANDWIDTH = 0x0010,
  SWITCH_STUN_ATTR_DESTINATION_ADDRESS = 0x0011, SWITCH_STUN_ATTR_SOURCE_ADDRESS2 = 0x0012, SWITCH_STUN_ATTR_DATA = 0x0013, SWITCH_STUN_ATTR_OPTIONS = 0x8001
}
enum  switch_stun_error_t {
  SWITCH_STUN_ERROR_BAD_REQUEST = 400, SWITCH_STUN_ERROR_UNAUTHORIZED = 401, SWITCH_STUN_ERROR_UNKNOWN_ATTRIBUTE = 420, SWITCH_STUN_ERROR_STALE_CREDENTIALS = 430,
  SWITCH_STUN_ERROR_INTEGRITY_CHECK_FAILURE = 431, SWITCH_STUN_ERROR_MISSING_USERNAME = 432, SWITCH_STUN_ERROR_USE_TLS = 433, SWITCH_STUN_ERROR_SERVER_ERROR = 500,
  SWITCH_STUN_ERROR_GLOBAL_FAILURE = 600
}
enum  switch_stun_type_t { SWITCH_STUN_TYPE_PACKET_TYPE, SWITCH_STUN_TYPE_ATTRIBUTE, SWITCH_STUN_TYPE_ERROR }

Functions

void switch_stun_random_string (char *buf, uint16_t len, char *set)
 Writes random characters into a buffer.
switch_stun_packet_tswitch_stun_packet_parse (uint8_t *buf, uint32_t len)
 Prepare a raw packet for parsing.
const char * switch_stun_value_to_name (int32_t type, uint32_t value)
 Obtain a printable string form of a given value.
uint8_t switch_stun_packet_attribute_get_mapped_address (switch_stun_packet_attribute_t *attribute, char *ipstr, uint16_t *port)
 Extract a mapped address (IP:PORT) from a packet attribute.
char * switch_stun_packet_attribute_get_username (switch_stun_packet_attribute_t *attribute, char *username, uint16_t len)
 Extract a username from a packet attribute.
switch_stun_packet_tswitch_stun_packet_build_header (switch_stun_message_t type, char *id, uint8_t *buf)
 Prepare a new outbound packet of a certian type and id.
uint8_t switch_stun_packet_attribute_add_username (switch_stun_packet_t *packet, char *username, uint16_t ulen)
 Add a username packet attribute.
uint8_t switch_stun_packet_attribute_add_binded_address (switch_stun_packet_t *packet, char *ipstr, uint16_t port)
 Add a binded address packet attribute.
switch_status_t switch_stun_lookup (char **ip, switch_port_t *port, char *stunip, switch_port_t stunport, char **err, switch_memory_pool_t *pool)
 Perform a stun lookup.


Define Documentation

#define SWITCH_STUN_ATTRIBUTE_MIN_LEN   8
 

#define switch_stun_attribute_padded_length attribute   )     ((uint16_t)(attribute->length + (sizeof(uint32_t)-1)) & ~sizeof(uint32_t))
 

Obtain the padded length of an attribute's value.

Parameters:
attribute the attribute
Returns:
the padded size in bytes

#define SWITCH_STUN_DEFAULT_PORT   3478
 

#define switch_stun_packet_first_attribute packet,
attribute   )     attribute = (switch_stun_packet_attribute_t *)(&packet->first_attribute);
 

set a switch_stun_packet_attribute_t pointer to point at the first attribute in a packet

Parameters:
packet the packet in question
attribute the pointer to set up

#define switch_stun_packet_length packet   )     ntohs(packet->header.length) + (sizeof(switch_stun_packet_header_t))
 

Obtain the correct length in bytes of a stun packet.

Parameters:
packet the packet in question
Returns:
the size in bytes (host order) of the entire packet

#define SWITCH_STUN_PACKET_MIN_LEN   20
 

#define switch_stun_packet_next_attribute attribute,
end   )     (attribute && (attribute = (switch_stun_packet_attribute_t *) (attribute->value + switch_stun_attribute_padded_length(attribute))) && ((void *)attribute < end) && attribute->length && ((void *)(attribute + switch_stun_attribute_padded_length(attribute)) < end))
 

Increment an attribute pointer to the next attribute in it's packet.

Parameters:
attribute the pointer to increment
end pointer to the end of the buffer
Returns:
true or false depending on if there are any more attributes


Enumeration Type Documentation

enum switch_stun_attribute_t
 

Enumeration values:
SWITCH_STUN_ATTR_MAPPED_ADDRESS 
SWITCH_STUN_ATTR_RESPONSE_ADDRESS 
SWITCH_STUN_ATTR_CHANGE_REQUEST 
SWITCH_STUN_ATTR_SOURCE_ADDRESS 
SWITCH_STUN_ATTR_CHANGED_ADDRESS 
SWITCH_STUN_ATTR_USERNAME 
SWITCH_STUN_ATTR_PASSWORD 
SWITCH_STUN_ATTR_MESSAGE_INTEGRITY 
SWITCH_STUN_ATTR_ERROR_CODE 
SWITCH_STUN_ATTR_UNKNOWN_ATTRIBUTES 
SWITCH_STUN_ATTR_REFLECTED_FROM 
SWITCH_STUN_ATTR_TRANSPORT_PREFERENCES 
SWITCH_STUN_ATTR_LIFETIME 
SWITCH_STUN_ATTR_ALTERNATE_SERVER 
SWITCH_STUN_ATTR_MAGIC_COOKIE 
SWITCH_STUN_ATTR_BANDWIDTH 
SWITCH_STUN_ATTR_DESTINATION_ADDRESS 
SWITCH_STUN_ATTR_SOURCE_ADDRESS2 
SWITCH_STUN_ATTR_DATA 
SWITCH_STUN_ATTR_OPTIONS 
00060              {
00061         SWITCH_STUN_ATTR_MAPPED_ADDRESS = 0x0001,       /* Address */
00062         SWITCH_STUN_ATTR_RESPONSE_ADDRESS = 0x0002,     /* Address */
00063         SWITCH_STUN_ATTR_CHANGE_REQUEST = 0x0003,       /* UInt32 */
00064         SWITCH_STUN_ATTR_SOURCE_ADDRESS = 0x0004,       /* Address */
00065         SWITCH_STUN_ATTR_CHANGED_ADDRESS = 0x0005,      /* Address */
00066         SWITCH_STUN_ATTR_USERNAME = 0x0006,     /* ByteString, multiple of 4 bytes */
00067         SWITCH_STUN_ATTR_PASSWORD = 0x0007,     /* ByteString, multiple of 4 bytes */
00068         SWITCH_STUN_ATTR_MESSAGE_INTEGRITY = 0x0008,    /* ByteString, 20 bytes */
00069         SWITCH_STUN_ATTR_ERROR_CODE = 0x0009,   /* ErrorCode */
00070         SWITCH_STUN_ATTR_UNKNOWN_ATTRIBUTES = 0x000a,   /* UInt16List */
00071         SWITCH_STUN_ATTR_REFLECTED_FROM = 0x000b,       /* Address */
00072         SWITCH_STUN_ATTR_TRANSPORT_PREFERENCES = 0x000c,        /* TransportPrefs */
00073         SWITCH_STUN_ATTR_LIFETIME = 0x000d,     /* UInt32 */
00074         SWITCH_STUN_ATTR_ALTERNATE_SERVER = 0x000e,     /* Address */
00075         SWITCH_STUN_ATTR_MAGIC_COOKIE = 0x000f, /* ByteString, 4 bytes */
00076         SWITCH_STUN_ATTR_BANDWIDTH = 0x0010,    /* UInt32 */
00077         SWITCH_STUN_ATTR_DESTINATION_ADDRESS = 0x0011,  /* Address */
00078         SWITCH_STUN_ATTR_SOURCE_ADDRESS2 = 0x0012,      /* Address */
00079         SWITCH_STUN_ATTR_DATA = 0x0013, /* ByteString */
00080         SWITCH_STUN_ATTR_OPTIONS = 0x8001       /* UInt32 */
00081 } switch_stun_attribute_t;

enum switch_stun_error_t
 

Enumeration values:
SWITCH_STUN_ERROR_BAD_REQUEST 
SWITCH_STUN_ERROR_UNAUTHORIZED 
SWITCH_STUN_ERROR_UNKNOWN_ATTRIBUTE 
SWITCH_STUN_ERROR_STALE_CREDENTIALS 
SWITCH_STUN_ERROR_INTEGRITY_CHECK_FAILURE 
SWITCH_STUN_ERROR_MISSING_USERNAME 
SWITCH_STUN_ERROR_USE_TLS 
SWITCH_STUN_ERROR_SERVER_ERROR 
SWITCH_STUN_ERROR_GLOBAL_FAILURE 

enum switch_stun_message_t
 

Enumeration values:
SWITCH_STUN_BINDING_REQUEST 
SWITCH_STUN_BINDING_RESPONSE 
SWITCH_STUN_BINDING_ERROR_RESPONSE 
SWITCH_STUN_SHARED_SECRET_REQUEST 
SWITCH_STUN_SHARED_SECRET_RESPONSE 
SWITCH_STUN_SHARED_SECRET_ERROR_RESPONSE 
SWITCH_STUN_ALLOCATE_REQUEST 
SWITCH_STUN_ALLOCATE_RESPONSE 
SWITCH_STUN_ALLOCATE_ERROR_RESPONSE 
SWITCH_STUN_SEND_REQUEST 
SWITCH_STUN_SEND_RESPONSE 
SWITCH_STUN_SEND_ERROR_RESPONSE 
SWITCH_STUN_DATA_INDICATION 

enum switch_stun_type_t
 

Enumeration values:
SWITCH_STUN_TYPE_PACKET_TYPE 
SWITCH_STUN_TYPE_ATTRIBUTE 
SWITCH_STUN_TYPE_ERROR 
00095              {
00096         SWITCH_STUN_TYPE_PACKET_TYPE,
00097         SWITCH_STUN_TYPE_ATTRIBUTE,
00098         SWITCH_STUN_TYPE_ERROR
00099 } switch_stun_type_t;


Function Documentation

switch_status_t switch_stun_lookup char **  ip,
switch_port_t port,
char *  stunip,
switch_port_t  stunport,
char **  err,
switch_memory_pool_t pool
 

Perform a stun lookup.

Parameters:
ip the local ip to use (replaced with stun results)
port the local port to use (replaced with stun results)
stunip the ip of the stun server
stunport the port of the stun server
err a pointer to describe errors
pool the memory pool to use
Returns:
SUCCESS or FAIL
00433 {
00434         switch_sockaddr_t *local_addr = NULL, *remote_addr = NULL, *from_addr = NULL;
00435         switch_socket_t *sock = NULL;
00436         uint8_t buf[260] = { 0 };
00437         uint8_t *start = buf;
00438         void *end_buf;
00439         switch_stun_packet_t *packet;
00440         switch_stun_packet_attribute_t *attr;
00441         switch_size_t bytes = 0;
00442         char username[33] = { 0 };
00443         char rip[16] = { 0 };
00444         uint16_t rport = 0;
00445         switch_time_t started = 0;
00446         unsigned int elapsed = 0;
00447         int funny = 0;
00448         int size = sizeof(buf);
00449 
00450         switch_assert(err);
00451 
00452         if (!strcmp(*err, "funny")) {
00453                 funny = 1;
00454         }
00455 
00456         *err = "Success";
00457 
00458         switch_sockaddr_info_get(&from_addr, NULL, SWITCH_UNSPEC, 0, 0, pool);
00459 
00460         if (switch_sockaddr_info_get(&local_addr, *ip, SWITCH_UNSPEC, *port, 0, pool) != SWITCH_STATUS_SUCCESS) {
00461                 *err = "Local Address Error!";
00462                 return SWITCH_STATUS_FALSE;
00463         }
00464 
00465         if (switch_sockaddr_info_get(&remote_addr, stunip, SWITCH_UNSPEC, stunport, 0, pool) != SWITCH_STATUS_SUCCESS) {
00466                 *err = "Remote Address Error!";
00467                 return SWITCH_STATUS_FALSE;
00468         }
00469 
00470         if (switch_socket_create(&sock, AF_INET, SOCK_DGRAM, 0, pool) != SWITCH_STATUS_SUCCESS) {
00471                 *err = "Socket Error!";
00472                 return SWITCH_STATUS_FALSE;
00473         }
00474 
00475         if (switch_socket_bind(sock, local_addr) != SWITCH_STATUS_SUCCESS) {
00476                 *err = "Bind Error!";
00477                 return SWITCH_STATUS_FALSE;
00478         }
00479 
00480         if (funny) {
00481                 *start++ = 0;
00482                 *start++ = 0;
00483                 *start++ = 0x22;
00484                 *start++ = 0x22;
00485         }
00486 
00487         switch_socket_opt_set(sock, SWITCH_SO_NONBLOCK, TRUE);
00488         packet = switch_stun_packet_build_header(SWITCH_STUN_BINDING_REQUEST, NULL, start);
00489         switch_stun_random_string(username, 32, NULL);
00490         switch_stun_packet_attribute_add_username(packet, username, 32);
00491         bytes = switch_stun_packet_length(packet);
00492 
00493         if (funny) {
00494                 packet = (switch_stun_packet_t *) buf;
00495                 bytes += 4;
00496                 buf[bytes++] = 0;
00497                 buf[bytes++] = 0;
00498                 buf[bytes++] = 0;
00499                 buf[bytes++] = 0;
00500         }
00501         
00502         switch_socket_sendto(sock, remote_addr, 0, (void *) packet, &bytes);
00503         started = switch_timestamp_now();
00504 
00505         *ip = NULL;
00506         *port = 0;
00507 
00508 
00509         for (;;) {
00510                 bytes = sizeof(buf);
00511                 if (switch_socket_recvfrom(from_addr, sock, 0, (char *) &buf, &bytes) == SWITCH_STATUS_SUCCESS && bytes > 0) {
00512                         break;
00513                 }
00514 
00515                 if ((elapsed = (unsigned int) ((switch_timestamp_now() - started) / 1000)) > 5000) {
00516                         *err = "Timeout";
00517                         switch_socket_shutdown(sock, SWITCH_SHUTDOWN_READWRITE);
00518                         switch_socket_close(sock);
00519                         return SWITCH_STATUS_TIMEOUT;
00520                 }
00521                 switch_yield(1000);
00522         }
00523         switch_socket_close(sock);
00524 
00525         if (funny) {
00526                 size -= 4;
00527         }
00528 
00529         packet = switch_stun_packet_parse(start, size);
00530         if (!packet) {
00531                 *err = "Invalid STUN/ICE packet";
00532                 return SWITCH_STATUS_FALSE;
00533         }
00534         end_buf = buf + ((sizeof(buf) > packet->header.length) ? packet->header.length : sizeof(buf));
00535 
00536         switch_stun_packet_first_attribute(packet, attr);
00537         do {
00538                 switch (attr->type) {
00539                 case SWITCH_STUN_ATTR_MAPPED_ADDRESS:
00540                         if (attr->type) {
00541                                 if (funny) {
00542                                         ((switch_stun_ip_t *) attr->value)->address ^= ntohl(0xabcdabcd);
00543                                 }
00544                                 switch_stun_packet_attribute_get_mapped_address(attr, rip, &rport);
00545                         }
00546                         break;
00547                 case SWITCH_STUN_ATTR_USERNAME:
00548                         if (attr->type) {
00549                                 switch_stun_packet_attribute_get_username(attr, username, 32);
00550                         }
00551                         break;
00552                 }
00553         } while (switch_stun_packet_next_attribute(attr, end_buf));
00554 
00555         if (packet->header.type == SWITCH_STUN_BINDING_RESPONSE) {
00556                 *ip = switch_core_strdup(pool, rip);
00557                 *port = rport;
00558                 return SWITCH_STATUS_SUCCESS;
00559         } else {
00560                 *err = "Invalid Reply";
00561         }
00562 
00563         return SWITCH_STATUS_FALSE;
00564 }

Here is the call graph for this function:

uint8_t switch_stun_packet_attribute_add_binded_address switch_stun_packet_t packet,
char *  ipstr,
uint16_t  port
 

Add a binded address packet attribute.

Parameters:
packet the packet to add the attribute to
ipstr the string representation of the ip
port the port of the mapped address
Returns:
true or false
00383 {
00384         switch_stun_packet_attribute_t *attribute;
00385         switch_stun_ip_t *ip;
00386         uint8_t *i, x;
00387         char *p = ipstr;
00388 
00389         attribute = (switch_stun_packet_attribute_t *) ((uint8_t *) &packet->first_attribute + ntohs(packet->header.length));
00390         attribute->type = htons(SWITCH_STUN_ATTR_MAPPED_ADDRESS);
00391         attribute->length = htons(8);
00392         ip = (switch_stun_ip_t *) attribute->value;
00393 
00394         ip->port = htons(port);
00395         ip->family = 1;
00396         i = (uint8_t *) &ip->address;
00397 
00398         for (x = 0; x < 4; x++) {
00399                 i[x] = (uint8_t) atoi(p);
00400                 if ((p = strchr(p, '.'))) {
00401                         p++;
00402                 } else {
00403                         break;
00404                 }
00405         }
00406 
00407         packet->header.length += htons(sizeof(switch_stun_packet_attribute_t)) + attribute->length;
00408         return 1;
00409 }

uint8_t switch_stun_packet_attribute_add_username switch_stun_packet_t packet,
char *  username,
uint16_t  ulen
 

Add a username packet attribute.

Parameters:
packet the packet to add the attribute to
username the string representation of the username
ulen the length of the username
Returns:
true or false
00412 {
00413         switch_stun_packet_attribute_t *attribute;
00414 
00415         if (ulen % 4 != 0) {
00416                 return 0;
00417         }
00418         attribute = (switch_stun_packet_attribute_t *) ((uint8_t *) &packet->first_attribute + ntohs(packet->header.length));
00419         attribute->type = htons(SWITCH_STUN_ATTR_USERNAME);
00420         attribute->length = htons(ulen);
00421         if (username) {
00422                 memcpy(attribute->value, username, ulen);
00423         } else {
00424                 switch_stun_random_string(attribute->value, ulen, NULL);
00425         }
00426 
00427         packet->header.length += htons(sizeof(switch_stun_packet_attribute_t)) + attribute->length;
00428         return 1;
00429 }

Here is the call graph for this function:

uint8_t switch_stun_packet_attribute_get_mapped_address switch_stun_packet_attribute_t attribute,
char *  ipstr,
uint16_t *  port
 

Extract a mapped address (IP:PORT) from a packet attribute.

Parameters:
attribute the attribute from which to extract
ipstr a buffer to write the string representation of the ip
port the port
Returns:
true or false
00340 {
00341         switch_stun_ip_t *ip;
00342         uint8_t x, *i;
00343         char *p = ipstr;
00344 
00345         ip = (switch_stun_ip_t *) attribute->value;
00346         i = (uint8_t *) &ip->address;
00347         *ipstr = 0;
00348         for (x = 0; x < 4; x++) {
00349                 sprintf(p, "%u%s", i[x], x == 3 ? "" : ".");
00350                 p = ipstr + strlen(ipstr);
00351         }
00352         *port = ip->port;
00353         return 1;
00354 }

char* switch_stun_packet_attribute_get_username switch_stun_packet_attribute_t attribute,
char *  username,
uint16_t  len
 

Extract a username from a packet attribute.

Parameters:
attribute the attribute from which to extract
username a buffer to write the string representation of the username
len the maximum size of the username buffer
Returns:
a pointer to the username or NULL
00357 {
00358         uint16_t cpylen;
00359 
00360         cpylen = attribute->length < len ? attribute->length : len;
00361         return memcpy(username, attribute->value, cpylen);
00362 }

switch_stun_packet_t* switch_stun_packet_build_header switch_stun_message_t  type,
char *  id,
uint8_t *  buf
 

Prepare a new outbound packet of a certian type and id.

Parameters:
id id to use (NULL for an auto generated id)
type the stun packet type
buf a pointer to data to use for the packet
Returns:
a pointer to a ready-to-use stun packet
00365 {
00366         switch_stun_packet_header_t *header;
00367 
00368 
00369         header = (switch_stun_packet_header_t *) buf;
00370         header->type = htons(type);
00371         header->length = 0;
00372 
00373         if (id) {
00374                 memcpy(header->id, id, 16);
00375         } else {
00376                 switch_stun_random_string(header->id, 16, NULL);
00377         }
00378 
00379         return (switch_stun_packet_t *) buf;
00380 }

Here is the call graph for this function:

switch_stun_packet_t* switch_stun_packet_parse uint8_t *  buf,
uint32_t  len
 

Prepare a raw packet for parsing.

Parameters:
buf the raw data
len the length of the data
Returns:
a stun packet pointer to buf to use as an access point
00118 {
00119         switch_stun_packet_t *packet;
00120         switch_stun_packet_attribute_t *attr;
00121         uint32_t bytes_left = len;
00122         void *end_buf = buf + len;
00123 
00124         if (len < SWITCH_STUN_PACKET_MIN_LEN) {
00125                 return NULL;
00126         }
00127 
00128         packet = (switch_stun_packet_t *) buf;
00129         packet->header.type = ntohs(packet->header.type);
00130         packet->header.length = ntohs(packet->header.length);
00131         bytes_left -= packet->header.length + 20;
00132 
00133         /*
00134          * Check packet type (RFC3489(bis?) values)
00135          */
00136         switch (packet->header.type) {
00137         case SWITCH_STUN_BINDING_REQUEST:
00138         case SWITCH_STUN_BINDING_RESPONSE:
00139         case SWITCH_STUN_BINDING_ERROR_RESPONSE:
00140         case SWITCH_STUN_SHARED_SECRET_REQUEST:
00141         case SWITCH_STUN_SHARED_SECRET_RESPONSE:
00142         case SWITCH_STUN_SHARED_SECRET_ERROR_RESPONSE:
00143         case SWITCH_STUN_ALLOCATE_REQUEST:
00144         case SWITCH_STUN_ALLOCATE_RESPONSE:
00145         case SWITCH_STUN_ALLOCATE_ERROR_RESPONSE:
00146         case SWITCH_STUN_SEND_REQUEST:
00147         case SWITCH_STUN_SEND_RESPONSE:
00148         case SWITCH_STUN_SEND_ERROR_RESPONSE:
00149         case SWITCH_STUN_DATA_INDICATION:
00150                 /* Valid */
00151                 break;
00152 
00153         default:
00154                 /* Invalid value */
00155                 return NULL;
00156         }
00157 
00158         /*
00159          * Check for length overflow
00160          */
00161         if (bytes_left <= 0) {
00162                 /* Invalid */
00163                 return NULL;
00164         }
00165 
00166         /*
00167          * No payload?
00168          */
00169         if (packet->header.length == 0) {
00170                 /* Invalid?! */
00171                 return NULL;
00172         }
00173 
00174         /* check if we have enough bytes left for an attribute */
00175         if (bytes_left < SWITCH_STUN_ATTRIBUTE_MIN_LEN) {
00176                 return NULL;
00177         }
00178 
00179         switch_stun_packet_first_attribute(packet, attr);
00180         do {
00181                 attr->length = ntohs(attr->length);
00182                 attr->type = ntohs(attr->type);
00183                 bytes_left -= 4;                /* attribute header consumed */
00184 
00185                 if (!attr->length || switch_stun_attribute_padded_length(attr) > bytes_left) {
00186                         /*
00187                          * Note we simply don't "break" here out of the loop anymore because
00188                          * we don't want the upper layers to have to deal with attributes without a value
00189                          * (or worse: invalid length)
00190                          */
00191                         return NULL;
00192                 }
00193 
00194                 /*
00195                  * Handle STUN attributes
00196                  */
00197                 switch (attr->type) {
00198                 case SWITCH_STUN_ATTR_MAPPED_ADDRESS:   /* Address, we only care about this one, but parse the others too */
00199                 case SWITCH_STUN_ATTR_RESPONSE_ADDRESS:
00200                 case SWITCH_STUN_ATTR_SOURCE_ADDRESS:
00201                 case SWITCH_STUN_ATTR_CHANGED_ADDRESS:
00202                 case SWITCH_STUN_ATTR_REFLECTED_FROM:
00203                 case SWITCH_STUN_ATTR_ALTERNATE_SERVER:
00204                 case SWITCH_STUN_ATTR_DESTINATION_ADDRESS:
00205                 case SWITCH_STUN_ATTR_SOURCE_ADDRESS2:
00206                         {
00207                                 switch_stun_ip_t *ip;
00208                                 uint32_t addr_length = 0;
00209                                 ip = (switch_stun_ip_t *) attr->value;
00210 
00211                                 switch (ip->family) {
00212                                 case 0x01:              /* IPv4 */
00213                                         addr_length = 4;
00214                                         break;
00215 
00216                                 case 0x02:              /* IPv6 */
00217                                         addr_length = 16;
00218                                         break;
00219 
00220                                 default:                /* Invalid */
00221                                         return NULL;
00222                                 }
00223 
00224                                 /* attribute payload length must be == address length + size of other payload fields (family...) */
00225                                 if (attr->length != addr_length + 4) {
00226                                         /* Invalid */
00227                                         return NULL;
00228                                 }
00229 
00230                                 ip->port = ntohs(ip->port);
00231                         }
00232                         break;
00233 
00234                 case SWITCH_STUN_ATTR_CHANGE_REQUEST:   /* UInt32 */
00235                 case SWITCH_STUN_ATTR_LIFETIME:
00236                 case SWITCH_STUN_ATTR_BANDWIDTH:
00237                 case SWITCH_STUN_ATTR_OPTIONS:
00238                         {
00239                                 uint32_t *val = (uint32_t *) attr->value;
00240 
00241                                 if (attr->length != sizeof(uint32_t)) {
00242                                         /* Invalid */
00243                                         return NULL;
00244                                 }
00245 
00246                                 *val = ntohl(*val);     /* should we do this here? */
00247                         }
00248                         break;
00249 
00250                 case SWITCH_STUN_ATTR_USERNAME: /* ByteString, multiple of 4 bytes */
00251                 case SWITCH_STUN_ATTR_PASSWORD: /* ByteString, multiple of 4 bytes */
00252                         if (attr->length % 4 != 0) {
00253                                 /* Invalid */
00254                                 return NULL;
00255                         }
00256                         break;
00257 
00258                 case SWITCH_STUN_ATTR_DATA:     /* ByteString */
00259                 case SWITCH_STUN_ATTR_ERROR_CODE:       /* ErrorCode */
00260                 case SWITCH_STUN_ATTR_TRANSPORT_PREFERENCES:    /* TransportPrefs */
00261                         /*
00262                          * No length checking here, since we already checked against the padded length
00263                          * before
00264                          */
00265                         break;
00266 
00267                 case SWITCH_STUN_ATTR_MESSAGE_INTEGRITY:        /* ByteString, 20 bytes */
00268                         if (attr->length != 20) {
00269                                 /* Invalid */
00270                                 return NULL;
00271                         }
00272                         break;
00273 
00274                 case SWITCH_STUN_ATTR_MAGIC_COOKIE:     /* ByteString, 4 bytes */
00275                         if (attr->length != 4) {
00276                                 /* Invalid */
00277                                 return NULL;
00278                         }
00279                         break;
00280 
00281                 case SWITCH_STUN_ATTR_UNKNOWN_ATTRIBUTES:       /* UInt16List (= multiple of 2 bytes) */
00282                         if (attr->length % 2 != 0) {
00283                                 return NULL;
00284                         }
00285                         break;
00286 
00287                 default:
00288                         /* Mandatory attribute range? => invalid */
00289                         if (attr->type <= 0x7FFF) {
00290                                 return NULL;
00291                         }
00292                         break;
00293                 }
00294                 bytes_left -= switch_stun_attribute_padded_length(attr);        /* attribute value consumed, substract padded length */
00295 
00296         } while (bytes_left >= SWITCH_STUN_ATTRIBUTE_MIN_LEN && switch_stun_packet_next_attribute(attr, end_buf));
00297 
00298         if ((uint32_t) (packet->header.length + 20) > (uint32_t) (len - bytes_left)) {
00299                 /*
00300                  * the packet length is longer than the length of all attributes?
00301                  * for now simply decrease the packet size
00302                  */
00303                 packet->header.length = (uint16_t) ((len - bytes_left) - 20);
00304         }
00305 
00306         return packet;
00307 }

void switch_stun_random_string char *  buf,
uint16_t  len,
char *  set
 

Writes random characters into a buffer.

Parameters:
buf the buffer
len the length of the data
set the set of chars to use (NULL for auto)
00097 {
00098         char chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
00099         int max;
00100         uint16_t x;
00101 
00102         if (!set) {
00103                 set = chars;
00104         }
00105 
00106         max = (int) strlen(set);
00107 
00108         srand((unsigned int) switch_timestamp_now());
00109 
00110         for (x = 0; x < len; x++) {
00111                 int j = (int) (max * 1.0 * rand() / (RAND_MAX + 1.0));
00112                 buf[x] = set[j];
00113         }
00114 }

Here is the call graph for this function:

const char* switch_stun_value_to_name int32_t  type,
uint32_t  value
 

Obtain a printable string form of a given value.

Parameters:
type the type of message
value the value to look up
Returns:
a sring version of value
00310 {
00311         uint32_t x = 0;
00312         const struct value_mapping *map = NULL;
00313         switch (type) {
00314         case SWITCH_STUN_TYPE_PACKET_TYPE:
00315                 map = PACKET_TYPES;
00316                 break;
00317         case SWITCH_STUN_TYPE_ATTRIBUTE:
00318                 map = ATTR_TYPES;
00319                 break;
00320         case SWITCH_STUN_TYPE_ERROR:
00321                 map = ERROR_TYPES;
00322                 break;
00323         default:
00324                 map = NULL;
00325                 break;
00326         }
00327 
00328         if (map) {
00329                 for (x = 0; map[x].value; x++) {
00330                         if (map[x].value == value) {
00331                                 return map[x].name;
00332                         }
00333                 }
00334         }
00335 
00336         return "INVALID";
00337 }


Generated on Fri Oct 10 11:25:19 2008 for FreeSWITCH by  doxygen 1.3.9.1