mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-08-13 09:36:46 +00:00
Addition of libdingaling and mod_dingaling to enable jingle support
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@995 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
31
libs/libdingaling/src/dingaling.def
Normal file
31
libs/libdingaling/src/dingaling.def
Normal file
@@ -0,0 +1,31 @@
|
||||
EXPORTS
|
||||
stun_random_string
|
||||
stun_packet_parse
|
||||
stun_value_to_name
|
||||
stun_packet_attribute_get_mapped_address
|
||||
stun_packet_attribute_get_username
|
||||
stun_packet_build_header
|
||||
stun_packet_attribute_add_username
|
||||
stun_packet_attribute_add_binded_address
|
||||
ldl_session_get_caller
|
||||
ldl_session_get_ip
|
||||
ldl_session_set_private
|
||||
ldl_session_get_private
|
||||
ldl_session_terminate
|
||||
ldl_handle_get_private
|
||||
ldl_session_candidates
|
||||
ldl_session_describe
|
||||
ldl_session_get_state
|
||||
ldl_session_get_candidates
|
||||
ldl_session_get_payloads
|
||||
ldl_global_init
|
||||
ldl_global_destroy
|
||||
ldl_global_set_log_stream
|
||||
ldl_handle_init
|
||||
ldl_handle_run
|
||||
ldl_handle_destroy
|
||||
ldl_handle_set_log_stream
|
||||
ldl_session_create
|
||||
ldl_handle_probe
|
||||
ldl_handle_ready
|
||||
ldl_session_get_id
|
63
libs/libdingaling/src/ldl_compat.h
Normal file
63
libs/libdingaling/src/ldl_compat.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* libDingaLing XMPP Jingle Library
|
||||
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libDingaLing XMPP Jingle Library
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Anthony Minessale II <anthmct@yahoo.com>
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Anthony Minessale II <anthmct@yahoo.com>
|
||||
*
|
||||
* ldl_compat.h -- Platform Compatability Header File
|
||||
*
|
||||
*/
|
||||
/*! \file ldl_compat.h
|
||||
\brief Platform Compatability Header File
|
||||
*/
|
||||
#ifndef LDL_COMPAT_H
|
||||
#define LDL_COMPAT_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __STUPIDFORMATBUG__
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#ifndef uint32_t
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
typedef __int8 int8_t;
|
||||
typedef __int16 int16_t;
|
||||
typedef __int32 int32_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned long in_addr_t;
|
||||
#endif
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
1127
libs/libdingaling/src/libdingaling.c
Normal file
1127
libs/libdingaling/src/libdingaling.c
Normal file
File diff suppressed because it is too large
Load Diff
392
libs/libdingaling/src/libdingaling.h
Normal file
392
libs/libdingaling/src/libdingaling.h
Normal file
@@ -0,0 +1,392 @@
|
||||
/*
|
||||
* libDingaLing XMPP Jingle Library
|
||||
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libDingaLing XMPP Jingle Library
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Anthony Minessale II <anthmct@yahoo.com>
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Anthony Minessale II <anthmct@yahoo.com>
|
||||
*
|
||||
* libdingaling.h -- Main Header File
|
||||
*
|
||||
*/
|
||||
/*! \file libdingaling.h
|
||||
\brief Main Header File
|
||||
*/
|
||||
|
||||
/*!
|
||||
\defgroup core1 libDingaLing Library
|
||||
\ingroup LIBDINGALING
|
||||
\{
|
||||
*/
|
||||
#ifndef LIBDINGALING_H
|
||||
#define LIBDINGALING_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __STUPIDFORMATBUG__
|
||||
}
|
||||
#endif
|
||||
|
||||
#define LDL_HANDLE_QLEN 2000
|
||||
#define LDL_MAX_CANDIDATES 10
|
||||
#define LDL_MAX_PAYLOADS 50
|
||||
#define LDL_RETRY 3
|
||||
|
||||
/*! \brief A structure to store a jingle candidate */
|
||||
struct ldl_candidate {
|
||||
/*! the name of the candidate */
|
||||
char *name;
|
||||
/*! the type of the candidate */
|
||||
char *type;
|
||||
/*! the protocol of the candidate */
|
||||
char *protocol;
|
||||
/*! the STUN username of the candidate */
|
||||
char *username;
|
||||
/*! the STUN password of the candidate */
|
||||
char *password;
|
||||
/*! the ip address of the candidate */
|
||||
char *address;
|
||||
/*! the stun/rtp port of the candidate */
|
||||
uint16_t port;
|
||||
/*! the preference level of the candidate */
|
||||
double pref;
|
||||
};
|
||||
typedef struct ldl_candidate ldl_candidate_t;
|
||||
|
||||
/*! \brief A structure to store a jingle payload */
|
||||
struct ldl_payload {
|
||||
/*! the iana name of the payload type */
|
||||
char *name;
|
||||
/*! the iana id of the payload type */
|
||||
unsigned int id;
|
||||
/*! the transfer rate of the payload type */
|
||||
unsigned int rate;
|
||||
};
|
||||
typedef struct ldl_payload ldl_payload_t;
|
||||
|
||||
struct ldl_handle;
|
||||
typedef struct ldl_handle ldl_handle_t;
|
||||
|
||||
struct ldl_session;
|
||||
typedef struct ldl_session ldl_session_t;
|
||||
|
||||
typedef enum {
|
||||
LDL_STATUS_SUCCESS,
|
||||
LDL_STATUS_FALSE,
|
||||
LDL_STATUS_MEMERR,
|
||||
} ldl_status;
|
||||
|
||||
typedef enum {
|
||||
LDL_FLAG_INIT = (1 << 0),
|
||||
LDL_FLAG_RUNNING = (1 << 1),
|
||||
LDL_FLAG_AUTHORIZED = (1 << 2),
|
||||
LDL_FLAG_READY = (1 << 3)
|
||||
} ldl_flag_t;
|
||||
|
||||
typedef enum {
|
||||
LDL_SIGNAL_NONE,
|
||||
LDL_SIGNAL_INITIATE,
|
||||
LDL_SIGNAL_CANDIDATES,
|
||||
LDL_SIGNAL_MSG,
|
||||
LDL_SIGNAL_TERMINATE,
|
||||
LDL_SIGNAL_ERROR
|
||||
} ldl_signal_t;
|
||||
|
||||
typedef enum {
|
||||
LDL_REPLY_ACK,
|
||||
LDL_REPLY_NACK,
|
||||
} ldl_reply_t;
|
||||
|
||||
typedef enum {
|
||||
LDL_STATE_NEW,
|
||||
LDL_STATE_ANSWERED,
|
||||
LDL_STATE_DESTROYED,
|
||||
} ldl_state_t;
|
||||
|
||||
typedef enum {
|
||||
LDL_DESCRIPTION_INITIATE,
|
||||
LDL_DESCRIPTION_ACCEPT
|
||||
} ldl_description_t;
|
||||
|
||||
typedef ldl_status (*ldl_loop_callback_t)(ldl_handle_t *);
|
||||
typedef ldl_status (*ldl_session_callback_t)(ldl_handle_t *, ldl_session_t *, ldl_signal_t, char *);
|
||||
typedef ldl_status (*ldl_response_callback_t)(ldl_handle_t *, char *);
|
||||
|
||||
#define ldl_yield(ms) apr_sleep(ms * 10); apr_thread_yield();
|
||||
|
||||
/*!
|
||||
\brief Test for the existance of a flag on an arbitary object
|
||||
\param obj the object to test
|
||||
\param flag the or'd list of flags to test
|
||||
\return true value if the object has the flags defined
|
||||
*/
|
||||
#define ldl_test_flag(obj, flag) ((obj)->flags & flag)
|
||||
|
||||
|
||||
/*!
|
||||
\brief Set a flag on an arbitrary object
|
||||
\param obj the object to set the flags on
|
||||
\param flag the or'd list of flags to set
|
||||
*/
|
||||
#define ldl_set_flag(obj, flag) (obj)->flags |= (flag)
|
||||
|
||||
/*!
|
||||
\brief Clear a flag on an arbitrary object
|
||||
\param obj the object to test
|
||||
\param flag the or'd list of flags to clear
|
||||
*/
|
||||
#define ldl_clear_flag(obj, flag) (obj)->flags &= ~(flag)
|
||||
|
||||
/*!
|
||||
\brief Copy flags from one arbitrary object to another
|
||||
\param dest the object to copy the flags to
|
||||
\param src the object to copy the flags from
|
||||
\param flags the flags to copy
|
||||
*/
|
||||
#define ldl_copy_flags(dest, src, flags) (dest)->flags &= ~(flags); (dest)->flags |= ((src)->flags & (flags))
|
||||
|
||||
/*!
|
||||
\brief Test for NULL or zero length string
|
||||
\param s the string to test
|
||||
\return true value if the string is NULL or zero length
|
||||
*/
|
||||
#define ldl_strlen_zero(s) (s && *s != '\0') ? 0 : 1
|
||||
|
||||
/*!
|
||||
\brief Destroy a Jingle Session
|
||||
\param session_p the session to destroy
|
||||
\return SUCCESS OR FAILURE
|
||||
*/
|
||||
ldl_status ldl_session_destroy(ldl_session_t **session_p);
|
||||
|
||||
/*!
|
||||
\brief Create a Jingle Session
|
||||
\param session_p pointer to reference the session
|
||||
\param handle handle to associate the session with
|
||||
\param id the id to use for the session
|
||||
\param them the id of the other end of the call
|
||||
\param me the id of our end of the call
|
||||
\return SUCCESS OR FAILURE
|
||||
*/
|
||||
ldl_status ldl_session_create(ldl_session_t **session_p, ldl_handle_t *handle, char *id, char *them, char *me);
|
||||
|
||||
/*!
|
||||
\brief get the id of a session
|
||||
\param session the session to get the id of
|
||||
\return the requested id
|
||||
*/
|
||||
char *ldl_session_get_id(ldl_session_t *session);
|
||||
|
||||
/*!
|
||||
\brief Get the caller name of a session
|
||||
\param session the session to get the caller from
|
||||
\return the caller name
|
||||
*/
|
||||
char *ldl_session_get_caller(ldl_session_t *session);
|
||||
|
||||
/*!
|
||||
\brief Get the ip of a session
|
||||
\param session the session to get the ip from
|
||||
\return the ip
|
||||
*/
|
||||
char *ldl_session_get_ip(ldl_session_t *session);
|
||||
|
||||
/*!
|
||||
\brief Set a private pointer to associate with the session
|
||||
\param session the session to set the data pointer to
|
||||
\param private_data the data to associate
|
||||
*/
|
||||
void ldl_session_set_private(ldl_session_t *session, void *private_data);
|
||||
|
||||
/*!
|
||||
\brief Get a private pointer from a session
|
||||
\param session the session to get the data from
|
||||
\return the data
|
||||
*/
|
||||
void *ldl_session_get_private(ldl_session_t *session);
|
||||
|
||||
/*!
|
||||
\brief Perform a probe on a given id to resolve the proper Jingle Resource
|
||||
\param handle the connection handle to use.
|
||||
\param id the id to probe
|
||||
\param buf a string to store the result
|
||||
\param len the size in bytes of the string
|
||||
\return a pointer to buf if a successful lookup was made otherwise NULL
|
||||
*/
|
||||
char *ldl_handle_probe(ldl_handle_t *handle, char *id, char *buf, unsigned int len);
|
||||
|
||||
/*!
|
||||
\brief Signal a termination request on a given session
|
||||
\param session the session to terminate
|
||||
\return TRUE if the signal was sent.
|
||||
*/
|
||||
unsigned int ldl_session_terminate(ldl_session_t *session);
|
||||
|
||||
/*!
|
||||
\brief Get the private data of a connection handle
|
||||
\param handle the conection handle
|
||||
\return the requested data
|
||||
*/
|
||||
void *ldl_handle_get_private(ldl_handle_t *handle);
|
||||
|
||||
/*!
|
||||
\brief Offer candidates to a potential session
|
||||
\param session the session to send candidates on
|
||||
\param candidates an array of candidate description objects
|
||||
\param clen the number of elements in the candidates array
|
||||
\return the message_id of the generated xmpp request
|
||||
*/
|
||||
unsigned int ldl_session_candidates(ldl_session_t *session,
|
||||
ldl_candidate_t *candidates,
|
||||
unsigned int clen);
|
||||
|
||||
/*!
|
||||
\brief Initiate or Accept a new session and provide transport options
|
||||
\param session the session to initiate or accept
|
||||
\param payloads an array of payload description objects
|
||||
\param plen the number of elements in the payloads array
|
||||
\param description the type of description LDL_DESCRIPTION_INITIATE or LDL_DESCRIPTION_ACCEPT
|
||||
\return the message_id of the generated xmpp request
|
||||
*/
|
||||
unsigned int ldl_session_describe(ldl_session_t *session,
|
||||
ldl_payload_t *payloads,
|
||||
unsigned int plen,
|
||||
ldl_description_t description);
|
||||
|
||||
|
||||
/*!
|
||||
\brief get a session's state
|
||||
\param session a session to get the state from
|
||||
\return the state
|
||||
*/
|
||||
ldl_state_t ldl_session_get_state(ldl_session_t *session);
|
||||
|
||||
|
||||
/*!
|
||||
\brief get the candidates
|
||||
\param session the session
|
||||
\param candidates pointer to point at array of the candidates
|
||||
\param len the resulting len of the array pointer
|
||||
\return success or failure
|
||||
*/
|
||||
ldl_status ldl_session_get_candidates(ldl_session_t *session, ldl_candidate_t **candidates, unsigned int *len);
|
||||
|
||||
/*!
|
||||
\brief get the payloads
|
||||
\param session the session
|
||||
\param payloads pointer to point at array of the payloads
|
||||
\param len the resulting len of the array pointer
|
||||
\return success or failure
|
||||
*/
|
||||
ldl_status ldl_session_get_payloads(ldl_session_t *session, ldl_payload_t **payloads, unsigned int *len);
|
||||
|
||||
/*!
|
||||
\brief Initilize libDingaLing
|
||||
\param debug debug level
|
||||
\return success or failure
|
||||
*/
|
||||
ldl_status ldl_global_init(int debug);
|
||||
|
||||
/*!
|
||||
\brief Destroy libDingaLing
|
||||
\return success or failure
|
||||
*/
|
||||
ldl_status ldl_global_destroy(void);
|
||||
|
||||
/*!
|
||||
\brief Set the log stream
|
||||
\param log_stream the new log stream
|
||||
*/
|
||||
void ldl_global_set_log_stream(FILE *log_stream);
|
||||
|
||||
int8_t ldl_handle_ready(ldl_handle_t *handle);
|
||||
|
||||
/*!
|
||||
\brief Initilize a new libDingaLing handle
|
||||
\param handle the Dingaling handle to initialize
|
||||
\param login the xmpp login
|
||||
\param password the password
|
||||
\param status_msg status message to advertise
|
||||
\param loop_callback optional loop callback
|
||||
\param session_callback function to call on session signalling
|
||||
\param response_callback function to call on responses
|
||||
\param private_info optional pointer to private data
|
||||
\return success or failure
|
||||
*/
|
||||
ldl_status ldl_handle_init(ldl_handle_t **handle,
|
||||
char *login,
|
||||
char *password,
|
||||
char *status_msg,
|
||||
ldl_loop_callback_t loop_callback,
|
||||
ldl_session_callback_t session_callback,
|
||||
ldl_response_callback_t response_callback,
|
||||
void *private_info);
|
||||
|
||||
/*!
|
||||
\brief Run a libDingaLing handle
|
||||
\param handle the Dingaling handle to run
|
||||
*/
|
||||
void ldl_handle_run(ldl_handle_t *handle);
|
||||
|
||||
/*!
|
||||
\brief Destroy a libDingaLing handle
|
||||
\param handle the Dingaling handle to destroy
|
||||
\return success or failure
|
||||
*/
|
||||
ldl_status ldl_handle_destroy(ldl_handle_t **handle);
|
||||
|
||||
/*!
|
||||
\brief Set the log stream on a handle
|
||||
\param handle the Dingaling handle
|
||||
\param log_stream the new log stream
|
||||
*/
|
||||
void ldl_handle_set_log_stream(ldl_handle_t *handle, FILE *log_stream);
|
||||
///\}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/** \mainpage libDingaling
|
||||
* libDingaling - Cross Platform Jingle (Google Talk) voip signaling library
|
||||
|
||||
* \section intro Introduction
|
||||
*
|
||||
* \section supports Supported Platforms
|
||||
* libDingaling has been built on the following platforms:
|
||||
*
|
||||
* - Linux (x86, x86_64)
|
||||
* - Windows (MSVC 2005)
|
||||
* - Mac OS X (intel & ppc )
|
||||
*
|
||||
* \section depends Dependencies
|
||||
* libDingaling makes use of the following external libraries.
|
||||
*
|
||||
* - APR (http://apr.apache.org)
|
||||
* - iksemel (http://iksemel.jabberstudio.org/)
|
||||
*
|
||||
* \section license Licensing
|
||||
*
|
||||
* libDingaling is licensed under the terms of the MPL 1.1
|
||||
*
|
||||
*/
|
||||
#endif
|
279
libs/libdingaling/src/stun_parser.c
Normal file
279
libs/libdingaling/src/stun_parser.c
Normal file
@@ -0,0 +1,279 @@
|
||||
/*
|
||||
* libDingaLing XMPP Jingle Library
|
||||
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libDingaLing XMPP Jingle Library
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Anthony Minessale II <anthmct@yahoo.com>
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Anthony Minessale II <anthmct@yahoo.com>
|
||||
*
|
||||
* stun_parser.c STUN packet manipulation
|
||||
*
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#ifdef WIN32
|
||||
#include <Winsock2.h>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#include "ldl_compat.h"
|
||||
#include "stun_parser.h"
|
||||
|
||||
struct value_mapping {
|
||||
const uint32_t value;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
static const struct value_mapping PACKET_TYPES[] = {
|
||||
{ STUN_BINDING_REQUEST, "BINDING_REQUEST" },
|
||||
{ STUN_BINDING_RESPONSE, "BINDING_RESPONSE" },
|
||||
{ STUN_BINDING_ERROR_RESPONSE, "BINDING_ERROR_RESPONSE" },
|
||||
{ STUN_SHARED_SECRET_REQUEST, "SHARED_SECRET_REQUEST" },
|
||||
{ STUN_SHARED_SECRET_RESPONSE, "SHARED_SECRET_RESPONSE" },
|
||||
{ STUN_SHARED_SECRET_ERROR_RESPONSE, "SHARED_SECRET_ERROR_RESPONSE" },
|
||||
{ STUN_ALLOCATE_REQUEST, "ALLOCATE_REQUEST" },
|
||||
{ STUN_ALLOCATE_RESPONSE, "ALLOCATE_RESPONSE" },
|
||||
{ STUN_ALLOCATE_ERROR_RESPONSE, "ALLOCATE_ERROR_RESPONSE" },
|
||||
{ STUN_SEND_REQUEST, "SEND_REQUEST" },
|
||||
{ STUN_SEND_RESPONSE, "SEND_RESPONSE" },
|
||||
{ STUN_SEND_ERROR_RESPONSE, "SEND_ERROR_RESPONSE" },
|
||||
{ STUN_DATA_INDICATION , "DATA_INDICATION"},
|
||||
{ 0, 0} };
|
||||
|
||||
static const struct value_mapping ATTR_TYPES[] = {
|
||||
{ STUN_ATTR_MAPPED_ADDRESS, "MAPPED_ADDRESS" },
|
||||
{ STUN_ATTR_RESPONSE_ADDRESS, "RESPONSE_ADDRESS" },
|
||||
{ STUN_ATTR_CHANGE_REQUEST, "CHANGE_REQUEST" },
|
||||
{ STUN_ATTR_SOURCE_ADDRESS, "SOURCE_ADDRESS" },
|
||||
{ STUN_ATTR_CHANGED_ADDRESS, "CHANGED_ADDRESS" },
|
||||
{ STUN_ATTR_USERNAME, "USERNAME" },
|
||||
{ STUN_ATTR_PASSWORD, "PASSWORD" },
|
||||
{ STUN_ATTR_MESSAGE_INTEGRITY, "MESSAGE_INTEGRITY" },
|
||||
{ STUN_ATTR_ERROR_CODE, "ERROR_CODE" },
|
||||
{ STUN_ATTR_UNKNOWN_ATTRIBUTES, "UNKNOWN_ATTRIBUTES" },
|
||||
{ STUN_ATTR_REFLECTED_FROM, "REFLECTED_FROM" },
|
||||
{ STUN_ATTR_TRANSPORT_PREFERENCES, "TRANSPORT_PREFERENCES" },
|
||||
{ STUN_ATTR_LIFETIME, "LIFETIME" },
|
||||
{ STUN_ATTR_ALTERNATE_SERVER, "ALTERNATE_SERVER" },
|
||||
{ STUN_ATTR_MAGIC_COOKIE, "MAGIC_COOKIE" },
|
||||
{ STUN_ATTR_BANDWIDTH, "BANDWIDTH" },
|
||||
{ STUN_ATTR_DESTINATION_ADDRESS, "DESTINATION_ADDRESS" },
|
||||
{ STUN_ATTR_SOURCE_ADDRESS2, "SOURCE_ADDRESS2" },
|
||||
{ STUN_ATTR_DATA, "DATA" },
|
||||
{ STUN_ATTR_OPTIONS, "OPTIONS" },
|
||||
{ 0, 0} };
|
||||
|
||||
static const struct value_mapping ERROR_TYPES[] = {
|
||||
{ STUN_ERROR_BAD_REQUEST, "BAD_REQUEST" },
|
||||
{ STUN_ERROR_UNAUTHORIZED, "UNAUTHORIZED" },
|
||||
{ STUN_ERROR_UNKNOWN_ATTRIBUTE, "UNKNOWN_ATTRIBUTE" },
|
||||
{ STUN_ERROR_STALE_CREDENTIALS, "STALE_CREDENTIALS" },
|
||||
{ STUN_ERROR_INTEGRITY_CHECK_FAILURE, "INTEGRITY_CHECK_FAILURE" },
|
||||
{ STUN_ERROR_MISSING_USERNAME, "MISSING_USERNAME" },
|
||||
{ STUN_ERROR_USE_TLS, "USE_TLS" },
|
||||
{ STUN_ERROR_SERVER_ERROR, "SERVER_ERROR" },
|
||||
{ STUN_ERROR_GLOBAL_FAILURE, "GLOBAL_FAILURE" },
|
||||
{ 0, 0 }};
|
||||
|
||||
void stun_random_string(char *buf, uint16_t len, char *set)
|
||||
{
|
||||
char chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||
int max;
|
||||
uint8_t x;
|
||||
|
||||
if (!set) {
|
||||
set = chars;
|
||||
}
|
||||
|
||||
max = (int)strlen(set) - 1;
|
||||
|
||||
for(x = 0; x < len; x++) {
|
||||
int j = 1+(int)(max*1.0*rand()/(RAND_MAX+1.0));
|
||||
buf[x] = set[j];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
stun_packet_t *stun_packet_parse(uint8_t *buf, uint32_t len)
|
||||
{
|
||||
stun_packet_t *packet;
|
||||
stun_packet_attribute_t *attr;
|
||||
|
||||
if (len < STUN_PACKET_MIN_LEN) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
packet = (stun_packet_t *) buf;
|
||||
packet->header.type = ntohs(packet->header.type);
|
||||
packet->header.length = ntohs(packet->header.length);
|
||||
attr = &packet->first_attribute;
|
||||
stun_packet_first_attribute(packet, attr);
|
||||
do {
|
||||
attr->length = ntohs(attr->length);
|
||||
attr->type = ntohs(attr->type);
|
||||
if (!attr->length) {
|
||||
break;
|
||||
}
|
||||
switch(attr->type) {
|
||||
case STUN_ATTR_MAPPED_ADDRESS:
|
||||
if (attr->type) {
|
||||
stun_ip_t *ip;
|
||||
ip = (stun_ip_t *) attr->value;
|
||||
ip->port = ntohs(ip->port);
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
} while (stun_packet_next_attribute(attr));
|
||||
return packet;
|
||||
}
|
||||
|
||||
const char *stun_value_to_name(int32_t type, int32_t value)
|
||||
|
||||
{
|
||||
uint32_t x = 0;
|
||||
const struct value_mapping *map = NULL;
|
||||
switch (type) {
|
||||
case STUN_TYPE_PACKET_TYPE:
|
||||
map = PACKET_TYPES;
|
||||
break;
|
||||
case STUN_TYPE_ATTRIBUTE:
|
||||
map = ATTR_TYPES;
|
||||
break;
|
||||
case STUN_TYPE_ERROR:
|
||||
map = ERROR_TYPES;
|
||||
break;
|
||||
default:
|
||||
map = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (map) {
|
||||
for(x = 0; map[x].value; x++) {
|
||||
if (map[x].value == value) {
|
||||
return map[x].name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "INVALID";
|
||||
}
|
||||
|
||||
uint8_t stun_packet_attribute_get_mapped_address(stun_packet_attribute_t *attribute, char *ipstr, uint16_t *port)
|
||||
{
|
||||
stun_ip_t *ip;
|
||||
uint8_t x, *i;
|
||||
char *p = ipstr;
|
||||
|
||||
ip = (stun_ip_t *) attribute->value;
|
||||
i = (uint8_t *) &ip->address;
|
||||
*ipstr = 0;
|
||||
for(x =0; x < 4; x++) {
|
||||
sprintf(p, "%u%s", i[x], x == 3 ? "" : ".");
|
||||
p = ipstr + strlen(ipstr);
|
||||
}
|
||||
*port = ip->port;
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *stun_packet_attribute_get_username(stun_packet_attribute_t *attribute, char *username, uint16_t len)
|
||||
{
|
||||
uint16_t cpylen;
|
||||
|
||||
cpylen = attribute->length > len ? attribute->length : len;
|
||||
return memcpy(username, attribute->value, cpylen);
|
||||
}
|
||||
|
||||
stun_packet_t *stun_packet_build_header(stun_message_t type,
|
||||
char *id,
|
||||
uint8_t *buf
|
||||
)
|
||||
{
|
||||
stun_packet_header_t *header;
|
||||
|
||||
|
||||
header = (stun_packet_header_t *) buf;
|
||||
header->type = htons(type);
|
||||
header->length = 0;
|
||||
|
||||
if (id) {
|
||||
memcpy(header->id, id, 16);
|
||||
} else {
|
||||
stun_random_string(header->id, 16, NULL);
|
||||
}
|
||||
|
||||
return (stun_packet_t *) buf;
|
||||
}
|
||||
|
||||
uint8_t stun_packet_attribute_add_binded_address(stun_packet_t *packet, char *ipstr, uint16_t port)
|
||||
{
|
||||
stun_packet_attribute_t *attribute;
|
||||
stun_ip_t *ip;
|
||||
uint8_t *i, x;
|
||||
char *p = ipstr;
|
||||
|
||||
attribute = (stun_packet_attribute_t *) ((uint8_t *) &packet->first_attribute + ntohs(packet->header.length));
|
||||
attribute->type = htons(STUN_ATTR_MAPPED_ADDRESS);
|
||||
attribute->length = htons(8);
|
||||
ip = (stun_ip_t *) attribute->value;
|
||||
|
||||
ip->port = htons(port);
|
||||
ip->family = 1;
|
||||
i = (uint8_t *) &ip->address;
|
||||
|
||||
for(x = 0; x < 4 ; x++) {
|
||||
i[x] = atoi(p);
|
||||
if ((p = strchr(p, '.'))) {
|
||||
p++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
packet->header.length += htons(sizeof(stun_packet_attribute_t)) + attribute->length;
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t stun_packet_attribute_add_username(stun_packet_t *packet, char *username, uint16_t ulen)
|
||||
{
|
||||
stun_packet_attribute_t *attribute;
|
||||
|
||||
if (ulen % 4 != 0) {
|
||||
return 0;
|
||||
}
|
||||
attribute = (stun_packet_attribute_t *) ((uint8_t *) &packet->first_attribute + ntohs(packet->header.length));
|
||||
attribute->type = htons(STUN_ATTR_USERNAME);
|
||||
attribute->length = htons(ulen);
|
||||
if (username) {
|
||||
memcpy(attribute->value, username, ulen);
|
||||
} else {
|
||||
stun_random_string(attribute->value, ulen, NULL);
|
||||
}
|
||||
|
||||
packet->header.length += htons(sizeof(stun_packet_attribute_t)) + attribute->length;
|
||||
return 1;
|
||||
}
|
223
libs/libdingaling/src/stun_parser.h
Normal file
223
libs/libdingaling/src/stun_parser.h
Normal file
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* libDingaLing XMPP Jingle Library
|
||||
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libDingaLing XMPP Jingle Library
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Anthony Minessale II <anthmct@yahoo.com>
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Anthony Minessale II <anthmct@yahoo.com>
|
||||
*
|
||||
* stun_parser.h STUN packet manipulation
|
||||
*
|
||||
*/
|
||||
/*! \file stun_parser.h
|
||||
\brief STUN packet manipulation
|
||||
*/
|
||||
|
||||
/*!
|
||||
\defgroup stun1 libDingaLing Stun Parser
|
||||
\ingroup LIBDINGALING
|
||||
\{
|
||||
*/
|
||||
#ifndef _STUN_PARSER_H
|
||||
#define _STUN_PARSER_H
|
||||
|
||||
#define STUN_PACKET_MIN_LEN 20
|
||||
|
||||
typedef enum {
|
||||
STUN_BINDING_REQUEST = 0x0001,
|
||||
STUN_BINDING_RESPONSE = 0x0101,
|
||||
STUN_BINDING_ERROR_RESPONSE = 0x0111,
|
||||
STUN_SHARED_SECRET_REQUEST = 0x0002,
|
||||
STUN_SHARED_SECRET_RESPONSE = 0x0102,
|
||||
STUN_SHARED_SECRET_ERROR_RESPONSE = 0x0112,
|
||||
STUN_ALLOCATE_REQUEST = 0x0003,
|
||||
STUN_ALLOCATE_RESPONSE = 0x0103,
|
||||
STUN_ALLOCATE_ERROR_RESPONSE = 0x0113,
|
||||
STUN_SEND_REQUEST = 0x0004,
|
||||
STUN_SEND_RESPONSE = 0x0104,
|
||||
STUN_SEND_ERROR_RESPONSE = 0x0114,
|
||||
STUN_DATA_INDICATION = 0x0115
|
||||
} stun_message_t;
|
||||
|
||||
typedef enum {
|
||||
STUN_ATTR_MAPPED_ADDRESS = 0x0001, /* Address */
|
||||
STUN_ATTR_RESPONSE_ADDRESS = 0x0002, /* Address */
|
||||
STUN_ATTR_CHANGE_REQUEST = 0x0003, /* UInt32 */
|
||||
STUN_ATTR_SOURCE_ADDRESS = 0x0004, /* Address */
|
||||
STUN_ATTR_CHANGED_ADDRESS = 0x0005, /* Address */
|
||||
STUN_ATTR_USERNAME = 0x0006, /* ByteString, multiple of 4 bytes */
|
||||
STUN_ATTR_PASSWORD = 0x0007, /* ByteString, multiple of 4 bytes */
|
||||
STUN_ATTR_MESSAGE_INTEGRITY = 0x0008, /* ByteString, 20 bytes */
|
||||
STUN_ATTR_ERROR_CODE = 0x0009, /* ErrorCode */
|
||||
STUN_ATTR_UNKNOWN_ATTRIBUTES = 0x000a, /* UInt16List */
|
||||
STUN_ATTR_REFLECTED_FROM = 0x000b, /* Address */
|
||||
STUN_ATTR_TRANSPORT_PREFERENCES = 0x000c, /* TransportPrefs */
|
||||
STUN_ATTR_LIFETIME = 0x000d, /* UInt32 */
|
||||
STUN_ATTR_ALTERNATE_SERVER = 0x000e, /* Address */
|
||||
STUN_ATTR_MAGIC_COOKIE = 0x000f, /* ByteString, 4 bytes */
|
||||
STUN_ATTR_BANDWIDTH = 0x0010, /* UInt32 */
|
||||
STUN_ATTR_DESTINATION_ADDRESS = 0x0011, /* Address */
|
||||
STUN_ATTR_SOURCE_ADDRESS2 = 0x0012, /* Address */
|
||||
STUN_ATTR_DATA = 0x0013, /* ByteString */
|
||||
STUN_ATTR_OPTIONS = 0x8001 /* UInt32 */
|
||||
} stun_attribute_t;
|
||||
|
||||
typedef enum {
|
||||
STUN_ERROR_BAD_REQUEST = 400,
|
||||
STUN_ERROR_UNAUTHORIZED = 401,
|
||||
STUN_ERROR_UNKNOWN_ATTRIBUTE = 420,
|
||||
STUN_ERROR_STALE_CREDENTIALS = 430,
|
||||
STUN_ERROR_INTEGRITY_CHECK_FAILURE = 431,
|
||||
STUN_ERROR_MISSING_USERNAME = 432,
|
||||
STUN_ERROR_USE_TLS = 433,
|
||||
STUN_ERROR_SERVER_ERROR = 500,
|
||||
STUN_ERROR_GLOBAL_FAILURE = 600
|
||||
} stun_error_t;
|
||||
|
||||
typedef enum {
|
||||
STUN_TYPE_PACKET_TYPE,
|
||||
STUN_TYPE_ATTRIBUTE,
|
||||
STUN_TYPE_ERROR
|
||||
} stun_type_t;
|
||||
|
||||
typedef struct {
|
||||
int16_t type;
|
||||
int16_t length;
|
||||
char id[16];
|
||||
} stun_packet_header_t;
|
||||
|
||||
typedef struct {
|
||||
int16_t type;
|
||||
uint16_t length;
|
||||
char value[0];
|
||||
} stun_packet_attribute_t;
|
||||
|
||||
typedef struct {
|
||||
stun_packet_header_t header;
|
||||
stun_packet_attribute_t first_attribute;
|
||||
} stun_packet_t;
|
||||
|
||||
typedef struct {
|
||||
int8_t wasted;
|
||||
int8_t family;
|
||||
int16_t port;
|
||||
int32_t address;
|
||||
} stun_ip_t;
|
||||
|
||||
|
||||
/*!
|
||||
\brief Writes random characters into a buffer
|
||||
\param buf the buffer
|
||||
\param len the length of the data
|
||||
\param set the set of chars to use (NULL for auto)
|
||||
*/
|
||||
void stun_random_string(char *buf, uint16_t len, char *set);
|
||||
|
||||
/*!
|
||||
\brief Prepare a raw packet for parsing
|
||||
\param buf the raw data
|
||||
\param len the length of the data
|
||||
\return a stun packet pointer to buf to use as an access point
|
||||
*/
|
||||
stun_packet_t *stun_packet_parse(uint8_t *buf, uint32_t len);
|
||||
|
||||
/*!
|
||||
\brief Obtain a printable string form of a given value
|
||||
\param type the type of message
|
||||
\param value the value to look up
|
||||
\return a sring version of value
|
||||
*/
|
||||
const char *stun_value_to_name(int32_t type, int32_t value);
|
||||
|
||||
|
||||
/*!
|
||||
\brief Extract a mapped address (IP:PORT) from a packet attribute
|
||||
\param attribute the attribute from which to extract
|
||||
\param ipstr a buffer to write the string representation of the ip
|
||||
\param port the port
|
||||
\return true or false
|
||||
*/
|
||||
uint8_t stun_packet_attribute_get_mapped_address(stun_packet_attribute_t *attribute, char *ipstr, uint16_t *port);
|
||||
|
||||
/*!
|
||||
\brief Extract a username from a packet attribute
|
||||
\param attribute the attribute from which to extract
|
||||
\param username a buffer to write the string representation of the username
|
||||
\param len the maximum size of the username buffer
|
||||
\return a pointer to the username or NULL
|
||||
*/
|
||||
char *stun_packet_attribute_get_username(stun_packet_attribute_t *attribute, char *username, uint16_t len);
|
||||
|
||||
|
||||
/*!
|
||||
\brief Prepare a new outbound packet of a certian type and id
|
||||
\param id id to use (NULL for an auto generated id)
|
||||
\param type the stun packet type
|
||||
\param buf a pointer to data to use for the packet
|
||||
\return a pointer to a ready-to-use stun packet
|
||||
*/
|
||||
stun_packet_t *stun_packet_build_header(stun_message_t type,
|
||||
char *id,
|
||||
uint8_t *buf
|
||||
);
|
||||
|
||||
/*!
|
||||
\brief Add a username packet attribute
|
||||
\param packet the packet to add the attribute to
|
||||
\param username the string representation of the username
|
||||
\param ulen the length of the username
|
||||
\return true or false
|
||||
*/
|
||||
uint8_t stun_packet_attribute_add_username(stun_packet_t *packet, char *username, uint16_t ulen);
|
||||
|
||||
|
||||
/*!
|
||||
\brief Add a binded address packet attribute
|
||||
\param packet the packet to add the attribute to
|
||||
\param ipstr the string representation of the ip
|
||||
\param port the port of the mapped address
|
||||
\return true or false
|
||||
*/
|
||||
uint8_t stun_packet_attribute_add_binded_address(stun_packet_t *packet, char *ipstr, uint16_t port);
|
||||
|
||||
/*!
|
||||
\brief set a stun_packet_attribute_t pointer to point at the first attribute in a packet
|
||||
\param packet the packet in question
|
||||
\param attribute the pointer to set up
|
||||
*/
|
||||
#define stun_packet_first_attribute(packet, attribute) attribute = &packet->first_attribute;
|
||||
|
||||
/*!
|
||||
\brief Increment an attribute pointer to the next attribute in it's packet
|
||||
\param attribute the pointer to increment
|
||||
\return true or false depending on if there are any more attributes
|
||||
*/
|
||||
#define stun_packet_next_attribute(attribute) (attribute = (stun_packet_attribute_t *) (attribute->value + attribute->length)) && attribute->length
|
||||
|
||||
/*!
|
||||
\brief Obtain the correct length in bytes of a stun packet
|
||||
\param packet the packet in question
|
||||
\return the size in bytes (host order) of the entire packet
|
||||
*/
|
||||
#define stun_packet_length(packet) ntohs(packet->header.length) + sizeof(stun_packet_header_t)
|
||||
///\}
|
||||
#endif
|
Reference in New Issue
Block a user