TURN episode #9

This commit is contained in:
bossiel 2014-05-11 22:25:35 +00:00
parent 4a39fe9cd1
commit 3fc0c3df85
97 changed files with 9179 additions and 7207 deletions

View File

@ -492,8 +492,14 @@ bool MediaSessionMgr::defaultsSetStunEnabled(bool stun_enabled){
bool MediaSessionMgr::defaultsSetIceStunEnabled(bool icestun_enabled){
return (tmedia_defaults_set_icestun_enabled(icestun_enabled ? tsk_true : tsk_false) == 0);
}
bool MediaSessionMgr::defaultsSetStunServer(const char* server_ip, uint16_t server_port, const char* usr_name /*= tsk_null*/, const char* usr_pwd /*= tsk_null*/){
return (tmedia_defaults_set_stun_server(server_ip, server_port, usr_name, usr_pwd) == 0);
bool MediaSessionMgr::defaultsSetIceTurnEnabled(bool iceturn_enabled){
return (tmedia_defaults_set_iceturn_enabled(iceturn_enabled ? tsk_true : tsk_false) == 0);
}
bool MediaSessionMgr::defaultsSetStunServer(const char* server_ip, uint16_t server_port){
return (tmedia_defaults_set_stun_server(server_ip, server_port) == 0);
}
bool MediaSessionMgr::defaultsSetStunCred(const char* username, const char* password){
return (tmedia_defaults_set_stun_cred(username, password) == 0);
}
bool MediaSessionMgr::defaultsSetIceEnabled(bool ice_enabled){
return (tmedia_defaults_set_ice_enabled(ice_enabled ? tsk_true : tsk_false) == 0);

View File

@ -142,7 +142,9 @@ public:
static bool defaultsGetRtcpMuxEnabled();
static bool defaultsSetStunEnabled(bool stun_enabled);
static bool defaultsSetIceStunEnabled(bool icestun_enabled);
static bool defaultsSetStunServer(const char* server_ip, uint16_t server_port, const char* usr_name = tsk_null, const char* usr_pwd = tsk_null);
static bool defaultsSetIceTurnEnabled(bool iceturn_enabled);
static bool defaultsSetStunServer(const char* server_ip, uint16_t server_port);
static bool defaultsSetStunCred(const char* username, const char* password);
static bool defaultsSetIceEnabled(bool ice_enabled);
static bool defaultsSetByPassEncoding(bool enabled);
static bool defaultsGetByPassEncoding();

View File

@ -463,6 +463,46 @@ bool CallSession::setICE(bool enabled)
TSIP_SSESSION_SET_NULL()) == 0);
}
bool CallSession::setICEStun(bool enabled)
{
return (tsip_ssession_set(m_pHandle,
TSIP_SSESSION_SET_MEDIA(
TSIP_MSESSION_SET_ICE_STUN(enabled ? tsk_true : tsk_false),
TSIP_MSESSION_SET_NULL()
),
TSIP_SSESSION_SET_NULL()) == 0);
}
bool CallSession::setICETurn(bool enabled)
{
return (tsip_ssession_set(m_pHandle,
TSIP_SSESSION_SET_MEDIA(
TSIP_MSESSION_SET_ICE_TURN(enabled ? tsk_true : tsk_false),
TSIP_MSESSION_SET_NULL()
),
TSIP_SSESSION_SET_NULL()) == 0);
}
bool CallSession::setSTUNServer(const char* hostname, uint16_t port)
{
return (tsip_ssession_set(m_pHandle,
TSIP_SSESSION_SET_MEDIA(
TSIP_MSESSION_SET_STUN_SERVER(hostname, port),
TSIP_MSESSION_SET_NULL()
),
TSIP_SSESSION_SET_NULL()) == 0);
}
bool CallSession::setSTUNCred(const char* username, const char* password)
{
return (tsip_ssession_set(m_pHandle,
TSIP_SSESSION_SET_MEDIA(
TSIP_MSESSION_SET_STUN_CRED(username, password),
TSIP_MSESSION_SET_NULL()
),
TSIP_SSESSION_SET_NULL()) == 0);
}
bool CallSession::setQoS(tmedia_qos_stype_t type, tmedia_qos_strength_t strength)
{
return (tsip_ssession_set(m_pHandle,

View File

@ -194,6 +194,10 @@ public: /* Public functions */
bool setSRtpMode(enum tmedia_srtp_mode_e mode);
bool setAvpfMode(enum tmedia_mode_e mode);
bool setICE(bool enabled);
bool setICEStun(bool enabled);
bool setICETurn(bool enabled);
bool setSTUNServer(const char* hostname, uint16_t port);
bool setSTUNCred(const char* username, const char* password);
bool setQoS(tmedia_qos_stype_t type, tmedia_qos_strength_t strength);
bool hold(ActionConfig* config=tsk_null);
bool resume(ActionConfig* config=tsk_null);

View File

@ -234,27 +234,48 @@ bool SipStack::removeSigCompCompartment(const char* compId)
TSIP_STACK_SET_NULL()) == 0);
}
// @deprecated
bool SipStack::setSTUNEnabledForICE(bool enabled)
{
#if 0
tsk_bool_t _enabled = enabled ? tsk_true : tsk_false;
return (tsip_stack_set(m_pHandle,
TSIP_STACK_SET_ICE_STUN_ENABLED(_enabled),
TSIP_STACK_SET_NULL()) == 0);
#else
// set global value
return (tmedia_defaults_set_icestun_enabled(enabled ? tsk_true : tsk_false) == 0);
// to set the value per session, use "CallSession::setICEStun()"
#endif
}
bool SipStack::setSTUNServer(const char* ip, unsigned short port)
// @deprecated
bool SipStack::setSTUNServer(const char* hostname, unsigned short port)
{
#if 0
unsigned _port = port;//promote
return (tsip_stack_set(m_pHandle,
TSIP_STACK_SET_STUN_SERVER(ip, _port),
TSIP_STACK_SET_STUN_SERVER(hostname, _port),
TSIP_STACK_SET_NULL()) == 0);
#else
// set global value
return (tmedia_defaults_set_stun_server(hostname, port) == 0);
// to set the value per session, use "CallSession::setSTUNServer()"
#endif
}
// @deprecated
bool SipStack::setSTUNCred(const char* login, const char* password)
{
#if 0
return (tsip_stack_set(m_pHandle,
TSIP_STACK_SET_STUN_CRED(login, password),
TSIP_STACK_SET_NULL()) == 0);
#else
// set global value
return (tmedia_defaults_set_stun_cred(login, password) == 0);
// to set the value per session, use "CallSession::setSTUNCred()"
#endif
}
bool SipStack::setSTUNEnabled(bool enabled)

View File

@ -65,9 +65,9 @@ public: /* API functions */
bool addSigCompCompartment(const char* compId);
bool removeSigCompCompartment(const char* compId);
bool setSTUNEnabledForICE(bool enabled);
bool setSTUNServer(const char* ip, unsigned short port);
bool setSTUNCred(const char* login, const char* password);
bool setSTUNEnabledForICE(bool enabled); // @deprecated
bool setSTUNServer(const char* hostname, unsigned short port); // @deprecated
bool setSTUNCred(const char* login, const char* password); // @deprecated
bool setSTUNEnabled(bool enabled);
bool setTLSSecAgree(bool enabled);

View File

@ -158,6 +158,26 @@ public class CallSession : InviteSession {
return ret;
}
public bool setICEStun(bool enabled) {
bool ret = tinyWRAPPINVOKE.CallSession_setICEStun(swigCPtr, enabled);
return ret;
}
public bool setICETurn(bool enabled) {
bool ret = tinyWRAPPINVOKE.CallSession_setICETurn(swigCPtr, enabled);
return ret;
}
public bool setSTUNServer(string hostname, ushort port) {
bool ret = tinyWRAPPINVOKE.CallSession_setSTUNServer(swigCPtr, hostname, port);
return ret;
}
public bool setSTUNCred(string username, string password) {
bool ret = tinyWRAPPINVOKE.CallSession_setSTUNCred(swigCPtr, username, password);
return ret;
}
public bool setQoS(tmedia_qos_stype_t type, tmedia_qos_strength_t strength) {
bool ret = tinyWRAPPINVOKE.CallSession_setQoS(swigCPtr, (int)type, (int)strength);
return ret;

View File

@ -344,18 +344,18 @@ public class MediaSessionMgr : IDisposable {
return ret;
}
public static bool defaultsSetStunServer(string server_ip, ushort server_port, string usr_name, string usr_pwd) {
bool ret = tinyWRAPPINVOKE.MediaSessionMgr_defaultsSetStunServer__SWIG_0(server_ip, server_port, usr_name, usr_pwd);
return ret;
}
public static bool defaultsSetStunServer(string server_ip, ushort server_port, string usr_name) {
bool ret = tinyWRAPPINVOKE.MediaSessionMgr_defaultsSetStunServer__SWIG_1(server_ip, server_port, usr_name);
public static bool defaultsSetIceTurnEnabled(bool iceturn_enabled) {
bool ret = tinyWRAPPINVOKE.MediaSessionMgr_defaultsSetIceTurnEnabled(iceturn_enabled);
return ret;
}
public static bool defaultsSetStunServer(string server_ip, ushort server_port) {
bool ret = tinyWRAPPINVOKE.MediaSessionMgr_defaultsSetStunServer__SWIG_2(server_ip, server_port);
bool ret = tinyWRAPPINVOKE.MediaSessionMgr_defaultsSetStunServer(server_ip, server_port);
return ret;
}
public static bool defaultsSetStunCred(string username, string password) {
bool ret = tinyWRAPPINVOKE.MediaSessionMgr_defaultsSetStunCred(username, password);
return ret;
}

View File

@ -163,8 +163,8 @@ public class SipStack : SafeObject {
return ret;
}
public bool setSTUNServer(string ip, ushort port) {
bool ret = tinyWRAPPINVOKE.SipStack_setSTUNServer(swigCPtr, ip, port);
public bool setSTUNServer(string hostname, ushort port) {
bool ret = tinyWRAPPINVOKE.SipStack_setSTUNServer(swigCPtr, hostname, port);
return ret;
}

View File

@ -471,14 +471,14 @@ class tinyWRAPPINVOKE {
[DllImport("tinyWRAP", EntryPoint="CSharp_MediaSessionMgr_defaultsSetIceStunEnabled")]
public static extern bool MediaSessionMgr_defaultsSetIceStunEnabled(bool jarg1);
[DllImport("tinyWRAP", EntryPoint="CSharp_MediaSessionMgr_defaultsSetStunServer__SWIG_0")]
public static extern bool MediaSessionMgr_defaultsSetStunServer__SWIG_0(string jarg1, ushort jarg2, string jarg3, string jarg4);
[DllImport("tinyWRAP", EntryPoint="CSharp_MediaSessionMgr_defaultsSetIceTurnEnabled")]
public static extern bool MediaSessionMgr_defaultsSetIceTurnEnabled(bool jarg1);
[DllImport("tinyWRAP", EntryPoint="CSharp_MediaSessionMgr_defaultsSetStunServer__SWIG_1")]
public static extern bool MediaSessionMgr_defaultsSetStunServer__SWIG_1(string jarg1, ushort jarg2, string jarg3);
[DllImport("tinyWRAP", EntryPoint="CSharp_MediaSessionMgr_defaultsSetStunServer")]
public static extern bool MediaSessionMgr_defaultsSetStunServer(string jarg1, ushort jarg2);
[DllImport("tinyWRAP", EntryPoint="CSharp_MediaSessionMgr_defaultsSetStunServer__SWIG_2")]
public static extern bool MediaSessionMgr_defaultsSetStunServer__SWIG_2(string jarg1, ushort jarg2);
[DllImport("tinyWRAP", EntryPoint="CSharp_MediaSessionMgr_defaultsSetStunCred")]
public static extern bool MediaSessionMgr_defaultsSetStunCred(string jarg1, string jarg2);
[DllImport("tinyWRAP", EntryPoint="CSharp_MediaSessionMgr_defaultsSetIceEnabled")]
public static extern bool MediaSessionMgr_defaultsSetIceEnabled(bool jarg1);
@ -954,6 +954,18 @@ class tinyWRAPPINVOKE {
[DllImport("tinyWRAP", EntryPoint="CSharp_CallSession_setICE")]
public static extern bool CallSession_setICE(HandleRef jarg1, bool jarg2);
[DllImport("tinyWRAP", EntryPoint="CSharp_CallSession_setICEStun")]
public static extern bool CallSession_setICEStun(HandleRef jarg1, bool jarg2);
[DllImport("tinyWRAP", EntryPoint="CSharp_CallSession_setICETurn")]
public static extern bool CallSession_setICETurn(HandleRef jarg1, bool jarg2);
[DllImport("tinyWRAP", EntryPoint="CSharp_CallSession_setSTUNServer")]
public static extern bool CallSession_setSTUNServer(HandleRef jarg1, string jarg2, ushort jarg3);
[DllImport("tinyWRAP", EntryPoint="CSharp_CallSession_setSTUNCred")]
public static extern bool CallSession_setSTUNCred(HandleRef jarg1, string jarg2, string jarg3);
[DllImport("tinyWRAP", EntryPoint="CSharp_CallSession_setQoS")]
public static extern bool CallSession_setQoS(HandleRef jarg1, int jarg2, int jarg3);

View File

@ -2330,41 +2330,19 @@ SWIGEXPORT unsigned int SWIGSTDCALL CSharp_MediaSessionMgr_defaultsSetIceStunEna
}
SWIGEXPORT unsigned int SWIGSTDCALL CSharp_MediaSessionMgr_defaultsSetStunServer__SWIG_0(char * jarg1, unsigned short jarg2, char * jarg3, char * jarg4) {
SWIGEXPORT unsigned int SWIGSTDCALL CSharp_MediaSessionMgr_defaultsSetIceTurnEnabled(unsigned int jarg1) {
unsigned int jresult ;
char *arg1 = (char *) 0 ;
uint16_t arg2 ;
char *arg3 = (char *) 0 ;
char *arg4 = (char *) 0 ;
bool arg1 ;
bool result;
arg1 = (char *)jarg1;
arg2 = (uint16_t)jarg2;
arg3 = (char *)jarg3;
arg4 = (char *)jarg4;
result = (bool)MediaSessionMgr::defaultsSetStunServer((char const *)arg1,arg2,(char const *)arg3,(char const *)arg4);
arg1 = jarg1 ? true : false;
result = (bool)MediaSessionMgr::defaultsSetIceTurnEnabled(arg1);
jresult = result;
return jresult;
}
SWIGEXPORT unsigned int SWIGSTDCALL CSharp_MediaSessionMgr_defaultsSetStunServer__SWIG_1(char * jarg1, unsigned short jarg2, char * jarg3) {
unsigned int jresult ;
char *arg1 = (char *) 0 ;
uint16_t arg2 ;
char *arg3 = (char *) 0 ;
bool result;
arg1 = (char *)jarg1;
arg2 = (uint16_t)jarg2;
arg3 = (char *)jarg3;
result = (bool)MediaSessionMgr::defaultsSetStunServer((char const *)arg1,arg2,(char const *)arg3);
jresult = result;
return jresult;
}
SWIGEXPORT unsigned int SWIGSTDCALL CSharp_MediaSessionMgr_defaultsSetStunServer__SWIG_2(char * jarg1, unsigned short jarg2) {
SWIGEXPORT unsigned int SWIGSTDCALL CSharp_MediaSessionMgr_defaultsSetStunServer(char * jarg1, unsigned short jarg2) {
unsigned int jresult ;
char *arg1 = (char *) 0 ;
uint16_t arg2 ;
@ -2378,6 +2356,20 @@ SWIGEXPORT unsigned int SWIGSTDCALL CSharp_MediaSessionMgr_defaultsSetStunServer
}
SWIGEXPORT unsigned int SWIGSTDCALL CSharp_MediaSessionMgr_defaultsSetStunCred(char * jarg1, char * jarg2) {
unsigned int jresult ;
char *arg1 = (char *) 0 ;
char *arg2 = (char *) 0 ;
bool result;
arg1 = (char *)jarg1;
arg2 = (char *)jarg2;
result = (bool)MediaSessionMgr::defaultsSetStunCred((char const *)arg1,(char const *)arg2);
jresult = result;
return jresult;
}
SWIGEXPORT unsigned int SWIGSTDCALL CSharp_MediaSessionMgr_defaultsSetIceEnabled(unsigned int jarg1) {
unsigned int jresult ;
bool arg1 ;
@ -4364,6 +4356,66 @@ SWIGEXPORT unsigned int SWIGSTDCALL CSharp_CallSession_setICE(void * jarg1, unsi
}
SWIGEXPORT unsigned int SWIGSTDCALL CSharp_CallSession_setICEStun(void * jarg1, unsigned int jarg2) {
unsigned int jresult ;
CallSession *arg1 = (CallSession *) 0 ;
bool arg2 ;
bool result;
arg1 = (CallSession *)jarg1;
arg2 = jarg2 ? true : false;
result = (bool)(arg1)->setICEStun(arg2);
jresult = result;
return jresult;
}
SWIGEXPORT unsigned int SWIGSTDCALL CSharp_CallSession_setICETurn(void * jarg1, unsigned int jarg2) {
unsigned int jresult ;
CallSession *arg1 = (CallSession *) 0 ;
bool arg2 ;
bool result;
arg1 = (CallSession *)jarg1;
arg2 = jarg2 ? true : false;
result = (bool)(arg1)->setICETurn(arg2);
jresult = result;
return jresult;
}
SWIGEXPORT unsigned int SWIGSTDCALL CSharp_CallSession_setSTUNServer(void * jarg1, char * jarg2, unsigned short jarg3) {
unsigned int jresult ;
CallSession *arg1 = (CallSession *) 0 ;
char *arg2 = (char *) 0 ;
uint16_t arg3 ;
bool result;
arg1 = (CallSession *)jarg1;
arg2 = (char *)jarg2;
arg3 = (uint16_t)jarg3;
result = (bool)(arg1)->setSTUNServer((char const *)arg2,arg3);
jresult = result;
return jresult;
}
SWIGEXPORT unsigned int SWIGSTDCALL CSharp_CallSession_setSTUNCred(void * jarg1, char * jarg2, char * jarg3) {
unsigned int jresult ;
CallSession *arg1 = (CallSession *) 0 ;
char *arg2 = (char *) 0 ;
char *arg3 = (char *) 0 ;
bool result;
arg1 = (CallSession *)jarg1;
arg2 = (char *)jarg2;
arg3 = (char *)jarg3;
result = (bool)(arg1)->setSTUNCred((char const *)arg2,(char const *)arg3);
jresult = result;
return jresult;
}
SWIGEXPORT unsigned int SWIGSTDCALL CSharp_CallSession_setQoS(void * jarg1, int jarg2, int jarg3) {
unsigned int jresult ;
CallSession *arg1 = (CallSession *) 0 ;

View File

@ -131,6 +131,22 @@ public class CallSession extends InviteSession {
return tinyWRAPJNI.CallSession_setICE(swigCPtr, this, enabled);
}
public boolean setICEStun(boolean enabled) {
return tinyWRAPJNI.CallSession_setICEStun(swigCPtr, this, enabled);
}
public boolean setICETurn(boolean enabled) {
return tinyWRAPJNI.CallSession_setICETurn(swigCPtr, this, enabled);
}
public boolean setSTUNServer(String hostname, int port) {
return tinyWRAPJNI.CallSession_setSTUNServer(swigCPtr, this, hostname, port);
}
public boolean setSTUNCred(String username, String password) {
return tinyWRAPJNI.CallSession_setSTUNCred(swigCPtr, this, username, password);
}
public boolean setQoS(tmedia_qos_stype_t type, tmedia_qos_strength_t strength) {
return tinyWRAPJNI.CallSession_setQoS(swigCPtr, this, type.swigValue(), strength.swigValue());
}

View File

@ -278,16 +278,16 @@ public class MediaSessionMgr {
return tinyWRAPJNI.MediaSessionMgr_defaultsSetIceStunEnabled(icestun_enabled);
}
public static boolean defaultsSetStunServer(String server_ip, int server_port, String usr_name, String usr_pwd) {
return tinyWRAPJNI.MediaSessionMgr_defaultsSetStunServer__SWIG_0(server_ip, server_port, usr_name, usr_pwd);
}
public static boolean defaultsSetStunServer(String server_ip, int server_port, String usr_name) {
return tinyWRAPJNI.MediaSessionMgr_defaultsSetStunServer__SWIG_1(server_ip, server_port, usr_name);
public static boolean defaultsSetIceTurnEnabled(boolean iceturn_enabled) {
return tinyWRAPJNI.MediaSessionMgr_defaultsSetIceTurnEnabled(iceturn_enabled);
}
public static boolean defaultsSetStunServer(String server_ip, int server_port) {
return tinyWRAPJNI.MediaSessionMgr_defaultsSetStunServer__SWIG_2(server_ip, server_port);
return tinyWRAPJNI.MediaSessionMgr_defaultsSetStunServer(server_ip, server_port);
}
public static boolean defaultsSetStunCred(String username, String password) {
return tinyWRAPJNI.MediaSessionMgr_defaultsSetStunCred(username, password);
}
public static boolean defaultsSetIceEnabled(boolean ice_enabled) {

View File

@ -135,8 +135,8 @@ public class SipStack extends SafeObject {
return tinyWRAPJNI.SipStack_setSTUNEnabledForICE(swigCPtr, this, enabled);
}
public boolean setSTUNServer(String ip, int port) {
return tinyWRAPJNI.SipStack_setSTUNServer(swigCPtr, this, ip, port);
public boolean setSTUNServer(String hostname, int port) {
return tinyWRAPJNI.SipStack_setSTUNServer(swigCPtr, this, hostname, port);
}
public boolean setSTUNCred(String login, String password) {

View File

@ -131,6 +131,22 @@ public class CallSession extends InviteSession {
return tinyWRAPJNI.CallSession_setICE(swigCPtr, this, enabled);
}
public boolean setICEStun(boolean enabled) {
return tinyWRAPJNI.CallSession_setICEStun(swigCPtr, this, enabled);
}
public boolean setICETurn(boolean enabled) {
return tinyWRAPJNI.CallSession_setICETurn(swigCPtr, this, enabled);
}
public boolean setSTUNServer(String hostname, int port) {
return tinyWRAPJNI.CallSession_setSTUNServer(swigCPtr, this, hostname, port);
}
public boolean setSTUNCred(String username, String password) {
return tinyWRAPJNI.CallSession_setSTUNCred(swigCPtr, this, username, password);
}
public boolean setQoS(tmedia_qos_stype_t type, tmedia_qos_strength_t strength) {
return tinyWRAPJNI.CallSession_setQoS(swigCPtr, this, type.swigValue(), strength.swigValue());
}

View File

@ -278,16 +278,16 @@ public class MediaSessionMgr {
return tinyWRAPJNI.MediaSessionMgr_defaultsSetIceStunEnabled(icestun_enabled);
}
public static boolean defaultsSetStunServer(String server_ip, int server_port, String usr_name, String usr_pwd) {
return tinyWRAPJNI.MediaSessionMgr_defaultsSetStunServer__SWIG_0(server_ip, server_port, usr_name, usr_pwd);
}
public static boolean defaultsSetStunServer(String server_ip, int server_port, String usr_name) {
return tinyWRAPJNI.MediaSessionMgr_defaultsSetStunServer__SWIG_1(server_ip, server_port, usr_name);
public static boolean defaultsSetIceTurnEnabled(boolean iceturn_enabled) {
return tinyWRAPJNI.MediaSessionMgr_defaultsSetIceTurnEnabled(iceturn_enabled);
}
public static boolean defaultsSetStunServer(String server_ip, int server_port) {
return tinyWRAPJNI.MediaSessionMgr_defaultsSetStunServer__SWIG_2(server_ip, server_port);
return tinyWRAPJNI.MediaSessionMgr_defaultsSetStunServer(server_ip, server_port);
}
public static boolean defaultsSetStunCred(String username, String password) {
return tinyWRAPJNI.MediaSessionMgr_defaultsSetStunCred(username, password);
}
public static boolean defaultsSetIceEnabled(boolean ice_enabled) {

View File

@ -135,8 +135,8 @@ public class SipStack extends SafeObject {
return tinyWRAPJNI.SipStack_setSTUNEnabledForICE(swigCPtr, this, enabled);
}
public boolean setSTUNServer(String ip, int port) {
return tinyWRAPJNI.SipStack_setSTUNServer(swigCPtr, this, ip, port);
public boolean setSTUNServer(String hostname, int port) {
return tinyWRAPJNI.SipStack_setSTUNServer(swigCPtr, this, hostname, port);
}
public boolean setSTUNCred(String login, String password) {

View File

@ -104,9 +104,9 @@ public class tinyWRAPJNI {
public final static native boolean MediaSessionMgr_defaultsGetRtcpMuxEnabled();
public final static native boolean MediaSessionMgr_defaultsSetStunEnabled(boolean jarg1);
public final static native boolean MediaSessionMgr_defaultsSetIceStunEnabled(boolean jarg1);
public final static native boolean MediaSessionMgr_defaultsSetStunServer__SWIG_0(String jarg1, int jarg2, String jarg3, String jarg4);
public final static native boolean MediaSessionMgr_defaultsSetStunServer__SWIG_1(String jarg1, int jarg2, String jarg3);
public final static native boolean MediaSessionMgr_defaultsSetStunServer__SWIG_2(String jarg1, int jarg2);
public final static native boolean MediaSessionMgr_defaultsSetIceTurnEnabled(boolean jarg1);
public final static native boolean MediaSessionMgr_defaultsSetStunServer(String jarg1, int jarg2);
public final static native boolean MediaSessionMgr_defaultsSetStunCred(String jarg1, String jarg2);
public final static native boolean MediaSessionMgr_defaultsSetIceEnabled(boolean jarg1);
public final static native boolean MediaSessionMgr_defaultsSetByPassEncoding(boolean jarg1);
public final static native boolean MediaSessionMgr_defaultsGetByPassEncoding();
@ -266,6 +266,10 @@ public class tinyWRAPJNI {
public final static native boolean CallSession_setSRtpMode(long jarg1, CallSession jarg1_, int jarg2);
public final static native boolean CallSession_setAvpfMode(long jarg1, CallSession jarg1_, int jarg2);
public final static native boolean CallSession_setICE(long jarg1, CallSession jarg1_, boolean jarg2);
public final static native boolean CallSession_setICEStun(long jarg1, CallSession jarg1_, boolean jarg2);
public final static native boolean CallSession_setICETurn(long jarg1, CallSession jarg1_, boolean jarg2);
public final static native boolean CallSession_setSTUNServer(long jarg1, CallSession jarg1_, String jarg2, int jarg3);
public final static native boolean CallSession_setSTUNCred(long jarg1, CallSession jarg1_, String jarg2, String jarg3);
public final static native boolean CallSession_setQoS(long jarg1, CallSession jarg1_, int jarg2, int jarg3);
public final static native boolean CallSession_hold__SWIG_0(long jarg1, CallSession jarg1_, long jarg2, ActionConfig jarg2_);
public final static native boolean CallSession_hold__SWIG_1(long jarg1, CallSession jarg1_);

View File

@ -3460,70 +3460,21 @@ SWIGEXPORT jboolean JNICALL Java_org_doubango_tinyWRAP_tinyWRAPJNI_MediaSessionM
}
SWIGEXPORT jboolean JNICALL Java_org_doubango_tinyWRAP_tinyWRAPJNI_MediaSessionMgr_1defaultsSetStunServer_1_1SWIG_10(JNIEnv *jenv, jclass jcls, jstring jarg1, jint jarg2, jstring jarg3, jstring jarg4) {
SWIGEXPORT jboolean JNICALL Java_org_doubango_tinyWRAP_tinyWRAPJNI_MediaSessionMgr_1defaultsSetIceTurnEnabled(JNIEnv *jenv, jclass jcls, jboolean jarg1) {
jboolean jresult = 0 ;
char *arg1 = (char *) 0 ;
uint16_t arg2 ;
char *arg3 = (char *) 0 ;
char *arg4 = (char *) 0 ;
bool arg1 ;
bool result;
(void)jenv;
(void)jcls;
arg1 = 0;
if (jarg1) {
arg1 = (char *)jenv->GetStringUTFChars(jarg1, 0);
if (!arg1) return 0;
}
arg2 = (uint16_t)jarg2;
arg3 = 0;
if (jarg3) {
arg3 = (char *)jenv->GetStringUTFChars(jarg3, 0);
if (!arg3) return 0;
}
arg4 = 0;
if (jarg4) {
arg4 = (char *)jenv->GetStringUTFChars(jarg4, 0);
if (!arg4) return 0;
}
result = (bool)MediaSessionMgr::defaultsSetStunServer((char const *)arg1,arg2,(char const *)arg3,(char const *)arg4);
arg1 = jarg1 ? true : false;
result = (bool)MediaSessionMgr::defaultsSetIceTurnEnabled(arg1);
jresult = (jboolean)result;
if (arg1) jenv->ReleaseStringUTFChars(jarg1, (const char *)arg1);
if (arg3) jenv->ReleaseStringUTFChars(jarg3, (const char *)arg3);
if (arg4) jenv->ReleaseStringUTFChars(jarg4, (const char *)arg4);
return jresult;
}
SWIGEXPORT jboolean JNICALL Java_org_doubango_tinyWRAP_tinyWRAPJNI_MediaSessionMgr_1defaultsSetStunServer_1_1SWIG_11(JNIEnv *jenv, jclass jcls, jstring jarg1, jint jarg2, jstring jarg3) {
jboolean jresult = 0 ;
char *arg1 = (char *) 0 ;
uint16_t arg2 ;
char *arg3 = (char *) 0 ;
bool result;
(void)jenv;
(void)jcls;
arg1 = 0;
if (jarg1) {
arg1 = (char *)jenv->GetStringUTFChars(jarg1, 0);
if (!arg1) return 0;
}
arg2 = (uint16_t)jarg2;
arg3 = 0;
if (jarg3) {
arg3 = (char *)jenv->GetStringUTFChars(jarg3, 0);
if (!arg3) return 0;
}
result = (bool)MediaSessionMgr::defaultsSetStunServer((char const *)arg1,arg2,(char const *)arg3);
jresult = (jboolean)result;
if (arg1) jenv->ReleaseStringUTFChars(jarg1, (const char *)arg1);
if (arg3) jenv->ReleaseStringUTFChars(jarg3, (const char *)arg3);
return jresult;
}
SWIGEXPORT jboolean JNICALL Java_org_doubango_tinyWRAP_tinyWRAPJNI_MediaSessionMgr_1defaultsSetStunServer_1_1SWIG_12(JNIEnv *jenv, jclass jcls, jstring jarg1, jint jarg2) {
SWIGEXPORT jboolean JNICALL Java_org_doubango_tinyWRAP_tinyWRAPJNI_MediaSessionMgr_1defaultsSetStunServer(JNIEnv *jenv, jclass jcls, jstring jarg1, jint jarg2) {
jboolean jresult = 0 ;
char *arg1 = (char *) 0 ;
uint16_t arg2 ;
@ -3544,6 +3495,32 @@ SWIGEXPORT jboolean JNICALL Java_org_doubango_tinyWRAP_tinyWRAPJNI_MediaSessionM
}
SWIGEXPORT jboolean JNICALL Java_org_doubango_tinyWRAP_tinyWRAPJNI_MediaSessionMgr_1defaultsSetStunCred(JNIEnv *jenv, jclass jcls, jstring jarg1, jstring jarg2) {
jboolean jresult = 0 ;
char *arg1 = (char *) 0 ;
char *arg2 = (char *) 0 ;
bool result;
(void)jenv;
(void)jcls;
arg1 = 0;
if (jarg1) {
arg1 = (char *)jenv->GetStringUTFChars(jarg1, 0);
if (!arg1) return 0;
}
arg2 = 0;
if (jarg2) {
arg2 = (char *)jenv->GetStringUTFChars(jarg2, 0);
if (!arg2) return 0;
}
result = (bool)MediaSessionMgr::defaultsSetStunCred((char const *)arg1,(char const *)arg2);
jresult = (jboolean)result;
if (arg1) jenv->ReleaseStringUTFChars(jarg1, (const char *)arg1);
if (arg2) jenv->ReleaseStringUTFChars(jarg2, (const char *)arg2);
return jresult;
}
SWIGEXPORT jboolean JNICALL Java_org_doubango_tinyWRAP_tinyWRAPJNI_MediaSessionMgr_1defaultsSetIceEnabled(JNIEnv *jenv, jclass jcls, jboolean jarg1) {
jboolean jresult = 0 ;
bool arg1 ;
@ -6195,6 +6172,93 @@ SWIGEXPORT jboolean JNICALL Java_org_doubango_tinyWRAP_tinyWRAPJNI_CallSession_1
}
SWIGEXPORT jboolean JNICALL Java_org_doubango_tinyWRAP_tinyWRAPJNI_CallSession_1setICEStun(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jboolean jarg2) {
jboolean jresult = 0 ;
CallSession *arg1 = (CallSession *) 0 ;
bool arg2 ;
bool result;
(void)jenv;
(void)jcls;
(void)jarg1_;
arg1 = *(CallSession **)&jarg1;
arg2 = jarg2 ? true : false;
result = (bool)(arg1)->setICEStun(arg2);
jresult = (jboolean)result;
return jresult;
}
SWIGEXPORT jboolean JNICALL Java_org_doubango_tinyWRAP_tinyWRAPJNI_CallSession_1setICETurn(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jboolean jarg2) {
jboolean jresult = 0 ;
CallSession *arg1 = (CallSession *) 0 ;
bool arg2 ;
bool result;
(void)jenv;
(void)jcls;
(void)jarg1_;
arg1 = *(CallSession **)&jarg1;
arg2 = jarg2 ? true : false;
result = (bool)(arg1)->setICETurn(arg2);
jresult = (jboolean)result;
return jresult;
}
SWIGEXPORT jboolean JNICALL Java_org_doubango_tinyWRAP_tinyWRAPJNI_CallSession_1setSTUNServer(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2, jint jarg3) {
jboolean jresult = 0 ;
CallSession *arg1 = (CallSession *) 0 ;
char *arg2 = (char *) 0 ;
uint16_t arg3 ;
bool result;
(void)jenv;
(void)jcls;
(void)jarg1_;
arg1 = *(CallSession **)&jarg1;
arg2 = 0;
if (jarg2) {
arg2 = (char *)jenv->GetStringUTFChars(jarg2, 0);
if (!arg2) return 0;
}
arg3 = (uint16_t)jarg3;
result = (bool)(arg1)->setSTUNServer((char const *)arg2,arg3);
jresult = (jboolean)result;
if (arg2) jenv->ReleaseStringUTFChars(jarg2, (const char *)arg2);
return jresult;
}
SWIGEXPORT jboolean JNICALL Java_org_doubango_tinyWRAP_tinyWRAPJNI_CallSession_1setSTUNCred(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2, jstring jarg3) {
jboolean jresult = 0 ;
CallSession *arg1 = (CallSession *) 0 ;
char *arg2 = (char *) 0 ;
char *arg3 = (char *) 0 ;
bool result;
(void)jenv;
(void)jcls;
(void)jarg1_;
arg1 = *(CallSession **)&jarg1;
arg2 = 0;
if (jarg2) {
arg2 = (char *)jenv->GetStringUTFChars(jarg2, 0);
if (!arg2) return 0;
}
arg3 = 0;
if (jarg3) {
arg3 = (char *)jenv->GetStringUTFChars(jarg3, 0);
if (!arg3) return 0;
}
result = (bool)(arg1)->setSTUNCred((char const *)arg2,(char const *)arg3);
jresult = (jboolean)result;
if (arg2) jenv->ReleaseStringUTFChars(jarg2, (const char *)arg2);
if (arg3) jenv->ReleaseStringUTFChars(jarg3, (const char *)arg3);
return jresult;
}
SWIGEXPORT jboolean JNICALL Java_org_doubango_tinyWRAP_tinyWRAPJNI_CallSession_1setQoS(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jint jarg2, jint jarg3) {
jboolean jresult = 0 ;
CallSession *arg1 = (CallSession *) 0 ;

View File

@ -104,9 +104,9 @@ public class tinyWRAPJNI {
public final static native boolean MediaSessionMgr_defaultsGetRtcpMuxEnabled();
public final static native boolean MediaSessionMgr_defaultsSetStunEnabled(boolean jarg1);
public final static native boolean MediaSessionMgr_defaultsSetIceStunEnabled(boolean jarg1);
public final static native boolean MediaSessionMgr_defaultsSetStunServer__SWIG_0(String jarg1, int jarg2, String jarg3, String jarg4);
public final static native boolean MediaSessionMgr_defaultsSetStunServer__SWIG_1(String jarg1, int jarg2, String jarg3);
public final static native boolean MediaSessionMgr_defaultsSetStunServer__SWIG_2(String jarg1, int jarg2);
public final static native boolean MediaSessionMgr_defaultsSetIceTurnEnabled(boolean jarg1);
public final static native boolean MediaSessionMgr_defaultsSetStunServer(String jarg1, int jarg2);
public final static native boolean MediaSessionMgr_defaultsSetStunCred(String jarg1, String jarg2);
public final static native boolean MediaSessionMgr_defaultsSetIceEnabled(boolean jarg1);
public final static native boolean MediaSessionMgr_defaultsSetByPassEncoding(boolean jarg1);
public final static native boolean MediaSessionMgr_defaultsGetByPassEncoding();
@ -266,6 +266,10 @@ public class tinyWRAPJNI {
public final static native boolean CallSession_setSRtpMode(long jarg1, CallSession jarg1_, int jarg2);
public final static native boolean CallSession_setAvpfMode(long jarg1, CallSession jarg1_, int jarg2);
public final static native boolean CallSession_setICE(long jarg1, CallSession jarg1_, boolean jarg2);
public final static native boolean CallSession_setICEStun(long jarg1, CallSession jarg1_, boolean jarg2);
public final static native boolean CallSession_setICETurn(long jarg1, CallSession jarg1_, boolean jarg2);
public final static native boolean CallSession_setSTUNServer(long jarg1, CallSession jarg1_, String jarg2, int jarg3);
public final static native boolean CallSession_setSTUNCred(long jarg1, CallSession jarg1_, String jarg2, String jarg3);
public final static native boolean CallSession_setQoS(long jarg1, CallSession jarg1_, int jarg2, int jarg3);
public final static native boolean CallSession_hold__SWIG_0(long jarg1, CallSession jarg1_, long jarg2, ActionConfig jarg2_);
public final static native boolean CallSession_hold__SWIG_1(long jarg1, CallSession jarg1_);

View File

@ -3460,70 +3460,21 @@ SWIGEXPORT jboolean JNICALL Java_org_doubango_tinyWRAP_tinyWRAPJNI_MediaSessionM
}
SWIGEXPORT jboolean JNICALL Java_org_doubango_tinyWRAP_tinyWRAPJNI_MediaSessionMgr_1defaultsSetStunServer_1_1SWIG_10(JNIEnv *jenv, jclass jcls, jstring jarg1, jint jarg2, jstring jarg3, jstring jarg4) {
SWIGEXPORT jboolean JNICALL Java_org_doubango_tinyWRAP_tinyWRAPJNI_MediaSessionMgr_1defaultsSetIceTurnEnabled(JNIEnv *jenv, jclass jcls, jboolean jarg1) {
jboolean jresult = 0 ;
char *arg1 = (char *) 0 ;
uint16_t arg2 ;
char *arg3 = (char *) 0 ;
char *arg4 = (char *) 0 ;
bool arg1 ;
bool result;
(void)jenv;
(void)jcls;
arg1 = 0;
if (jarg1) {
arg1 = (char *)jenv->GetStringUTFChars(jarg1, 0);
if (!arg1) return 0;
}
arg2 = (uint16_t)jarg2;
arg3 = 0;
if (jarg3) {
arg3 = (char *)jenv->GetStringUTFChars(jarg3, 0);
if (!arg3) return 0;
}
arg4 = 0;
if (jarg4) {
arg4 = (char *)jenv->GetStringUTFChars(jarg4, 0);
if (!arg4) return 0;
}
result = (bool)MediaSessionMgr::defaultsSetStunServer((char const *)arg1,arg2,(char const *)arg3,(char const *)arg4);
arg1 = jarg1 ? true : false;
result = (bool)MediaSessionMgr::defaultsSetIceTurnEnabled(arg1);
jresult = (jboolean)result;
if (arg1) jenv->ReleaseStringUTFChars(jarg1, (const char *)arg1);
if (arg3) jenv->ReleaseStringUTFChars(jarg3, (const char *)arg3);
if (arg4) jenv->ReleaseStringUTFChars(jarg4, (const char *)arg4);
return jresult;
}
SWIGEXPORT jboolean JNICALL Java_org_doubango_tinyWRAP_tinyWRAPJNI_MediaSessionMgr_1defaultsSetStunServer_1_1SWIG_11(JNIEnv *jenv, jclass jcls, jstring jarg1, jint jarg2, jstring jarg3) {
jboolean jresult = 0 ;
char *arg1 = (char *) 0 ;
uint16_t arg2 ;
char *arg3 = (char *) 0 ;
bool result;
(void)jenv;
(void)jcls;
arg1 = 0;
if (jarg1) {
arg1 = (char *)jenv->GetStringUTFChars(jarg1, 0);
if (!arg1) return 0;
}
arg2 = (uint16_t)jarg2;
arg3 = 0;
if (jarg3) {
arg3 = (char *)jenv->GetStringUTFChars(jarg3, 0);
if (!arg3) return 0;
}
result = (bool)MediaSessionMgr::defaultsSetStunServer((char const *)arg1,arg2,(char const *)arg3);
jresult = (jboolean)result;
if (arg1) jenv->ReleaseStringUTFChars(jarg1, (const char *)arg1);
if (arg3) jenv->ReleaseStringUTFChars(jarg3, (const char *)arg3);
return jresult;
}
SWIGEXPORT jboolean JNICALL Java_org_doubango_tinyWRAP_tinyWRAPJNI_MediaSessionMgr_1defaultsSetStunServer_1_1SWIG_12(JNIEnv *jenv, jclass jcls, jstring jarg1, jint jarg2) {
SWIGEXPORT jboolean JNICALL Java_org_doubango_tinyWRAP_tinyWRAPJNI_MediaSessionMgr_1defaultsSetStunServer(JNIEnv *jenv, jclass jcls, jstring jarg1, jint jarg2) {
jboolean jresult = 0 ;
char *arg1 = (char *) 0 ;
uint16_t arg2 ;
@ -3544,6 +3495,32 @@ SWIGEXPORT jboolean JNICALL Java_org_doubango_tinyWRAP_tinyWRAPJNI_MediaSessionM
}
SWIGEXPORT jboolean JNICALL Java_org_doubango_tinyWRAP_tinyWRAPJNI_MediaSessionMgr_1defaultsSetStunCred(JNIEnv *jenv, jclass jcls, jstring jarg1, jstring jarg2) {
jboolean jresult = 0 ;
char *arg1 = (char *) 0 ;
char *arg2 = (char *) 0 ;
bool result;
(void)jenv;
(void)jcls;
arg1 = 0;
if (jarg1) {
arg1 = (char *)jenv->GetStringUTFChars(jarg1, 0);
if (!arg1) return 0;
}
arg2 = 0;
if (jarg2) {
arg2 = (char *)jenv->GetStringUTFChars(jarg2, 0);
if (!arg2) return 0;
}
result = (bool)MediaSessionMgr::defaultsSetStunCred((char const *)arg1,(char const *)arg2);
jresult = (jboolean)result;
if (arg1) jenv->ReleaseStringUTFChars(jarg1, (const char *)arg1);
if (arg2) jenv->ReleaseStringUTFChars(jarg2, (const char *)arg2);
return jresult;
}
SWIGEXPORT jboolean JNICALL Java_org_doubango_tinyWRAP_tinyWRAPJNI_MediaSessionMgr_1defaultsSetIceEnabled(JNIEnv *jenv, jclass jcls, jboolean jarg1) {
jboolean jresult = 0 ;
bool arg1 ;
@ -6195,6 +6172,93 @@ SWIGEXPORT jboolean JNICALL Java_org_doubango_tinyWRAP_tinyWRAPJNI_CallSession_1
}
SWIGEXPORT jboolean JNICALL Java_org_doubango_tinyWRAP_tinyWRAPJNI_CallSession_1setICEStun(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jboolean jarg2) {
jboolean jresult = 0 ;
CallSession *arg1 = (CallSession *) 0 ;
bool arg2 ;
bool result;
(void)jenv;
(void)jcls;
(void)jarg1_;
arg1 = *(CallSession **)&jarg1;
arg2 = jarg2 ? true : false;
result = (bool)(arg1)->setICEStun(arg2);
jresult = (jboolean)result;
return jresult;
}
SWIGEXPORT jboolean JNICALL Java_org_doubango_tinyWRAP_tinyWRAPJNI_CallSession_1setICETurn(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jboolean jarg2) {
jboolean jresult = 0 ;
CallSession *arg1 = (CallSession *) 0 ;
bool arg2 ;
bool result;
(void)jenv;
(void)jcls;
(void)jarg1_;
arg1 = *(CallSession **)&jarg1;
arg2 = jarg2 ? true : false;
result = (bool)(arg1)->setICETurn(arg2);
jresult = (jboolean)result;
return jresult;
}
SWIGEXPORT jboolean JNICALL Java_org_doubango_tinyWRAP_tinyWRAPJNI_CallSession_1setSTUNServer(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2, jint jarg3) {
jboolean jresult = 0 ;
CallSession *arg1 = (CallSession *) 0 ;
char *arg2 = (char *) 0 ;
uint16_t arg3 ;
bool result;
(void)jenv;
(void)jcls;
(void)jarg1_;
arg1 = *(CallSession **)&jarg1;
arg2 = 0;
if (jarg2) {
arg2 = (char *)jenv->GetStringUTFChars(jarg2, 0);
if (!arg2) return 0;
}
arg3 = (uint16_t)jarg3;
result = (bool)(arg1)->setSTUNServer((char const *)arg2,arg3);
jresult = (jboolean)result;
if (arg2) jenv->ReleaseStringUTFChars(jarg2, (const char *)arg2);
return jresult;
}
SWIGEXPORT jboolean JNICALL Java_org_doubango_tinyWRAP_tinyWRAPJNI_CallSession_1setSTUNCred(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2, jstring jarg3) {
jboolean jresult = 0 ;
CallSession *arg1 = (CallSession *) 0 ;
char *arg2 = (char *) 0 ;
char *arg3 = (char *) 0 ;
bool result;
(void)jenv;
(void)jcls;
(void)jarg1_;
arg1 = *(CallSession **)&jarg1;
arg2 = 0;
if (jarg2) {
arg2 = (char *)jenv->GetStringUTFChars(jarg2, 0);
if (!arg2) return 0;
}
arg3 = 0;
if (jarg3) {
arg3 = (char *)jenv->GetStringUTFChars(jarg3, 0);
if (!arg3) return 0;
}
result = (bool)(arg1)->setSTUNCred((char const *)arg2,(char const *)arg3);
jresult = (jboolean)result;
if (arg2) jenv->ReleaseStringUTFChars(jarg2, (const char *)arg2);
if (arg3) jenv->ReleaseStringUTFChars(jarg3, (const char *)arg3);
return jresult;
}
SWIGEXPORT jboolean JNICALL Java_org_doubango_tinyWRAP_tinyWRAPJNI_CallSession_1setQoS(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jint jarg2, jint jarg3) {
jboolean jresult = 0 ;
CallSession *arg1 = (CallSession *) 0 ;

View File

@ -291,7 +291,9 @@ sub DESTROY {
*defaultsGetRtcpMuxEnabled = *tinyWRAPc::MediaSessionMgr_defaultsGetRtcpMuxEnabled;
*defaultsSetStunEnabled = *tinyWRAPc::MediaSessionMgr_defaultsSetStunEnabled;
*defaultsSetIceStunEnabled = *tinyWRAPc::MediaSessionMgr_defaultsSetIceStunEnabled;
*defaultsSetIceTurnEnabled = *tinyWRAPc::MediaSessionMgr_defaultsSetIceTurnEnabled;
*defaultsSetStunServer = *tinyWRAPc::MediaSessionMgr_defaultsSetStunServer;
*defaultsSetStunCred = *tinyWRAPc::MediaSessionMgr_defaultsSetStunCred;
*defaultsSetIceEnabled = *tinyWRAPc::MediaSessionMgr_defaultsSetIceEnabled;
*defaultsSetByPassEncoding = *tinyWRAPc::MediaSessionMgr_defaultsSetByPassEncoding;
*defaultsGetByPassEncoding = *tinyWRAPc::MediaSessionMgr_defaultsGetByPassEncoding;
@ -1058,6 +1060,10 @@ sub DESTROY {
*setSRtpMode = *tinyWRAPc::CallSession_setSRtpMode;
*setAvpfMode = *tinyWRAPc::CallSession_setAvpfMode;
*setICE = *tinyWRAPc::CallSession_setICE;
*setICEStun = *tinyWRAPc::CallSession_setICEStun;
*setICETurn = *tinyWRAPc::CallSession_setICETurn;
*setSTUNServer = *tinyWRAPc::CallSession_setSTUNServer;
*setSTUNCred = *tinyWRAPc::CallSession_setSTUNCred;
*setQoS = *tinyWRAPc::CallSession_setQoS;
*hold = *tinyWRAPc::CallSession_hold;
*resume = *tinyWRAPc::CallSession_resume;

View File

@ -5158,118 +5158,35 @@ XS(_wrap_MediaSessionMgr_defaultsSetIceStunEnabled) {
}
XS(_wrap_MediaSessionMgr_defaultsSetStunServer__SWIG_0) {
XS(_wrap_MediaSessionMgr_defaultsSetIceTurnEnabled) {
{
char *arg1 = (char *) 0 ;
uint16_t arg2 ;
char *arg3 = (char *) 0 ;
char *arg4 = (char *) 0 ;
int res1 ;
char *buf1 = 0 ;
int alloc1 = 0 ;
unsigned short val2 ;
int ecode2 = 0 ;
int res3 ;
char *buf3 = 0 ;
int alloc3 = 0 ;
int res4 ;
char *buf4 = 0 ;
int alloc4 = 0 ;
bool arg1 ;
bool val1 ;
int ecode1 = 0 ;
int argvi = 0;
bool result;
dXSARGS;
if ((items < 4) || (items > 4)) {
SWIG_croak("Usage: MediaSessionMgr_defaultsSetStunServer(server_ip,server_port,usr_name,usr_pwd);");
if ((items < 1) || (items > 1)) {
SWIG_croak("Usage: MediaSessionMgr_defaultsSetIceTurnEnabled(iceturn_enabled);");
}
res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MediaSessionMgr_defaultsSetStunServer" "', argument " "1"" of type '" "char const *""'");
}
arg1 = reinterpret_cast< char * >(buf1);
ecode2 = SWIG_AsVal_unsigned_SS_short SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
if (!SWIG_IsOK(ecode2)) {
SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "MediaSessionMgr_defaultsSetStunServer" "', argument " "2"" of type '" "uint16_t""'");
ecode1 = SWIG_AsVal_bool SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
if (!SWIG_IsOK(ecode1)) {
SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "MediaSessionMgr_defaultsSetIceTurnEnabled" "', argument " "1"" of type '" "bool""'");
}
arg2 = static_cast< uint16_t >(val2);
res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
if (!SWIG_IsOK(res3)) {
SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "MediaSessionMgr_defaultsSetStunServer" "', argument " "3"" of type '" "char const *""'");
}
arg3 = reinterpret_cast< char * >(buf3);
res4 = SWIG_AsCharPtrAndSize(ST(3), &buf4, NULL, &alloc4);
if (!SWIG_IsOK(res4)) {
SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "MediaSessionMgr_defaultsSetStunServer" "', argument " "4"" of type '" "char const *""'");
}
arg4 = reinterpret_cast< char * >(buf4);
result = (bool)MediaSessionMgr::defaultsSetStunServer((char const *)arg1,arg2,(char const *)arg3,(char const *)arg4);
arg1 = static_cast< bool >(val1);
result = (bool)MediaSessionMgr::defaultsSetIceTurnEnabled(arg1);
ST(argvi) = SWIG_From_bool SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
XSRETURN(argvi);
fail:
if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
SWIG_croak_null();
}
}
XS(_wrap_MediaSessionMgr_defaultsSetStunServer__SWIG_1) {
{
char *arg1 = (char *) 0 ;
uint16_t arg2 ;
char *arg3 = (char *) 0 ;
int res1 ;
char *buf1 = 0 ;
int alloc1 = 0 ;
unsigned short val2 ;
int ecode2 = 0 ;
int res3 ;
char *buf3 = 0 ;
int alloc3 = 0 ;
int argvi = 0;
bool result;
dXSARGS;
if ((items < 3) || (items > 3)) {
SWIG_croak("Usage: MediaSessionMgr_defaultsSetStunServer(server_ip,server_port,usr_name);");
}
res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MediaSessionMgr_defaultsSetStunServer" "', argument " "1"" of type '" "char const *""'");
}
arg1 = reinterpret_cast< char * >(buf1);
ecode2 = SWIG_AsVal_unsigned_SS_short SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
if (!SWIG_IsOK(ecode2)) {
SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "MediaSessionMgr_defaultsSetStunServer" "', argument " "2"" of type '" "uint16_t""'");
}
arg2 = static_cast< uint16_t >(val2);
res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
if (!SWIG_IsOK(res3)) {
SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "MediaSessionMgr_defaultsSetStunServer" "', argument " "3"" of type '" "char const *""'");
}
arg3 = reinterpret_cast< char * >(buf3);
result = (bool)MediaSessionMgr::defaultsSetStunServer((char const *)arg1,arg2,(char const *)arg3);
ST(argvi) = SWIG_From_bool SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
XSRETURN(argvi);
fail:
if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
SWIG_croak_null();
}
}
XS(_wrap_MediaSessionMgr_defaultsSetStunServer__SWIG_2) {
XS(_wrap_MediaSessionMgr_defaultsSetStunServer) {
{
char *arg1 = (char *) 0 ;
uint16_t arg2 ;
@ -5308,139 +5225,43 @@ XS(_wrap_MediaSessionMgr_defaultsSetStunServer__SWIG_2) {
}
XS(_wrap_MediaSessionMgr_defaultsSetStunServer) {
dXSARGS;
XS(_wrap_MediaSessionMgr_defaultsSetStunCred) {
{
unsigned long _index = 0;
SWIG_TypeRank _rank = 0;
if (items == 2) {
SWIG_TypeRank _ranki = 0;
SWIG_TypeRank _rankm = 0;
SWIG_TypeRank _pi = 1;
int _v = 0;
{
int res = SWIG_AsCharPtrAndSize(ST(0), 0, NULL, 0);
_v = SWIG_CheckState(res);
}
if (!_v) goto check_1;
_ranki += _v*_pi;
_rankm += _pi;
_pi *= SWIG_MAXCASTRANK;
{
{
int res = SWIG_AsVal_unsigned_SS_short SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
_v = SWIG_CheckState(res);
}
}
if (!_v) goto check_1;
_ranki += _v*_pi;
_rankm += _pi;
_pi *= SWIG_MAXCASTRANK;
if (!_index || (_ranki < _rank)) {
_rank = _ranki; _index = 1;
if (_rank == _rankm) goto dispatch;
}
}
check_1:
char *arg1 = (char *) 0 ;
char *arg2 = (char *) 0 ;
int res1 ;
char *buf1 = 0 ;
int alloc1 = 0 ;
int res2 ;
char *buf2 = 0 ;
int alloc2 = 0 ;
int argvi = 0;
bool result;
dXSARGS;
if (items == 3) {
SWIG_TypeRank _ranki = 0;
SWIG_TypeRank _rankm = 0;
SWIG_TypeRank _pi = 1;
int _v = 0;
{
int res = SWIG_AsCharPtrAndSize(ST(0), 0, NULL, 0);
_v = SWIG_CheckState(res);
}
if (!_v) goto check_2;
_ranki += _v*_pi;
_rankm += _pi;
_pi *= SWIG_MAXCASTRANK;
{
{
int res = SWIG_AsVal_unsigned_SS_short SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
_v = SWIG_CheckState(res);
}
}
if (!_v) goto check_2;
_ranki += _v*_pi;
_rankm += _pi;
_pi *= SWIG_MAXCASTRANK;
{
int res = SWIG_AsCharPtrAndSize(ST(2), 0, NULL, 0);
_v = SWIG_CheckState(res);
}
if (!_v) goto check_2;
_ranki += _v*_pi;
_rankm += _pi;
_pi *= SWIG_MAXCASTRANK;
if (!_index || (_ranki < _rank)) {
_rank = _ranki; _index = 2;
if (_rank == _rankm) goto dispatch;
}
if ((items < 2) || (items > 2)) {
SWIG_croak("Usage: MediaSessionMgr_defaultsSetStunCred(username,password);");
}
check_2:
if (items == 4) {
SWIG_TypeRank _ranki = 0;
SWIG_TypeRank _rankm = 0;
SWIG_TypeRank _pi = 1;
int _v = 0;
{
int res = SWIG_AsCharPtrAndSize(ST(0), 0, NULL, 0);
_v = SWIG_CheckState(res);
}
if (!_v) goto check_3;
_ranki += _v*_pi;
_rankm += _pi;
_pi *= SWIG_MAXCASTRANK;
{
{
int res = SWIG_AsVal_unsigned_SS_short SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
_v = SWIG_CheckState(res);
}
}
if (!_v) goto check_3;
_ranki += _v*_pi;
_rankm += _pi;
_pi *= SWIG_MAXCASTRANK;
{
int res = SWIG_AsCharPtrAndSize(ST(2), 0, NULL, 0);
_v = SWIG_CheckState(res);
}
if (!_v) goto check_3;
_ranki += _v*_pi;
_rankm += _pi;
_pi *= SWIG_MAXCASTRANK;
{
int res = SWIG_AsCharPtrAndSize(ST(3), 0, NULL, 0);
_v = SWIG_CheckState(res);
}
if (!_v) goto check_3;
_ranki += _v*_pi;
_rankm += _pi;
_pi *= SWIG_MAXCASTRANK;
if (!_index || (_ranki < _rank)) {
_rank = _ranki; _index = 3;
if (_rank == _rankm) goto dispatch;
}
res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MediaSessionMgr_defaultsSetStunCred" "', argument " "1"" of type '" "char const *""'");
}
check_3:
dispatch:
switch(_index) {
case 1:
PUSHMARK(MARK); SWIG_CALLXS(_wrap_MediaSessionMgr_defaultsSetStunServer__SWIG_2); return;
case 2:
PUSHMARK(MARK); SWIG_CALLXS(_wrap_MediaSessionMgr_defaultsSetStunServer__SWIG_1); return;
case 3:
PUSHMARK(MARK); SWIG_CALLXS(_wrap_MediaSessionMgr_defaultsSetStunServer__SWIG_0); return;
arg1 = reinterpret_cast< char * >(buf1);
res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
if (!SWIG_IsOK(res2)) {
SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "MediaSessionMgr_defaultsSetStunCred" "', argument " "2"" of type '" "char const *""'");
}
arg2 = reinterpret_cast< char * >(buf2);
result = (bool)MediaSessionMgr::defaultsSetStunCred((char const *)arg1,(char const *)arg2);
ST(argvi) = SWIG_From_bool SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
XSRETURN(argvi);
fail:
if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
SWIG_croak_null();
}
croak("No matching function for overloaded 'MediaSessionMgr_defaultsSetStunServer'");
XSRETURN(0);
}
@ -12422,6 +12243,181 @@ XS(_wrap_CallSession_setICE) {
}
XS(_wrap_CallSession_setICEStun) {
{
CallSession *arg1 = (CallSession *) 0 ;
bool arg2 ;
void *argp1 = 0 ;
int res1 = 0 ;
bool val2 ;
int ecode2 = 0 ;
int argvi = 0;
bool result;
dXSARGS;
if ((items < 2) || (items > 2)) {
SWIG_croak("Usage: CallSession_setICEStun(self,enabled);");
}
res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_CallSession, 0 | 0 );
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CallSession_setICEStun" "', argument " "1"" of type '" "CallSession *""'");
}
arg1 = reinterpret_cast< CallSession * >(argp1);
ecode2 = SWIG_AsVal_bool SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
if (!SWIG_IsOK(ecode2)) {
SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "CallSession_setICEStun" "', argument " "2"" of type '" "bool""'");
}
arg2 = static_cast< bool >(val2);
result = (bool)(arg1)->setICEStun(arg2);
ST(argvi) = SWIG_From_bool SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
XSRETURN(argvi);
fail:
SWIG_croak_null();
}
}
XS(_wrap_CallSession_setICETurn) {
{
CallSession *arg1 = (CallSession *) 0 ;
bool arg2 ;
void *argp1 = 0 ;
int res1 = 0 ;
bool val2 ;
int ecode2 = 0 ;
int argvi = 0;
bool result;
dXSARGS;
if ((items < 2) || (items > 2)) {
SWIG_croak("Usage: CallSession_setICETurn(self,enabled);");
}
res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_CallSession, 0 | 0 );
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CallSession_setICETurn" "', argument " "1"" of type '" "CallSession *""'");
}
arg1 = reinterpret_cast< CallSession * >(argp1);
ecode2 = SWIG_AsVal_bool SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
if (!SWIG_IsOK(ecode2)) {
SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "CallSession_setICETurn" "', argument " "2"" of type '" "bool""'");
}
arg2 = static_cast< bool >(val2);
result = (bool)(arg1)->setICETurn(arg2);
ST(argvi) = SWIG_From_bool SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
XSRETURN(argvi);
fail:
SWIG_croak_null();
}
}
XS(_wrap_CallSession_setSTUNServer) {
{
CallSession *arg1 = (CallSession *) 0 ;
char *arg2 = (char *) 0 ;
uint16_t arg3 ;
void *argp1 = 0 ;
int res1 = 0 ;
int res2 ;
char *buf2 = 0 ;
int alloc2 = 0 ;
unsigned short val3 ;
int ecode3 = 0 ;
int argvi = 0;
bool result;
dXSARGS;
if ((items < 3) || (items > 3)) {
SWIG_croak("Usage: CallSession_setSTUNServer(self,hostname,port);");
}
res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_CallSession, 0 | 0 );
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CallSession_setSTUNServer" "', argument " "1"" of type '" "CallSession *""'");
}
arg1 = reinterpret_cast< CallSession * >(argp1);
res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
if (!SWIG_IsOK(res2)) {
SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "CallSession_setSTUNServer" "', argument " "2"" of type '" "char const *""'");
}
arg2 = reinterpret_cast< char * >(buf2);
ecode3 = SWIG_AsVal_unsigned_SS_short SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
if (!SWIG_IsOK(ecode3)) {
SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "CallSession_setSTUNServer" "', argument " "3"" of type '" "uint16_t""'");
}
arg3 = static_cast< uint16_t >(val3);
result = (bool)(arg1)->setSTUNServer((char const *)arg2,arg3);
ST(argvi) = SWIG_From_bool SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
XSRETURN(argvi);
fail:
if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
SWIG_croak_null();
}
}
XS(_wrap_CallSession_setSTUNCred) {
{
CallSession *arg1 = (CallSession *) 0 ;
char *arg2 = (char *) 0 ;
char *arg3 = (char *) 0 ;
void *argp1 = 0 ;
int res1 = 0 ;
int res2 ;
char *buf2 = 0 ;
int alloc2 = 0 ;
int res3 ;
char *buf3 = 0 ;
int alloc3 = 0 ;
int argvi = 0;
bool result;
dXSARGS;
if ((items < 3) || (items > 3)) {
SWIG_croak("Usage: CallSession_setSTUNCred(self,username,password);");
}
res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_CallSession, 0 | 0 );
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CallSession_setSTUNCred" "', argument " "1"" of type '" "CallSession *""'");
}
arg1 = reinterpret_cast< CallSession * >(argp1);
res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
if (!SWIG_IsOK(res2)) {
SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "CallSession_setSTUNCred" "', argument " "2"" of type '" "char const *""'");
}
arg2 = reinterpret_cast< char * >(buf2);
res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
if (!SWIG_IsOK(res3)) {
SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "CallSession_setSTUNCred" "', argument " "3"" of type '" "char const *""'");
}
arg3 = reinterpret_cast< char * >(buf3);
result = (bool)(arg1)->setSTUNCred((char const *)arg2,(char const *)arg3);
ST(argvi) = SWIG_From_bool SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
XSRETURN(argvi);
fail:
if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
SWIG_croak_null();
}
}
XS(_wrap_CallSession_setQoS) {
{
CallSession *arg1 = (CallSession *) 0 ;
@ -22411,7 +22407,7 @@ XS(_wrap_SipStack_setSTUNServer) {
dXSARGS;
if ((items < 3) || (items > 3)) {
SWIG_croak("Usage: SipStack_setSTUNServer(self,ip,port);");
SWIG_croak("Usage: SipStack_setSTUNServer(self,hostname,port);");
}
res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_SipStack, 0 | 0 );
if (!SWIG_IsOK(res1)) {
@ -27772,7 +27768,9 @@ static swig_command_info swig_commands[] = {
{"tinyWRAPc::MediaSessionMgr_defaultsGetRtcpMuxEnabled", _wrap_MediaSessionMgr_defaultsGetRtcpMuxEnabled},
{"tinyWRAPc::MediaSessionMgr_defaultsSetStunEnabled", _wrap_MediaSessionMgr_defaultsSetStunEnabled},
{"tinyWRAPc::MediaSessionMgr_defaultsSetIceStunEnabled", _wrap_MediaSessionMgr_defaultsSetIceStunEnabled},
{"tinyWRAPc::MediaSessionMgr_defaultsSetIceTurnEnabled", _wrap_MediaSessionMgr_defaultsSetIceTurnEnabled},
{"tinyWRAPc::MediaSessionMgr_defaultsSetStunServer", _wrap_MediaSessionMgr_defaultsSetStunServer},
{"tinyWRAPc::MediaSessionMgr_defaultsSetStunCred", _wrap_MediaSessionMgr_defaultsSetStunCred},
{"tinyWRAPc::MediaSessionMgr_defaultsSetIceEnabled", _wrap_MediaSessionMgr_defaultsSetIceEnabled},
{"tinyWRAPc::MediaSessionMgr_defaultsSetByPassEncoding", _wrap_MediaSessionMgr_defaultsSetByPassEncoding},
{"tinyWRAPc::MediaSessionMgr_defaultsGetByPassEncoding", _wrap_MediaSessionMgr_defaultsGetByPassEncoding},
@ -27904,6 +27902,10 @@ static swig_command_info swig_commands[] = {
{"tinyWRAPc::CallSession_setSRtpMode", _wrap_CallSession_setSRtpMode},
{"tinyWRAPc::CallSession_setAvpfMode", _wrap_CallSession_setAvpfMode},
{"tinyWRAPc::CallSession_setICE", _wrap_CallSession_setICE},
{"tinyWRAPc::CallSession_setICEStun", _wrap_CallSession_setICEStun},
{"tinyWRAPc::CallSession_setICETurn", _wrap_CallSession_setICETurn},
{"tinyWRAPc::CallSession_setSTUNServer", _wrap_CallSession_setSTUNServer},
{"tinyWRAPc::CallSession_setSTUNCred", _wrap_CallSession_setSTUNCred},
{"tinyWRAPc::CallSession_setQoS", _wrap_CallSession_setQoS},
{"tinyWRAPc::CallSession_hold", _wrap_CallSession_hold},
{"tinyWRAPc::CallSession_resume", _wrap_CallSession_resume},

View File

@ -289,8 +289,12 @@ class MediaSessionMgr(_object):
if _newclass:defaultsSetStunEnabled = staticmethod(_tinyWRAP.MediaSessionMgr_defaultsSetStunEnabled)
__swig_getmethods__["defaultsSetIceStunEnabled"] = lambda x: _tinyWRAP.MediaSessionMgr_defaultsSetIceStunEnabled
if _newclass:defaultsSetIceStunEnabled = staticmethod(_tinyWRAP.MediaSessionMgr_defaultsSetIceStunEnabled)
__swig_getmethods__["defaultsSetIceTurnEnabled"] = lambda x: _tinyWRAP.MediaSessionMgr_defaultsSetIceTurnEnabled
if _newclass:defaultsSetIceTurnEnabled = staticmethod(_tinyWRAP.MediaSessionMgr_defaultsSetIceTurnEnabled)
__swig_getmethods__["defaultsSetStunServer"] = lambda x: _tinyWRAP.MediaSessionMgr_defaultsSetStunServer
if _newclass:defaultsSetStunServer = staticmethod(_tinyWRAP.MediaSessionMgr_defaultsSetStunServer)
__swig_getmethods__["defaultsSetStunCred"] = lambda x: _tinyWRAP.MediaSessionMgr_defaultsSetStunCred
if _newclass:defaultsSetStunCred = staticmethod(_tinyWRAP.MediaSessionMgr_defaultsSetStunCred)
__swig_getmethods__["defaultsSetIceEnabled"] = lambda x: _tinyWRAP.MediaSessionMgr_defaultsSetIceEnabled
if _newclass:defaultsSetIceEnabled = staticmethod(_tinyWRAP.MediaSessionMgr_defaultsSetIceEnabled)
__swig_getmethods__["defaultsSetByPassEncoding"] = lambda x: _tinyWRAP.MediaSessionMgr_defaultsSetByPassEncoding
@ -526,10 +530,18 @@ def MediaSessionMgr_defaultsSetIceStunEnabled(*args):
return _tinyWRAP.MediaSessionMgr_defaultsSetIceStunEnabled(*args)
MediaSessionMgr_defaultsSetIceStunEnabled = _tinyWRAP.MediaSessionMgr_defaultsSetIceStunEnabled
def MediaSessionMgr_defaultsSetIceTurnEnabled(*args):
return _tinyWRAP.MediaSessionMgr_defaultsSetIceTurnEnabled(*args)
MediaSessionMgr_defaultsSetIceTurnEnabled = _tinyWRAP.MediaSessionMgr_defaultsSetIceTurnEnabled
def MediaSessionMgr_defaultsSetStunServer(*args):
return _tinyWRAP.MediaSessionMgr_defaultsSetStunServer(*args)
MediaSessionMgr_defaultsSetStunServer = _tinyWRAP.MediaSessionMgr_defaultsSetStunServer
def MediaSessionMgr_defaultsSetStunCred(*args):
return _tinyWRAP.MediaSessionMgr_defaultsSetStunCred(*args)
MediaSessionMgr_defaultsSetStunCred = _tinyWRAP.MediaSessionMgr_defaultsSetStunCred
def MediaSessionMgr_defaultsSetIceEnabled(*args):
return _tinyWRAP.MediaSessionMgr_defaultsSetIceEnabled(*args)
MediaSessionMgr_defaultsSetIceEnabled = _tinyWRAP.MediaSessionMgr_defaultsSetIceEnabled
@ -977,6 +989,10 @@ class CallSession(InviteSession):
def setSRtpMode(self, *args): return _tinyWRAP.CallSession_setSRtpMode(self, *args)
def setAvpfMode(self, *args): return _tinyWRAP.CallSession_setAvpfMode(self, *args)
def setICE(self, *args): return _tinyWRAP.CallSession_setICE(self, *args)
def setICEStun(self, *args): return _tinyWRAP.CallSession_setICEStun(self, *args)
def setICETurn(self, *args): return _tinyWRAP.CallSession_setICETurn(self, *args)
def setSTUNServer(self, *args): return _tinyWRAP.CallSession_setSTUNServer(self, *args)
def setSTUNCred(self, *args): return _tinyWRAP.CallSession_setSTUNCred(self, *args)
def setQoS(self, *args): return _tinyWRAP.CallSession_setQoS(self, *args)
def hold(self, *args): return _tinyWRAP.CallSession_hold(self, *args)
def resume(self, *args): return _tinyWRAP.CallSession_resume(self, *args)

View File

@ -7915,111 +7915,29 @@ fail:
}
SWIGINTERN PyObject *_wrap_MediaSessionMgr_defaultsSetStunServer__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
SWIGINTERN PyObject *_wrap_MediaSessionMgr_defaultsSetIceTurnEnabled(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
char *arg1 = (char *) 0 ;
uint16_t arg2 ;
char *arg3 = (char *) 0 ;
char *arg4 = (char *) 0 ;
int res1 ;
char *buf1 = 0 ;
int alloc1 = 0 ;
unsigned short val2 ;
int ecode2 = 0 ;
int res3 ;
char *buf3 = 0 ;
int alloc3 = 0 ;
int res4 ;
char *buf4 = 0 ;
int alloc4 = 0 ;
bool arg1 ;
bool val1 ;
int ecode1 = 0 ;
PyObject * obj0 = 0 ;
PyObject * obj1 = 0 ;
PyObject * obj2 = 0 ;
PyObject * obj3 = 0 ;
bool result;
if (!PyArg_ParseTuple(args,(char *)"OOOO:MediaSessionMgr_defaultsSetStunServer",&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, NULL, &alloc1);
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MediaSessionMgr_defaultsSetStunServer" "', argument " "1"" of type '" "char const *""'");
}
arg1 = reinterpret_cast< char * >(buf1);
ecode2 = SWIG_AsVal_unsigned_SS_short(obj1, &val2);
if (!SWIG_IsOK(ecode2)) {
SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "MediaSessionMgr_defaultsSetStunServer" "', argument " "2"" of type '" "uint16_t""'");
if (!PyArg_ParseTuple(args,(char *)"O:MediaSessionMgr_defaultsSetIceTurnEnabled",&obj0)) SWIG_fail;
ecode1 = SWIG_AsVal_bool(obj0, &val1);
if (!SWIG_IsOK(ecode1)) {
SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "MediaSessionMgr_defaultsSetIceTurnEnabled" "', argument " "1"" of type '" "bool""'");
}
arg2 = static_cast< uint16_t >(val2);
res3 = SWIG_AsCharPtrAndSize(obj2, &buf3, NULL, &alloc3);
if (!SWIG_IsOK(res3)) {
SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "MediaSessionMgr_defaultsSetStunServer" "', argument " "3"" of type '" "char const *""'");
}
arg3 = reinterpret_cast< char * >(buf3);
res4 = SWIG_AsCharPtrAndSize(obj3, &buf4, NULL, &alloc4);
if (!SWIG_IsOK(res4)) {
SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "MediaSessionMgr_defaultsSetStunServer" "', argument " "4"" of type '" "char const *""'");
}
arg4 = reinterpret_cast< char * >(buf4);
result = (bool)MediaSessionMgr::defaultsSetStunServer((char const *)arg1,arg2,(char const *)arg3,(char const *)arg4);
arg1 = static_cast< bool >(val1);
result = (bool)MediaSessionMgr::defaultsSetIceTurnEnabled(arg1);
resultobj = SWIG_From_bool(static_cast< bool >(result));
if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
return resultobj;
fail:
if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
return NULL;
}
SWIGINTERN PyObject *_wrap_MediaSessionMgr_defaultsSetStunServer__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
char *arg1 = (char *) 0 ;
uint16_t arg2 ;
char *arg3 = (char *) 0 ;
int res1 ;
char *buf1 = 0 ;
int alloc1 = 0 ;
unsigned short val2 ;
int ecode2 = 0 ;
int res3 ;
char *buf3 = 0 ;
int alloc3 = 0 ;
PyObject * obj0 = 0 ;
PyObject * obj1 = 0 ;
PyObject * obj2 = 0 ;
bool result;
if (!PyArg_ParseTuple(args,(char *)"OOO:MediaSessionMgr_defaultsSetStunServer",&obj0,&obj1,&obj2)) SWIG_fail;
res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, NULL, &alloc1);
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MediaSessionMgr_defaultsSetStunServer" "', argument " "1"" of type '" "char const *""'");
}
arg1 = reinterpret_cast< char * >(buf1);
ecode2 = SWIG_AsVal_unsigned_SS_short(obj1, &val2);
if (!SWIG_IsOK(ecode2)) {
SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "MediaSessionMgr_defaultsSetStunServer" "', argument " "2"" of type '" "uint16_t""'");
}
arg2 = static_cast< uint16_t >(val2);
res3 = SWIG_AsCharPtrAndSize(obj2, &buf3, NULL, &alloc3);
if (!SWIG_IsOK(res3)) {
SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "MediaSessionMgr_defaultsSetStunServer" "', argument " "3"" of type '" "char const *""'");
}
arg3 = reinterpret_cast< char * >(buf3);
result = (bool)MediaSessionMgr::defaultsSetStunServer((char const *)arg1,arg2,(char const *)arg3);
resultobj = SWIG_From_bool(static_cast< bool >(result));
if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
return resultobj;
fail:
if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
return NULL;
}
SWIGINTERN PyObject *_wrap_MediaSessionMgr_defaultsSetStunServer__SWIG_2(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
SWIGINTERN PyObject *_wrap_MediaSessionMgr_defaultsSetStunServer(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
char *arg1 = (char *) 0 ;
uint16_t arg2 ;
@ -8053,78 +7971,40 @@ fail:
}
SWIGINTERN PyObject *_wrap_MediaSessionMgr_defaultsSetStunServer(PyObject *self, PyObject *args) {
int argc;
PyObject *argv[5];
int ii;
SWIGINTERN PyObject *_wrap_MediaSessionMgr_defaultsSetStunCred(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
char *arg1 = (char *) 0 ;
char *arg2 = (char *) 0 ;
int res1 ;
char *buf1 = 0 ;
int alloc1 = 0 ;
int res2 ;
char *buf2 = 0 ;
int alloc2 = 0 ;
PyObject * obj0 = 0 ;
PyObject * obj1 = 0 ;
bool result;
if (!PyTuple_Check(args)) SWIG_fail;
argc = args ? (int)PyObject_Length(args) : 0;
for (ii = 0; (ii < 4) && (ii < argc); ii++) {
argv[ii] = PyTuple_GET_ITEM(args,ii);
if (!PyArg_ParseTuple(args,(char *)"OO:MediaSessionMgr_defaultsSetStunCred",&obj0,&obj1)) SWIG_fail;
res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, NULL, &alloc1);
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MediaSessionMgr_defaultsSetStunCred" "', argument " "1"" of type '" "char const *""'");
}
if (argc == 2) {
int _v;
int res = SWIG_AsCharPtrAndSize(argv[0], 0, NULL, 0);
_v = SWIG_CheckState(res);
if (_v) {
{
int res = SWIG_AsVal_unsigned_SS_short(argv[1], NULL);
_v = SWIG_CheckState(res);
}
if (_v) {
return _wrap_MediaSessionMgr_defaultsSetStunServer__SWIG_2(self, args);
}
}
arg1 = reinterpret_cast< char * >(buf1);
res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
if (!SWIG_IsOK(res2)) {
SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "MediaSessionMgr_defaultsSetStunCred" "', argument " "2"" of type '" "char const *""'");
}
if (argc == 3) {
int _v;
int res = SWIG_AsCharPtrAndSize(argv[0], 0, NULL, 0);
_v = SWIG_CheckState(res);
if (_v) {
{
int res = SWIG_AsVal_unsigned_SS_short(argv[1], NULL);
_v = SWIG_CheckState(res);
}
if (_v) {
int res = SWIG_AsCharPtrAndSize(argv[2], 0, NULL, 0);
_v = SWIG_CheckState(res);
if (_v) {
return _wrap_MediaSessionMgr_defaultsSetStunServer__SWIG_1(self, args);
}
}
}
}
if (argc == 4) {
int _v;
int res = SWIG_AsCharPtrAndSize(argv[0], 0, NULL, 0);
_v = SWIG_CheckState(res);
if (_v) {
{
int res = SWIG_AsVal_unsigned_SS_short(argv[1], NULL);
_v = SWIG_CheckState(res);
}
if (_v) {
int res = SWIG_AsCharPtrAndSize(argv[2], 0, NULL, 0);
_v = SWIG_CheckState(res);
if (_v) {
int res = SWIG_AsCharPtrAndSize(argv[3], 0, NULL, 0);
_v = SWIG_CheckState(res);
if (_v) {
return _wrap_MediaSessionMgr_defaultsSetStunServer__SWIG_0(self, args);
}
}
}
}
}
arg2 = reinterpret_cast< char * >(buf2);
result = (bool)MediaSessionMgr::defaultsSetStunCred((char const *)arg1,(char const *)arg2);
resultobj = SWIG_From_bool(static_cast< bool >(result));
if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
return resultobj;
fail:
SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'MediaSessionMgr_defaultsSetStunServer'.\n"
" Possible C/C++ prototypes are:\n"
" MediaSessionMgr::defaultsSetStunServer(char const *,uint16_t,char const *,char const *)\n"
" MediaSessionMgr::defaultsSetStunServer(char const *,uint16_t,char const *)\n"
" MediaSessionMgr::defaultsSetStunServer(char const *,uint16_t)\n");
return 0;
if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
return NULL;
}
@ -13594,6 +13474,157 @@ fail:
}
SWIGINTERN PyObject *_wrap_CallSession_setICEStun(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
CallSession *arg1 = (CallSession *) 0 ;
bool arg2 ;
void *argp1 = 0 ;
int res1 = 0 ;
bool val2 ;
int ecode2 = 0 ;
PyObject * obj0 = 0 ;
PyObject * obj1 = 0 ;
bool result;
if (!PyArg_ParseTuple(args,(char *)"OO:CallSession_setICEStun",&obj0,&obj1)) SWIG_fail;
res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_CallSession, 0 | 0 );
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CallSession_setICEStun" "', argument " "1"" of type '" "CallSession *""'");
}
arg1 = reinterpret_cast< CallSession * >(argp1);
ecode2 = SWIG_AsVal_bool(obj1, &val2);
if (!SWIG_IsOK(ecode2)) {
SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "CallSession_setICEStun" "', argument " "2"" of type '" "bool""'");
}
arg2 = static_cast< bool >(val2);
result = (bool)(arg1)->setICEStun(arg2);
resultobj = SWIG_From_bool(static_cast< bool >(result));
return resultobj;
fail:
return NULL;
}
SWIGINTERN PyObject *_wrap_CallSession_setICETurn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
CallSession *arg1 = (CallSession *) 0 ;
bool arg2 ;
void *argp1 = 0 ;
int res1 = 0 ;
bool val2 ;
int ecode2 = 0 ;
PyObject * obj0 = 0 ;
PyObject * obj1 = 0 ;
bool result;
if (!PyArg_ParseTuple(args,(char *)"OO:CallSession_setICETurn",&obj0,&obj1)) SWIG_fail;
res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_CallSession, 0 | 0 );
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CallSession_setICETurn" "', argument " "1"" of type '" "CallSession *""'");
}
arg1 = reinterpret_cast< CallSession * >(argp1);
ecode2 = SWIG_AsVal_bool(obj1, &val2);
if (!SWIG_IsOK(ecode2)) {
SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "CallSession_setICETurn" "', argument " "2"" of type '" "bool""'");
}
arg2 = static_cast< bool >(val2);
result = (bool)(arg1)->setICETurn(arg2);
resultobj = SWIG_From_bool(static_cast< bool >(result));
return resultobj;
fail:
return NULL;
}
SWIGINTERN PyObject *_wrap_CallSession_setSTUNServer(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
CallSession *arg1 = (CallSession *) 0 ;
char *arg2 = (char *) 0 ;
uint16_t arg3 ;
void *argp1 = 0 ;
int res1 = 0 ;
int res2 ;
char *buf2 = 0 ;
int alloc2 = 0 ;
unsigned short val3 ;
int ecode3 = 0 ;
PyObject * obj0 = 0 ;
PyObject * obj1 = 0 ;
PyObject * obj2 = 0 ;
bool result;
if (!PyArg_ParseTuple(args,(char *)"OOO:CallSession_setSTUNServer",&obj0,&obj1,&obj2)) SWIG_fail;
res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_CallSession, 0 | 0 );
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CallSession_setSTUNServer" "', argument " "1"" of type '" "CallSession *""'");
}
arg1 = reinterpret_cast< CallSession * >(argp1);
res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
if (!SWIG_IsOK(res2)) {
SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "CallSession_setSTUNServer" "', argument " "2"" of type '" "char const *""'");
}
arg2 = reinterpret_cast< char * >(buf2);
ecode3 = SWIG_AsVal_unsigned_SS_short(obj2, &val3);
if (!SWIG_IsOK(ecode3)) {
SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "CallSession_setSTUNServer" "', argument " "3"" of type '" "uint16_t""'");
}
arg3 = static_cast< uint16_t >(val3);
result = (bool)(arg1)->setSTUNServer((char const *)arg2,arg3);
resultobj = SWIG_From_bool(static_cast< bool >(result));
if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
return resultobj;
fail:
if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
return NULL;
}
SWIGINTERN PyObject *_wrap_CallSession_setSTUNCred(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
CallSession *arg1 = (CallSession *) 0 ;
char *arg2 = (char *) 0 ;
char *arg3 = (char *) 0 ;
void *argp1 = 0 ;
int res1 = 0 ;
int res2 ;
char *buf2 = 0 ;
int alloc2 = 0 ;
int res3 ;
char *buf3 = 0 ;
int alloc3 = 0 ;
PyObject * obj0 = 0 ;
PyObject * obj1 = 0 ;
PyObject * obj2 = 0 ;
bool result;
if (!PyArg_ParseTuple(args,(char *)"OOO:CallSession_setSTUNCred",&obj0,&obj1,&obj2)) SWIG_fail;
res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_CallSession, 0 | 0 );
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CallSession_setSTUNCred" "', argument " "1"" of type '" "CallSession *""'");
}
arg1 = reinterpret_cast< CallSession * >(argp1);
res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
if (!SWIG_IsOK(res2)) {
SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "CallSession_setSTUNCred" "', argument " "2"" of type '" "char const *""'");
}
arg2 = reinterpret_cast< char * >(buf2);
res3 = SWIG_AsCharPtrAndSize(obj2, &buf3, NULL, &alloc3);
if (!SWIG_IsOK(res3)) {
SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "CallSession_setSTUNCred" "', argument " "3"" of type '" "char const *""'");
}
arg3 = reinterpret_cast< char * >(buf3);
result = (bool)(arg1)->setSTUNCred((char const *)arg2,(char const *)arg3);
resultobj = SWIG_From_bool(static_cast< bool >(result));
if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
return resultobj;
fail:
if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
return NULL;
}
SWIGINTERN PyObject *_wrap_CallSession_setQoS(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
CallSession *arg1 = (CallSession *) 0 ;
@ -26134,7 +26165,9 @@ static PyMethodDef SwigMethods[] = {
{ (char *)"MediaSessionMgr_defaultsGetRtcpMuxEnabled", _wrap_MediaSessionMgr_defaultsGetRtcpMuxEnabled, METH_VARARGS, NULL},
{ (char *)"MediaSessionMgr_defaultsSetStunEnabled", _wrap_MediaSessionMgr_defaultsSetStunEnabled, METH_VARARGS, NULL},
{ (char *)"MediaSessionMgr_defaultsSetIceStunEnabled", _wrap_MediaSessionMgr_defaultsSetIceStunEnabled, METH_VARARGS, NULL},
{ (char *)"MediaSessionMgr_defaultsSetIceTurnEnabled", _wrap_MediaSessionMgr_defaultsSetIceTurnEnabled, METH_VARARGS, NULL},
{ (char *)"MediaSessionMgr_defaultsSetStunServer", _wrap_MediaSessionMgr_defaultsSetStunServer, METH_VARARGS, NULL},
{ (char *)"MediaSessionMgr_defaultsSetStunCred", _wrap_MediaSessionMgr_defaultsSetStunCred, METH_VARARGS, NULL},
{ (char *)"MediaSessionMgr_defaultsSetIceEnabled", _wrap_MediaSessionMgr_defaultsSetIceEnabled, METH_VARARGS, NULL},
{ (char *)"MediaSessionMgr_defaultsSetByPassEncoding", _wrap_MediaSessionMgr_defaultsSetByPassEncoding, METH_VARARGS, NULL},
{ (char *)"MediaSessionMgr_defaultsGetByPassEncoding", _wrap_MediaSessionMgr_defaultsGetByPassEncoding, METH_VARARGS, NULL},
@ -26287,6 +26320,10 @@ static PyMethodDef SwigMethods[] = {
{ (char *)"CallSession_setSRtpMode", _wrap_CallSession_setSRtpMode, METH_VARARGS, NULL},
{ (char *)"CallSession_setAvpfMode", _wrap_CallSession_setAvpfMode, METH_VARARGS, NULL},
{ (char *)"CallSession_setICE", _wrap_CallSession_setICE, METH_VARARGS, NULL},
{ (char *)"CallSession_setICEStun", _wrap_CallSession_setICEStun, METH_VARARGS, NULL},
{ (char *)"CallSession_setICETurn", _wrap_CallSession_setICETurn, METH_VARARGS, NULL},
{ (char *)"CallSession_setSTUNServer", _wrap_CallSession_setSTUNServer, METH_VARARGS, NULL},
{ (char *)"CallSession_setSTUNCred", _wrap_CallSession_setSTUNCred, METH_VARARGS, NULL},
{ (char *)"CallSession_setQoS", _wrap_CallSession_setQoS, METH_VARARGS, NULL},
{ (char *)"CallSession_hold", _wrap_CallSession_hold, METH_VARARGS, NULL},
{ (char *)"CallSession_resume", _wrap_CallSession_resume, METH_VARARGS, NULL},

View File

@ -6,7 +6,7 @@
#
AC_PREREQ([2.0])
AC_INIT(libdoubango, 2.0.1062, doubango(at)googlegroups(dot)com)
AC_INIT(libdoubango, 2.0.1086, doubango(at)googlegroups(dot)com)
AC_CANONICAL_SYSTEM
AM_INIT_AUTOMAKE
AC_CONFIG_MACRO_DIR([m4])

View File

@ -37,7 +37,7 @@ TINYBFCP_API int tbfcp_session_prepare(struct tbfcp_session_s* p_self);
TINYBFCP_API int tbfcp_session_start(struct tbfcp_session_s* p_self);
TINYBFCP_API int tbfcp_session_pause(struct tbfcp_session_s* p_self);
TINYBFCP_API int tbfcp_session_stop(struct tbfcp_session_s* p_self);
TINYBFCP_API int tbfcp_session_set_natt_ctx(struct tbfcp_session_s* p_self, struct tnet_nat_context_s* p_natt_ctx);
TINYBFCP_API int tbfcp_session_set_natt_ctx(struct tbfcp_session_s* p_self, struct tnet_nat_ctx_s* p_natt_ctx);
TINYBFCP_API int tbfcp_session_set_remote_address(struct tbfcp_session_s* p_self, const char* pc_ip, tnet_port_t u_port);
TINYBFCP_API int tbfcp_session_set_remote_role(struct tbfcp_session_s* p_self, enum tbfcp_role_e e_role_remote);
TINYBFCP_API int tbfcp_session_set_remote_setup(struct tbfcp_session_s* p_self, enum tbfcp_setup_e e_setup_remote);

View File

@ -59,7 +59,7 @@ typedef struct tbfcp_session_s {
tnet_port_t u_remote_port;
struct sockaddr_storage remote_addr;
struct tnet_nat_context_s* p_natt_ctx;
struct tnet_nat_ctx_s* p_natt_ctx;
struct tnet_ice_ctx_s* p_ice_ctx;
struct tnet_transport_s* p_transport;
@ -360,7 +360,7 @@ bail:
return ret;
}
int tbfcp_session_set_natt_ctx(tbfcp_session_t* p_self, struct tnet_nat_context_s* p_natt_ctx)
int tbfcp_session_set_natt_ctx(tbfcp_session_t* p_self, struct tnet_nat_ctx_s* p_natt_ctx)
{
if (!p_self) {
TSK_DEBUG_ERROR("Invalid parameter");

View File

@ -73,7 +73,7 @@ typedef struct tdav_session_msrp_s
//uint16_t local_port;
/* NAT Traversal context */
tnet_nat_context_handle_t* natt_ctx;
struct tnet_nat_ctx_s* natt_ctx;
char* remote_ip;
uint16_t remote_port;

View File

@ -64,7 +64,7 @@ typedef struct tdav_session_av_s
struct tdav_sdp_caps_s* sdp_caps;
/* NAT Traversal context */
tnet_nat_context_handle_t* natt_ctx;
struct tnet_nat_ctx_s* natt_ctx;
struct tnet_ice_ctx_s* ice_ctx;
char* local_ip;

View File

@ -49,7 +49,7 @@ typedef struct tdav_session_bfcp_s
//uint16_t local_port;
/* NAT Traversal context */
struct tnet_nat_context_s* p_natt_ctx;
struct tnet_nat_ctx_s* p_natt_ctx;
char* p_remote_ip;
uint16_t u_remote_port;

View File

@ -1160,7 +1160,7 @@ const tsdp_header_M_t* tdav_session_av_get_lo(tdav_session_av_t* self, tsk_bool_
// FIXME: for RTCP, use "RFC 3605"in addition to "rtcp-mux"
// "a=ice-mismatch" if "C=" line is not included in the candidates
if((candidate = tnet_ice_ctx_get_local_candidate_at(self->ice_ctx, 0))){ // at least one candidate
if ((candidate = tnet_ice_ctx_get_local_candidate_first(self->ice_ctx))) { // at least one candidate
base->M.lo->port = candidate->socket->port;
tsdp_header_M_remove(base->M.lo, tsdp_htype_C);
@ -1177,10 +1177,15 @@ const tsdp_header_M_t* tdav_session_av_get_lo(tdav_session_av_t* self, tsk_bool_
// TSDP_HEADER_A_VA_ARGS("mid", self->media_type & tmedia_audio ? "audio" : "video"),
// tsk_null);
while((candidate = tnet_ice_ctx_get_local_candidate_at(self->ice_ctx, index++))){
if(self->use_rtcpmux && remote_use_rtcpmux && candidate->comp_id == TNET_ICE_CANDIDATE_COMPID_RTCP){
while ((candidate = tnet_ice_ctx_get_local_candidate_at(self->ice_ctx, index++))) {
if (self->use_rtcpmux && remote_use_rtcpmux && candidate->comp_id == TNET_ICE_CANDIDATE_COMPID_RTCP) {
continue; // do not add RTCP candidates if RTCP-MUX is activated (local + remote)
}
#if 0 //TURN:FORCE
if (candidate->type_e != tnet_ice_cand_type_relay) {
continue;
}
#endif
tsdp_header_M_add_headers(base->M.lo,
TSDP_HEADER_A_VA_ARGS("candidate", tnet_ice_candidate_tostring((tnet_ice_candidate_t*)candidate)),
tsk_null);
@ -1652,15 +1657,15 @@ static int _tdav_session_av_raise_error_async(struct tdav_session_av_s* self, ts
tsk_safeobj_lock(self);
tsk_object_ref(self); // see _tdav_session_av_error_async_thread()
tsk_object_ref(self); // do not unref(), see _tdav_session_av_error_async_thread()
if(self->last_error.tid[0]){
if (self->last_error.tid[0]) {
tsk_thread_join(self->last_error.tid);
}
self->last_error.is_fatal = is_fatal;
tsk_strupdate(&self->last_error.reason, reason);
if((ret = tsk_thread_create(self->last_error.tid, _tdav_session_av_error_async_thread, self)) != 0){
if ((ret = tsk_thread_create(self->last_error.tid, _tdav_session_av_error_async_thread, self)) != 0) {
tsk_object_unref(self);
goto bail;
}
@ -1674,7 +1679,7 @@ bail:
#if HAVE_SRTP
static int _tdav_session_av_srtp_dtls_cb(const void* usrdata, enum trtp_srtp_dtls_event_type_e type, const char* reason)
{
tdav_session_av_t* self = (tdav_session_av_t*)usrdata;
tdav_session_av_t* self = tsk_object_ref((tdav_session_av_t*)usrdata);
tsk_safeobj_lock(self);
switch(type){
@ -1702,6 +1707,7 @@ static int _tdav_session_av_srtp_dtls_cb(const void* usrdata, enum trtp_srtp_dtl
}
}
tsk_safeobj_unlock(self);
tsk_object_unref(self);
return 0;
}

View File

@ -101,12 +101,16 @@ TINYMEDIA_API tsk_bool_t tmedia_defaults_get_rtcp_enabled();
TINYMEDIA_API int tmedia_defaults_set_rtcp_enabled(tsk_bool_t rtcp_enabled);
TINYMEDIA_API tsk_bool_t tmedia_defaults_get_rtcpmux_enabled();
TINYMEDIA_API int tmedia_defaults_set_rtcpmux_enabled(tsk_bool_t rtcpmux_enabled);
TINYMEDIA_API int tmedia_defaults_set_stun_server(const char* server_ip, uint16_t server_port, const char* usr_name, const char* usr_pwd);
TINYMEDIA_API int tmedia_defaults_get_stun_server(const char** server_ip, uint16_t*const server_port, const char** usr_name, const char** usr_pwd);
TINYMEDIA_API int tmedia_defaults_set_stun_server(const char* server_ip, uint16_t server_port);
TINYMEDIA_API int tmedia_defaults_get_stun_server(const char** server_ip, uint16_t*const server_port);
TINYMEDIA_API int tmedia_defaults_set_stun_cred(const char* usr_name, const char* usr_pwd);
TINYMEDIA_API int tmedia_defaults_get_stun_cred(const char** usr_name, const char** usr_pwd);
TINYMEDIA_API int tmedia_defaults_set_stun_enabled(tsk_bool_t stun_enabled);
TINYMEDIA_API tsk_bool_t tmedia_defaults_get_stun_enabled();
TINYMEDIA_API int tmedia_defaults_set_icestun_enabled(tsk_bool_t icestun_enabled);
TINYMEDIA_API tsk_bool_t tmedia_defaults_get_icestun_enabled();
TINYMEDIA_API int tmedia_defaults_set_iceturn_enabled(tsk_bool_t iceturn_enabled);
TINYMEDIA_API tsk_bool_t tmedia_defaults_get_iceturn_enabled();
TINYMEDIA_API int tmedia_defaults_set_ice_enabled(tsk_bool_t ice_enabled);
TINYMEDIA_API tsk_bool_t tmedia_defaults_get_ice_enabled();
TINYMEDIA_API int tmedia_defaults_set_bypass_encoding(tsk_bool_t enabled);

View File

@ -302,7 +302,7 @@ typedef struct tmedia_session_mgr_s
tmedia_bandwidth_level_t bl;
/* NAT Traversal context */
tnet_nat_context_handle_t* natt_ctx;
struct tnet_nat_ctx_s* natt_ctx;
struct {
struct tnet_ice_ctx_s *ctx_audio;
struct tnet_ice_ctx_s *ctx_video;
@ -506,7 +506,7 @@ TINYMEDIA_API tmedia_session_mgr_t* tmedia_session_mgr_create(tmedia_type_t type
TINYMEDIA_API int tmedia_session_mgr_set_media_type(tmedia_session_mgr_t* self, tmedia_type_t type);
TINYMEDIA_API int tmedia_session_mgr_set_codecs_supported(tmedia_session_mgr_t* self, tmedia_codec_id_t codecs_supported);
TINYMEDIA_API tmedia_session_t* tmedia_session_mgr_find(tmedia_session_mgr_t* self, tmedia_type_t type);
TINYMEDIA_API int tmedia_session_mgr_set_natt_ctx(tmedia_session_mgr_t* self, tnet_nat_context_handle_t* natt_ctx, const char* public_addr);
TINYMEDIA_API int tmedia_session_mgr_set_natt_ctx(tmedia_session_mgr_t* self, struct tnet_nat_ctx_s* natt_ctx, const char* public_addr);
TINYMEDIA_API int tmedia_session_mgr_set_ice_ctx(tmedia_session_mgr_t* self, struct tnet_ice_ctx_s* ctx_audio, struct tnet_ice_ctx_s* ctx_video);
TINYMEDIA_API int tmedia_session_mgr_start(tmedia_session_mgr_t* self);
TINYMEDIA_API int tmedia_session_mgr_set(tmedia_session_mgr_t* self, ...);

View File

@ -73,6 +73,7 @@ static char* __stun_usr_name = tsk_null; // STUN/TURN credentials
static char* __stun_usr_pwd = tsk_null; // STUN/TURN credentials
static tsk_bool_t __stun_enabled = tsk_false; // Whether STUN for SIP headers is enabled
static tsk_bool_t __icestun_enabled = tsk_true; // Whether STUN for ICE (reflexive candidates) is enabled
static tsk_bool_t __iceturn_enabled = tsk_false; // Whether TURN for ICE (relay candidates) is enabled
static tsk_bool_t __bypass_encoding_enabled = tsk_false;
static tsk_bool_t __bypass_decoding_enabled = tsk_false;
static tsk_bool_t __videojb_enabled = tsk_true;
@ -424,17 +425,24 @@ int tmedia_defaults_set_rtcpmux_enabled(tsk_bool_t rtcpmux_enabled){
return 0;
}
int tmedia_defaults_set_stun_server(const char* server_ip, uint16_t server_port, const char* usr_name, const char* usr_pwd){
int tmedia_defaults_set_stun_server(const char* server_ip, uint16_t server_port){
tsk_strupdate(&__stun_server_ip, server_ip);
__stun_server_port = server_port;
return 0;
}
int tmedia_defaults_get_stun_server(const char** server_ip, uint16_t*const server_port){
static const char* __stun_server_ip_default = "numb.viagenie.ca"; // default server for backward compatibility
if(server_ip) *server_ip = tsk_strnullORempty(__stun_server_ip) ? __stun_server_ip_default : __stun_server_ip;
if(server_port) *server_port = __stun_server_port;
return 0;
}
int tmedia_defaults_set_stun_cred(const char* usr_name, const char* usr_pwd) {
tsk_strupdate(&__stun_usr_name, usr_name);
tsk_strupdate(&__stun_usr_pwd, usr_pwd);
return 0;
}
int tmedia_defaults_get_stun_server(const char** server_ip, uint16_t*const server_port, const char** usr_name, const char** usr_pwd){
static const char* __stun_server_ip_default = "numb.viagenie.ca"; // default server for backward compatibility
if(server_ip) *server_ip = tsk_strnullORempty(__stun_server_ip) ? __stun_server_ip_default : __stun_server_ip;
if(server_port) *server_port = __stun_server_port;
int tmedia_defaults_get_stun_cred(const char** usr_name, const char** usr_pwd){
if(usr_name) *usr_name = __stun_usr_name;
if(usr_pwd) *usr_pwd = __stun_usr_pwd;
return 0;
@ -456,6 +464,14 @@ tsk_bool_t tmedia_defaults_get_icestun_enabled(){
return __icestun_enabled;
}
int tmedia_defaults_set_iceturn_enabled(tsk_bool_t iceturn_enabled){
__iceturn_enabled = iceturn_enabled;
return 0;
}
tsk_bool_t tmedia_defaults_get_iceturn_enabled(){
return __iceturn_enabled;
}
int tmedia_defaults_set_ice_enabled(tsk_bool_t ice_enabled){
__ice_enabled = ice_enabled;
return 0;

View File

@ -829,7 +829,7 @@ tmedia_session_t* tmedia_session_mgr_find(tmedia_session_mgr_t* self, tmedia_typ
/**@ingroup tmedia_session_group
*/
int tmedia_session_mgr_set_natt_ctx(tmedia_session_mgr_t* self, tnet_nat_context_handle_t* natt_ctx, const char* public_addr)
int tmedia_session_mgr_set_natt_ctx(tmedia_session_mgr_t* self, struct tnet_nat_ctx_s* natt_ctx, const char* public_addr)
{
if(!self || !natt_ctx){
TSK_DEBUG_ERROR("Invalid parameter");

View File

@ -57,6 +57,7 @@ libtinyNET_la_SOURCES += src/ice/tnet_ice_candidate.c\
libtinyNET_la_SOURCES += src/stun/tnet_stun.c\
src/stun/tnet_stun_attr.c\
src/stun/tnet_stun_binding.c\
src/stun/tnet_stun_pkt.c\
src/stun/tnet_stun_utils.c\
\

View File

@ -44,8 +44,8 @@ static int _tnet_ice_candidate_tostring(
const tsk_params_L_t *extension_att_list,
char** output);
static const char* _tnet_ice_candidate_get_foundation(tnet_ice_cand_type_t type);
static tnet_stun_message_t * _tnet_ice_candidate_stun_create_bind_request(tnet_ice_candidate_t* self, const char* username, const char* password);
static tsk_bool_t _tnet_ice_candidate_stun_transac_id_equals(const tnet_stun_transacid_t id1, const tnet_stun_transacid_t id2);
static tnet_stun_pkt_t * _tnet_ice_candidate_stun_create_bind_request(tnet_ice_candidate_t* self, const char* username, const char* password);
static tsk_bool_t _tnet_ice_candidate_stun_transac_id_equals(const tnet_stun_transac_id_t id1, const tnet_stun_transac_id_t id2);
static const char* _tnet_ice_candidate_get_transport_str(tnet_socket_type_t transport_e);
static tnet_socket_type_t _tnet_ice_candidate_get_transport_type(tsk_bool_t ipv6, const char* transport_str);
static const char* _tnet_ice_candidate_get_candtype_str(tnet_ice_cand_type_t candtype_e);
@ -68,11 +68,15 @@ static tsk_object_t* tnet_ice_candidate_dtor(tsk_object_t * self)
TSK_SAFE_FREE(candidate->cand_type_str);
TSK_OBJECT_SAFE_FREE(candidate->extension_att_list);
TSK_OBJECT_SAFE_FREE(candidate->socket);
TSK_SAFE_FREE(candidate->stun.nonce);
TSK_SAFE_FREE(candidate->stun.realm);
TSK_SAFE_FREE(candidate->stun.srflx_addr);
TSK_SAFE_FREE(candidate->turn.relay_addr);
TSK_OBJECT_SAFE_FREE(candidate->turn.ss);
TSK_SAFE_FREE(candidate->ufrag);
TSK_SAFE_FREE(candidate->pwd);
@ -312,10 +316,10 @@ const char* tnet_ice_candidate_tostring(tnet_ice_candidate_t* self)
}
break;
}
default:
{
break;
}
default:
{
break;
}
}
// WebRTC (Chrome) specific
@ -342,7 +346,7 @@ const char* tnet_ice_candidate_tostring(tnet_ice_candidate_t* self)
int tnet_ice_candidate_send_stun_bind_request(tnet_ice_candidate_t* self, struct sockaddr_storage* server_addr, const char* username, const char* password)
{
tnet_stun_message_t *request = tsk_null;
tnet_stun_pkt_t *request = tsk_null;
tsk_buffer_t *buffer = tsk_null;
int ret, sendBytes;
@ -358,15 +362,14 @@ int tnet_ice_candidate_send_stun_bind_request(tnet_ice_candidate_t* self, struct
goto bail;
}
if(!(buffer = tnet_stun_message_serialize(request))){
if((ret = tnet_stun_pkt_write_with_padding_2(request, &buffer))){
TSK_DEBUG_ERROR("Failed to serialize STUN request");
ret = -3;
goto bail;
}
sendBytes = tnet_sockfd_sendto(self->socket->fd, (const struct sockaddr*)server_addr, buffer->data, buffer->size);// return number of sent bytes
if(sendBytes == buffer->size){
memcpy(self->stun.transac_id, request->transaction_id, sizeof(tnet_stun_transacid_t));
memcpy(self->stun.transac_id, request->transac_id, sizeof(tnet_stun_transac_id_t));
ret = 0;
}
else{
@ -382,7 +385,7 @@ bail:
return 0;
}
int tnet_ice_candidate_process_stun_response(tnet_ice_candidate_t* self, const tnet_stun_response_t* response, tnet_fd_t fd)
int tnet_ice_candidate_process_stun_response(tnet_ice_candidate_t* self, const tnet_stun_pkt_resp_t* response, tnet_fd_t fd)
{
int ret = 0;
@ -391,45 +394,49 @@ int tnet_ice_candidate_process_stun_response(tnet_ice_candidate_t* self, const
return -1;
}
//if(!(_tnet_ice_candidate_stun_transac_id_equals(response->transaction_id, self->stun.transac_id))){
//if(!(_tnet_ice_candidate_stun_transac_id_equals(response->transac_id, self->stun.transac_id))){
// TSK_DEBUG_ERROR("Transaction id mismatch");
// return -2;
//}
if(TNET_STUN_RESPONSE_IS_ERROR(response)){
short code = tnet_stun_message_get_errorcode(response);
const char* realm = tnet_stun_message_get_realm(response);
const char* nonce = tnet_stun_message_get_nonce(response);
if(code == 401 && realm && nonce){
if(!self->stun.nonce){
/* First time we get a nonce */
tsk_strupdate(&self->stun.nonce, nonce);
tsk_strupdate(&self->stun.realm, realm);
return 0;
}
else{
TSK_DEBUG_ERROR("Authentication failed");
return -3;
}
if (TNET_STUN_PKT_RESP_IS_ERROR(response)) {
uint16_t u_code;
if ((ret = tnet_stun_pkt_get_errorcode(response, &u_code))) {
return ret;
}
else{
TSK_DEBUG_ERROR("STUN error: %hi", code);
if (u_code == kStunErrCodeUnauthorized || u_code == kStunErrCodeStaleNonce) {
const tnet_stun_attr_vdata_t* pc_attr;
if (u_code == kStunErrCodeUnauthorized) {
// Make sure this is not an authentication failure (#2 401)
// Do not send another req to avoid endless messages
if ((tnet_stun_pkt_attr_exists(response, tnet_stun_attr_type_message_integrity))) { // already has a MESSAGE-INTEGRITY?
TSK_DEBUG_ERROR("TURN authentication failed");
return -3;
}
}
if ((ret = tnet_stun_pkt_attr_find_first(response, tnet_stun_attr_type_nonce, (const tnet_stun_attr_t**)&pc_attr)) == 0 && pc_attr) {
tsk_strupdate(&self->stun.nonce, pc_attr->p_data_ptr);
}
if ((ret = tnet_stun_pkt_attr_find_first(response, tnet_stun_attr_type_realm, (const tnet_stun_attr_t**)&pc_attr)) == 0 && pc_attr) {
tsk_strupdate(&self->stun.realm, pc_attr->p_data_ptr);
}
return 0;
}
else {
TSK_DEBUG_ERROR("STUN error: %hu", u_code);
return -4;
}
}
else if(TNET_STUN_RESPONSE_IS_SUCCESS(response)){
const tnet_stun_attribute_t *attribute;
if((attribute = tnet_stun_message_get_attribute(response, stun_xor_mapped_address))){
const tnet_stun_attribute_xmapped_addr_t *xmaddr = (const tnet_stun_attribute_xmapped_addr_t *)attribute;
tnet_ice_utils_stun_address_tostring(xmaddr->xaddress, xmaddr->family, &self->stun.srflx_addr);
self->stun.srflx_port = xmaddr->xport;
}
else if((attribute = tnet_stun_message_get_attribute(response, stun_mapped_address))){
const tnet_stun_attribute_mapped_addr_t *maddr = (const tnet_stun_attribute_mapped_addr_t *)attribute;
ret = tnet_ice_utils_stun_address_tostring(maddr->address, maddr->family, &self->stun.srflx_addr);
self->stun.srflx_port = maddr->port;
else if(TNET_STUN_PKT_RESP_IS_SUCCESS(response)) {
const tnet_stun_attr_address_t* pc_attr_addr;
if (((ret = tnet_stun_pkt_attr_find_first(response, tnet_stun_attr_type_xor_mapped_address, (const tnet_stun_attr_t**)&pc_attr_addr)) == 0 && pc_attr_addr)
|| ((ret = tnet_stun_pkt_attr_find_first(response, tnet_stun_attr_type_mapped_address, (const tnet_stun_attr_t**)&pc_attr_addr)) == 0 && pc_attr_addr)) {
tnet_ip_t ip;
if ((ret = tnet_stun_utils_inet_ntop((pc_attr_addr->e_family == tnet_stun_address_family_ipv6), &pc_attr_addr->address, &ip))) {
return ret;
}
tsk_strupdate(&self->stun.srflx_addr, ip);
self->stun.srflx_port = pc_attr_addr->u_port;
}
}
@ -517,10 +524,10 @@ static const char* _tnet_ice_candidate_get_foundation(tnet_ice_cand_type_t type)
}
static tsk_bool_t _tnet_ice_candidate_stun_transac_id_equals(const tnet_stun_transacid_t id1, const tnet_stun_transacid_t id2)
static tsk_bool_t _tnet_ice_candidate_stun_transac_id_equals(const tnet_stun_transac_id_t id1, const tnet_stun_transac_id_t id2)
{
tsk_size_t i;
static const tsk_size_t size = sizeof(tnet_stun_transacid_t);
static const tsk_size_t size = sizeof(tnet_stun_transac_id_t);
for(i = 0; i < size; i++){
if(id1[i] != id2[i]){
return tsk_false;
@ -529,31 +536,38 @@ static tsk_bool_t _tnet_ice_candidate_stun_transac_id_equals(const tnet_stun_tra
return tsk_true;
}
static tnet_stun_message_t * _tnet_ice_candidate_stun_create_bind_request(tnet_ice_candidate_t* self, const char* username, const char* password)
static tnet_stun_pkt_t * _tnet_ice_candidate_stun_create_bind_request(tnet_ice_candidate_t* self, const char* username, const char* password)
{
tnet_stun_message_t *request = tsk_null;
tnet_stun_pkt_t *request = tsk_null;
int ret;
if(!self){
if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return tsk_null;
}
request = tnet_stun_message_create(username, password);
if(request){
tnet_stun_attribute_t* attribute;
request->realm = tsk_strdup(self->stun.realm);
request->nonce = tsk_strdup(self->stun.nonce);
/* Set the request type (RFC 5389 defines only one type) */
request->type = stun_binding_request;
/* Add software attribute */
if((attribute = (tnet_stun_attribute_t*)tnet_stun_attribute_software_create(TNET_SOFTWARE, tsk_strlen(TNET_SOFTWARE)))){
tnet_stun_message_add_attribute(request, &attribute);
if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_binding_request, &request))) {
TSK_DEBUG_ERROR("Failed to create STUN Bind request");
goto bail;
}
// add attributes
request->opt.dontfrag = 0;
ret = tnet_stun_pkt_attrs_add(request,
TNET_STUN_PKT_ATTR_ADD_SOFTWARE_ZT(kStunSoftware),
TNET_STUN_PKT_ATTR_ADD_NULL());
if (ret) {
goto bail;
}
if (username && self->stun.realm && self->stun.nonce) {
if ((ret = tnet_stun_pkt_auth_prepare(request, username, password, self->stun.realm, self->stun.nonce))) {
goto bail;
}
}
bail:
if (ret) {
TSK_OBJECT_SAFE_FREE(request);
}
return request;
}
@ -597,10 +611,10 @@ static const char* _tnet_ice_candidate_get_candtype_str(tnet_ice_cand_type_t can
switch(candtype_e){
case tnet_ice_cand_type_unknown:
default: return "unknown";
case tnet_ice_cand_type_host: return "host";
case tnet_ice_cand_type_srflx: return "srflx";
case tnet_ice_cand_type_prflx: return "prflx";
case tnet_ice_cand_type_relay: return "relay";
case tnet_ice_cand_type_host: return TNET_ICE_CANDIDATE_TYPE_HOST;
case tnet_ice_cand_type_srflx: return TNET_ICE_CANDIDATE_TYPE_SRFLX;
case tnet_ice_cand_type_prflx: return TNET_ICE_CANDIDATE_TYPE_PRFLX;
case tnet_ice_cand_type_relay: return TNET_ICE_CANDIDATE_TYPE_RELAY;
}
}
@ -621,4 +635,4 @@ static tnet_ice_cand_type_t _tnet_ice_candtype_get_transport_type(const char* ca
else{
return tnet_ice_cand_type_unknown;
}
}
}

View File

@ -24,7 +24,9 @@
#include "tinynet_config.h"
#include "stun/tnet_stun_message.h"
#include "stun/tnet_stun_pkt.h"
#include "stun/tnet_stun_attr.h"
#include "stun/tnet_stun_utils.h"
#include "tnet_socket.h"
#include "tsk_params.h"
@ -56,7 +58,7 @@ TNET_BEGIN_DECLS
#define TNET_ICE_CANDIDATE_COMPID_RTP 1
#define TNET_ICE_CANDIDATE_COMPID_RTCP 2
#define TNET_ICE_CANDIDATE_FOUND_SIZE_PREF 9
#define TNET_ICE_CANDIDATE_FOUND_SIZE_PREF 15
typedef enum tnet_ice_cand_type_e
{
@ -96,9 +98,14 @@ typedef struct tnet_ice_candidate_s
char* nonce;
char* realm;
char* srflx_addr;
tnet_stun_transacid_t transac_id;
tnet_stun_transac_id_t transac_id;
tnet_port_t srflx_port;
} stun;
struct {
struct tnet_turn_session_s* ss;
char* relay_addr;
tnet_port_t relay_port;
} turn;
char *tostring;
}
@ -114,7 +121,7 @@ TINYNET_API const char* tnet_ice_candidate_get_att_value(const tnet_ice_candidat
int tnet_ice_candidate_set_local_pref(tnet_ice_candidate_t* self, uint16_t local_pref);
TINYNET_API const char* tnet_ice_candidate_tostring(tnet_ice_candidate_t* self);
int tnet_ice_candidate_send_stun_bind_request(tnet_ice_candidate_t* self, struct sockaddr_storage* server_addr, const char* username, const char* password);
int tnet_ice_candidate_process_stun_response(tnet_ice_candidate_t* self, const tnet_stun_response_t* response, tnet_fd_t fd);
int tnet_ice_candidate_process_stun_response(tnet_ice_candidate_t* self, const tnet_stun_pkt_resp_t* response, tnet_fd_t fd);
const tnet_ice_candidate_t* tnet_ice_candidate_find_by_fd(tnet_ice_candidates_L_t* candidates, tnet_fd_t fd);
const char* tnet_ice_candidate_get_ufrag(const tnet_ice_candidate_t* self);
const char* tnet_ice_candidate_get_pwd(const tnet_ice_candidate_t* self);

File diff suppressed because it is too large Load Diff

View File

@ -52,6 +52,8 @@ TINYNET_API int tnet_ice_ctx_set_stun(
const char* password);
TINYNET_API int tnet_ice_ctx_set_sync_mode(struct tnet_ice_ctx_s* self, tsk_bool_t sync_mode);
TINYNET_API int tnet_ice_ctx_set_silent_mode(struct tnet_ice_ctx_s* self, tsk_bool_t silent_mode);
TINYNET_API int tnet_ice_ctx_set_stun_enabled(struct tnet_ice_ctx_s* self, tsk_bool_t stun_enabled);
TINYNET_API int tnet_ice_ctx_set_turn_enabled(struct tnet_ice_ctx_s* self, tsk_bool_t turn_enabled);
TINYNET_API int tnet_ice_ctx_start(struct tnet_ice_ctx_s* self);
TINYNET_API int tnet_ice_ctx_rtp_callback(struct tnet_ice_ctx_s* self, tnet_ice_rtp_callback_f rtp_callback, const void* rtp_callback_data);
TINYNET_API int tnet_ice_ctx_set_concheck_timeout(struct tnet_ice_ctx_s* self, int64_t timeout);
@ -60,8 +62,11 @@ TINYNET_API int tnet_ice_ctx_set_rtcpmux(struct tnet_ice_ctx_s* self, tsk_bool_t
TINYNET_API tsk_size_t tnet_ice_ctx_count_local_candidates(const struct tnet_ice_ctx_s* self);
TINYNET_API tsk_bool_t tnet_ice_ctx_got_local_candidates(const struct tnet_ice_ctx_s* self);
TINYNET_API const struct tnet_ice_candidate_s* tnet_ice_ctx_get_local_candidate_at(const struct tnet_ice_ctx_s* self, tsk_size_t index);
#define tnet_ice_ctx_get_local_candidate_first(self) tnet_ice_ctx_get_local_candidate_at((self), 0)
TINYNET_API tsk_bool_t tnet_ice_ctx_is_started(const struct tnet_ice_ctx_s* self);
TINYNET_API tsk_bool_t tnet_ice_ctx_is_active(const struct tnet_ice_ctx_s* self);
TINYNET_API tsk_bool_t tnet_ice_ctx_is_turn_rtp_active(const struct tnet_ice_ctx_s* self);
TINYNET_API tsk_bool_t tnet_ice_ctx_is_turn_rtcp_active(const struct tnet_ice_ctx_s* self);
TINYNET_API tsk_bool_t tnet_ice_ctx_is_connected(const struct tnet_ice_ctx_s* self);
TINYNET_API tsk_bool_t tnet_ice_ctx_is_can_send(const struct tnet_ice_ctx_s* self);
TINYNET_API tsk_bool_t tnet_ice_ctx_is_can_recv(const struct tnet_ice_ctx_s* self);
@ -72,6 +77,8 @@ TINYNET_API int tnet_ice_ctx_get_nominated_symetric_candidates(const struct tnet
const struct tnet_ice_candidate_s** candidate_answer_src,
const struct tnet_ice_candidate_s** candidate_answer_dest);
TINYNET_API int tnet_ice_ctx_recv_stun_message(struct tnet_ice_ctx_s* self, const void* data, tsk_size_t size, tnet_fd_t local_fd, const struct sockaddr_storage* remote_addr, tsk_bool_t *role_conflict);
TINYNET_API int tnet_ice_ctx_send_turn_rtp(struct tnet_ice_ctx_s* self, const void* data, tsk_size_t size);
TINYNET_API int tnet_ice_ctx_send_turn_rtcp(struct tnet_ice_ctx_s* self, const void* data, tsk_size_t size);
TINYNET_API const char* tnet_ice_ctx_get_ufrag(const struct tnet_ice_ctx_s* self);
TINYNET_API const char* tnet_ice_ctx_get_pwd(const struct tnet_ice_ctx_s* self);

View File

@ -40,10 +40,13 @@ typedef enum tnet_ice_event_type_e
tnet_ice_event_type_gathering_host_candidates_succeed,
tnet_ice_event_type_gathering_reflexive_candidates_failed,
tnet_ice_event_type_gathering_reflexive_candidates_succeed,
tnet_ice_event_type_gathering_relay_candidates_failed,
tnet_ice_event_type_gathering_relay_candidates_succeed,
tnet_ice_event_type_gathering_completed,
tnet_ice_event_type_conncheck_succeed,
tnet_ice_event_type_conncheck_failed,
tnet_ice_event_type_cancelled,
tnet_ice_event_type_turn_connection_broken,
// Private events
tnet_ice_event_type_action

View File

@ -4,6 +4,8 @@
#include "stun/tnet_stun.h"
#include "stun/tnet_stun_message.h"
#include "stun/tnet_stun_types.h"
#include "turn/tnet_turn_session.h"
#include "tnet_endianness.h"
#include "tnet_utils.h"
@ -91,6 +93,7 @@ tnet_ice_pair_t* tnet_ice_pair_create(const tnet_ice_candidate_t* candidate_offe
pair->priority = (((uint64_t)TSK_MIN(candidate_offer->priority, candidate_answer->priority)) << 32) +
(TSK_MAX(candidate_offer->priority, candidate_answer->priority) << 1) +
((candidate_offer->priority > candidate_answer->priority) ? 1 : 0);
pair->turn_peer_id = kTurnPeerIdInvalid;
}
return pair;
@ -105,34 +108,35 @@ tnet_ice_pair_t* tnet_ice_pair_prflx_create(tnet_ice_pairs_L_t* pairs, uint16_t
tnet_ip_t remote_ip;
tnet_port_t remote_port;
if(!pairs || !remote_addr){
if (!pairs || !remote_addr) {
TSK_DEBUG_ERROR("Invalid parameter");
return tsk_null;
}
}
if((ret = tnet_get_sockip_n_port((const struct sockaddr*)remote_addr, &remote_ip, &remote_port))){
TNET_PRINT_LAST_ERROR("tnet_get_sockip_n_port() failed");
return tsk_null;
}
tsk_list_foreach(item, pairs){
if(!(pair = item->data) || !pair->candidate_offer || !pair->candidate_answer || !pair->candidate_offer->socket || pair->candidate_offer->socket->fd != local_fd){
tsk_list_foreach(item, pairs) {
if (!(pair = item->data) || !pair->candidate_offer || !pair->candidate_answer || !pair->candidate_offer->socket || pair->candidate_offer->socket->fd != local_fd) {
continue;
}
pair_local = pair;
break;
}
if(!pair_local){
if ((ret = tnet_get_sockip_n_port((const struct sockaddr*)remote_addr, &remote_ip, &remote_port))) {
TNET_PRINT_LAST_ERROR("tnet_get_sockip_n_port() failed");
return tsk_null;
}
if (!pair_local) {
TSK_DEBUG_ERROR("Cannot create prflx candidate with remote ip = %s and remote port = %u", remote_ip, remote_port);
return tsk_null;
}
else{
else {
tnet_ice_pair_t* pair_peer = tsk_null;
tnet_ice_candidate_t* cand_local = tnet_ice_candidate_create(tnet_ice_cand_type_prflx, pair_local->candidate_offer->socket, pair_local->is_ice_jingle, pair_local->candidate_offer->is_rtp, pair_local->candidate_offer->is_video, pair_local->candidate_offer->ufrag, pair_local->candidate_offer->pwd, pair_local->candidate_offer->foundation);
tnet_ice_candidate_t* cand_remote = tnet_ice_candidate_create(tnet_ice_cand_type_prflx, tsk_null, pair_local->is_ice_jingle, pair_local->candidate_answer->is_rtp, pair_local->candidate_answer->is_video, pair_local->candidate_answer->ufrag, pair_local->candidate_answer->pwd, pair_local->candidate_answer->foundation);
if(cand_local && cand_remote){
tnet_ice_candidate_t* cand_local;
tnet_ice_candidate_t* cand_remote;
cand_local = tnet_ice_candidate_create(tnet_ice_cand_type_prflx, pair_local->candidate_offer->socket, pair_local->is_ice_jingle, pair_local->candidate_offer->is_rtp, pair_local->candidate_offer->is_video, pair_local->candidate_offer->ufrag, pair_local->candidate_offer->pwd, pair_local->candidate_offer->foundation);
cand_remote = tnet_ice_candidate_create(tnet_ice_cand_type_prflx, tsk_null, pair_local->is_ice_jingle, pair_local->candidate_answer->is_rtp, pair_local->candidate_answer->is_video, pair_local->candidate_answer->ufrag, pair_local->candidate_answer->pwd, pair_local->candidate_answer->foundation);
if (cand_local && cand_remote) {
tsk_strupdate(&cand_remote->transport_str, pair_local->candidate_offer->transport_str);
cand_remote->comp_id = pair_local->candidate_offer->comp_id;
memcpy(cand_remote->connection_addr, remote_ip, sizeof(tnet_ip_t));
@ -160,243 +164,274 @@ tnet_ice_pair_t* tnet_ice_pair_prflx_create(tnet_ice_pairs_L_t* pairs, uint16_t
int tnet_ice_pair_send_conncheck(tnet_ice_pair_t *self)
{
char* username = tsk_null;
const char* password;
uint32_t priority;
struct sockaddr_storage remote_addr;
tnet_stun_attribute_t *stun_att;
int ret;
if(!self){
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if((ret = tnet_sockaddr_init(self->candidate_answer->connection_addr, self->candidate_answer->port, self->candidate_offer->socket->type, &remote_addr))){
TNET_PRINT_LAST_ERROR("tnet_sockaddr_init(%s:%d) failed", self->candidate_answer->connection_addr, self->candidate_answer->port);
goto bail;
if (self->candidate_offer->turn.ss) {
enum tnet_stun_state_e e_state;
if ((ret = tnet_turn_session_get_state_createperm(self->candidate_offer->turn.ss, self->turn_peer_id, &e_state))) {
goto bail;
}
if (e_state != tnet_stun_state_ok) {
TSK_DEBUG_INFO("TURN CreatePerm not ready yet... to send STUN ConnCheck");
goto bail;
}
}
// 7.1.2.3. Forming Credentials
// username= "RFRAG:LFRAG"
// password= "RPASS"
if(self->is_ice_jingle){
tsk_sprintf(&username, "%s%s", tnet_ice_candidate_get_ufrag(self->candidate_answer), tnet_ice_candidate_get_ufrag(self->candidate_offer));
}
else{
tsk_sprintf(&username, "%s:%s", tnet_ice_candidate_get_ufrag(self->candidate_answer), tnet_ice_candidate_get_ufrag(self->candidate_offer));
}
password = tnet_ice_candidate_get_pwd(self->candidate_answer);
if(!self->last_request && (self->last_request = tnet_stun_message_create(username, password))){
self->last_request->type = stun_binding_request;
// 7.1.2.1. PRIORITY
priority = tnet_ice_utils_get_priority(tnet_ice_cand_type_prflx, self->candidate_offer->local_pref, self->candidate_offer->is_rtp);
if((stun_att = (tnet_stun_attribute_t*)tnet_stun_attribute_ice_priority_create(priority))){
tnet_stun_message_add_attribute(self->last_request, &stun_att);
if (!self->last_request) {
uint32_t priority;
// Init remote address
if ((ret = tnet_sockaddr_init(self->candidate_answer->connection_addr, self->candidate_answer->port, self->candidate_offer->socket->type, &self->remote_addr))) {
TNET_PRINT_LAST_ERROR("tnet_sockaddr_init(%s:%d) failed", self->candidate_answer->connection_addr, self->candidate_answer->port);
goto bail;
}
// 7.1.2.1. USE-CANDIDATE
if(self->is_controlling){ // aggressive mode
if((stun_att = (tnet_stun_attribute_t*)tnet_stun_attribute_ice_use_candidate_create())){
tnet_stun_message_add_attribute(self->last_request, &stun_att);
if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_binding_request, &self->last_request))) {
goto bail;
}
// 7.1.2.3. Forming Credentials
// username= "RFRAG:LFRAG"
// password= "RPASS"
{
char* p_uname = tsk_null;
const char* pc_pwd;
if (self->is_ice_jingle) {
tsk_sprintf(&p_uname, "%s%s", tnet_ice_candidate_get_ufrag(self->candidate_answer), tnet_ice_candidate_get_ufrag(self->candidate_offer));
}
else{
tsk_sprintf(&p_uname, "%s:%s", tnet_ice_candidate_get_ufrag(self->candidate_answer), tnet_ice_candidate_get_ufrag(self->candidate_offer));
}
pc_pwd = tnet_ice_candidate_get_pwd(self->candidate_answer);
ret = tnet_stun_pkt_auth_prepare_shortterm(self->last_request, p_uname, pc_pwd);
TSK_FREE(p_uname);
if (ret) {
goto bail;
}
}
priority = tnet_ice_utils_get_priority(tnet_ice_cand_type_prflx, self->candidate_offer->local_pref, self->candidate_offer->is_rtp);
// add attributes
self->last_request->opt.dontfrag = 0;
ret = tnet_stun_pkt_attrs_add(self->last_request,
TNET_STUN_PKT_ATTR_ADD_SOFTWARE_ZT(kStunSoftware),
// 7.1.2.1. PRIORITY
TNET_STUN_PKT_ATTR_ADD_ICE_PRIORITY(priority),
TNET_STUN_PKT_ATTR_ADD_NULL());
if (ret) {
goto bail;
}
// 7.1.2.2. ICE-CONTROLLING / ICE-CONTROLLED
if(self->is_controlling){
if((stun_att = (tnet_stun_attribute_t*)tnet_stun_attribute_ice_controlling_create(self->tie_breaker))){
tnet_stun_message_add_attribute(self->last_request, &stun_att);
if (self->is_controlling) {
ret = tnet_stun_pkt_attrs_add(self->last_request,
// 7.1.2.2. ICE-CONTROLLING
TNET_STUN_PKT_ATTR_ADD_ICE_CONTROLLING(self->tie_breaker),
// 7.1.2.1. USE-CANDIDATE - aggressive mode
TNET_STUN_PKT_ATTR_ADD_ICE_USE_CANDIDATE(),
TNET_STUN_PKT_ATTR_ADD_NULL());
if (ret) {
goto bail;
}
}
else{
if((stun_att = (tnet_stun_attribute_t*)tnet_stun_attribute_ice_controlled_create(self->tie_breaker))){
tnet_stun_message_add_attribute(self->last_request, &stun_att);
}
}
// SOFTWARE
if((stun_att = (tnet_stun_attribute_t*)tnet_stun_attribute_software_create(TNET_SOFTWARE, tsk_strlen(TNET_SOFTWARE)))){
tnet_stun_message_add_attribute(self->last_request, &stun_att);
}
}
else if(self->last_request){
if(self->is_controlling){
tnet_stun_message_remove_attribute(self->last_request, stun_ice_controlled);
if(!tnet_stun_message_has_attribute(self->last_request, stun_ice_controlling)){
if((stun_att = (tnet_stun_attribute_t*)tnet_stun_attribute_ice_controlling_create(self->tie_breaker))){
tnet_stun_message_add_attribute(self->last_request, &stun_att);
}
}
if(!tnet_stun_message_has_attribute(self->last_request, stun_ice_use_candidate)){
if((stun_att = (tnet_stun_attribute_t*)tnet_stun_attribute_ice_use_candidate_create())){
tnet_stun_message_add_attribute(self->last_request, &stun_att);
}
}
}
else{
tnet_stun_message_remove_attribute(self->last_request, stun_ice_use_candidate);
tnet_stun_message_remove_attribute(self->last_request, stun_ice_controlling);
if(!tnet_stun_message_has_attribute(self->last_request, stun_ice_controlled)){
if((stun_att = (tnet_stun_attribute_t*)tnet_stun_attribute_ice_controlled_create(self->tie_breaker))){
tnet_stun_message_add_attribute(self->last_request, &stun_att);
}
else {
ret = tnet_stun_pkt_attrs_add(self->last_request,
// 7.1.2.2. ICE-CONTROLLED
TNET_STUN_PKT_ATTR_ADD_ICE_CONTROLLED(self->tie_breaker),
TNET_STUN_PKT_ATTR_ADD_NULL());
if (ret) {
goto bail;
}
}
}
else {
tsk_bool_t b_changed = tsk_false;
if (self->is_controlling) {
tnet_stun_pkt_attr_remove(self->last_request, tnet_stun_attr_type_ice_controlled);
if (!tnet_stun_pkt_attr_exists(self->last_request, tnet_stun_attr_type_ice_controlling)) {
ret = tnet_stun_pkt_attrs_add(self->last_request,
TNET_STUN_PKT_ATTR_ADD_ICE_CONTROLLING(self->tie_breaker),
TNET_STUN_PKT_ATTR_ADD_NULL());
if (ret) {
goto bail;
}
b_changed = tsk_true;
}
if (!tnet_stun_pkt_attr_exists(self->last_request, tnet_stun_attr_type_ice_use_candidate)) {
ret = tnet_stun_pkt_attrs_add(self->last_request,
TNET_STUN_PKT_ATTR_ADD_ICE_USE_CANDIDATE(),
TNET_STUN_PKT_ATTR_ADD_NULL());
if (ret) {
goto bail;
}
b_changed = tsk_true;
}
}
else {
tnet_stun_pkt_attr_remove(self->last_request, tnet_stun_attr_type_ice_use_candidate);
tnet_stun_pkt_attr_remove(self->last_request, tnet_stun_attr_type_ice_controlling);
if (!tnet_stun_pkt_attr_exists(self->last_request, tnet_stun_attr_type_ice_controlled)) {
ret = tnet_stun_pkt_attrs_add(self->last_request,
TNET_STUN_PKT_ATTR_ADD_ICE_CONTROLLED(self->tie_breaker),
TNET_STUN_PKT_ATTR_ADD_NULL());
if (ret) {
goto bail;
}
b_changed = tsk_true;
}
}
// update transac-id if the request structure changed
if ((b_changed && (ret = tnet_stun_utils_transac_id_rand(&self->last_request->transac_id)))) {
goto bail;
}
}
if(self->last_request){
tsk_buffer_t *req_buffer;
self->last_request->fingerprint = !self->is_ice_jingle;
if((req_buffer = tnet_stun_message_serialize(self->last_request))){
/*int sendBytes =*/ tnet_sockfd_sendto(self->candidate_offer->socket->fd, (const struct sockaddr*)&remote_addr, req_buffer->data, req_buffer->size);
TSK_OBJECT_SAFE_FREE(req_buffer);
// Send request
{
tsk_buffer_t *req_buffer = tsk_null;
self->last_request->opt.fingerprint = !self->is_ice_jingle;
if ((ret = tnet_stun_pkt_write_with_padding_2(self->last_request, &req_buffer))) {
goto bail;
}
if (self->candidate_offer->turn.ss) {
// Send using TURN session. Above, we already checked that the TURN session is ready (Alloc=OK, Permission=OK)
ret = tnet_turn_session_send_data(self->candidate_offer->turn.ss, self->turn_peer_id, req_buffer->data, (uint16_t)req_buffer->size);
}
else {
int sendBytes = tnet_sockfd_sendto(self->candidate_offer->socket->fd, (const struct sockaddr*)&self->remote_addr, req_buffer->data, req_buffer->size);
ret = (sendBytes == req_buffer->size) ? 0 : -9;
}
TSK_OBJECT_SAFE_FREE(req_buffer);
if (ret) {
goto bail;
}
}
bail:
TSK_FREE(username);
if(ret == 0 && self->state_offer == tnet_ice_pair_state_frozen){
if (ret == 0 && self->state_offer == tnet_ice_pair_state_frozen) {
self->state_offer = tnet_ice_pair_state_in_progress;
}
return ret;
}
int tnet_ice_pair_send_response(tnet_ice_pair_t *self, const tnet_stun_request_t* request, const short code, const char* phrase, const struct sockaddr_storage *remote_addr)
int tnet_ice_pair_send_response(tnet_ice_pair_t *self, const tnet_stun_pkt_req_t* request, const short code, const char* phrase, const struct sockaddr_storage *remote_addr)
{
tnet_stun_message_t* message;
tnet_stun_pkt_t* message = tsk_null;
const char *password, *username;
int ret = -1;
tnet_stun_attribute_t *stun_att = tsk_null;
struct sockaddr_storage dest_addr;
tnet_stun_attr_t *stun_att = tsk_null;
tsk_bool_t is_error = ((code / 100) != 2);
if(!self || !phrase || !request || !self->candidate_offer || !self->candidate_answer){
TSK_DEBUG_ERROR("Invalid paramter");
return -1;
}
if((ret = tnet_sockaddr_init(self->candidate_answer->connection_addr, self->candidate_answer->port, self->candidate_offer->socket->type, &dest_addr))){
TNET_PRINT_LAST_ERROR("tnet_sockaddr_init(%s:%d) failed", self->candidate_answer->connection_addr, self->candidate_answer->port);
return ret;
}
}
// FIXME: "username" and "password" not used
username = tsk_null;
password = tnet_ice_candidate_get_pwd(self->candidate_offer);
password = tnet_ice_candidate_get_pwd(self->candidate_offer);
if((message = tnet_stun_message_create(username, password))){
tsk_buffer_t *req_buffer;
message->type = is_error ? stun_binding_error_response : stun_binding_success_response;
memcpy(message->transaction_id, request->transaction_id, sizeof(request->transaction_id));
message->nointegrity = self->is_ice_jingle;
message->fingerprint = !self->is_ice_jingle;
if ((ret = tnet_stun_pkt_create_empty(is_error ? tnet_stun_pkt_type_binding_error_response : tnet_stun_pkt_type_binding_success_response, &message)) == 0) {
tsk_buffer_t *req_buffer = tsk_null;
memcpy(message->transac_id, request->transac_id, sizeof(request->transac_id));
message->opt.fingerprint = !self->is_ice_jingle;
message->opt.dontfrag = 0;
// SOFWARE
ret = tnet_stun_pkt_attrs_add(message,
TNET_STUN_PKT_ATTR_ADD_SOFTWARE_ZT(kStunSoftware),
TNET_STUN_PKT_ATTR_ADD_NULL());
if (ret) {
goto bail;
}
// SHORT-TERM authentication even for responses
if ((ret = tnet_stun_pkt_auth_prepare_shortterm_2(message, password))) {
goto bail;
}
// ERROR
if(is_error){
tnet_stun_attribute_errorcode_t* stun_att_err;
if((stun_att_err = tnet_stun_attribute_errorcode_create(tsk_null, 0))){
stun_att_err->_class = ((code / 100) & 0x07);
stun_att_err->number = (code - ((code / 100) * 100));
stun_att_err->reason_phrase = tsk_strdup(phrase);
TNET_STUN_ATTRIBUTE(stun_att_err)->length = 4 + tsk_strlen(phrase);
tnet_stun_message_add_attribute(message, (tnet_stun_attribute_t**)&stun_att_err);
if (is_error) {
ret = tnet_stun_pkt_attrs_add(message,
TNET_STUN_PKT_ATTR_ADD_ERROR_CODE(((code / 100) & 0x07), (code - ((code / 100) * 100)), phrase),
TNET_STUN_PKT_ATTR_ADD_NULL());
if (ret) {
goto bail;
}
}
else{
tnet_stun_attribute_xmapped_addr_t* stun_att_xma;
if(self->is_ice_jingle){
const tnet_stun_attribute_username_t * stun_att_usr_name;
tnet_stun_attribute_mapped_addr_t* stun_att_ma;
else {
tnet_ip_t remote_ip;
tnet_port_t remote_port;
if (self->is_ice_jingle) {
const tnet_stun_attr_vdata_t *pc_attr_vdata;
// USERNAME
if((stun_att_usr_name = (const tnet_stun_attribute_username_t *)tnet_stun_message_get_attribute(request, stun_username))){
stun_att_usr_name = tsk_object_ref((tsk_object_t*)stun_att_usr_name);
tnet_stun_message_add_attribute(message, (tnet_stun_attribute_t**)&stun_att_usr_name);
}
// MAPPED-ADDRESS
if((stun_att_ma = tnet_stun_attribute_mapped_address_create(tsk_null, 0))){
uint32_t addr;
if(TNET_SOCKET_TYPE_IS_IPV6(self->candidate_offer->socket->type)){
tsk_size_t i;
const struct sockaddr_in6* sin6 = (const struct sockaddr_in6*)remote_addr;
stun_att_ma->family = stun_ipv6;
stun_att_ma->port = tnet_ntohs(sin6->sin6_port);
for(i = 0; i < 16; i+=4){
addr = tnet_ntohl_2(&sin6->sin6_addr.s6_addr[i]);
memcpy(&stun_att_ma->address[i], &addr, 4);
}
TNET_STUN_ATTRIBUTE(stun_att_ma)->length = 4 + 16;
if ((ret = tnet_stun_pkt_attr_find_first(request, tnet_stun_attr_type_username, (const tnet_stun_attr_t **)&pc_attr_vdata)) == 0 && pc_attr_vdata) {
ret = tnet_stun_pkt_attrs_add(message,
TNET_STUN_PKT_ATTR_ADD_USERNAME(pc_attr_vdata->p_data_ptr, pc_attr_vdata->u_data_size),
TNET_STUN_PKT_ATTR_ADD_NULL());
if (ret) {
goto bail;
}
else{
const struct sockaddr_in* sin = (const struct sockaddr_in*)remote_addr;
stun_att_ma->family = stun_ipv4;
stun_att_ma->port = tnet_ntohs(sin->sin_port);
addr = tnet_ntohl(sin->sin_addr.s_addr);
memcpy(&stun_att_ma->address[0], &addr, 4);
TNET_STUN_ATTRIBUTE(stun_att_ma)->length = 4 + 4;
}
tnet_stun_message_add_attribute(message, (tnet_stun_attribute_t**)&stun_att_ma);
}
}
// XOR-MAPPED-ADDRESS
if((stun_att_xma = tnet_stun_attribute_xmapped_address_create(tsk_null, 0))){//JINGLE_ICE
tsk_size_t addr_size;
tsk_size_t i;
uint32_t addr;
if(TNET_SOCKET_TYPE_IS_IPV6(self->candidate_offer->socket->type)){
addr_size = 16;
stun_att_xma->family = stun_ipv6;
}
else{
addr_size = 4;
stun_att_xma->family = stun_ipv4;
}
if(stun_att_xma->family == stun_ipv4){
const struct sockaddr_in* sin = (const struct sockaddr_in*)remote_addr;
stun_att_xma->xport = tnet_ntohs(sin->sin_port) ^ 0x2112;
addr = (tnet_ntohl(sin->sin_addr.s_addr) ^ TNET_STUN_MAGIC_COOKIE);
memcpy(&stun_att_xma->xaddress[0], &addr, 4);
}
else{
const struct sockaddr_in6* sin6 = (const struct sockaddr_in6*)remote_addr;
stun_att_xma->xport = tnet_ntohs(sin6->sin6_port) ^ 0x2112;
for(i = 0; i < addr_size; i+=4){
addr = (tnet_ntohl_2(&sin6->sin6_addr.s6_addr[i]) ^ TNET_STUN_MAGIC_COOKIE);
memcpy(&stun_att_xma->xaddress[i], &addr, 4);
// MAPPED-ADDRESS and XOR-MAPPED-ADDRESS
if ((ret = tnet_get_sockip_n_port((const struct sockaddr*)remote_addr, &remote_ip, &remote_port)) == 0) {
tnet_stun_addr_t _addr;
tnet_stun_address_family_t _familly = (remote_addr->ss_family == AF_INET6) ? tnet_stun_address_family_ipv6 : tnet_stun_address_family_ipv4;
if ((ret = tnet_stun_utils_inet_pton((_familly == tnet_stun_address_family_ipv6), remote_ip, &_addr)) == 0) {
ret = tnet_stun_pkt_attrs_add(message,
TNET_STUN_PKT_ATTR_ADD_MAPPED_ADDRESS(_familly, remote_port, &_addr),
TNET_STUN_PKT_ATTR_ADD_XOR_MAPPED_ADDRESS(_familly, remote_port, &_addr),
TNET_STUN_PKT_ATTR_ADD_NULL());
if (ret) {
goto bail;
}
}
TNET_STUN_ATTRIBUTE(stun_att_xma)->length = 4 + addr_size;
tnet_stun_message_add_attribute(message, (tnet_stun_attribute_t**)&stun_att_xma);
}
// SOFTWARE
if((stun_att = (tnet_stun_attribute_t*)tnet_stun_attribute_software_create(TNET_SOFTWARE, tsk_strlen(TNET_SOFTWARE)))){
tnet_stun_message_add_attribute(message, &stun_att);
}
}
if((req_buffer = tnet_stun_message_serialize(message))){
int sendBytes = tnet_sockfd_sendto(self->candidate_offer->socket->fd, (const struct sockaddr*)&dest_addr, req_buffer->data, req_buffer->size);
if (self->candidate_offer->turn.ss) {
enum tnet_stun_state_e e_state;
if ((ret = tnet_turn_session_get_state_createperm(self->candidate_offer->turn.ss, self->turn_peer_id, &e_state))) {
goto bail;
}
if (e_state != tnet_stun_state_ok) {
TSK_DEBUG_INFO("TURN CreatePerm not ready yet... to send STUN response");
goto bail;
}
if ((ret = tnet_stun_pkt_write_with_padding_2(message, &req_buffer))) {
goto bail;
}
if ((ret = tnet_turn_session_send_data(self->candidate_offer->turn.ss, self->turn_peer_id, req_buffer->data, req_buffer->size))) {
goto bail;
}
}
else {
struct sockaddr_storage dest_addr;
int sendBytes;
if ((ret = tnet_sockaddr_init(self->candidate_answer->connection_addr, self->candidate_answer->port, self->candidate_offer->socket->type, &dest_addr))) {
TNET_PRINT_LAST_ERROR("tnet_sockaddr_init(%s:%d) failed", self->candidate_answer->connection_addr, self->candidate_answer->port);
goto bail;
}
if ((ret = tnet_stun_pkt_write_with_padding_2(message, &req_buffer))) {
goto bail;
}
sendBytes = tnet_sockfd_sendto(self->candidate_offer->socket->fd, (const struct sockaddr*)&dest_addr, req_buffer->data, req_buffer->size);
TSK_OBJECT_SAFE_FREE(req_buffer);
ret = (sendBytes > 0) ? 0 : -2;
if(ret != 0){
if (ret != 0) {
TSK_DEBUG_ERROR("ICE pair-answer: failed to send response");
}
}
TSK_OBJECT_SAFE_FREE(message);
}
if(ret == 0 && !is_error){
if (ret == 0 && !is_error) {
tsk_bool_t change_state =
self->is_ice_jingle || // ICE-JINGLE don't have ICE-CONTROLLING/ICE-CONTROLLED attributes
(!self->is_controlling && tnet_stun_message_has_attribute(request, stun_ice_use_candidate)) || // Sender is controlling and uses "ICE-USE-CANDIDATE" attribute
(!self->is_controlling && tnet_stun_pkt_attr_exists(request, tnet_stun_attr_type_ice_use_candidate)) || // Sender is controlling and uses "ICE-USE-CANDIDATE" attribute
(self->is_controlling) // We always use agressive nomination and final check-list will have high-priority pairs on the top
;
TNET_ICE_PAIR_DEBUG_INFO("ICE pair-answer changing state to 'succeed' ? %s, comp-id=%d, found=%s, addr=%s",
@ -405,22 +440,25 @@ int tnet_ice_pair_send_response(tnet_ice_pair_t *self, const tnet_stun_request_t
self->candidate_answer->foundation,
self->candidate_answer->connection_addr
);
if(change_state){
if (change_state) {
self->state_answer = tnet_ice_pair_state_succeed;
}
}
bail:
TSK_OBJECT_SAFE_FREE(message);
return ret;
}
int tnet_ice_pair_auth_conncheck(const tnet_ice_pair_t *self, const tnet_stun_request_t* request, const void* request_buff, tsk_size_t request_buff_size, short* resp_code, char** resp_phrase)
int tnet_ice_pair_auth_conncheck(const tnet_ice_pair_t *self, const tnet_stun_pkt_req_t* request, const void* request_buff, tsk_size_t request_buff_size, short* resp_code, char** resp_phrase)
{
const uint8_t* _request_buff = (const uint8_t*)request_buff;
const tnet_stun_attribute_t* stun_att;
const tnet_stun_attribute_username_t *stun_att_usr_name;
const tnet_stun_attribute_fingerprint_t *stun_att_fingerprint;
const tnet_stun_attribute_integrity_t *stun_att_integrity;
const tnet_stun_attr_t* stun_att;
const tnet_stun_attr_vdata_t *stun_att_usr_name;
const tnet_stun_attr_vdata_t *stun_att_fingerprint;
const tnet_stun_attr_vdata_t *stun_att_integrity;
const tsk_list_item_t *item;
tsk_sha1digest_t hmac;
@ -433,7 +471,7 @@ int tnet_ice_pair_auth_conncheck(const tnet_ice_pair_t *self, const tnet_stun_re
return -1;
}
if(!TNET_IS_STUN2_MSG(_request_buff, request_buff_size)){
if(!TNET_STUN_BUFF_IS_STUN2(_request_buff, request_buff_size)){
TSK_DEBUG_ERROR("Not STUN buffer");
return -1;
}
@ -443,52 +481,52 @@ int tnet_ice_pair_auth_conncheck(const tnet_ice_pair_t *self, const tnet_stun_re
stun_att_fingerprint = tsk_null;
stun_att_integrity = tsk_null;
tsk_list_foreach(item, request->attributes){
if((!(stun_att = item->data))){
tsk_list_foreach(item, request->p_list_attrs) {
if ((!(stun_att = (const tnet_stun_attr_t*)item->data))) {
continue;
}
switch(stun_att->type){
case stun_username:
switch (stun_att->hdr.e_type) {
case tnet_stun_attr_type_username:
{
stun_att_usr_name = (const tnet_stun_attribute_username_t *)stun_att;
stun_att_usr_name = (const tnet_stun_attr_vdata_t *)stun_att;
break;
}
case stun_fingerprint:
case tnet_stun_attr_type_fingerprint:
{
stun_att_fingerprint = (const tnet_stun_attribute_fingerprint_t *)stun_att;
stun_att_fingerprint = (const tnet_stun_attr_vdata_t *)stun_att;
break;
}
case stun_message_integrity:
case tnet_stun_attr_type_message_integrity:
{
stun_att_integrity = (const tnet_stun_attribute_integrity_t *)stun_att;
stun_att_integrity = (const tnet_stun_attr_vdata_t *)stun_att;
break;
}
default: break;
}
if(!stun_att_integrity){
if((length = (4 + stun_att->length)) & 0x03){
if (!stun_att_integrity) {
if ((length = (kStunAttrHdrSizeInOctets + stun_att->hdr.u_length)) & 0x03) {
length += (4 - (length & 0x03));
}
msg_integrity_start += length;
}
}
if(!stun_att_usr_name){
if (!stun_att_usr_name) {
TSK_DEBUG_ERROR("USERNAME is missing");
*resp_code = 400;
tsk_strupdate(resp_phrase, "USERNAME is missing");
return -2;
}
if(!stun_att_integrity){
if(self->is_ice_jingle){ // Bug introduced in Chrome 20.0.1120.0
if (!stun_att_integrity || stun_att_integrity->u_data_size != TSK_SHA1_DIGEST_SIZE) {
if (self->is_ice_jingle) { // Bug introduced in Chrome 20.0.1120.0 (Not security issue as ICE-JINGLE is deprecated and will never be ON)
*resp_code = 200;
tsk_strupdate(resp_phrase, "MESSAGE-INTEGRITY is missing but accepted");
return 0;
}
else{
else {
TSK_DEBUG_ERROR("MESSAGE-INTEGRITY is missing");
*resp_code = 400;
tsk_strupdate(resp_phrase, "MESSAGE-INTEGRITY is missing");
@ -496,37 +534,37 @@ int tnet_ice_pair_auth_conncheck(const tnet_ice_pair_t *self, const tnet_stun_re
}
}
if((TNET_STUN_HEADER_SIZE + msg_integrity_start) >= request_buff_size){
if ((kStunPktHdrSizeInOctets + msg_integrity_start) >= request_buff_size) {
TSK_DEBUG_ERROR("Invalid length");
*resp_code = 400;
tsk_strupdate(resp_phrase, "Invalid length");
return -20;
}
if(request->length != msg_integrity_start){
tsk_size_t size = (TNET_STUN_HEADER_SIZE + msg_integrity_start);
if (request->u_length != msg_integrity_start) {
tsk_size_t size = (kStunPktHdrSizeInOctets + msg_integrity_start);
uint8_t* new_buffer = (uint8_t*)tsk_calloc(size, 1);
if(!new_buffer){
if (!new_buffer) {
TSK_DEBUG_ERROR("Failed to allocate buffer with size = %u", msg_integrity_start);
return -30;
}
memcpy(new_buffer, request_buff, size);
length = msg_integrity_start + (2/* Type */ + 2 /* Length */+ TSK_SHA1_DIGEST_SIZE /* INTEGRITY VALUE*/);
length = msg_integrity_start + (kStunAttrHdrSizeInOctets + TSK_SHA1_DIGEST_SIZE /* INTEGRITY VALUE*/);
new_buffer[2] = (length >> 8) & 0xFF;
new_buffer[3] = (length & 0xFF);
hmac_sha1digest_compute(new_buffer, size, pwd, tsk_strlen(pwd), hmac);
TSK_FREE(new_buffer);
}
else{
else {
// must never happen
hmac_sha1digest_compute(request_buff, request_buff_size, pwd, tsk_strlen(pwd), hmac);
}
for(i = 0; i < TSK_SHA1_DIGEST_SIZE; ++i){
if(hmac[i] != stun_att_integrity->sha1digest[i]){
TSK_DEBUG_ERROR("MESSAGE-INTEGRITY MISMATCH");
for (i = 0; i < TSK_SHA1_DIGEST_SIZE; ++i) {
if (hmac[i] != stun_att_integrity->p_data_ptr[i]) {
TSK_DEBUG_ERROR("MESSAGE-INTEGRITY mismatch");
*resp_code = 401;
tsk_strupdate(resp_phrase, "MESSAGE-INTEGRITY MISMATCH");
tsk_strupdate(resp_phrase, "MESSAGE-INTEGRITY mismatch");
return -40;
}
}
@ -537,12 +575,12 @@ int tnet_ice_pair_auth_conncheck(const tnet_ice_pair_t *self, const tnet_stun_re
return 0;
}
int tnet_ice_pair_recv_response(tnet_ice_pair_t *self, const tnet_stun_response_t* response)
int tnet_ice_pair_recv_response(tnet_ice_pair_t *self, const tnet_stun_pkt_resp_t* response)
{
if(self && response){
if(self->last_request && tnet_stun_message_transac_id_equals(self->last_request->transaction_id, response->transaction_id)){
if(self->last_request && tnet_stun_utils_transac_id_equals(self->last_request->transac_id, response->transac_id)){
// ignore errors (e.g. STALE-CREDENTIALS) which could happen in some special cases before success
if(TNET_STUN_RESPONSE_IS_SUCCESS(response)){
if(TNET_STUN_PKT_RESP_IS_SUCCESS(response)){
self->state_offer = tnet_ice_pair_state_succeed;
TNET_ICE_PAIR_DEBUG_INFO("ICE pair-offer changing state to 'succeed', comp-id=%d, found=%s, addr=%s",
self->candidate_offer->comp_id,
@ -555,26 +593,28 @@ int tnet_ice_pair_recv_response(tnet_ice_pair_t *self, const tnet_stun_response_
return 0;
}
const tnet_ice_pair_t* tnet_ice_pairs_find_by_response(tnet_ice_pairs_L_t* pairs, const tnet_stun_message_t* response)
const tnet_ice_pair_t* tnet_ice_pairs_find_by_response(tnet_ice_pairs_L_t* pairs, const tnet_stun_pkt_t* response)
{
if(pairs && response){
const tsk_list_item_t *item;
const tnet_ice_pair_t *pair;
tnet_port_t mapped_port;
char* mapped_addr_str = tsk_null;
tnet_ip_t mapped_ip;
tsk_list_foreach(item, pairs){
if(!(pair = item->data) || !pair->candidate_answer || !pair->candidate_offer){
continue;
}
if(pair->last_request && tnet_stun_message_transac_id_equals(pair->last_request->transaction_id, response->transaction_id)){
if(pair->last_request && tnet_stun_utils_transac_id_equals(pair->last_request->transac_id, response->transac_id)){
// check that mapped/xmapped address match destination
const tnet_stun_attribute_xmapped_addr_t *xmapped_addr;
const tnet_stun_attribute_mapped_addr_t* mapped_addr = tsk_null;
const tnet_stun_attr_address_t *xmapped_addr = tsk_null;
const tnet_stun_attr_address_t* mapped_addr = tsk_null;
const tnet_stun_attr_address_t* _addr;
if(!(xmapped_addr = (const tnet_stun_attribute_xmapped_addr_t *)tnet_stun_message_get_attribute(response, stun_xor_mapped_address))){
mapped_addr = (const tnet_stun_attribute_mapped_addr_t *)tnet_stun_message_get_attribute(response, stun_mapped_address);
}
if(!xmapped_addr && !mapped_addr){
tnet_stun_pkt_attr_find_first(response, tnet_stun_attr_type_xor_mapped_address, (const tnet_stun_attr_t **)&xmapped_addr);
tnet_stun_pkt_attr_find_first(response, tnet_stun_attr_type_mapped_address, (const tnet_stun_attr_t **)&mapped_addr);
_addr = xmapped_addr ? xmapped_addr : mapped_addr;
if (!_addr) {
return pair; // do nothing if the client doesn't return mapped address STUN attribute
}
/* rfc 5245 7.1.3.2.1. Discovering Peer Reflexive Candidates
@ -599,16 +639,16 @@ const tnet_ice_pair_t* tnet_ice_pairs_find_by_response(tnet_ice_pairs_L_t* pairs
candidates for the media stream. Its username fragment and password
are the same as all other local candidates for that media stream.
*/
tnet_ice_utils_stun_address_tostring(xmapped_addr ? xmapped_addr->xaddress : mapped_addr->address, xmapped_addr ? xmapped_addr->family : mapped_addr->family, &mapped_addr_str);
mapped_port = xmapped_addr ? xmapped_addr->xport : mapped_addr->port;
if((mapped_port != pair->candidate_offer->port || !tsk_striequals(mapped_addr_str, pair->candidate_offer->connection_addr))){
tnet_stun_utils_inet_ntop((_addr->e_family == tnet_stun_address_family_ipv6), &_addr->address, &mapped_ip);
mapped_port = _addr->u_port;
if ((mapped_port != pair->candidate_offer->port || !tsk_striequals(mapped_ip, pair->candidate_offer->connection_addr))) {
TSK_DEBUG_INFO("Mapped address different than local connection address...probably symetric NAT: %s#%s or %u#%u",
pair->candidate_offer->connection_addr, mapped_addr_str,
pair->candidate_offer->connection_addr, mapped_ip,
pair->candidate_offer->port, mapped_port);
// do we really need to add new local candidate?
// continue;
}
return pair;
}
}
@ -650,6 +690,7 @@ const tnet_ice_pair_t* tnet_ice_pairs_find_by_fd_and_addr(tnet_ice_pairs_L_t* pa
return tsk_null;
}
static tsk_bool_t _tnet_ice_pairs_none_succeed(const tnet_ice_pairs_L_t* pairs, uint32_t comp_id, const char* foundation, tsk_bool_t answer){
if(pairs && foundation){
const tsk_list_item_t *item;
@ -758,10 +799,10 @@ tsk_bool_t tnet_ice_pairs_have_nominated_symetric(const tnet_ice_pairs_L_t* pair
const tnet_ice_candidate_t *candidate_offer, *candidate_answer_src, *candidate_answer_dest;
tsk_bool_t is_nominated_rtp, is_nominated_rtcp = tsk_true;
int ret = tnet_ice_pairs_get_nominated_symetric(pairs, TNET_ICE_CANDIDATE_COMPID_RTP, &candidate_offer, &candidate_answer_src, &candidate_answer_dest);
int ret = tnet_ice_pairs_get_nominated_symetric_candidates(pairs, TNET_ICE_CANDIDATE_COMPID_RTP, &candidate_offer, &candidate_answer_src, &candidate_answer_dest);
is_nominated_rtp = (ret == 0 && candidate_offer && candidate_answer_src && candidate_answer_dest);
if(is_nominated_rtp && check_rtcp){
ret = tnet_ice_pairs_get_nominated_symetric(pairs, TNET_ICE_CANDIDATE_COMPID_RTCP, &candidate_offer, &candidate_answer_src, &candidate_answer_dest);
ret = tnet_ice_pairs_get_nominated_symetric_candidates(pairs, TNET_ICE_CANDIDATE_COMPID_RTCP, &candidate_offer, &candidate_answer_src, &candidate_answer_dest);
is_nominated_rtcp = (ret == 0 && candidate_offer && candidate_answer_src && candidate_answer_dest);
}
return (is_nominated_rtp && is_nominated_rtcp);
@ -769,17 +810,14 @@ tsk_bool_t tnet_ice_pairs_have_nominated_symetric(const tnet_ice_pairs_L_t* pair
// gets symetric nominated candidates with the highest priority
// will succeed only if both RTP and RTCP are ok
int tnet_ice_pairs_get_nominated_symetric(const tnet_ice_pairs_L_t* pairs, uint32_t comp_id,
int tnet_ice_pairs_get_nominated_symetric_candidates(const tnet_ice_pairs_L_t* pairs, uint32_t comp_id,
const tnet_ice_candidate_t** candidate_offer,
const tnet_ice_candidate_t** candidate_answer_src,
const tnet_ice_candidate_t** candidate_answer_dest)
{
const tnet_ice_pair_t *pair_offer = tsk_null;
const tnet_ice_pair_t *pair_answer = tsk_null;
tsk_size_t i_offer, i_answer;
static const tsk_bool_t __check_fullness = tsk_false; // pairs will be checked seperatly
if(!pairs || !candidate_offer || !candidate_answer_src || !candidate_answer_dest){
int ret;
const tnet_ice_pair_t *pair_offer = tsk_null, *pair_answer_src = tsk_null, *pair_answer_dest = tsk_null;
if (!pairs || !candidate_offer || !candidate_answer_src || !candidate_answer_dest) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
@ -787,25 +825,52 @@ int tnet_ice_pairs_get_nominated_symetric(const tnet_ice_pairs_L_t* pairs, uint3
*candidate_offer = tsk_null;
*candidate_answer_src = tsk_null;
*candidate_answer_dest = tsk_null;
if ((ret = tnet_ice_pairs_get_nominated_symetric_pairs(pairs, comp_id, &pair_offer, &pair_answer_src, &pair_answer_dest)) == 0) {
*candidate_offer = pair_offer ? pair_offer->candidate_offer : tsk_null;
*candidate_answer_src = pair_answer_src ? pair_answer_src->candidate_answer : tsk_null;
*candidate_answer_dest = pair_answer_dest ? pair_answer_dest->candidate_answer : tsk_null;
}
return ret;
}
int tnet_ice_pairs_get_nominated_symetric_pairs(const tnet_ice_pairs_L_t* pairs, uint32_t comp_id,
const struct tnet_ice_pair_s** _pair_offer,
const struct tnet_ice_pair_s** _pair_answer_src,
const struct tnet_ice_pair_s** _pair_answer_dest)
{
const tnet_ice_pair_t *pair_offer = tsk_null;
const tnet_ice_pair_t *pair_answer = tsk_null;
tsk_size_t i_offer, i_answer;
static const tsk_bool_t __check_fullness = tsk_false; // pairs will be checked seperatly
if (!pairs || !_pair_offer || !_pair_answer_src || !_pair_answer_dest) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
*_pair_offer = tsk_null;
*_pair_answer_src = tsk_null;
*_pair_answer_dest = tsk_null;
i_offer = 0;
while(1){
while (1) {
_tnet_ice_pairs_get_nominated_offer_at((pairs), i_offer, comp_id, __check_fullness, (pair_offer)); // pair with socket SO as sender
if(!pair_offer) return 0;
++i_offer;
if(pair_offer->candidate_offer->comp_id != comp_id) continue;
if (pair_offer->candidate_offer->comp_id != comp_id) continue;
// find another pair with socket SO as receiver
i_answer = 0;
while(1){
while (1) {
_tnet_ice_pairs_get_nominated_answer_at((pairs), i_answer, comp_id, __check_fullness, (pair_answer));
if(!pair_answer) break;
if (!pair_answer) break;
++i_answer;
if(pair_answer->candidate_offer->comp_id != comp_id) continue;
if(pair_answer->candidate_offer == pair_offer->candidate_offer){
*candidate_offer = pair_offer->candidate_offer;
*candidate_answer_src = pair_answer->candidate_answer;
*candidate_answer_dest = pair_offer->candidate_answer;
if (pair_answer->candidate_offer->comp_id != comp_id) continue;
if (pair_answer->candidate_offer == pair_offer->candidate_offer) {
*_pair_offer = pair_offer;
*_pair_answer_src = pair_answer;
*_pair_answer_dest = pair_offer;
return 0;
}
}

View File

@ -25,6 +25,7 @@
#include "tinynet_config.h"
#include "tnet_types.h"
#include "stun/tnet_stun_types.h"
#include "tsk_list.h"
@ -51,27 +52,34 @@ typedef struct tnet_ice_pair_s
tnet_ice_pair_state_t state_answer;
tsk_bool_t is_ice_jingle;
tsk_bool_t is_controlling;
tsk_bool_t is_nominated;
uint64_t tie_breaker;
struct tnet_ice_candidate_s* candidate_offer;
struct tnet_ice_candidate_s* candidate_answer;
struct tnet_stun_message_s* last_request;
struct tnet_stun_pkt_s* last_request;
struct sockaddr_storage remote_addr;
tnet_turn_peer_id_t turn_peer_id;
}
tnet_ice_pair_t;
tnet_ice_pair_t* tnet_ice_pair_create(const struct tnet_ice_candidate_s* candidate_offer, const struct tnet_ice_candidate_s* candidate_answer, tsk_bool_t is_controlling, uint64_t tie_breaker, tsk_bool_t is_ice_jingle);
tnet_ice_pair_t* tnet_ice_pair_prflx_create(tnet_ice_pairs_L_t* pairs, uint16_t local_fd, const struct sockaddr_storage *remote_addr);
int tnet_ice_pair_send_conncheck(tnet_ice_pair_t *self);
int tnet_ice_pair_send_response(tnet_ice_pair_t *self, const struct tnet_stun_message_s* request, const short code, const char* phrase, const struct sockaddr_storage *remote_addr);
int tnet_ice_pair_auth_conncheck(const tnet_ice_pair_t *self, const struct tnet_stun_message_s* request, const void* request_buff, tsk_size_t request_buff_size, short* resp_code, char** resp_phrase);
int tnet_ice_pair_recv_response(tnet_ice_pair_t *self, const struct tnet_stun_message_s* response);
const tnet_ice_pair_t* tnet_ice_pairs_find_by_response(tnet_ice_pairs_L_t* pairs, const struct tnet_stun_message_s* response);
int tnet_ice_pair_send_response(tnet_ice_pair_t *self, const struct tnet_stun_pkt_s* request, const short code, const char* phrase, const struct sockaddr_storage *remote_addr);
int tnet_ice_pair_auth_conncheck(const tnet_ice_pair_t *self, const struct tnet_stun_pkt_s* request, const void* request_buff, tsk_size_t request_buff_size, short* resp_code, char** resp_phrase);
int tnet_ice_pair_recv_response(tnet_ice_pair_t *self, const struct tnet_stun_pkt_s* response);
const tnet_ice_pair_t* tnet_ice_pairs_find_by_response(tnet_ice_pairs_L_t* pairs, const struct tnet_stun_pkt_s* response);
const tnet_ice_pair_t* tnet_ice_pairs_find_by_fd_and_addr(tnet_ice_pairs_L_t* pairs, uint16_t local_fd, const struct sockaddr_storage *remote_addr);
tsk_bool_t tnet_ice_pairs_have_nominated_offer(const tnet_ice_pairs_L_t* pairs, tsk_bool_t check_rtcp);
tsk_bool_t tnet_ice_pairs_have_nominated_answer(const tnet_ice_pairs_L_t* pairs, tsk_bool_t check_rtcp);
tsk_bool_t tnet_ice_pairs_have_nominated_symetric(const tnet_ice_pairs_L_t* pairs, tsk_bool_t check_rtcp);
int tnet_ice_pairs_get_nominated_symetric(const tnet_ice_pairs_L_t* pairs, uint32_t comp_id,
int tnet_ice_pairs_get_nominated_symetric_candidates(const tnet_ice_pairs_L_t* pairs, uint32_t comp_id,
const struct tnet_ice_candidate_s** candidate_offer,
const struct tnet_ice_candidate_s** candidate_answer_src,
const struct tnet_ice_candidate_s** candidate_answer_dest);
int tnet_ice_pairs_get_nominated_symetric_pairs(const tnet_ice_pairs_L_t* pairs, uint32_t comp_id,
const struct tnet_ice_pair_s** pair_offer,
const struct tnet_ice_pair_s** pair_answer_src,
const struct tnet_ice_pair_s** pair_answer_dest);
#endif /* TNET_ICE_PAIR_H */

View File

@ -125,24 +125,6 @@ int tnet_ice_utils_create_sockets(tnet_socket_type_t socket_type, const char* lo
return -1;
}
// FIXME: use tnet_stun_utils_inet_ntop()
int tnet_ice_utils_stun_address_tostring(const uint8_t in_ip[16], enum tnet_stun_addr_family_e family, char** out_ip)
{
if(family == stun_ipv6){
tsk_sprintf(out_ip, "%x:%x:%x:%x:%x:%x:%x:%x",
TSK_TO_UINT16(&in_ip[0]), TSK_TO_UINT16(&in_ip[2]), TSK_TO_UINT16(&in_ip[4]), TSK_TO_UINT16(&in_ip[6]),
TSK_TO_UINT16(&in_ip[8]), TSK_TO_UINT16(&in_ip[10]), TSK_TO_UINT16(&in_ip[12]), TSK_TO_UINT16(&in_ip[14]));
}
else if(family == stun_ipv4){
tsk_sprintf(out_ip, "%u.%u.%u.%u", in_ip[0], in_ip[1], in_ip[2], in_ip[3]);
return 0;
}
else{
TSK_DEBUG_ERROR("Unsupported address family: %u.", family);
}
return -1;
}
int tnet_ice_utils_set_ufrag(char** ufrag)
{
if(ufrag){

View File

@ -35,7 +35,6 @@ struct tnet_socket_s;
uint32_t tnet_ice_utils_get_priority(enum tnet_ice_cand_type_e type, uint16_t local_pref, tsk_bool_t is_rtp);
int tnet_ice_utils_compute_foundation(char* foundation, tsk_size_t size);
int tnet_ice_utils_create_sockets(enum tnet_socket_type_e socket_type, const char* local_ip, struct tnet_socket_s** socket_rtp, struct tnet_socket_s** socket_rtcp);
int tnet_ice_utils_stun_address_tostring(const uint8_t in_ip[16], enum tnet_stun_addr_family_e family, char** out_ip);
int tnet_ice_utils_set_ufrag(char** ufrag);
int tnet_ice_utils_set_pwd(char** pwd);

View File

@ -1,440 +1,440 @@
/*
* Copyright (C) 2010-2011 Mamadou Diop.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
*/
/**@file tnet_stun.c
* @brief Session Traversal Utilities for NAT (STUN) implementation as per RFC 5389 and RFC 3489(Obsolete).
*
* @author Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
*/
#include "tnet_stun.h"
#include "../tnet_nat.h"
#include "../tnet_utils.h"
#include "tsk_md5.h"
#include "tsk_string.h"
#include "tsk_memory.h"
#include "tsk_buffer.h"
#include "tsk_debug.h"
#include <string.h>
/**@defgroup tnet_stun_group STUN2 (RFC 5389) implementation.
*/
/**@ingroup tnet_stun_group
* Creates new @ref tnet_stun_binding_t object.
*/
tnet_stun_binding_t* tnet_stun_binding_create(tnet_fd_t fd, tnet_socket_type_t socket_type, const char* server_address, tnet_port_t server_port, const char* username, const char* password)
{
return tsk_object_new(tnet_stun_binding_def_t, fd, socket_type, server_address, server_port, username, password);
}
/**@ingroup tnet_stun_group
*
* Create generic STUN2 request with all mandatory headers and attributes.
*
* @param [in,out] binding The binding object from which to create the request.
*
* @retval STUN2 request if succeed and NULL otherwise.
**/
tnet_stun_message_t *tnet_stun_create_request(const tnet_stun_binding_t* binding)
{
tnet_stun_message_t *message = tnet_stun_message_create(binding->username, binding->password);
if(message) {
message->realm = tsk_strdup(binding->realm);
message->nonce = tsk_strdup(binding->nonce);
/* Set the request type (RFC 5389 defines only one type) */
message->type = stun_binding_request;
{ /* Create random transaction id */
tsk_istr_t random;
tsk_md5digest_t digest;
tsk_strrandom(&random);
TSK_MD5_DIGEST_CALC(random, sizeof(random), digest);
memcpy(message->transaction_id, digest, TNET_STUN_TRANSACID_SIZE);
}
/* Add software attribute */
if(binding->software) {
tnet_stun_attribute_t* attribute = (tnet_stun_attribute_t*)tnet_stun_attribute_software_create(binding->software, tsk_strlen(binding->software));
tnet_stun_message_add_attribute(message, &attribute);
}
}
return message;
}
int tnet_stun_send_reliably(const tnet_stun_message_t* message)
{
return -1;
}
/**@ingroup tnet_stun_group
*
* Internal function to send a STUN message using unrealiable protocol such as UDP.
*
*
* @param localFD The local file descriptor.
* @param RTO The Retransmission TimeOut.
* @param Rc The Number of retransmissions.
* @param [in,out] message The message to send.
* @param [in,out] server The destination STUN server.
*
* @return The response from the server or NULL if transport error.
**/
tnet_stun_response_t* tnet_stun_send_unreliably(tnet_fd_t localFD, uint16_t RTO, uint16_t Rc, const tnet_stun_message_t* message, struct sockaddr* server)
{
/* RFC 5389 - 7.2.1. Sending over UDP
STUN indications are not retransmitted; thus, indication transactions over UDP
are not reliable.
*/
//int retransmit = (message->type == stun_binding_request);
int ret = -1;
uint16_t i, rto = RTO;
struct timeval tv;
fd_set set;
tsk_buffer_t *buffer = tnet_stun_message_serialize(message);
tnet_stun_response_t *response = tsk_null;
if(!buffer) {
goto bail;
}
{
//#ifndef SIO_UDP_CONNRESET
//# ifndef IOC_VENDOR
//# define IOC_VENDOR 0x18000000
//# endif
//# ifndef _WSAIOW
//# define _WSAIOW(x,y) (IOC_IN|(x)|(y))
//# endif
//# define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
///*
//* Copyright (C) 2010-2011 Mamadou Diop.
//*
//* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
//*
//* This file is part of Open Source Doubango Framework.
//*
//* DOUBANGO is free software: you can redistribute it and/or modify
//* it under the terms of the GNU General Public License as published by
//* the Free Software Foundation, either version 3 of the License, or
//* (at your option) any later version.
//*
//* DOUBANGO is distributed in the hope that it will be useful,
//* but WITHOUT ANY WARRANTY; without even the implied warranty of
//* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//* GNU General Public License for more details.
//*
//* You should have received a copy of the GNU General Public License
//* along with DOUBANGO.
//*
//*/
//
///**@file tnet_stun.c
// * @brief Session Traversal Utilities for NAT (STUN) implementation as per RFC 5389 and RFC 3489(Obsolete).
// *
// * @author Mamadou Diop <diopmamadou(at)doubango[dot]org>
// *
//
// */
//#include "tnet_stun.h"
//
//#include "../tnet_nat.h"
//#include "../tnet_utils.h"
//
//#include "tsk_md5.h"
//#include "tsk_string.h"
//#include "tsk_memory.h"
//#include "tsk_buffer.h"
//#include "tsk_debug.h"
//
//#include <string.h>
//
///**@defgroup tnet_stun_group STUN2 (RFC 5389) implementation.
//*/
//
//
///**@ingroup tnet_stun_group
//* Creates new @ref tnet_stun_binding_t object.
//*/
//tnet_stun_binding_t* tnet_stun_binding_create(tnet_fd_t fd, tnet_socket_type_t socket_type, const char* server_address, tnet_port_t server_port, const char* username, const char* password)
//{
// return tsk_object_new(tnet_stun_binding_def_t, fd, socket_type, server_address, server_port, username, password);
//}
//
///**@ingroup tnet_stun_group
// *
// * Create generic STUN2 request with all mandatory headers and attributes.
// *
// * @param [in,out] binding The binding object from which to create the request.
// *
// * @retval STUN2 request if succeed and NULL otherwise.
//**/
//tnet_stun_pkt_t *tnet_stun_create_request(const tnet_stun_binding_t* binding)
//{
// tnet_stun_pkt_t *message = tnet_stun_message_create(binding->username, binding->password);
//
// if(message) {
// message->realm = tsk_strdup(binding->realm);
// message->nonce = tsk_strdup(binding->nonce);
//
// /* Set the request type (RFC 5389 defines only one type) */
// message->type = stun_binding_request;
//
// { /* Create random transaction id */
// tsk_istr_t random;
// tsk_md5digest_t digest;
//
// tsk_strrandom(&random);
// TSK_MD5_DIGEST_CALC(random, sizeof(random), digest);
//
// memcpy(message->transac_id, digest, TNET_STUN_TRANSACID_SIZE);
// }
//
// /* Add software attribute */
// if(binding->software) {
// tnet_stun_attr_t* attribute = (tnet_stun_attr_t*)tnet_stun_attribute_software_create(binding->software, tsk_strlen(binding->software));
// tnet_stun_message_add_attribute(message, &attribute);
// }
// }
//
// return message;
//}
//
//int tnet_stun_send_reliably(const tnet_stun_pkt_t* message)
//{
// return -1;
//}
//
//
///**@ingroup tnet_stun_group
// *
// * Internal function to send a STUN message using unrealiable protocol such as UDP.
// *
// *
// * @param localFD The local file descriptor.
// * @param RTO The Retransmission TimeOut.
// * @param Rc The Number of retransmissions.
// * @param [in,out] message The message to send.
// * @param [in,out] server The destination STUN server.
// *
// * @return The response from the server or NULL if transport error.
//**/
//tnet_stun_pkt_resp_t* tnet_stun_send_unreliably(tnet_fd_t localFD, uint16_t RTO, uint16_t Rc, const tnet_stun_pkt_t* message, struct sockaddr* server)
//{
// /* RFC 5389 - 7.2.1. Sending over UDP
// STUN indications are not retransmitted; thus, indication transactions over UDP
// are not reliable.
// */
// //int retransmit = (message->type == stun_binding_request);
//
// int ret = -1;
// uint16_t i, rto = RTO;
// struct timeval tv;
// fd_set set;
//
// tsk_buffer_t *buffer = tnet_stun_pkt_serialize(message);
// tnet_stun_pkt_resp_t *response = tsk_null;
//
// if(!buffer) {
// goto bail;
// }
//
// {
////#ifndef SIO_UDP_CONNRESET
////# ifndef IOC_VENDOR
////# define IOC_VENDOR 0x18000000
////# endif
////# ifndef _WSAIOW
////# define _WSAIOW(x,y) (IOC_IN|(x)|(y))
////# endif
////# define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
////#endif
//// DWORD dwBytesReturned = 0;
//// BOOL bNewBehavior = TRUE;
//// DWORD status;
////
//// // disable new behavior using
//// // IOCTL: SIO_UDP_CONNRESET
//// status = WSAIoctl(localFD, SIO_UDP_CONNRESET, &bNewBehavior, sizeof(bNewBehavior),
//// NULL, 0, &dwBytesReturned, NULL, NULL);
// }
//
// tv.tv_sec = 0;
// tv.tv_usec = 0;
//
// /* RFC 5389 - 7.2.1. Sending over UDP
// A client SHOULD retransmit a STUN request message starting with an
// interval of RTO ("Retransmission TimeOut"), doubling after each
// retransmission.
//
// e.g. 0 ms, 500 ms, 1500 ms, 3500 ms, 7500ms, 15500 ms, and 31500 ms
// */
// for(i=0; i<Rc; i++) {
// tv.tv_sec += rto/1000;
// tv.tv_usec += (rto% 1000) * 1000;
//
// FD_ZERO(&set);
// FD_SET(localFD, &set);
//
// ret = tnet_sockfd_sendto(localFD, server, buffer->data, buffer->size);
//
// if((ret = select(localFD+1, &set, NULL, NULL, &tv))<0) {
// goto bail;
// }
// else if(ret == 0) {
// /* timeout */
// TSK_DEBUG_INFO("STUN request timedout at %d", i);
// rto *= 2;
// continue;
// }
// else if(FD_ISSET(localFD, &set)) {
// /* there is data to read */
//
// tsk_size_t len = 0;
// void* data = 0;
//
// TSK_DEBUG_INFO("STUN request got response");
//
// /* Check how how many bytes are pending */
// if((ret = tnet_ioctlt(localFD, FIONREAD, &len))<0) {
// goto bail;
// }
//
// if(len==0) {
// TSK_DEBUG_INFO("tnet_ioctlt() returent zero bytes");
// continue;
// }
//
// /* Receive pending data */
// data = tsk_calloc(len, sizeof(uint8_t));
// if((ret = tnet_sockfd_recvfrom(localFD, data, len, 0, server))<0) {
// TSK_FREE(data);
//
// TSK_DEBUG_ERROR("Recving STUN dgrams failed with error code:%d", tnet_geterrno());
// goto bail;
// }
//
// /* Parse the incoming response. */
// response = tnet_stun_message_deserialize(data, (tsk_size_t)ret);
// TSK_FREE(data);
//
// if(response) {
// if(tnet_stun_transacid_cmp(message->transac_id, response->transac_id)) {
// /* Not same transaction id */
// TSK_OBJECT_SAFE_FREE(response);
// continue;
// }
// }
//
// goto bail;
// }
// else {
// continue;
// }
// }
//
//bail:
// TSK_OBJECT_SAFE_FREE(buffer);
//
// return response;
//}
//
///**@ingroup tnet_stun_group
// * Internal function to send a STUN2 binding request over the network.
// *
// * @param [in,out] context The NAT context holding the user preferences.
// * @param [in,out] binding The STUN binding object used to create the message to send.
// *
// * @return Zero if succeed and non-zero error code otherwise.
//**/
//int tnet_stun_send_bind(const tnet_nat_context_t* context, tnet_stun_binding_t *binding)
//{
// int ret = -1;
// tnet_stun_pkt_resp_t *response = 0;
// tnet_stun_pkt_req_t *request = 0;
//
//
// goto stun_phase0;
//
// /* RFC 5389 - 10.2.1.1. First Request
// If the client has not completed a successful request/response
// transaction with the server (as identified by hostname, if the DNS
// procedures of Section 9 are used, else IP address if not), it SHOULD
// omit the USERNAME, MESSAGE-INTEGRITY, REALM, and NONCE attributes.
// In other words, the very first request is sent as if there were no
// authentication or message integrity applied.
// */
//stun_phase0: {
// if(!(request = tnet_stun_create_request(binding))) {
// goto bail;
// }
//
// if(TNET_SOCKET_TYPE_IS_DGRAM(context->socket_type)) {
// response = tnet_stun_send_unreliably(binding->localFD, context->RTO, context->Rc, request, (struct sockaddr*)&binding->server);
// }
//
// if(response) {
// if(TNET_STUN_PKT_RESP_IS_ERROR(response)) {
// short code = tnet_stun_message_get_errorcode(response);
// const char* realm = tnet_stun_message_get_realm(response);
// const char* nonce = tnet_stun_message_get_nonce(response);
//
// if(code == 401 && realm && nonce) {
// if(!binding->nonce) {
// /* First time we get a nonce */
// tsk_strupdate(&binding->nonce, nonce);
// tsk_strupdate(&binding->realm, realm);
//
// /* Delete the message and response before retrying*/
// TSK_OBJECT_SAFE_FREE(response);
// TSK_OBJECT_SAFE_FREE(request);
//
// // Send again using new transaction identifier
// return tnet_stun_send_bind(context, binding);
// }
// else {
// ret = -3;
// }
// }
// else {
// ret = -2;
// }
// }
// else {
// const tnet_stun_attr_t *attribute;
// if((attribute= tnet_stun_message_get_attribute(response, stun_xor_mapped_address))) {
// ret = 0;
// binding->xmaddr = tsk_object_ref((void*)attribute);
// }
// else if((attribute= tnet_stun_message_get_attribute(response, stun_mapped_address))) {
// ret = 0;
// binding->maddr = tsk_object_ref((void*)attribute);
// }
// }
// }
// }
// /* END OF stun_phase0 */
//
//bail:
// TSK_OBJECT_SAFE_FREE(response);
// TSK_OBJECT_SAFE_FREE(request);
//
// return ret;
//}
//
///**@ingroup tnet_stun_group
// *
// * Public function to create a binding context.
// *
// * @param [in,out] nat_context The NAT context.
// * @param localFD The local file descriptor for which to create the binding context.
// *
// * @return A valid binding id if succeed and @ref kStunBindingInvalidId otherwise. If the returned id is valid then
// * the newly created binding will contain the server reflexive address associated to the local file descriptor.
//**/
//tnet_stun_binding_id_t tnet_stun_bind(const tnet_nat_context_t* nat_context, tnet_fd_t localFD)
//{
// tnet_stun_binding_id_t id = kStunBindingInvalidId;
//
// tnet_stun_binding_t *binding = 0;
//
// if(nat_context && localFD != TNET_INVALID_FD) {
// if(!(binding = tnet_stun_binding_create(localFD, nat_context->socket_type, nat_context->server_address, nat_context->server_port, nat_context->username, nat_context->password))) {
// goto bail;
// }
//
// if(tnet_stun_send_bind(nat_context, binding)) {
// TSK_OBJECT_SAFE_FREE(binding);
// goto bail;
// }
//
// id = binding->id;
// tsk_list_push_back_data(nat_context->stun_bindings, (void**)&binding);
// }
//
//bail:
// return id;
//}
//
///**@ingroup tnet_stun_group
// * Compares two transaction ids.
// *
// * @param id1 The first transaction identifier.
// * @param id2 The second transaction identifier.
// *
// * @return Zero if the two identifiers are equal and non-zero value otherwise.
//**/
//int tnet_stun_transacid_cmp(const tnet_stun_transac_id_t id1, const tnet_stun_transac_id_t id2)
//{
// tsk_size_t i;
// for(i=0; i<sizeof(tnet_stun_transac_id_t); i++) {
// if(id1[i] != id2[i]) {
// return (id1[i] - id2[i]);
// }
// }
// return 0;
//}
//
//
//
//
//
//
//
//
//
//
////=================================================================================================
//// STUN2 BINDING object definition
////
//static tsk_object_t* tnet_stun_binding_ctor(tsk_object_t * self, va_list * app)
//{
// tnet_stun_binding_t *binding = self;
// if(binding) {
// static tnet_stun_binding_id_t __binding_unique_id = 0;
//
// const char* server_address;
// tnet_port_t server_port;
//
// binding->id = ++__binding_unique_id;
//
// binding->localFD = va_arg(*app, tnet_fd_t);
// binding->socket_type = va_arg(*app, tnet_socket_type_t);
//
// server_address = tsk_strdup(va_arg(*app, const char*));
//#if defined(__GNUC__)
// server_port = (tnet_port_t)va_arg(*app, unsigned);
//#else
// server_port = va_arg(*app, tnet_port_t);
//#endif
// DWORD dwBytesReturned = 0;
// BOOL bNewBehavior = TRUE;
// DWORD status;
//
// // disable new behavior using
// // IOCTL: SIO_UDP_CONNRESET
// status = WSAIoctl(localFD, SIO_UDP_CONNRESET, &bNewBehavior, sizeof(bNewBehavior),
// NULL, 0, &dwBytesReturned, NULL, NULL);
}
tv.tv_sec = 0;
tv.tv_usec = 0;
/* RFC 5389 - 7.2.1. Sending over UDP
A client SHOULD retransmit a STUN request message starting with an
interval of RTO ("Retransmission TimeOut"), doubling after each
retransmission.
e.g. 0 ms, 500 ms, 1500 ms, 3500 ms, 7500ms, 15500 ms, and 31500 ms
*/
for(i=0; i<Rc; i++) {
tv.tv_sec += rto/1000;
tv.tv_usec += (rto% 1000) * 1000;
FD_ZERO(&set);
FD_SET(localFD, &set);
ret = tnet_sockfd_sendto(localFD, server, buffer->data, buffer->size);
if((ret = select(localFD+1, &set, NULL, NULL, &tv))<0) {
goto bail;
}
else if(ret == 0) {
/* timeout */
TSK_DEBUG_INFO("STUN request timedout at %d", i);
rto *= 2;
continue;
}
else if(FD_ISSET(localFD, &set)) {
/* there is data to read */
tsk_size_t len = 0;
void* data = 0;
TSK_DEBUG_INFO("STUN request got response");
/* Check how how many bytes are pending */
if((ret = tnet_ioctlt(localFD, FIONREAD, &len))<0) {
goto bail;
}
if(len==0) {
TSK_DEBUG_INFO("tnet_ioctlt() returent zero bytes");
continue;
}
/* Receive pending data */
data = tsk_calloc(len, sizeof(uint8_t));
if((ret = tnet_sockfd_recvfrom(localFD, data, len, 0, server))<0) {
TSK_FREE(data);
TSK_DEBUG_ERROR("Recving STUN dgrams failed with error code:%d", tnet_geterrno());
goto bail;
}
/* Parse the incoming response. */
response = tnet_stun_message_deserialize(data, (tsk_size_t)ret);
TSK_FREE(data);
if(response) {
if(tnet_stun_transacid_cmp(message->transaction_id, response->transaction_id)) {
/* Not same transaction id */
TSK_OBJECT_SAFE_FREE(response);
continue;
}
}
goto bail;
}
else {
continue;
}
}
bail:
TSK_OBJECT_SAFE_FREE(buffer);
return response;
}
/**@ingroup tnet_stun_group
* Internal function to send a STUN2 binding request over the network.
*
* @param [in,out] context The NAT context holding the user preferences.
* @param [in,out] binding The STUN binding object used to create the message to send.
*
* @return Zero if succeed and non-zero error code otherwise.
**/
int tnet_stun_send_bind(const tnet_nat_context_t* context, tnet_stun_binding_t *binding)
{
int ret = -1;
tnet_stun_response_t *response = 0;
tnet_stun_request_t *request = 0;
goto stun_phase0;
/* RFC 5389 - 10.2.1.1. First Request
If the client has not completed a successful request/response
transaction with the server (as identified by hostname, if the DNS
procedures of Section 9 are used, else IP address if not), it SHOULD
omit the USERNAME, MESSAGE-INTEGRITY, REALM, and NONCE attributes.
In other words, the very first request is sent as if there were no
authentication or message integrity applied.
*/
stun_phase0: {
if(!(request = tnet_stun_create_request(binding))) {
goto bail;
}
if(TNET_SOCKET_TYPE_IS_DGRAM(context->socket_type)) {
response = tnet_stun_send_unreliably(binding->localFD, context->RTO, context->Rc, request, (struct sockaddr*)&binding->server);
}
if(response) {
if(TNET_STUN_RESPONSE_IS_ERROR(response)) {
short code = tnet_stun_message_get_errorcode(response);
const char* realm = tnet_stun_message_get_realm(response);
const char* nonce = tnet_stun_message_get_nonce(response);
if(code == 401 && realm && nonce) {
if(!binding->nonce) {
/* First time we get a nonce */
tsk_strupdate(&binding->nonce, nonce);
tsk_strupdate(&binding->realm, realm);
/* Delete the message and response before retrying*/
TSK_OBJECT_SAFE_FREE(response);
TSK_OBJECT_SAFE_FREE(request);
// Send again using new transaction identifier
return tnet_stun_send_bind(context, binding);
}
else {
ret = -3;
}
}
else {
ret = -2;
}
}
else {
const tnet_stun_attribute_t *attribute;
if((attribute= tnet_stun_message_get_attribute(response, stun_xor_mapped_address))) {
ret = 0;
binding->xmaddr = tsk_object_ref((void*)attribute);
}
else if((attribute= tnet_stun_message_get_attribute(response, stun_mapped_address))) {
ret = 0;
binding->maddr = tsk_object_ref((void*)attribute);
}
}
}
}
/* END OF stun_phase0 */
bail:
TSK_OBJECT_SAFE_FREE(response);
TSK_OBJECT_SAFE_FREE(request);
return ret;
}
/**@ingroup tnet_stun_group
*
* Public function to create a binding context.
*
* @param [in,out] nat_context The NAT context.
* @param localFD The local file descriptor for which to create the binding context.
*
* @return A valid binding id if succeed and @ref TNET_STUN_INVALID_BINDING_ID otherwise. If the returned id is valid then
* the newly created binding will contain the server reflexive address associated to the local file descriptor.
**/
tnet_stun_binding_id_t tnet_stun_bind(const tnet_nat_context_t* nat_context, tnet_fd_t localFD)
{
tnet_stun_binding_id_t id = TNET_STUN_INVALID_BINDING_ID;
tnet_stun_binding_t *binding = 0;
if(nat_context && localFD != TNET_INVALID_FD) {
if(!(binding = tnet_stun_binding_create(localFD, nat_context->socket_type, nat_context->server_address, nat_context->server_port, nat_context->username, nat_context->password))) {
goto bail;
}
if(tnet_stun_send_bind(nat_context, binding)) {
TSK_OBJECT_SAFE_FREE(binding);
goto bail;
}
id = binding->id;
tsk_list_push_back_data(nat_context->stun_bindings, (void**)&binding);
}
bail:
return id;
}
/**@ingroup tnet_stun_group
* Compares two transaction ids.
*
* @param id1 The first transaction identifier.
* @param id2 The second transaction identifier.
*
* @return Zero if the two identifiers are equal and non-zero value otherwise.
**/
int tnet_stun_transacid_cmp(const tnet_stun_transacid_t id1, const tnet_stun_transacid_t id2)
{
tsk_size_t i;
for(i=0; i<sizeof(tnet_stun_transacid_t); i++) {
if(id1[i] != id2[i]) {
return (id1[i] - id2[i]);
}
}
return 0;
}
//=================================================================================================
// STUN2 BINDING object definition
// binding->username = tsk_strdup(va_arg(*app, const char*));
// binding->password = tsk_strdup(va_arg(*app, const char*));
//
// if(server_address) {
// tnet_sockaddr_init(server_address, server_port, binding->socket_type, &binding->server);
// }
//
// binding->software = tsk_strdup(TNET_SOFTWARE);
// }
// return self;
//}
//
//static tsk_object_t* tnet_stun_binding_dtor(tsk_object_t * self)
//{
// tnet_stun_binding_t *binding = self;
// if(binding) {
// TSK_FREE(binding->username);
// TSK_FREE(binding->password);
// TSK_FREE(binding->realm);
// TSK_FREE(binding->nonce);
//
// TSK_FREE(binding->software);
//
// TSK_OBJECT_SAFE_FREE(binding->maddr);
// TSK_OBJECT_SAFE_FREE(binding->xmaddr);
// }
//
// return self;
//}
//
//static const tsk_object_def_t tnet_stun_binding_def_s = {
// sizeof(tnet_stun_binding_t),
// tnet_stun_binding_ctor,
// tnet_stun_binding_dtor,
// tsk_null,
//};
//const tsk_object_def_t *tnet_stun_binding_def_t = &tnet_stun_binding_def_s;
//
//
static tsk_object_t* tnet_stun_binding_ctor(tsk_object_t * self, va_list * app)
{
tnet_stun_binding_t *binding = self;
if(binding) {
static tnet_stun_binding_id_t __binding_unique_id = 0;
const char* server_address;
tnet_port_t server_port;
binding->id = ++__binding_unique_id;
binding->localFD = va_arg(*app, tnet_fd_t);
binding->socket_type = va_arg(*app, tnet_socket_type_t);
server_address = tsk_strdup(va_arg(*app, const char*));
#if defined(__GNUC__)
server_port = (tnet_port_t)va_arg(*app, unsigned);
#else
server_port = va_arg(*app, tnet_port_t);
#endif
binding->username = tsk_strdup(va_arg(*app, const char*));
binding->password = tsk_strdup(va_arg(*app, const char*));
if(server_address) {
tnet_sockaddr_init(server_address, server_port, binding->socket_type, &binding->server);
}
binding->software = tsk_strdup(TNET_SOFTWARE);
}
return self;
}
static tsk_object_t* tnet_stun_binding_dtor(tsk_object_t * self)
{
tnet_stun_binding_t *binding = self;
if(binding) {
TSK_FREE(binding->username);
TSK_FREE(binding->password);
TSK_FREE(binding->realm);
TSK_FREE(binding->nonce);
TSK_FREE(binding->software);
TSK_OBJECT_SAFE_FREE(binding->maddr);
TSK_OBJECT_SAFE_FREE(binding->xmaddr);
}
return self;
}
static const tsk_object_def_t tnet_stun_binding_def_s = {
sizeof(tnet_stun_binding_t),
tnet_stun_binding_ctor,
tnet_stun_binding_dtor,
tsk_null,
};
const tsk_object_def_t *tnet_stun_binding_def_t = &tnet_stun_binding_def_s;

View File

@ -1,127 +1,127 @@
/*
* Copyright (C) 2010-2011 Mamadou Diop.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
*/
/**@file tnet_stun.h
* @brief Session Traversal Utilities for NAT (STUN) implementation as per RFC 5389 and RFC 3489(Obsolete).
*
* @author Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
*/
#ifndef TNET_STUN_H
#define TNET_STUN_H
#include "tinynet_config.h"
#include "stun/tnet_stun_message.h"
#include "tnet_types.h"
#include "tnet_socket.h"
#include "tsk_object.h"
TNET_BEGIN_DECLS
/**@ingroup tnet_stun_group
*/
typedef uint64_t tnet_stun_binding_id_t;
/**@ingroup tnet_stun_group
* @def TNET_STUN_INVALID_BINDING_ID
* STUN2 invalid binding id.
**/
/**@ingroup tnet_stun_group
* @def TNET_STUN_IS_VALID_BINDING_ID
* Checks the validity of the STUN @a id.
**/
#define TNET_STUN_INVALID_BINDING_ID 0
#define TNET_STUN_IS_VALID_BINDING_ID(id) (id != TNET_STUN_INVALID_BINDING_ID)
/**@ingroup tnet_stun_group
* Default port for both TCP and UDP protos as per RFC 5389 subclause 9.
**/
#define TNET_STUN_TCP_UDP_DEFAULT_PORT 3478
/**@ingroup tnet_stun_group
* Default port for TLS protocol as per RFC 5389 subclause 9.
**/
#define TNET_STUN_TLS_DEFAULT_PORT 5349
/**@ingroup tnet_stun_group
* STUN2 magic cookie value in network byte order as per RFC 5389 subclause 6.
**/
#define TNET_STUN_MAGIC_COOKIE 0x2112A442
/**@ingroup tnet_stun_group
* STUN2 header size as per RFC 5389 subclause 6.
**/
#define TNET_STUN_HEADER_SIZE 20
/**@ingroup tnet_stun_group
* STUN2 binding context.
**/
typedef struct tnet_stun_binding_s {
TSK_DECLARE_OBJECT;
//! A unique id to identify this binding.
tnet_stun_binding_id_t id;
//! The username to authenticate to the STUN server.
char* username;
//! The password to authenticate to the STUN server.
char* password;
//! The realm.
char* realm;
//! The nonce.
char* nonce;
//! The client name.
char* software;
//! Local file descriptor for which to get server reflexive address.
tnet_fd_t localFD;
//! The type of the bound socket.
tnet_socket_type_t socket_type;
//! The address of the STUN server.
struct sockaddr_storage server;
//! Server reflexive address of the local socket(STUN1 as per RFC 3489).
tnet_stun_attribute_mapped_addr_t *maddr;
//! XORed server reflexive address (STUN2 as per RFC 5389).
tnet_stun_attribute_xmapped_addr_t *xmaddr;
} tnet_stun_binding_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_binding_def_t;
/**@ingroup tnet_stun_group
* List of @ref tnet_stun_binding_t elements.
**/
typedef tsk_list_t tnet_stun_bindings_L_t;
//#if defined(__SYMBIAN32__) || ANDROID /* Forward declaration */
struct tnet_nat_context_s;
//#endif
int tnet_stun_send_reliably(const tnet_stun_message_t* message);
tnet_stun_response_t* tnet_stun_send_unreliably(tnet_fd_t localFD, uint16_t RTO, uint16_t Rc, const tnet_stun_message_t* message, struct sockaddr* server);
TINYNET_API tnet_stun_binding_id_t tnet_stun_bind(const struct tnet_nat_context_s* nat_context, tnet_fd_t localFD);
int tnet_stun_transacid_cmp(const tnet_stun_transacid_t id1, const tnet_stun_transacid_t id2);
TNET_END_DECLS
#endif /* TNET_STUN_H */
///*
//* Copyright (C) 2010-2011 Mamadou Diop.
//*
//* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
//*
//* This file is part of Open Source Doubango Framework.
//*
//* DOUBANGO is free software: you can redistribute it and/or modify
//* it under the terms of the GNU General Public License as published by
//* the Free Software Foundation, either version 3 of the License, or
//* (at your option) any later version.
//*
//* DOUBANGO is distributed in the hope that it will be useful,
//* but WITHOUT ANY WARRANTY; without even the implied warranty of
//* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//* GNU General Public License for more details.
//*
//* You should have received a copy of the GNU General Public License
//* along with DOUBANGO.
//*
//*/
//
///**@file tnet_stun.h
// * @brief Session Traversal Utilities for NAT (STUN) implementation as per RFC 5389 and RFC 3489(Obsolete).
// *
// * @author Mamadou Diop <diopmamadou(at)doubango[dot]org>
// *
//
// */
//#ifndef TNET_STUN_H
//#define TNET_STUN_H
//
//#include "tinynet_config.h"
//#include "stun/tnet_stun_message.h"
//#include "tnet_types.h"
//#include "tnet_socket.h"
//
//#include "tsk_object.h"
//
//TNET_BEGIN_DECLS
//
///**@ingroup tnet_stun_group
//*/
////typedef uint64_t tnet_stun_binding_id_t;
///**@ingroup tnet_stun_group
// * @def kStunBindingInvalidId
// * STUN2 invalid binding id.
//**/
///**@ingroup tnet_stun_group
// * @def TNET_STUN_IS_VALID_BINDING_ID
// * Checks the validity of the STUN @a id.
//**/
//#define kStunBindingInvalidId 0
//#define TNET_STUN_IS_VALID_BINDING_ID(id) (id != kStunBindingInvalidId)
//
///**@ingroup tnet_stun_group
// * Default port for both TCP and UDP protos as per RFC 5389 subclause 9.
//**/
//#define TNET_STUN_TCP_UDP_DEFAULT_PORT 3478
//
///**@ingroup tnet_stun_group
// * Default port for TLS protocol as per RFC 5389 subclause 9.
//**/
//#define TNET_STUN_TLS_DEFAULT_PORT 5349
//
//
///**@ingroup tnet_stun_group
// * STUN2 magic cookie value in network byte order as per RFC 5389 subclause 6.
//**/
//#define kStunMagicCookieLong 0x2112A442
//
///**@ingroup tnet_stun_group
// * STUN2 header size as per RFC 5389 subclause 6.
//**/
//#define kStunAttrHdrSizeInOctets 20
//
///**@ingroup tnet_stun_group
// * STUN2 binding context.
//**/
//typedef struct tnet_stun_binding_s {
// TSK_DECLARE_OBJECT;
//
// //! A unique id to identify this binding.
// tnet_stun_binding_id_t id;
//
// //! The username to authenticate to the STUN server.
// char* username;
// //! The password to authenticate to the STUN server.
// char* password;
// //! The realm.
// char* realm;
// //! The nonce.
// char* nonce;
// //! The client name.
// char* software;
// //! Local file descriptor for which to get server reflexive address.
// tnet_fd_t localFD;
// //! The type of the bound socket.
// tnet_socket_type_t socket_type;
// //! The address of the STUN server.
// struct sockaddr_storage server;
// //! Server reflexive address of the local socket(STUN1 as per RFC 3489).
// tnet_stun_attribute_mapped_addr_t *maddr;
// //! XORed server reflexive address (STUN2 as per RFC 5389).
// tnet_stun_attribute_xmapped_addr_t *xmaddr;
//} tnet_stun_binding_t;
//
//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_binding_def_t;
///**@ingroup tnet_stun_group
// * List of @ref tnet_stun_binding_t elements.
//**/
//typedef tsk_list_t tnet_stun_bindings_L_t;
//
////#if defined(__SYMBIAN32__) || ANDROID /* Forward declaration */
//struct struct tnet_nat_ctx_s;
////#endif
//
//int tnet_stun_send_reliably(const tnet_stun_pkt_t* message);
//tnet_stun_pkt_resp_t* tnet_stun_send_unreliably(tnet_fd_t localFD, uint16_t RTO, uint16_t Rc, const tnet_stun_pkt_t* message, struct sockaddr* server);
//TINYNET_API tnet_stun_binding_id_t tnet_stun_bind(const struct struct tnet_nat_ctx_s* nat_context, tnet_fd_t localFD);
//int tnet_stun_transacid_cmp(const tnet_stun_transac_id_t id1, const tnet_stun_transac_id_t id2);
//
//TNET_END_DECLS
//
//
//#endif /* TNET_STUN_H */
//

View File

@ -28,6 +28,10 @@
#define kWithoutPadding tsk_false
#define kWithPadding tsk_true
#if !defined(PRINT_DESTROYED_MSG)
# define PRINT_DESTROYED_MSG 0
#endif
#define ALIGN_ON_32BITS(size_in_octes) if (((size_in_octes) & 3)) (size_in_octes) += (4 - ((size_in_octes) & 3));
#define ALIGN_ON_32BITS_AND_SET_PADDING_ZEROS(p_buffer, size_in_octes) \
if (((size_in_octes) & 3)) { \
@ -507,7 +511,9 @@ static tsk_object_t* tnet_stun_attr_vdata_dtor(tsk_object_t * self)
{
tnet_stun_attr_vdata_t *p_vdata = (tnet_stun_attr_vdata_t *)self;
if (p_vdata) {
#if PRINT_DESTROYED_MSG
TSK_DEBUG_INFO("*** STUN Attribute(VDATA) destroyed ***");
#endif
TSK_FREE(p_vdata->p_data_ptr);
}
return self;
@ -564,7 +570,9 @@ static tsk_object_t* tnet_stun_attr_address_dtor(tsk_object_t * self)
{
tnet_stun_attr_address_t *p_addr = (tnet_stun_attr_address_t *)self;
if (p_addr) {
#if PRINT_DESTROYED_MSG
TSK_DEBUG_INFO("*** STUN Attribute(ADDRESS) destroyed ***");
#endif
}
return self;
}
@ -624,7 +632,9 @@ static tsk_object_t* tnet_stun_attr_error_code_dtor(tsk_object_t * self)
{
tnet_stun_attr_error_code_t *p_ec = (tnet_stun_attr_error_code_t *)self;
if (p_ec) {
#if PRINT_DESTROYED_MSG
TSK_DEBUG_INFO("*** STUN Attribute(ERROR-CODE) destroyed ***");
#endif
TSK_FREE(p_ec->p_reason_phrase);
}
return self;

File diff suppressed because it is too large Load Diff

View File

@ -1,356 +1,356 @@
/*
* Copyright (C) 2010-2011 Mamadou Diop.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
*/
/**@file tnet_stun_attribute.h
* @brief STUN2(RFC 5389) attribute parser.
*
* @author Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
*/
#ifndef TNET_STUN_ATTRIBUTE_H
#define TNET_STUN_ATTRIBUTE_H
#include "tinynet_config.h"
#include "tnet_types.h"
#include "tsk_object.h"
#include "tsk_buffer.h"
#include "tsk_sha1.h"
/**@ingroup tnet_stun_group
* @def TNET_STUN_ATTRIBUTE
* Converts (cast) any STUN attribute to @ref tnet_stun_attribute_t pointer.
* @param self The attribute to convert (cast).
* @retval A pointer to @ref tnet_stun_attribute_t object.
*/
TNET_BEGIN_DECLS
#define TNET_STUN_ATTRIBUTE(self) ((tnet_stun_attribute_t*)(self))
/**@ingroup tnet_stun_group
* STUN IP family as per RFC 5389 subclause 15.1.
**/
typedef enum tnet_stun_addr_family_e {
stun_ipv4 = 0x01,
stun_ipv6 = 0x02
}
tnet_stun_addr_family_t;
/**@ingroup tnet_stun_group
* STUN attribute types as per RFC 5389 subclause 18.2.
**/
typedef enum tnet_stun_attribute_type_e {
/* === RFC 5389 - Comprehension-required range (0x0000-0x7FFF) */
stun_reserved = 0x0000, /**< (Reserved) */
stun_mapped_address = 0x0001, /**< http://tools.ietf.org/html/rfc5389#page-32 */
stun_response_address = 0x0002, /**< (Reserved; was RESPONSE-ADDRESS) */
stun_change_address = 0x0003, /**< (Reserved; was CHANGE-ADDRESS) */
stun_source_address = 0x0004, /**< (Reserved; was SOURCE-ADDRESS) */
stun_changed_address = 0x0005, /**< (Reserved; was CHANGED-ADDRESS) */
stun_username = 0x0006, /**< http://tools.ietf.org/html/rfc5389#page-34 */
stun_password = 0x0007, /**< (Reserved; was PASSWORD) */
stun_message_integrity = 0x0008, /**< http://tools.ietf.org/html/rfc5389#page-34 */
stun_error_code = 0x0009, /**< http://tools.ietf.org/html/rfc5389#page-36 */
stun_unknown_attributes = 0x000A, /**< http://tools.ietf.org/html/rfc5389#page-38 */
stun_reflected_from = 0x000B, /**< (Reserved; was REFLECTED-FROM) */
stun_realm = 0x0014, /**< http://tools.ietf.org/html/rfc5389#page-38 */
stun_nonce = 0x0015, /**< http://tools.ietf.org/html/rfc5389#page-38 */
stun_xor_mapped_address = 0x0020, /**< http://tools.ietf.org/html/rfc5389#page-33 */
/* === RFC 5389 - Comprehension-optional range (0x8000-0xFFFF) */
stun_software = 0x8022, /**< http://tools.ietf.org/html/rfc5389#page-39 */
stun_alternate_server = 0x8023, /**< http://tools.ietf.org/html/rfc5389#page-39 */
stun_fingerprint = 0x8028, /**< http://tools.ietf.org/html/rfc5389#page-36 */
/* === draft-ietf-behave-turn-16 */
stun_channel_number = 0x000C, /**< draft-ietf-behave-turn-16 - CHANNEL-NUMBER */
stun_lifetime = 0x000D, /**< draft-ietf-behave-turn-16 - LIFETIME */
stun_reserved2 = 0x0010, /**< draft-ietf-behave-turn-16 - Reserved (was BANDWIDTH) */
stun_xor_peer_address = 0x0012, /**< draft-ietf-behave-turn-16 - XOR-PEER-ADDRESS */
stun_data = 0x0013, /**< draft-ietf-behave-turn-16 - DATA */
stun_xor_relayed_address = 0x0016, /**< draft-ietf-behave-turn-16 - XOR-RELAYED-ADDRESS */
stun_even_port = 0x0018, /**< draft-ietf-behave-turn-16 - EVEN-PORT */
stun_requested_transport = 0x0019, /**< draft-ietf-behave-turn-16 - REQUESTED-TRANSPORT */
stun_dont_fragment = 0x001A, /**< draft-ietf-behave-turn-16 - DONT-FRAGMENT */
stun_reserved3 = 0x0021, /**< draft-ietf-behave-turn-16 - Reserved (was TIMER-VAL) */
stun_reservation_token = 0x0022, /**< draft-ietf-behave-turn-16 - RESERVATION-TOKEN */
/* RFC 5245 */
stun_ice_priority = 0x0024, /**< 21.2. STUN Attributes */
stun_ice_use_candidate = 0x0025, /**< 21.2. STUN Attributes */
stun_ice_controlled = 0x8029, /**< 21.2. STUN Attributes */
stun_ice_controlling = 0x802A, /**< 21.2. STUN Attributes */
}
tnet_stun_attribute_type_t;
/**@ingroup tnet_stun_group
RFC 5389 - 15. STUN Attributes
*/
typedef struct tnet_stun_attribute_s {
TSK_DECLARE_OBJECT;
/*
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Value (variable) ....
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
tnet_stun_attribute_type_t type;
uint16_t length;
}
tnet_stun_attribute_t;
typedef tsk_list_t tnet_stun_attributes_L_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_def_t;
#define TNET_STUN_DECLARE_ATTRIBUTE tnet_stun_attribute_t attribute
/**@ingroup tnet_stun_group
*RFC 5389 - 15.1. MAPPED-ADDRESS
*/
typedef struct tnet_stun_attribute_mapped_addr_s {
TNET_STUN_DECLARE_ATTRIBUTE;
/*
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|0 0 0 0 0 0 0 0| Family | Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| Address (32 bits or 128 bits) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
tnet_stun_addr_family_t family;
uint16_t port;
uint8_t address[16];
}
tnet_stun_attribute_mapped_addr_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_mapped_addr_def_t;
/**@ingroup tnet_stun_group
* RFC 5389 - 15.2. XOR-MAPPED-ADDRESS
*/
typedef struct tnet_stun_attribute_xmapped_addr_s {
TNET_STUN_DECLARE_ATTRIBUTE;
/*
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|x x x x x x x x| Family | X-Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| X-Address (Variable)
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
tnet_stun_addr_family_t family;
uint16_t xport;
uint8_t xaddress[16];
}
tnet_stun_attribute_xmapped_addr_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_xmapped_addr_def_t;
/**@ingroup tnet_stun_group
* RFC 5389 - 15.3. USERNAME.
*/
typedef struct tnet_stun_attribute_username_s {
TNET_STUN_DECLARE_ATTRIBUTE;
char* value;
}
tnet_stun_attribute_username_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_username_def_t;
/**@ingroup tnet_stun_group
* RFC 5389 - 15.4. MESSAGE-INTEGRITY.
*/
typedef struct tnet_stun_attribute_integrity_s {
TNET_STUN_DECLARE_ATTRIBUTE;
tsk_sha1digest_t sha1digest;
}
tnet_stun_attribute_integrity_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_integrity_def_t;
/**@ingroup tnet_stun_group
* RFC 5389 - 15.5. FINGERPRINT.
*/
typedef struct tnet_stun_attribute_fingerprint_s {
TNET_STUN_DECLARE_ATTRIBUTE;
uint32_t value;
}
tnet_stun_attribute_fingerprint_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_fingerprint_def_t;
/**@ingroup tnet_stun_group
*RFC 5389 - 15.6. ERROR-CODE
*/
typedef struct tnet_stun_attribute_errorcode_s {
TNET_STUN_DECLARE_ATTRIBUTE;
/*
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Reserved, should be 0 |Class| Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Reason Phrase (variable) ..
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
uint8_t _class;
uint8_t number;
char* reason_phrase;
}
tnet_stun_attribute_errorcode_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_errorcode_def_t;
/**@ingroup tnet_stun_group
* RFC 5389 - 15.7. REALM. */
typedef struct tnet_stun_attribute_realm_s {
TNET_STUN_DECLARE_ATTRIBUTE;
char* value;
}
tnet_stun_attribute_realm_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_realm_def_t;
/**@ingroup tnet_stun_group
* RFC 5389 - 15.8. NONCE. */
typedef struct tnet_stun_attribute_nonce_s {
TNET_STUN_DECLARE_ATTRIBUTE;
char* value;
}
tnet_stun_attribute_nonce_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_nonce_def_t;
/**@ingroup tnet_stun_group
* RFC 5389 - 15.9. UNKNOWN-ATTRIBUTES. */
typedef struct tnet_stun_attribute_unknowns_s {
TNET_STUN_DECLARE_ATTRIBUTE;
tsk_buffer_t *value;
}
tnet_stun_attribute_unknowns_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_unknowns_def_t;
/**@ingroup tnet_stun_group
* RFC 5389 - 15.10. SOFTWARE. */
typedef struct tnet_stun_attribute_software_s {
TNET_STUN_DECLARE_ATTRIBUTE;
char *value;
}
tnet_stun_attribute_software_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_software_def_t;
/**@ingroup tnet_stun_group
* RFC 5389 - 15.11. ALTERNATE-SERVER. */
typedef struct tnet_stun_attribute_altserver_s {
TNET_STUN_DECLARE_ATTRIBUTE;
tnet_stun_addr_family_t family;
uint16_t port;
uint8_t server[128];
}
tnet_stun_attribute_altserver_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_altserver_def_t;
/**@ingroup tnet_stun_group
* RFC 5245 - 19.1. New Attributes */
typedef struct tnet_stun_attribute_ice_priority_s {
TNET_STUN_DECLARE_ATTRIBUTE;
uint32_t value;
}
tnet_stun_attribute_ice_priority_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_ice_priority_def_t;
/**@ingroup tnet_stun_group
* RFC 5245 - 19.1. New Attributes */
typedef struct tnet_stun_attribute_ice_use_candidate_s {
TNET_STUN_DECLARE_ATTRIBUTE;
}
tnet_stun_attribute_ice_use_candidate_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_ice_use_candidate_def_t;
/**@ingroup tnet_stun_group
* RFC 5245 - 19.1. New Attributes */
typedef struct tnet_stun_attribute_ice_controlled_s {
TNET_STUN_DECLARE_ATTRIBUTE;
uint64_t value;
}
tnet_stun_attribute_ice_controlled_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_ice_controlled_def_t;
/**@ingroup tnet_stun_group
* RFC 5245 - 19.1. New Attributes */
typedef struct tnet_stun_attribute_ice_controlling_s {
TNET_STUN_DECLARE_ATTRIBUTE;
uint64_t value;
}
tnet_stun_attribute_ice_controlling_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_ice_controlling_def_t;
tnet_stun_attribute_t* tnet_stun_attribute_deserialize(const void* data, tsk_size_t size);
int tnet_stun_attribute_serialize(const tnet_stun_attribute_t* attribute, tsk_buffer_t *output);
void tnet_stun_attribute_pad(const tnet_stun_attribute_t* attribute, tsk_buffer_t *output);
tnet_stun_attribute_t* tnet_stun_attribute_create();
TINYNET_API tnet_stun_attribute_mapped_addr_t* tnet_stun_attribute_mapped_address_create(const void* payload, tsk_size_t payload_size);
TINYNET_API tnet_stun_attribute_xmapped_addr_t* tnet_stun_attribute_xmapped_address_create(const void* payload, tsk_size_t payload_size);
TINYNET_API tnet_stun_attribute_username_t* tnet_stun_attribute_username_create(const void* payload, tsk_size_t payload_size);
TINYNET_API tnet_stun_attribute_integrity_t* tnet_stun_attribute_integrity_create(const void* payload, tsk_size_t payload_size);
TINYNET_API tnet_stun_attribute_fingerprint_t* tnet_stun_attribute_fingerprint_create(uint32_t fingerprint);
TINYNET_API tnet_stun_attribute_errorcode_t* tnet_stun_attribute_errorcode_create(const void* payload, tsk_size_t payload_size);
TINYNET_API tnet_stun_attribute_realm_t* tnet_stun_attribute_realm_create(const void* payload, tsk_size_t payload_size);
TINYNET_API tnet_stun_attribute_nonce_t* tnet_stun_attribute_nonce_create(const void* payload, tsk_size_t payload_size);
TINYNET_API tnet_stun_attribute_unknowns_t* tnet_stun_attribute_unknowns_create(const void* payload, tsk_size_t payload_size);
TINYNET_API tnet_stun_attribute_software_t* tnet_stun_attribute_software_create(const void* payload, tsk_size_t payload_size);
TINYNET_API tnet_stun_attribute_altserver_t* tnet_stun_attribute_altserver_create(const void* payload, tsk_size_t payload_size);
TINYNET_API tnet_stun_attribute_ice_priority_t* tnet_stun_attribute_ice_priority_create(uint32_t value);
TINYNET_API tnet_stun_attribute_ice_use_candidate_t* tnet_stun_attribute_ice_use_candidate_create();
TINYNET_API tnet_stun_attribute_ice_controlled_t* tnet_stun_attribute_ice_controlled_create(uint64_t value);
TINYNET_API tnet_stun_attribute_ice_controlling_t* tnet_stun_attribute_ice_controlling_create(uint64_t value);
TNET_END_DECLS
#endif /* TNET_STUN_ATTRIBUTE_H */
///*
//* Copyright (C) 2010-2011 Mamadou Diop.
//*
//* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
//*
//* This file is part of Open Source Doubango Framework.
//*
//* DOUBANGO is free software: you can redistribute it and/or modify
//* it under the terms of the GNU General Public License as published by
//* the Free Software Foundation, either version 3 of the License, or
//* (at your option) any later version.
//*
//* DOUBANGO is distributed in the hope that it will be useful,
//* but WITHOUT ANY WARRANTY; without even the implied warranty of
//* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//* GNU General Public License for more details.
//*
//* You should have received a copy of the GNU General Public License
//* along with DOUBANGO.
//*
//*/
//
///**@file tnet_stun_attribute.h
// * @brief STUN2(RFC 5389) attribute parser.
// *
// * @author Mamadou Diop <diopmamadou(at)doubango[dot]org>
// *
//
// */
//#ifndef TNET_STUN_ATTRIBUTE_H
//#define TNET_STUN_ATTRIBUTE_H
//
//#include "tinynet_config.h"
//
//#include "tnet_types.h"
//
//#include "tsk_object.h"
//#include "tsk_buffer.h"
//#include "tsk_sha1.h"
//
///**@ingroup tnet_stun_group
//* @def TNET_STUN_ATTRIBUTE
//* Converts (cast) any STUN attribute to @ref tnet_stun_attr_t pointer.
//* @param self The attribute to convert (cast).
//* @retval A pointer to @ref tnet_stun_attr_t object.
//*/
//TNET_BEGIN_DECLS
//
//#define TNET_STUN_ATTRIBUTE(self) ((tnet_stun_attr_t*)(self))
//
///**@ingroup tnet_stun_group
// * STUN IP family as per RFC 5389 subclause 15.1.
//**/
//typedef enum tnet_stun_addr_family_e {
// stun_ipv4 = 0x01,
// stun_ipv6 = 0x02
//}
//tnet_stun_addr_family_t;
//
///**@ingroup tnet_stun_group
// * STUN attribute types as per RFC 5389 subclause 18.2.
//**/
//typedef enum tnet_stun_attr_type_e {
// /* === RFC 5389 - Comprehension-required range (0x0000-0x7FFF) */
// stun_reserved = 0x0000, /**< (Reserved) */
// stun_mapped_address = 0x0001, /**< http://tools.ietf.org/html/rfc5389#page-32 */
// stun_response_address = 0x0002, /**< (Reserved; was RESPONSE-ADDRESS) */
// stun_change_address = 0x0003, /**< (Reserved; was CHANGE-ADDRESS) */
// stun_source_address = 0x0004, /**< (Reserved; was SOURCE-ADDRESS) */
// stun_changed_address = 0x0005, /**< (Reserved; was CHANGED-ADDRESS) */
// stun_username = 0x0006, /**< http://tools.ietf.org/html/rfc5389#page-34 */
// stun_password = 0x0007, /**< (Reserved; was PASSWORD) */
// stun_message_integrity = 0x0008, /**< http://tools.ietf.org/html/rfc5389#page-34 */
// stun_error_code = 0x0009, /**< http://tools.ietf.org/html/rfc5389#page-36 */
// stun_unknown_attributes = 0x000A, /**< http://tools.ietf.org/html/rfc5389#page-38 */
// stun_reflected_from = 0x000B, /**< (Reserved; was REFLECTED-FROM) */
// stun_realm = 0x0014, /**< http://tools.ietf.org/html/rfc5389#page-38 */
// stun_nonce = 0x0015, /**< http://tools.ietf.org/html/rfc5389#page-38 */
// stun_xor_mapped_address = 0x0020, /**< http://tools.ietf.org/html/rfc5389#page-33 */
//
// /* === RFC 5389 - Comprehension-optional range (0x8000-0xFFFF) */
// stun_software = 0x8022, /**< http://tools.ietf.org/html/rfc5389#page-39 */
// stun_alternate_server = 0x8023, /**< http://tools.ietf.org/html/rfc5389#page-39 */
// stun_fingerprint = 0x8028, /**< http://tools.ietf.org/html/rfc5389#page-36 */
//
// /* === draft-ietf-behave-turn-16 */
// stun_channel_number = 0x000C, /**< draft-ietf-behave-turn-16 - CHANNEL-NUMBER */
// stun_lifetime = 0x000D, /**< draft-ietf-behave-turn-16 - LIFETIME */
// stun_reserved2 = 0x0010, /**< draft-ietf-behave-turn-16 - Reserved (was BANDWIDTH) */
// stun_xor_peer_address = 0x0012, /**< draft-ietf-behave-turn-16 - XOR-PEER-ADDRESS */
// stun_data = 0x0013, /**< draft-ietf-behave-turn-16 - DATA */
// stun_xor_relayed_address = 0x0016, /**< draft-ietf-behave-turn-16 - XOR-RELAYED-ADDRESS */
// stun_even_port = 0x0018, /**< draft-ietf-behave-turn-16 - EVEN-PORT */
// stun_requested_transport = 0x0019, /**< draft-ietf-behave-turn-16 - REQUESTED-TRANSPORT */
// stun_dont_fragment = 0x001A, /**< draft-ietf-behave-turn-16 - DONT-FRAGMENT */
// stun_reserved3 = 0x0021, /**< draft-ietf-behave-turn-16 - Reserved (was TIMER-VAL) */
// stun_reservation_token = 0x0022, /**< draft-ietf-behave-turn-16 - RESERVATION-TOKEN */
//
// /* RFC 5245 */
// stun_ice_priority = 0x0024, /**< 21.2. STUN Attributes */
// stun_ice_use_candidate = 0x0025, /**< 21.2. STUN Attributes */
// stun_ice_controlled = 0x8029, /**< 21.2. STUN Attributes */
// stun_ice_controlling = 0x802A, /**< 21.2. STUN Attributes */
//}
//tnet_stun_attr_type_t;
//
//
///**@ingroup tnet_stun_group
// RFC 5389 - 15. STUN Attributes
//*/
//typedef struct tnet_stun_attribute_s {
// TSK_DECLARE_OBJECT;
// /*
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Type | Length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Value (variable) ....
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// */
// tnet_stun_attr_type_t type;
// uint16_t length;
//}
//tnet_stun_attr_t;
//
//typedef tsk_list_t tnet_stun_attributes_L_t;
//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_def_t;
//
//#define TNET_STUN_DECLARE_ATTRIBUTE tnet_stun_attr_t attribute
//
//
///**@ingroup tnet_stun_group
// *RFC 5389 - 15.1. MAPPED-ADDRESS
// */
//typedef struct tnet_stun_attribute_mapped_addr_s {
// TNET_STUN_DECLARE_ATTRIBUTE;
//
// /*
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |0 0 0 0 0 0 0 0| Family | Port |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | |
// | Address (32 bits or 128 bits) |
// | |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// */
// tnet_stun_addr_family_t family;
// uint16_t port;
// uint8_t address[16];
//}
//tnet_stun_attribute_mapped_addr_t;
//
//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_mapped_addr_def_t;
//
//
///**@ingroup tnet_stun_group
//* RFC 5389 - 15.2. XOR-MAPPED-ADDRESS
//*/
//typedef struct tnet_stun_attribute_xmapped_addr_s {
// TNET_STUN_DECLARE_ATTRIBUTE;
//
// /*
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |x x x x x x x x| Family | X-Port |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | X-Address (Variable)
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// */
// tnet_stun_addr_family_t family;
// uint16_t xport;
// uint8_t xaddress[16];
//}
//tnet_stun_attribute_xmapped_addr_t;
//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_xmapped_addr_def_t;
//
//
///**@ingroup tnet_stun_group
//* RFC 5389 - 15.3. USERNAME.
//*/
//typedef struct tnet_stun_attribute_username_s {
// TNET_STUN_DECLARE_ATTRIBUTE;
//
// char* value;
//}
//tnet_stun_attribute_username_t;
//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_username_def_t;
//
//
///**@ingroup tnet_stun_group
//* RFC 5389 - 15.4. MESSAGE-INTEGRITY.
//*/
//typedef struct tnet_stun_attribute_integrity_s {
// TNET_STUN_DECLARE_ATTRIBUTE;
//
// tsk_sha1digest_t sha1digest;
//}
//tnet_stun_attribute_integrity_t;
//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_integrity_def_t;
//
//
///**@ingroup tnet_stun_group
//* RFC 5389 - 15.5. FINGERPRINT.
//*/
//typedef struct tnet_stun_attribute_fingerprint_s {
// TNET_STUN_DECLARE_ATTRIBUTE;
//
// uint32_t value;
//}
//tnet_stun_attribute_fingerprint_t;
//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_fingerprint_def_t;
//
///**@ingroup tnet_stun_group
// *RFC 5389 - 15.6. ERROR-CODE
//*/
//typedef struct tnet_stun_attribute_errorcode_s {
// TNET_STUN_DECLARE_ATTRIBUTE;
// /*
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Reserved, should be 0 |Class| Number |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Reason Phrase (variable) ..
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// */
// uint8_t _class;
// uint8_t number;
// char* reason_phrase;
//}
//tnet_stun_attribute_errorcode_t;
//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_errorcode_def_t;
//
//
//
///**@ingroup tnet_stun_group
//* RFC 5389 - 15.7. REALM. */
//typedef struct tnet_stun_attribute_realm_s {
// TNET_STUN_DECLARE_ATTRIBUTE;
//
// char* value;
//}
//tnet_stun_attribute_realm_t;
//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_realm_def_t;
//
//
///**@ingroup tnet_stun_group
//* RFC 5389 - 15.8. NONCE. */
//typedef struct tnet_stun_attribute_nonce_s {
// TNET_STUN_DECLARE_ATTRIBUTE;
//
// char* value;
//}
//tnet_stun_attribute_nonce_t;
//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_nonce_def_t;
//
///**@ingroup tnet_stun_group
//* RFC 5389 - 15.9. UNKNOWN-ATTRIBUTES. */
//typedef struct tnet_stun_attribute_unknowns_s {
// TNET_STUN_DECLARE_ATTRIBUTE;
//
// tsk_buffer_t *value;
//}
//tnet_stun_attribute_unknowns_t;
//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_unknowns_def_t;
//
///**@ingroup tnet_stun_group
//* RFC 5389 - 15.10. SOFTWARE. */
//typedef struct tnet_stun_attribute_software_s {
// TNET_STUN_DECLARE_ATTRIBUTE;
//
// char *value;
//}
//tnet_stun_attribute_software_t;
//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_software_def_t;
//
///**@ingroup tnet_stun_group
//* RFC 5389 - 15.11. ALTERNATE-SERVER. */
//typedef struct tnet_stun_attribute_altserver_s {
// TNET_STUN_DECLARE_ATTRIBUTE;
//
// tnet_stun_addr_family_t family;
// uint16_t port;
// uint8_t server[128];
//}
//tnet_stun_attribute_altserver_t;
//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_altserver_def_t;
//
///**@ingroup tnet_stun_group
//* RFC 5245 - 19.1. New Attributes */
//typedef struct tnet_stun_attribute_ice_priority_s {
// TNET_STUN_DECLARE_ATTRIBUTE;
// uint32_t value;
//}
//tnet_stun_attribute_ice_priority_t;
//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_ice_priority_def_t;
//
///**@ingroup tnet_stun_group
//* RFC 5245 - 19.1. New Attributes */
//typedef struct tnet_stun_attribute_ice_use_candidate_s {
// TNET_STUN_DECLARE_ATTRIBUTE;
//}
//tnet_stun_attribute_ice_use_candidate_t;
//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_ice_use_candidate_def_t;
//
///**@ingroup tnet_stun_group
//* RFC 5245 - 19.1. New Attributes */
//typedef struct tnet_stun_attribute_ice_controlled_s {
// TNET_STUN_DECLARE_ATTRIBUTE;
// uint64_t value;
//}
//tnet_stun_attribute_ice_controlled_t;
//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_ice_controlled_def_t;
//
///**@ingroup tnet_stun_group
//* RFC 5245 - 19.1. New Attributes */
//typedef struct tnet_stun_attribute_ice_controlling_s {
// TNET_STUN_DECLARE_ATTRIBUTE;
// uint64_t value;
//}
//tnet_stun_attribute_ice_controlling_t;
//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_ice_controlling_def_t;
//
//tnet_stun_attr_t* tnet_stun_attribute_deserialize(const void* data, tsk_size_t size);
//int tnet_stun_attribute_serialize(const tnet_stun_attr_t* attribute, tsk_buffer_t *output);
//void tnet_stun_attribute_pad(const tnet_stun_attr_t* attribute, tsk_buffer_t *output);
//
//
//
//
//tnet_stun_attr_t* tnet_stun_attribute_create();
//TINYNET_API tnet_stun_attribute_mapped_addr_t* tnet_stun_attribute_mapped_address_create(const void* payload, tsk_size_t payload_size);
//TINYNET_API tnet_stun_attribute_xmapped_addr_t* tnet_stun_attribute_xmapped_address_create(const void* payload, tsk_size_t payload_size);
//TINYNET_API tnet_stun_attribute_username_t* tnet_stun_attribute_username_create(const void* payload, tsk_size_t payload_size);
//TINYNET_API tnet_stun_attribute_integrity_t* tnet_stun_attribute_integrity_create(const void* payload, tsk_size_t payload_size);
//TINYNET_API tnet_stun_attribute_fingerprint_t* tnet_stun_attribute_fingerprint_create(uint32_t fingerprint);
//TINYNET_API tnet_stun_attribute_errorcode_t* tnet_stun_attribute_errorcode_create(const void* payload, tsk_size_t payload_size);
//TINYNET_API tnet_stun_attribute_realm_t* tnet_stun_attribute_realm_create(const void* payload, tsk_size_t payload_size);
//TINYNET_API tnet_stun_attribute_nonce_t* tnet_stun_attribute_nonce_create(const void* payload, tsk_size_t payload_size);
//TINYNET_API tnet_stun_attribute_unknowns_t* tnet_stun_attribute_unknowns_create(const void* payload, tsk_size_t payload_size);
//TINYNET_API tnet_stun_attribute_software_t* tnet_stun_attribute_software_create(const void* payload, tsk_size_t payload_size);
//TINYNET_API tnet_stun_attribute_altserver_t* tnet_stun_attribute_altserver_create(const void* payload, tsk_size_t payload_size);
//TINYNET_API tnet_stun_attribute_ice_priority_t* tnet_stun_attribute_ice_priority_create(uint32_t value);
//TINYNET_API tnet_stun_attribute_ice_use_candidate_t* tnet_stun_attribute_ice_use_candidate_create();
//TINYNET_API tnet_stun_attribute_ice_controlled_t* tnet_stun_attribute_ice_controlled_create(uint64_t value);
//TINYNET_API tnet_stun_attribute_ice_controlling_t* tnet_stun_attribute_ice_controlling_create(uint64_t value);
//
//
//TNET_END_DECLS
//
//#endif /* TNET_STUN_ATTRIBUTE_H */
//

View File

@ -0,0 +1,127 @@
/* Copyright (C) 2014 Mamadou DIOP.
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
*/
#include "stun/tnet_stun_binding.h"
#include "stun/tnet_stun_pkt.h"
#include "stun/tnet_stun_attr.h"
#include "tnet_utils.h"
#include "tsk_string.h"
#include "tsk_memory.h"
#include "tsk_debug.h"
int tnet_stun_binding_create(tnet_fd_t fd, enum tnet_socket_type_e socket_type, const char* pc_server_address, tnet_port_t server_port, const char* pc_username, const char* pc_password, tnet_stun_binding_t** pp_bind)
{
extern const tsk_object_def_t *tnet_stun_binding_def_t;
static long __unique_id = 0;
if (!pp_bind) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if (!(*pp_bind = tsk_object_new(tnet_stun_binding_def_t))) {
TSK_DEBUG_ERROR("Failed to create STUN binding object");
return -2;
}
tsk_atomic_inc(&__unique_id);
(*pp_bind)->id = __unique_id;
(*pp_bind)->localFD = fd;
(*pp_bind)->socket_type = socket_type;
(*pp_bind)->p_username = tsk_strdup(pc_username);
(*pp_bind)->p_password = tsk_strdup(pc_password);
if (pc_server_address && server_port) {
int ret;
if ((ret = tnet_sockaddr_init(pc_server_address, server_port, socket_type, &(*pp_bind)->addr_server))) {
TSK_OBJECT_SAFE_FREE((*pp_bind));
TSK_DEBUG_ERROR("Failed to init STUN server address");
return ret;
}
}
return 0;
}
int tnet_stun_binding_create_req(const struct tnet_stun_binding_s* pc_self, struct tnet_stun_pkt_s **pp_req)
{
int ret;
if (!pc_self || !pp_req) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_binding_request, pp_req))) {
TSK_DEBUG_ERROR("Failed to create STUN Bind request");
goto bail;
}
// add attributes
(*pp_req)->opt.dontfrag = 0;
ret = tnet_stun_pkt_attrs_add(*pp_req,
TNET_STUN_PKT_ATTR_ADD_SOFTWARE_ZT(kStunSoftware),
TNET_STUN_PKT_ATTR_ADD_NULL());
if (ret) {
goto bail;
}
if (pc_self->p_username && pc_self->p_realm && pc_self->p_nonce) {
if ((ret = tnet_stun_pkt_auth_prepare(*pp_req, pc_self->p_username, pc_self->p_password, pc_self->p_realm, pc_self->p_nonce))) {
goto bail;
}
}
bail:
if (ret) {
TSK_OBJECT_SAFE_FREE(*pp_req);
}
return ret;
}
static tsk_object_t* tnet_stun_binding_ctor(tsk_object_t * self, va_list * app)
{
tnet_stun_binding_t *p_bind = (tnet_stun_binding_t *)self;
if (p_bind) {
}
return self;
}
static tsk_object_t* tnet_stun_binding_dtor(tsk_object_t * self)
{
tnet_stun_binding_t *p_bind = (tnet_stun_binding_t *)self;
if (p_bind) {
TSK_DEBUG_INFO("*** STUN BINDING destroyed ***");
TSK_FREE(p_bind->p_username);
TSK_FREE(p_bind->p_password);
TSK_FREE(p_bind->p_realm);
TSK_FREE(p_bind->p_nonce);
TSK_OBJECT_SAFE_FREE(p_bind->p_maddr);
TSK_OBJECT_SAFE_FREE(p_bind->p_xmaddr);
}
return self;
}
static int tnet_stun_binding_cmp(const tsk_object_t *_bind1, const tsk_object_t *_bind2)
{
const tnet_stun_binding_t *pc_bind1 = (const tnet_stun_binding_t *)_bind1;
const tnet_stun_binding_t *pc_bind2 = (const tnet_stun_binding_t *)_bind2;
return (pc_bind1 && pc_bind2) ? (int)(pc_bind1->id - pc_bind2->id) : (int)(pc_bind1 - pc_bind2);
}
static const tsk_object_def_t tnet_stun_binding_def_s = {
sizeof(tnet_stun_binding_t),
tnet_stun_binding_ctor,
tnet_stun_binding_dtor,
tnet_stun_binding_cmp,
};
const tsk_object_def_t *tnet_stun_binding_def_t = &tnet_stun_binding_def_s;

View File

@ -0,0 +1,67 @@
/* Copyright (C) 2014 Mamadou DIOP.
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
*/
#ifndef TNET_STUN_BINDING_H
#define TNET_STUN_BINDING_H
#include "tinynet_config.h"
#include "tnet_types.h"
#include "stun/tnet_stun_types.h"
#include "stun/tnet_stun_attr.h"
#include "tsk_object.h"
#include "tsk_list.h"
TNET_BEGIN_DECLS
enum tnet_socket_type_e;
typedef struct tnet_stun_binding_s {
TSK_DECLARE_OBJECT;
//! A unique id to identify this binding.
tnet_stun_binding_id_t id;
//! The username to authenticate to the STUN server.
char* p_username;
//! The password to authenticate to the STUN server.
char* p_password;
//! The realm.
char* p_realm;
//! The nonce.
char* p_nonce;
//! Local file descriptor for which to get server reflexive address.
tnet_fd_t localFD;
//! The type of the bound socket.
enum tnet_socket_type_e socket_type;
//! The address of the STUN server.
struct sockaddr_storage addr_server;
//! Server reflexive address of the local socket(STUN1 as per RFC 3489).
struct tnet_stun_attr_address_s *p_maddr;
//! XORed server reflexive address (STUN2 as per RFC 5389).
struct tnet_stun_attr_address_s *p_xmaddr;
}
tnet_stun_binding_t;
typedef tsk_list_t tnet_stun_bindings_L_t;
int tnet_stun_binding_create(tnet_fd_t fd, enum tnet_socket_type_e socket_type, const char* pc_server_address, tnet_port_t server_port, const char* pc_username, const char* pc_password, tnet_stun_binding_t** pp_bind);
int tnet_stun_binding_create_req(const struct tnet_stun_binding_s* pc_self, struct tnet_stun_pkt_s **pp_req);
TNET_END_DECLS
#endif /* TNET_STUN_BINDING_H */

View File

@ -1,494 +1,495 @@
/*
* Copyright (C) 2010-2011 Mamadou Diop.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
*/
/**@file tnet_stun_message.c
* @brief STUN2 (RFC 5389) message parser.
*
* @author Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
*/
#include "tnet_stun_message.h"
#include "tnet_stun.h"
#include "../tnet_types.h"
#include "../tnet_endianness.h"
#include "../turn/tnet_turn_attribute.h"
#include "tsk_memory.h"
#include "tsk_hmac.h"
#include "tsk_string.h"
#include "tsk_ppfcs32.h"
#include <string.h>
static int __pred_find_attribute_by_type(const tsk_list_item_t *item, const void *att_type)
{
if(item && item->data) {
tnet_stun_attribute_t *att = item->data;
tnet_stun_attribute_type_t type = *((tnet_stun_attribute_type_t*)att_type);
return (att->type - type);
}
return -1;
}
/**@ingroup tnet_stun_group
* Creates new STUN message.
* @retval @ref tnet_stun_message_t object.
* @sa tnet_stun_message_create_null.
*/
tnet_stun_message_t* tnet_stun_message_create(const char* username, const char* password)
{
return tsk_object_new(tnet_stun_message_def_t, username, password);
}
/**@ingroup tnet_stun_group
* Creates new STUN message.
* @retval @ref tnet_stun_message_t object.
* @sa tnet_stun_message_create.
*/
tnet_stun_message_t* tnet_stun_message_create_null()
{
return tnet_stun_message_create(tsk_null, tsk_null);
}
#define SERIALIZE_N_ADD_ATTRIBUTE(att_name, payload, payload_size) \
attribute = (tnet_stun_attribute_t *)tnet_stun_attribute_##att_name##_create(payload, payload_size); \
tnet_stun_attribute_serialize(attribute, output); \
tnet_stun_attribute_pad(attribute, output); \
TSK_OBJECT_SAFE_FREE(attribute);
/**@ingroup tnet_stun_group
* Serializes a STUN message as binary data.
* @param [in,out] self The STUN message to serialize.
* @retval A buffer holding the binary data (result) if serialization succeed and zero otherwise.
**/
tsk_buffer_t* tnet_stun_message_serialize(const tnet_stun_message_t *self)
{
tsk_buffer_t *output = 0;
tnet_stun_attribute_t *attribute;
unsigned compute_integrity = self->integrity;
if(!self) {
goto bail;
}
output = tsk_buffer_create_null();
/* RFC 5389 - 6. STUN Message Structure
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|0 0| STUN Message Type | Message Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Magic Cookie |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| Transaction ID (96 bits) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/* STUN Message Type
*/
{
uint16_t type = tnet_htons(self->type);
tsk_buffer_append(output, &(type), 2);
}
/* Message Length ==> Will be updated after attributes have been added. */
{
static const uint16_t length = 0;
tsk_buffer_append(output, &(length), 2);
}
/* Magic Cookie
*/
{
uint32_t cookie = tnet_htonl(self->cookie);
tsk_buffer_append(output, &(cookie), 4);
}
/* Transaction ID (96 bits==>16bytes)
*/
tsk_buffer_append(output, self->transaction_id, TNET_STUN_TRANSACID_SIZE);
/* DONT-FRAGMENT
*/
if(self->dontfrag) {
attribute = (tnet_stun_attribute_t *)tnet_turn_attribute_dontfrag_create();
tnet_stun_attribute_serialize(attribute, output);
TSK_OBJECT_SAFE_FREE(attribute);
}
/* AUTHENTICATION */
if(self->realm && self->nonce) { // long term
SERIALIZE_N_ADD_ATTRIBUTE(realm, self->realm, tsk_strlen(self->realm));
SERIALIZE_N_ADD_ATTRIBUTE(nonce, self->nonce, tsk_strlen(self->nonce));
compute_integrity = !self->nointegrity;
}
else if(self->password) { // short term
compute_integrity = !self->nointegrity;
}
if(compute_integrity && self->username) {
SERIALIZE_N_ADD_ATTRIBUTE(username, self->username, tsk_strlen(self->username));
}
/*=== Attributes === */
{
tsk_list_item_t *item;
tsk_list_foreach(item, self->attributes) {
attribute = item->data;
tnet_stun_attribute_serialize(attribute, output);
tnet_stun_attribute_pad(attribute, output);
}
}
/* Message Length: The message length MUST contain the size, in bytes, of the message
not including the 20-byte STUN header.
*/
{
// compute length for 'MESSAGE-INTEGRITY'
// will be computed again to store the correct value
uint16_t length = (output->size) - TNET_STUN_HEADER_SIZE;
#if 0
if(self->fingerprint) {
length += (2/* Type */ + 2 /* Length */+ 4 /* FINGERPRINT VALUE*/);
}
#endif
if(compute_integrity) {
length += (2/* Type */ + 2 /* Length */+ TSK_SHA1_DIGEST_SIZE /* INTEGRITY VALUE*/);
}
*(((uint16_t*)output->data)+1) = tnet_htons(length);
}
/* MESSAGE-INTEGRITY */
if(compute_integrity) {
/* RFC 5389 - 15.4. MESSAGE-INTEGRITY
The MESSAGE-INTEGRITY attribute contains an HMAC-SHA1 [RFC2104] of the STUN message.
For long-term credentials ==> key = MD5(username ":" realm ":" SASLprep(password))
For short-term credentials ==> key = SASLprep(password)
*/
tsk_sha1digest_t hmac;
if(self->username && self->realm && self->password) { // long term
char* keystr = tsk_null;
tsk_md5digest_t md5;
tsk_sprintf(&keystr, "%s:%s:%s", self->username, self->realm, self->password);
TSK_MD5_DIGEST_CALC(keystr, tsk_strlen(keystr), md5);
hmac_sha1digest_compute(output->data, output->size, (const char*)md5, TSK_MD5_DIGEST_SIZE, hmac);
TSK_FREE(keystr);
}
else { // short term
hmac_sha1digest_compute(output->data, output->size, self->password, tsk_strlen(self->password), hmac);
}
SERIALIZE_N_ADD_ATTRIBUTE(integrity, hmac, TSK_SHA1_DIGEST_SIZE);
}
// LENGTH
*(((uint16_t*)output->data) + 1) = tnet_htons((output->size - TNET_STUN_HEADER_SIZE + (self->fingerprint ? 8 : 0)));
/* FINGERPRINT */
if(self->fingerprint) { //JINGLE_ICE
/* RFC 5389 - 15.5. FINGERPRINT
The FINGERPRINT attribute MAY be present in all STUN messages. The
value of the attribute is computed as the CRC-32 of the STUN message
up to (but excluding) the FINGERPRINT attribute itself, XOR'ed with
the 32-bit value 0x5354554e
*/
uint32_t fingerprint = tsk_pppfcs32(TSK_PPPINITFCS32, output->data, output->size);
fingerprint ^= 0x5354554e;
fingerprint = tnet_htonl(fingerprint);
attribute = (tnet_stun_attribute_t *)tnet_stun_attribute_fingerprint_create(fingerprint);
tnet_stun_attribute_serialize(attribute, output);
TSK_OBJECT_SAFE_FREE(attribute);
}
bail:
return output;
}
/**@ingroup tnet_stun_group
*
* Deserializes a STUN message from binary data.
*
* @param [in,out] data A pointer to the binary data.
* @param size The size of the binary data.
*
* @retval A STUN message if deserialization succeed or NULL otherwise.
**/
tnet_stun_message_t* tnet_stun_message_deserialize(const uint8_t *data, tsk_size_t size)
{
tnet_stun_message_t *message = 0;
uint8_t* dataPtr, *dataEnd;
if(!data || (size < TNET_STUN_HEADER_SIZE) || !TNET_IS_STUN2_MSG(data, size)) {
goto bail;
}
dataPtr = (uint8_t*)data;
dataEnd = (dataPtr + size);
message = tnet_stun_message_create_null();
/* Message Type
*/
message->type = (tnet_stun_message_type_t)tnet_ntohs_2(dataPtr);
dataPtr += 2;
/* Message Length
*/
message->length = tnet_ntohs_2(dataPtr);
dataPtr += 2;
/* Check message validity
*/
if((message->length + TNET_STUN_HEADER_SIZE) != size) {
TSK_OBJECT_SAFE_FREE(message);
goto bail;
}
/* Magic Cookie
==> already set by the constructor and checked by @ref TNET_IS_STUN2
*/
dataPtr += 4;
/* Transaction ID
*/
memcpy(message->transaction_id, dataPtr, TNET_STUN_TRANSACID_SIZE);
dataPtr += TNET_STUN_TRANSACID_SIZE;
/* == Parse attributes
*/
while(dataPtr < dataEnd) {
tnet_stun_attribute_t *attribute = tnet_stun_attribute_deserialize(dataPtr, (dataEnd - dataPtr));
if(attribute) {
tsk_size_t att_size = (attribute->length + 2 /* Type*/ + 2/* Length */);
att_size += (att_size & 0x03) ? 4-(att_size & 0x03) : 0; // Skip zero bytes used to pad the attribute.
dataPtr += att_size;
tsk_list_push_back_data(message->attributes, (void**)&attribute);
continue;
}
else {
continue;
}
}
bail:
return message;
}
/**@ingroup tnet_stun_group
*/
tsk_bool_t tnet_stun_message_has_attribute(const tnet_stun_message_t *self, tnet_stun_attribute_type_t type)
{
return (tnet_stun_message_get_attribute(self, type) != tsk_null);
}
/**@ingroup tnet_stun_group
* Adds an attribute to a STUN message.
* @param self The STUN message into which to add the attribute.
* @param attribute The attribute to add.
* @retval Zero if succeed and non-zero error code otherwise.
*/
int tnet_stun_message_add_attribute(tnet_stun_message_t *self, tnet_stun_attribute_t** attribute)
{
if(self && attribute && *attribute) {
tsk_list_push_back_data(self->attributes, (void**)attribute);
return 0;
}
return -1;
}
/**@ingroup tnet_stun_group
*/
int tnet_stun_message_remove_attribute(tnet_stun_message_t *self, tnet_stun_attribute_type_t type)
{
if(self && self->attributes) {
tsk_list_remove_item_by_pred(self->attributes, __pred_find_attribute_by_type, &type);
}
return 0;
}
/**@ingroup tnet_stun_group
* Gets a STUN attribute from a message.
* @param self The message from which to get the attribute.
* @param type The type of the attribute to retrieve.
* @retval @ref tnet_stun_attribute_t object if found and NULL otherwise.
*/
const tnet_stun_attribute_t* tnet_stun_message_get_attribute(const tnet_stun_message_t *self, tnet_stun_attribute_type_t type)
{
tnet_stun_attribute_t* attribute;
if(self && !TSK_LIST_IS_EMPTY(self->attributes)) {
tsk_list_item_t *item;
tsk_list_foreach(item, self->attributes) {
if((attribute = item->data) && attribute->type == type) {
return attribute;
}
}
}
return 0;
}
/**@ingroup tnet_stun_group
* Gets the STUN error-code attribute value from the message.
* @param self The STUN message from which to get the error code.
* @retval The error code if the message contain such attribute or -1 otherwise.
*/
short tnet_stun_message_get_errorcode(const tnet_stun_message_t *self)
{
const tnet_stun_attribute_errorcode_t* error = (const tnet_stun_attribute_errorcode_t*)tnet_stun_message_get_attribute(self, stun_error_code);
if(error) {
return ((error->_class*100) + error->number);
}
return -1;
}
/**@ingroup tnet_stun_group
* Gets the STUN @b realm attribute value from the message.
* @param self The STUN message from which to get the @b realm.
* @retval The @b realm as a string pointer code if the message contain such attribute or NULL otherwise.
*/
const char* tnet_stun_message_get_realm(const tnet_stun_message_t *self)
{
const tnet_stun_attribute_realm_t* realm = (const tnet_stun_attribute_realm_t*)tnet_stun_message_get_attribute(self, stun_realm);
if(realm) {
return realm->value;
}
return 0;
}
/**@ingroup tnet_stun_group
* Gets the STUN @b nonce attribute value from the message.
* @param self The STUN message from which to get the @b nonce.
* @retval The @b nonce as a string pointer code if the message contain such attribute or NULL otherwise.
*/
const char* tnet_stun_message_get_nonce(const tnet_stun_message_t *self)
{
const tnet_stun_attribute_nonce_t* nonce = (const tnet_stun_attribute_nonce_t*)tnet_stun_message_get_attribute(self, stun_nonce);
if(nonce) {
return nonce->value;
}
return 0;
}
/**@ingroup tnet_stun_group
* Gets the STUN @b lifetime attribute value from the message.
* @param self The STUN message from which to get the @b lifetime.
* @retval The @b lifetime (any positive value) if the message contain such attribute or -1 otherwise.
*/
int32_t tnet_stun_message_get_lifetime(const tnet_stun_message_t *self)
{
const tnet_turn_attribute_lifetime_t* lifetime = (const tnet_turn_attribute_lifetime_t*)tnet_stun_message_get_attribute(self, stun_lifetime);
if(lifetime) {
return lifetime->value;
}
return -1;
}
/**@ingroup tnet_stun_group
*/
tsk_bool_t tnet_stun_message_transac_id_equals(const tnet_stun_transacid_t id1, const tnet_stun_transacid_t id2)
{
tsk_size_t i;
static const tsk_size_t size = sizeof(tnet_stun_transacid_t);
for(i = 0; i < size; i++) {
if(id1[i] != id2[i]) {
return tsk_false;
}
}
return tsk_true;
}
//=================================================================================================
// STUN2 MESSAGE object definition
///*
//* Copyright (C) 2010-2011 Mamadou Diop.
//*
//* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
//*
//* This file is part of Open Source Doubango Framework.
//*
//* DOUBANGO is free software: you can redistribute it and/or modify
//* it under the terms of the GNU General Public License as published by
//* the Free Software Foundation, either version 3 of the License, or
//* (at your option) any later version.
//*
//* DOUBANGO is distributed in the hope that it will be useful,
//* but WITHOUT ANY WARRANTY; without even the implied warranty of
//* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//* GNU General Public License for more details.
//*
//* You should have received a copy of the GNU General Public License
//* along with DOUBANGO.
//*
//*/
//
///**@file tnet_stun_message.c
// * @brief STUN2 (RFC 5389) message parser.
// *
// * @author Mamadou Diop <diopmamadou(at)doubango[dot]org>
// *
//
// */
//#include "tnet_stun_message.h"
//
//#include "tnet_stun.h"
//
//#include "../tnet_types.h"
//#include "../tnet_endianness.h"
//#include "../turn/tnet_turn_attribute.h"
//#include "stun/tnet_stun_types.h"
//
//#include "tsk_memory.h"
//#include "tsk_hmac.h"
//#include "tsk_string.h"
//#include "tsk_ppfcs32.h"
//
//#include <string.h>
//
//static int __pred_find_attribute_by_type(const tsk_list_item_t *item, const void *att_type)
//{
// if(item && item->data) {
// tnet_stun_attr_t *att = item->data;
// tnet_stun_attr_type_t type = *((tnet_stun_attr_type_t*)att_type);
// return (att->type - type);
// }
// return -1;
//}
//
///**@ingroup tnet_stun_group
//* Creates new STUN message.
//* @retval @ref tnet_stun_pkt_t object.
//* @sa tnet_stun_message_create_null.
//*/
//
//tnet_stun_pkt_t* tnet_stun_message_create(const char* username, const char* password)
//{
// return tsk_object_new(tnet_stun_message_def_t, username, password);
//}
//
///**@ingroup tnet_stun_group
//* Creates new STUN message.
//* @retval @ref tnet_stun_pkt_t object.
//* @sa tnet_stun_message_create.
//*/
//tnet_stun_pkt_t* tnet_stun_message_create_null()
//{
// return tnet_stun_message_create(tsk_null, tsk_null);
//}
//
//#define SERIALIZE_N_ADD_ATTRIBUTE(att_name, payload, payload_size) \
// attribute = (tnet_stun_attr_t *)tnet_stun_attribute_##att_name##_create(payload, payload_size); \
// tnet_stun_attribute_serialize(attribute, output); \
// tnet_stun_attribute_pad(attribute, output); \
// TSK_OBJECT_SAFE_FREE(attribute);
//
///**@ingroup tnet_stun_group
// * Serializes a STUN message as binary data.
// * @param [in,out] self The STUN message to serialize.
// * @retval A buffer holding the binary data (result) if serialization succeed and zero otherwise.
//**/
//tsk_buffer_t* tnet_stun_pkt_serialize(const tnet_stun_pkt_t *self)
//{
// tsk_buffer_t *output = 0;
// tnet_stun_attr_t *attribute;
// unsigned compute_integrity = self->integrity;
//
// if(!self) {
// goto bail;
// }
//
// output = tsk_buffer_create_null();
//
// /* RFC 5389 - 6. STUN Message Structure
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |0 0| STUN Message Type | Message Length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Magic Cookie |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | |
// | Transaction ID (96 bits) |
// | |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// */
//
// /* STUN Message Type
// */
// {
// uint16_t type = tnet_htons(self->type);
// tsk_buffer_append(output, &(type), 2);
// }
//
// /* Message Length ==> Will be updated after attributes have been added. */
// {
// static const uint16_t length = 0;
// tsk_buffer_append(output, &(length), 2);
// }
//
// /* Magic Cookie
// */
// {
// uint32_t cookie = tnet_htonl(self->cookie);
// tsk_buffer_append(output, &(cookie), 4);
// }
//
//
// /* Transaction ID (96 bits==>16bytes)
// */
// tsk_buffer_append(output, self->transac_id, TNET_STUN_TRANSACID_SIZE);
//
// /* DONT-FRAGMENT
// */
// if(self->dontfrag) {
// /*attribute = (tnet_stun_attr_t *)tnet_turn_attribute_dontfrag_create();
// tnet_stun_attribute_serialize(attribute, output);
// TSK_OBJECT_SAFE_FREE(attribute);*/
// }
//
// /* AUTHENTICATION */
// if(self->realm && self->nonce) { // long term
// SERIALIZE_N_ADD_ATTRIBUTE(realm, self->realm, tsk_strlen(self->realm));
// SERIALIZE_N_ADD_ATTRIBUTE(nonce, self->nonce, tsk_strlen(self->nonce));
//
// compute_integrity = !self->nointegrity;
// }
// else if(self->password) { // short term
// compute_integrity = !self->nointegrity;
// }
//
// if(compute_integrity && self->username) {
// SERIALIZE_N_ADD_ATTRIBUTE(username, self->username, tsk_strlen(self->username));
// }
//
// /*=== Attributes === */
// {
// tsk_list_item_t *item;
// tsk_list_foreach(item, self->attributes) {
// attribute = item->data;
// tnet_stun_attribute_serialize(attribute, output);
// tnet_stun_attribute_pad(attribute, output);
// }
// }
//
// /* Message Length: The message length MUST contain the size, in bytes, of the message
// not including the 20-byte STUN header.
// */
// {
// // compute length for 'MESSAGE-INTEGRITY'
// // will be computed again to store the correct value
// uint16_t length = (output->size) - kStunAttrHdrSizeInOctets;
//#if 0
// if(self->fingerprint) {
// length += (2/* Type */ + 2 /* Length */+ 4 /* FINGERPRINT VALUE*/);
// }
//#endif
//
// if(compute_integrity) {
// length += (2/* Type */ + 2 /* Length */+ TSK_SHA1_DIGEST_SIZE /* INTEGRITY VALUE*/);
// }
//
// *(((uint16_t*)output->data)+1) = tnet_htons(length);
// }
//
// /* MESSAGE-INTEGRITY */
// if(compute_integrity) {
// /* RFC 5389 - 15.4. MESSAGE-INTEGRITY
// The MESSAGE-INTEGRITY attribute contains an HMAC-SHA1 [RFC2104] of the STUN message.
//
// For long-term credentials ==> key = MD5(username ":" realm ":" SASLprep(password))
// For short-term credentials ==> key = SASLprep(password)
// */
//
// tsk_sha1digest_t hmac;
//
// if(self->username && self->realm && self->password) { // long term
// char* keystr = tsk_null;
// tsk_md5digest_t md5;
// tsk_sprintf(&keystr, "%s:%s:%s", self->username, self->realm, self->password);
// TSK_MD5_DIGEST_CALC(keystr, tsk_strlen(keystr), md5);
// hmac_sha1digest_compute(output->data, output->size, (const char*)md5, TSK_MD5_DIGEST_SIZE, hmac);
//
// TSK_FREE(keystr);
// }
// else { // short term
// hmac_sha1digest_compute(output->data, output->size, self->password, tsk_strlen(self->password), hmac);
// }
//
// SERIALIZE_N_ADD_ATTRIBUTE(integrity, hmac, TSK_SHA1_DIGEST_SIZE);
// }
//
// // LENGTH
// *(((uint16_t*)output->data) + 1) = tnet_htons((output->size - kStunAttrHdrSizeInOctets + (self->fingerprint ? 8 : 0)));
//
// /* FINGERPRINT */
// if(self->fingerprint) { //JINGLE_ICE
// /* RFC 5389 - 15.5. FINGERPRINT
// The FINGERPRINT attribute MAY be present in all STUN messages. The
// value of the attribute is computed as the CRC-32 of the STUN message
// up to (but excluding) the FINGERPRINT attribute itself, XOR'ed with
// the 32-bit value 0x5354554e
// */
// uint32_t fingerprint = tsk_pppfcs32(TSK_PPPINITFCS32, output->data, output->size);
// fingerprint ^= 0x5354554e;
// fingerprint = tnet_htonl(fingerprint);
//
// attribute = (tnet_stun_attr_t *)tnet_stun_attribute_fingerprint_create(fingerprint);
// tnet_stun_attribute_serialize(attribute, output);
// TSK_OBJECT_SAFE_FREE(attribute);
// }
//
//bail:
// return output;
//}
//
//
///**@ingroup tnet_stun_group
// *
// * Deserializes a STUN message from binary data.
// *
// * @param [in,out] data A pointer to the binary data.
// * @param size The size of the binary data.
// *
// * @retval A STUN message if deserialization succeed or NULL otherwise.
//**/
//tnet_stun_pkt_t* tnet_stun_message_deserialize(const uint8_t *data, tsk_size_t size)
//{
// tnet_stun_pkt_t *message = 0;
// uint8_t* dataPtr, *dataEnd;
//
//
// if(!data || (size < kStunAttrHdrSizeInOctets) || !TNET_STUN_BUFF_IS_STUN2(data, size)) {
// goto bail;
// }
//
// dataPtr = (uint8_t*)data;
// dataEnd = (dataPtr + size);
//
// message = tnet_stun_message_create_null();
//
// /* Message Type
// */
// message->type = (tnet_stun_pkt_type_t)tnet_ntohs_2(dataPtr);
// dataPtr += 2;
//
// /* Message Length
// */
// message->length = tnet_ntohs_2(dataPtr);
// dataPtr += 2;
//
// /* Check message validity
// */
// if((message->length + kStunAttrHdrSizeInOctets) != size) {
// TSK_OBJECT_SAFE_FREE(message);
// goto bail;
// }
//
// /* Magic Cookie
// ==> already set by the constructor and checked by @ref TNET_IS_STUN2
// */
// dataPtr += 4;
//
// /* Transaction ID
// */
// memcpy(message->transac_id, dataPtr, TNET_STUN_TRANSACID_SIZE);
// dataPtr += TNET_STUN_TRANSACID_SIZE;
//
// /* == Parse attributes
// */
// while(dataPtr < dataEnd) {
// tnet_stun_attr_t *attribute = tnet_stun_attribute_deserialize(dataPtr, (dataEnd - dataPtr));
// if(attribute) {
// tsk_size_t att_size = (attribute->length + 2 /* Type*/ + 2/* Length */);
// att_size += (att_size & 0x03) ? 4-(att_size & 0x03) : 0; // Skip zero bytes used to pad the attribute.
//
// dataPtr += att_size;
// tsk_list_push_back_data(message->attributes, (void**)&attribute);
//
// continue;
// }
// else {
// continue;
// }
// }
//
//bail:
// return message;
//}
//
///**@ingroup tnet_stun_group
//*/
//tsk_bool_t tnet_stun_message_has_attribute(const tnet_stun_pkt_t *self, tnet_stun_attr_type_t type)
//{
// return (tnet_stun_message_get_attribute(self, type) != tsk_null);
//}
//
///**@ingroup tnet_stun_group
//* Adds an attribute to a STUN message.
//* @param self The STUN message into which to add the attribute.
//* @param attribute The attribute to add.
//* @retval Zero if succeed and non-zero error code otherwise.
//*/
//int tnet_stun_message_add_attribute(tnet_stun_pkt_t *self, tnet_stun_attr_t** attribute)
//{
// if(self && attribute && *attribute) {
// tsk_list_push_back_data(self->attributes, (void**)attribute);
// return 0;
// }
// return -1;
//}
//
///**@ingroup tnet_stun_group
//*/
//int tnet_stun_message_remove_attribute(tnet_stun_pkt_t *self, tnet_stun_attr_type_t type)
//{
// if(self && self->attributes) {
// tsk_list_remove_item_by_pred(self->attributes, __pred_find_attribute_by_type, &type);
// }
// return 0;
//}
//
//
///**@ingroup tnet_stun_group
//* Gets a STUN attribute from a message.
//* @param self The message from which to get the attribute.
//* @param type The type of the attribute to retrieve.
//* @retval @ref tnet_stun_attr_t object if found and NULL otherwise.
//*/
//const tnet_stun_attr_t* tnet_stun_message_get_attribute(const tnet_stun_pkt_t *self, tnet_stun_attr_type_t type)
//{
// tnet_stun_attr_t* attribute;
//
// if(self && !TSK_LIST_IS_EMPTY(self->attributes)) {
// tsk_list_item_t *item;
// tsk_list_foreach(item, self->attributes) {
// if((attribute = item->data) && attribute->type == type) {
// return attribute;
// }
// }
// }
// return 0;
//}
//
///**@ingroup tnet_stun_group
//* Gets the STUN error-code attribute value from the message.
//* @param self The STUN message from which to get the error code.
//* @retval The error code if the message contain such attribute or -1 otherwise.
//*/
//short tnet_stun_message_get_errorcode(const tnet_stun_pkt_t *self)
//{
// const tnet_stun_attribute_errorcode_t* error = (const tnet_stun_attribute_errorcode_t*)tnet_stun_message_get_attribute(self, stun_error_code);
// if(error) {
// return ((error->_class*100) + error->number);
// }
// return -1;
//}
//
///**@ingroup tnet_stun_group
//* Gets the STUN @b realm attribute value from the message.
//* @param self The STUN message from which to get the @b realm.
//* @retval The @b realm as a string pointer code if the message contain such attribute or NULL otherwise.
//*/
//const char* tnet_stun_message_get_realm(const tnet_stun_pkt_t *self)
//{
// const tnet_stun_attribute_realm_t* realm = (const tnet_stun_attribute_realm_t*)tnet_stun_message_get_attribute(self, stun_realm);
// if(realm) {
// return realm->value;
// }
// return 0;
//}
//
///**@ingroup tnet_stun_group
//* Gets the STUN @b nonce attribute value from the message.
//* @param self The STUN message from which to get the @b nonce.
//* @retval The @b nonce as a string pointer code if the message contain such attribute or NULL otherwise.
//*/
//const char* tnet_stun_message_get_nonce(const tnet_stun_pkt_t *self)
//{
// const tnet_stun_attribute_nonce_t* nonce = (const tnet_stun_attribute_nonce_t*)tnet_stun_message_get_attribute(self, stun_nonce);
// if(nonce) {
// return nonce->value;
// }
// return 0;
//}
//
///**@ingroup tnet_stun_group
//* Gets the STUN @b lifetime attribute value from the message.
//* @param self The STUN message from which to get the @b lifetime.
//* @retval The @b lifetime (any positive value) if the message contain such attribute or -1 otherwise.
//*/
//int32_t tnet_stun_message_get_lifetime(const tnet_stun_pkt_t *self)
//{
// /*const tnet_turn_attribute_lifetime_t* lifetime = (const tnet_turn_attribute_lifetime_t*)tnet_stun_message_get_attribute(self, stun_lifetime);
// if(lifetime) {
// return lifetime->value;
// }*/
// return -1;
//}
//
///**@ingroup tnet_stun_group
//*/
//tsk_bool_t tnet_stun_utils_transac_id_equals(const tnet_stun_transac_id_t id1, const tnet_stun_transac_id_t id2)
//{
// tsk_size_t i;
// static const tsk_size_t size = sizeof(tnet_stun_transac_id_t);
// for(i = 0; i < size; i++) {
// if(id1[i] != id2[i]) {
// return tsk_false;
// }
// }
// return tsk_true;
//}
//
//
//
//
//
//
////=================================================================================================
//// STUN2 MESSAGE object definition
////
//static tsk_object_t* tnet_stun_message_ctor(tsk_object_t * self, va_list * app)
//{
// tnet_stun_pkt_t *message = self;
// if(message) {
// message->username = tsk_strdup(va_arg(*app, const char*));
// message->password = tsk_strdup(va_arg(*app, const char*));
//
// message->cookie = kStunMagicCookieLong;
// message->attributes = tsk_list_create();
//
// message->fingerprint = 1;
// message->integrity = 0;
//
// {
// // Create random transaction id
// int i;
// for(i = 0; i < sizeof(message->transac_id)/sizeof(message->transac_id[0]); ++i) {
// message->transac_id[i] = rand();
// }
// }
// }
// return self;
//}
//
//static tsk_object_t* tnet_stun_message_dtor(tsk_object_t * self)
//{
// tnet_stun_pkt_t *message = self;
// if(message) {
// TSK_FREE(message->username);
// TSK_FREE(message->password);
// TSK_FREE(message->realm);
// TSK_FREE(message->nonce);
//
// TSK_OBJECT_SAFE_FREE(message->attributes);
// }
//
// return self;
//}
//
//static const tsk_object_def_t tnet_stun_message_def_s = {
// sizeof(tnet_stun_pkt_t),
// tnet_stun_message_ctor,
// tnet_stun_message_dtor,
// tsk_null,
//};
//const tsk_object_def_t *tnet_stun_message_def_t = &tnet_stun_message_def_s;
//
static tsk_object_t* tnet_stun_message_ctor(tsk_object_t * self, va_list * app)
{
tnet_stun_message_t *message = self;
if(message) {
message->username = tsk_strdup(va_arg(*app, const char*));
message->password = tsk_strdup(va_arg(*app, const char*));
message->cookie = TNET_STUN_MAGIC_COOKIE;
message->attributes = tsk_list_create();
message->fingerprint = 1;
message->integrity = 0;
{
// Create random transaction id
int i;
for(i = 0; i < sizeof(message->transaction_id)/sizeof(message->transaction_id[0]); ++i) {
message->transaction_id[i] = rand();
}
}
}
return self;
}
static tsk_object_t* tnet_stun_message_dtor(tsk_object_t * self)
{
tnet_stun_message_t *message = self;
if(message) {
TSK_FREE(message->username);
TSK_FREE(message->password);
TSK_FREE(message->realm);
TSK_FREE(message->nonce);
TSK_OBJECT_SAFE_FREE(message->attributes);
}
return self;
}
static const tsk_object_def_t tnet_stun_message_def_s = {
sizeof(tnet_stun_message_t),
tnet_stun_message_ctor,
tnet_stun_message_dtor,
tsk_null,
};
const tsk_object_def_t *tnet_stun_message_def_t = &tnet_stun_message_def_s;

View File

@ -1,246 +1,246 @@
/*
* Copyright (C) 2010-2011 Mamadou Diop.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
*/
/**@file tnet_stun_message.h
* @brief STUN2 (RFC 5389) message parser.
*
* @author Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
*/
#ifndef TNET_STUN_MESSAGE_H
#define TNET_STUN_MESSAGE_H
#include "tinynet_config.h"
#include "stun/tnet_stun_attribute.h"
#include "tsk_buffer.h"
TNET_BEGIN_DECLS
#define TNET_STUN_CLASS_REQUEST_MASK (0x0000)
#define TNET_STUN_CLASS_INDICATION_MASK (0x0010)
#define TNET_STUN_CLASS_SUCCESS_MASK (0x0100)
#define TNET_STUN_CLASS_ERROR_MASK (0x0110)
/**@ingroup tnet_stun_group
* @def TNET_STUN_MESSAGE_IS_REQUEST
* Checks whether the STUN message is a request or not.
*/
/**@ingroup tnet_stun_group
* @def TNET_STUN_MESSAGE_IS_INDICATION
* Checks whether the STUN message is an indicaton message or not.
*/
/**@ingroup tnet_stun_group
* @def TNET_STUN_RESPONSE_IS_SUCCESS
* Checks whether the STUN message is a success response or not.
*/
/**@ingroup tnet_stun_group
* @def TNET_STUN_RESPONSE_IS_ERROR
* Checks whether the STUN message is an error response or not.
*/
#define TNET_STUN_MESSAGE_IS_REQUEST(self) ((self) && (((self)->type & 0x0110) == TNET_STUN_CLASS_REQUEST_MASK))
#define TNET_STUN_MESSAGE_IS_RESPONSE(self) (TNET_STUN_RESPONSE_IS_SUCCESS((self)) || TNET_STUN_RESPONSE_IS_ERROR((self)))
#define TNET_STUN_MESSAGE_IS_INDICATION(self) ((self) && (((self)->type & 0x0110) == TNET_STUN_CLASS_INDICATION_MASK))
#define TNET_STUN_RESPONSE_IS_SUCCESS(self) ((self) && (((self)->type & 0x0110) == TNET_STUN_CLASS_SUCCESS_MASK))
#define TNET_STUN_RESPONSE_IS_ERROR(self) ((self) && (((self)->type & 0x0110) == TNET_STUN_CLASS_ERROR_MASK))
/**@ingroup tnet_stun_group
* Checks if the pointer to the buffer hold a STUN header by checking that it starts with 0b00 and contain the magic cookie.
* As per RFC 5389 subclause 19: Explicitly point out that the most significant 2 bits of STUN are
* 0b00, allowing easy differentiation with RTP packets when used with ICE.
* As per RFC 5389 subclause 6: The magic cookie field MUST contain the fixed value 0x2112A442 in
* network byte order.
*
* @param PU8 The pointer to the buffer holding the STUN raw data.
**/
#define TNET_IS_STUN2_MSG(PU8, SIZE) \
( \
((PU8)) && \
((SIZE) >= TNET_STUN_HEADER_SIZE) && \
(((PU8)[0] & 0xc0) == 0x00) && \
( PU8[4] == 0x21 && PU8[5] == 0x12 && PU8[6] == 0xA4 && PU8[7] == 0x42 ) \
)
#define TNET_IS_STUN2 TNET_IS_STUN2_MSG // for backward compatibility
/**@ingroup tnet_stun_group
* STUN trasactionn ID size (96bits = 12bytes).
*/
#define TNET_STUN_TRANSACID_SIZE 12
/**@ingroup tnet_stun_group
* Defines an alias representing the STUN transaction id type.
**/
typedef uint8_t tnet_stun_transacid_t[TNET_STUN_TRANSACID_SIZE];
/**@ingroup tnet_stun_group
* List of all supported STUN classes as per RFC 5389 subcaluse 6.
**/
typedef enum tnet_stun_class_type_e {
stun_class_request = 0x00, /**< Request class: 0b00 */
stun_class_indication = 0x01, /**< Indication class: 0b01 */
stun_class_success_response = 0x02, /**< Success response class: 0b10 */
stun_class_error_response = 0x03, /**< Error/failure response class: 0b11 */
}
tnet_stun_class_type_t;
/**@ingroup tnet_stun_group
* List of all supported STUN methods.
* RFC 5389 only define one method(Bining). All other methods have been defined
* by TURN (draft-ietf-behave-turn-16 and draft-ietf-behave-turn-tcp-05).
**/
typedef enum tnet_stun_method_type_e {
stun_method_binding = 0x0001, /**< RFC 5389 - Binding method: 0b000000000001 */
stun_method_allocate = 0x0003, /**< draft-ietf-behave-turn-16 - Allocate (only request/response semantics defined) */
stun_method_refresh = 0x0004, /**< draft-ietf-behave-turn-16 - Refresh (only request/response semantics defined) */
stun_method_send = 0x0006, /**< draft-ietf-behave-turn-16 - Send (only indication semantics defined) */
stun_method_data = 0x0007, /**< draft-ietf-behave-turn-16 - Data (only indication semantics defined) */
stun_method_createpermission = 0x0008, /**< draft-ietf-behave-turn-16 - CreatePermission (only request/response semantics defined */
stun_method_channelbind = 0x0009, /**< draft-ietf-behave-turn-16 - ChannelBind (only request/response semantics defined) */
}
tnet_stun_method_type_t;
/**@ingroup tnet_stun_group
* List of all supported STUN types.
*/
typedef enum tnet_stun_message_type_e {
/* RFC 5389 - 6. STUN Message Structure
The message type defines the message class (request, success
response, failure response, or indication) and the message method
(the primary function) of the STUN message. Although there are four
message classes, there are only two types of transactions in STUN:
request/response transactions (which consist of a request message and
a response message) and indication transactions (which consist of a
single indication message). Response classes are split into error
and success responses to aid in quickly processing the STUN message.
The message type field is decomposed further into the following
structure:
0 1
2 3 4 5 6 7 8 9 0 1 2 3 4 5
+--+--+-+-+-+-+-+-+-+-+-+-+-+-+
|M |M |M|M|M|C|M|M|M|C|M|M|M|M|
|11|10|9|8|7|1|6|5|4|0|3|2|1|0|
+--+--+-+-+-+-+-+-+-+-+-+-+-+-+
*/
stun_binding_request = (stun_method_binding | TNET_STUN_CLASS_REQUEST_MASK),
stun_binding_indication = (stun_method_binding | TNET_STUN_CLASS_INDICATION_MASK),
stun_binding_success_response = (stun_method_binding | TNET_STUN_CLASS_SUCCESS_MASK),
stun_binding_error_response = (stun_method_binding | TNET_STUN_CLASS_ERROR_MASK),
stun_allocate_request = (stun_method_allocate | TNET_STUN_CLASS_REQUEST_MASK),
stun_allocate_indication = (stun_method_allocate | TNET_STUN_CLASS_INDICATION_MASK),
stun_allocate_success_response = (stun_method_allocate | TNET_STUN_CLASS_SUCCESS_MASK),
stun_allocate_error_response = (stun_method_allocate | TNET_STUN_CLASS_ERROR_MASK),
stun_refresh_request = (stun_method_refresh | TNET_STUN_CLASS_REQUEST_MASK),
stun_refresh_indication = (stun_method_refresh | TNET_STUN_CLASS_INDICATION_MASK),
stun_refresh_success_response = (stun_method_refresh | TNET_STUN_CLASS_SUCCESS_MASK),
stun_refresh_error_response = (stun_method_refresh | TNET_STUN_CLASS_ERROR_MASK),
stun_send_indication = (stun_method_send | TNET_STUN_CLASS_INDICATION_MASK),
stun_data_indication = (stun_method_data | TNET_STUN_CLASS_INDICATION_MASK),
stun_createpermission_request = (stun_method_createpermission | TNET_STUN_CLASS_REQUEST_MASK),
stun_createpermission_indication = (stun_method_createpermission | TNET_STUN_CLASS_INDICATION_MASK),
stun_createpermission_success_response = (stun_method_createpermission | TNET_STUN_CLASS_SUCCESS_MASK),
stun_createpermission_error_response = (stun_method_createpermission | TNET_STUN_CLASS_ERROR_MASK),
stun_channelbind_request = (stun_method_channelbind | TNET_STUN_CLASS_REQUEST_MASK),
stun_channelbind_indication = (stun_method_channelbind | TNET_STUN_CLASS_INDICATION_MASK),
stun_channelbind_success_response = (stun_method_channelbind | TNET_STUN_CLASS_SUCCESS_MASK),
stun_channelbind_error_response = (stun_method_channelbind | TNET_STUN_CLASS_ERROR_MASK),
}
tnet_stun_message_type_t;
/**@ingroup tnet_stun_group
*
* STUN Message structure as per RFC 5389 subclause 6.
* http://tools.ietf.org/html/rfc5389#section-6
*/
typedef struct tnet_stun_message_s {
TSK_DECLARE_OBJECT;
/*
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|0 0| STUN Message Type | Message Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Magic Cookie |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| Transaction ID (96 bits) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
tnet_stun_message_type_t type;
uint16_t length;
uint32_t cookie;
tnet_stun_transacid_t transaction_id;
unsigned fingerprint:1;
unsigned integrity:1;
unsigned dontfrag:1;
unsigned nointegrity:1;
char* username;
char* password;
char* realm;
char* nonce;
tnet_stun_attributes_L_t *attributes; /**< List of all attributes associated to this message */
}
tnet_stun_message_t;
typedef tnet_stun_message_t tnet_stun_response_t;
typedef tnet_stun_message_t tnet_stun_request_t;
TINYNET_API tsk_buffer_t* tnet_stun_message_serialize(const tnet_stun_message_t *message);
tnet_stun_message_t* tnet_stun_message_deserialize(const uint8_t *data, tsk_size_t size);
tsk_bool_t tnet_stun_message_has_attribute(const tnet_stun_message_t *self, tnet_stun_attribute_type_t type);
TINYNET_API int tnet_stun_message_add_attribute(tnet_stun_message_t *self, tnet_stun_attribute_t** attribute);
int tnet_stun_message_remove_attribute(tnet_stun_message_t *self, tnet_stun_attribute_type_t type);
const tnet_stun_attribute_t* tnet_stun_message_get_attribute(const tnet_stun_message_t *self, tnet_stun_attribute_type_t type);
short tnet_stun_message_get_errorcode(const tnet_stun_message_t *self);
const char* tnet_stun_message_get_realm(const tnet_stun_message_t *self);
const char* tnet_stun_message_get_nonce(const tnet_stun_message_t *self);
int32_t tnet_stun_message_get_lifetime(const tnet_stun_message_t *self);
tsk_bool_t tnet_stun_message_transac_id_equals(const tnet_stun_transacid_t id1, const tnet_stun_transacid_t id2);
TINYNET_API tnet_stun_message_t* tnet_stun_message_create(const char* username, const char* password);
TINYNET_API tnet_stun_message_t* tnet_stun_message_create_null();
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_message_def_t;
TNET_END_DECLS
#endif /* TNET_STUN_MESSAGE_H */
///*
//* Copyright (C) 2010-2011 Mamadou Diop.
//*
//* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
//*
//* This file is part of Open Source Doubango Framework.
//*
//* DOUBANGO is free software: you can redistribute it and/or modify
//* it under the terms of the GNU General Public License as published by
//* the Free Software Foundation, either version 3 of the License, or
//* (at your option) any later version.
//*
//* DOUBANGO is distributed in the hope that it will be useful,
//* but WITHOUT ANY WARRANTY; without even the implied warranty of
//* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//* GNU General Public License for more details.
//*
//* You should have received a copy of the GNU General Public License
//* along with DOUBANGO.
//*
//*/
//
///**@file tnet_stun_message.h
// * @brief STUN2 (RFC 5389) message parser.
// *
// * @author Mamadou Diop <diopmamadou(at)doubango[dot]org>
// *
//
// */
//#ifndef TNET_STUN_MESSAGE_H
//#define TNET_STUN_MESSAGE_H
//
//#include "tinynet_config.h"
//#include "stun/tnet_stun_attribute.h"
//
//#include "tsk_buffer.h"
//
//TNET_BEGIN_DECLS
//
//#define TNET_STUN_CLASS_REQUEST_MASK (0x0000)
//#define TNET_STUN_CLASS_INDICATION_MASK (0x0010)
//#define TNET_STUN_CLASS_SUCCESS_MASK (0x0100)
//#define TNET_STUN_CLASS_ERROR_MASK (0x0110)
//
///**@ingroup tnet_stun_group
//* @def TNET_STUN_MESSAGE_IS_REQUEST
//* Checks whether the STUN message is a request or not.
//*/
///**@ingroup tnet_stun_group
//* @def TNET_STUN_MESSAGE_IS_INDICATION
//* Checks whether the STUN message is an indicaton message or not.
//*/
///**@ingroup tnet_stun_group
//* @def TNET_STUN_PKT_RESP_IS_SUCCESS
//* Checks whether the STUN message is a success response or not.
//*/
///**@ingroup tnet_stun_group
//* @def TNET_STUN_PKT_RESP_IS_ERROR
//* Checks whether the STUN message is an error response or not.
//*/
//#define TNET_STUN_MESSAGE_IS_REQUEST(self) ((self) && (((self)->type & 0x0110) == TNET_STUN_CLASS_REQUEST_MASK))
//#define TNET_STUN_MESSAGE_IS_RESPONSE(self) (TNET_STUN_PKT_RESP_IS_SUCCESS((self)) || TNET_STUN_PKT_RESP_IS_ERROR((self)))
//#define TNET_STUN_MESSAGE_IS_INDICATION(self) ((self) && (((self)->type & 0x0110) == TNET_STUN_CLASS_INDICATION_MASK))
//#define TNET_STUN_PKT_RESP_IS_SUCCESS(self) ((self) && (((self)->type & 0x0110) == TNET_STUN_CLASS_SUCCESS_MASK))
//#define TNET_STUN_PKT_RESP_IS_ERROR(self) ((self) && (((self)->type & 0x0110) == TNET_STUN_CLASS_ERROR_MASK))
//
///**@ingroup tnet_stun_group
// * Checks if the pointer to the buffer hold a STUN header by checking that it starts with 0b00 and contain the magic cookie.
// * As per RFC 5389 subclause 19: Explicitly point out that the most significant 2 bits of STUN are
// * 0b00, allowing easy differentiation with RTP packets when used with ICE.
// * As per RFC 5389 subclause 6: The magic cookie field MUST contain the fixed value 0x2112A442 in
// * network byte order.
// *
// * @param PU8 The pointer to the buffer holding the STUN raw data.
//**/
//#define TNET_STUN_BUFF_IS_STUN2(PU8, SIZE) \
// ( \
// ((PU8)) && \
// ((SIZE) >= kStunAttrHdrSizeInOctets) && \
// (((PU8)[0] & 0xc0) == 0x00) && \
// ( PU8[4] == 0x21 && PU8[5] == 0x12 && PU8[6] == 0xA4 && PU8[7] == 0x42 ) \
// )
//#define TNET_IS_STUN2 TNET_STUN_BUFF_IS_STUN2 // for backward compatibility
//
///**@ingroup tnet_stun_group
// * STUN trasactionn ID size (96bits = 12bytes).
//*/
//#define TNET_STUN_TRANSACID_SIZE 12
//
///**@ingroup tnet_stun_group
// * Defines an alias representing the STUN transaction id type.
//**/
//typedef uint8_t tnet_stun_transac_id_t[TNET_STUN_TRANSACID_SIZE];
//
///**@ingroup tnet_stun_group
// * List of all supported STUN classes as per RFC 5389 subcaluse 6.
//**/
//typedef enum tnet_stun_class_type_e {
// stun_class_request = 0x00, /**< Request class: 0b00 */
// stun_class_indication = 0x01, /**< Indication class: 0b01 */
// stun_class_success_response = 0x02, /**< Success response class: 0b10 */
// stun_class_error_response = 0x03, /**< Error/failure response class: 0b11 */
//}
//tnet_stun_class_type_t;
//
///**@ingroup tnet_stun_group
// * List of all supported STUN methods.
// * RFC 5389 only define one method(Bining). All other methods have been defined
// * by TURN (draft-ietf-behave-turn-16 and draft-ietf-behave-turn-tcp-05).
//**/
//typedef enum tnet_stun_method_type_e {
// stun_method_binding = 0x0001, /**< RFC 5389 - Binding method: 0b000000000001 */
//
// stun_method_allocate = 0x0003, /**< draft-ietf-behave-turn-16 - Allocate (only request/response semantics defined) */
// stun_method_refresh = 0x0004, /**< draft-ietf-behave-turn-16 - Refresh (only request/response semantics defined) */
// stun_method_send = 0x0006, /**< draft-ietf-behave-turn-16 - Send (only indication semantics defined) */
// stun_method_data = 0x0007, /**< draft-ietf-behave-turn-16 - Data (only indication semantics defined) */
// stun_method_createpermission = 0x0008, /**< draft-ietf-behave-turn-16 - CreatePermission (only request/response semantics defined */
// stun_method_channelbind = 0x0009, /**< draft-ietf-behave-turn-16 - ChannelBind (only request/response semantics defined) */
//}
//tnet_stun_method_type_t;
//
///**@ingroup tnet_stun_group
//* List of all supported STUN types.
//*/
//typedef enum tnet_stun_pkt_type_e {
// /* RFC 5389 - 6. STUN Message Structure
//
// The message type defines the message class (request, success
// response, failure response, or indication) and the message method
// (the primary function) of the STUN message. Although there are four
// message classes, there are only two types of transactions in STUN:
// request/response transactions (which consist of a request message and
// a response message) and indication transactions (which consist of a
// single indication message). Response classes are split into error
// and success responses to aid in quickly processing the STUN message.
//
// The message type field is decomposed further into the following
// structure:
//
// 0 1
// 2 3 4 5 6 7 8 9 0 1 2 3 4 5
// +--+--+-+-+-+-+-+-+-+-+-+-+-+-+
// |M |M |M|M|M|C|M|M|M|C|M|M|M|M|
// |11|10|9|8|7|1|6|5|4|0|3|2|1|0|
// +--+--+-+-+-+-+-+-+-+-+-+-+-+-+
// */
// stun_binding_request = (stun_method_binding | TNET_STUN_CLASS_REQUEST_MASK),
// stun_binding_indication = (stun_method_binding | TNET_STUN_CLASS_INDICATION_MASK),
// stun_binding_success_response = (stun_method_binding | TNET_STUN_CLASS_SUCCESS_MASK),
// stun_binding_error_response = (stun_method_binding | TNET_STUN_CLASS_ERROR_MASK),
//
// stun_allocate_request = (stun_method_allocate | TNET_STUN_CLASS_REQUEST_MASK),
// stun_allocate_indication = (stun_method_allocate | TNET_STUN_CLASS_INDICATION_MASK),
// stun_allocate_success_response = (stun_method_allocate | TNET_STUN_CLASS_SUCCESS_MASK),
// stun_allocate_error_response = (stun_method_allocate | TNET_STUN_CLASS_ERROR_MASK),
//
// stun_refresh_request = (stun_method_refresh | TNET_STUN_CLASS_REQUEST_MASK),
// stun_refresh_indication = (stun_method_refresh | TNET_STUN_CLASS_INDICATION_MASK),
// stun_refresh_success_response = (stun_method_refresh | TNET_STUN_CLASS_SUCCESS_MASK),
// stun_refresh_error_response = (stun_method_refresh | TNET_STUN_CLASS_ERROR_MASK),
//
// stun_send_indication = (stun_method_send | TNET_STUN_CLASS_INDICATION_MASK),
//
// stun_data_indication = (stun_method_data | TNET_STUN_CLASS_INDICATION_MASK),
//
// stun_createpermission_request = (stun_method_createpermission | TNET_STUN_CLASS_REQUEST_MASK),
// stun_createpermission_indication = (stun_method_createpermission | TNET_STUN_CLASS_INDICATION_MASK),
// stun_createpermission_success_response = (stun_method_createpermission | TNET_STUN_CLASS_SUCCESS_MASK),
// stun_createpermission_error_response = (stun_method_createpermission | TNET_STUN_CLASS_ERROR_MASK),
//
// stun_channelbind_request = (stun_method_channelbind | TNET_STUN_CLASS_REQUEST_MASK),
// stun_channelbind_indication = (stun_method_channelbind | TNET_STUN_CLASS_INDICATION_MASK),
// stun_channelbind_success_response = (stun_method_channelbind | TNET_STUN_CLASS_SUCCESS_MASK),
// stun_channelbind_error_response = (stun_method_channelbind | TNET_STUN_CLASS_ERROR_MASK),
//}
//tnet_stun_pkt_type_t;
//
///**@ingroup tnet_stun_group
// *
// * STUN Message structure as per RFC 5389 subclause 6.
// * http://tools.ietf.org/html/rfc5389#section-6
//*/
//typedef struct tnet_stun_pkt_s {
// TSK_DECLARE_OBJECT;
//
// /*
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |0 0| STUN Message Type | Message Length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Magic Cookie |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | |
// | Transaction ID (96 bits) |
// | |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// */
//
// tnet_stun_pkt_type_t type;
// uint16_t length;
// uint32_t cookie;
// tnet_stun_transac_id_t transaction_id;
//
// unsigned fingerprint:1;
// unsigned integrity:1;
// unsigned dontfrag:1;
// unsigned nointegrity:1;
//
// char* username;
// char* password;
// char* realm;
// char* nonce;
//
// tnet_stun_attributes_L_t *attributes; /**< List of all attributes associated to this message */
//}
//tnet_stun_pkt_t;
//
//typedef tnet_stun_pkt_t tnet_stun_pkt_resp_t;
//typedef tnet_stun_pkt_t tnet_stun_pkt_req_t;
//
//TINYNET_API tsk_buffer_t* tnet_stun_pkt_serialize(const tnet_stun_pkt_t *message);
//tnet_stun_pkt_t* tnet_stun_message_deserialize(const uint8_t *data, tsk_size_t size);
//tsk_bool_t tnet_stun_message_has_attribute(const tnet_stun_pkt_t *self, tnet_stun_attr_type_t type);
//TINYNET_API int tnet_stun_message_add_attribute(tnet_stun_pkt_t *self, tnet_stun_attr_t** attribute);
//int tnet_stun_message_remove_attribute(tnet_stun_pkt_t *self, tnet_stun_attr_type_t type);
//const tnet_stun_attr_t* tnet_stun_message_get_attribute(const tnet_stun_pkt_t *self, tnet_stun_attr_type_t type);
//short tnet_stun_message_get_errorcode(const tnet_stun_pkt_t *self);
//const char* tnet_stun_message_get_realm(const tnet_stun_pkt_t *self);
//const char* tnet_stun_message_get_nonce(const tnet_stun_pkt_t *self);
//int32_t tnet_stun_message_get_lifetime(const tnet_stun_pkt_t *self);
//tsk_bool_t tnet_stun_utils_transac_id_equals(const tnet_stun_transac_id_t id1, const tnet_stun_transac_id_t id2);
//
//
//TINYNET_API tnet_stun_pkt_t* tnet_stun_message_create(const char* username, const char* password);
//TINYNET_API tnet_stun_pkt_t* tnet_stun_message_create_null();
//
//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_message_def_t;
//
//
//TNET_END_DECLS
//
//
//#endif /* TNET_STUN_MESSAGE_H */
//

View File

@ -30,6 +30,10 @@
#include "tsk_memory.h"
#include "tsk_debug.h"
#if !defined(PRINT_DESTROYED_MSG)
# define PRINT_DESTROYED_MSG 0
#endif
int tnet_stun_pkt_create(tnet_stun_pkt_type_t e_type, uint16_t u_length, const tnet_stun_transac_id_t* pc_transac_id, tnet_stun_pkt_t** pp_attr)
{
extern const tsk_object_def_t *tnet_stun_pkt_def_t;
@ -169,6 +173,27 @@ bail:
return ret;
}
int tnet_stun_pkt_attr_remove(struct tnet_stun_pkt_s* p_self, enum tnet_stun_attr_type_e e_type)
{
tsk_list_item_t* pc_item;
tnet_stun_attr_t* pc_attr;
if (!p_self || !p_self->p_list_attrs) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
again:
tsk_list_foreach(pc_item, p_self->p_list_attrs) {
if ((pc_attr = (tnet_stun_attr_t*)pc_item->data)) {
if (pc_attr->hdr.e_type == e_type) {
tsk_list_remove_item(p_self->p_list_attrs, pc_item);
goto again;
}
}
}
return 0;
}
int tnet_stun_pkt_attr_find(const tnet_stun_pkt_t* pc_self, tnet_stun_attr_type_t e_type, tsk_size_t u_index, const tnet_stun_attr_t** ppc_attr)
{
const tsk_list_item_t* pc_item;
@ -381,6 +406,32 @@ int tnet_stun_pkt_write_with_padding(const tnet_stun_pkt_t* pc_self, uint8_t* p_
return 0;
}
int tnet_stun_pkt_write_with_padding_2(const struct tnet_stun_pkt_s* pc_self, struct tsk_buffer_s** pp_buff)
{
tsk_size_t u_buff_size;
int ret;
if (!pc_self || !pp_buff) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
*pp_buff = tsk_null;
if ((ret = tnet_stun_pkt_get_size_in_octetunits_with_padding(pc_self, &u_buff_size))) {
goto bail;
}
u_buff_size += kStunBuffMinPad;
if (!(*pp_buff = tsk_buffer_create(tsk_null, u_buff_size))) {
goto bail;
}
if ((ret = tnet_stun_pkt_write_with_padding(pc_self, (*pp_buff)->data, (*pp_buff)->size, &(*pp_buff)->size))) {
goto bail;
}
bail:
if (ret) {
TSK_OBJECT_SAFE_FREE(*pp_buff);
}
return ret;
}
int tnet_stun_pkt_is_complete(const uint8_t* pc_buff_ptr, tsk_size_t n_buff_size, tsk_bool_t *pb_is_complete)
{
if (!pb_is_complete) {
@ -408,7 +459,7 @@ int tnet_stun_pkt_read(const uint8_t* pc_buff_ptr, tsk_size_t n_buff_size, tnet
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if (!TNET_STUN_PKT_IS_STUN2(pc_buff_ptr, n_buff_size)) {
if (!TNET_STUN_BUFF_IS_STUN2(pc_buff_ptr, n_buff_size)) {
TSK_DEBUG_ERROR("Buffer doesn't contain a valid STUN2 pkt");
return -2;
}
@ -461,59 +512,65 @@ int tnet_stun_pkt_auth_prepare(tnet_stun_pkt_t* p_self, const char* pc_usr_name,
int ret;
static const tsk_sha1digest_t __pc_sha1digestEmpty = { 0 };
static const uint16_t __u_sha1digestEmpty = sizeof(__pc_sha1digestEmpty);
if (!p_self || !pc_usr_name || !pc_realm || !pc_nonce) {
if (!p_self /*|| !pc_usr_name*/ || !pc_pwd /*|| !pc_realm || !pc_nonce*/) { // "username", "realm" and "nonce" are null for short-term authentication
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
// USERNAME
if ((ret = tnet_stun_pkt_attr_find_first(p_self, tnet_stun_attr_type_username, &pc_attr))) {
goto bail;
}
if (pc_attr) {
if ((ret = tnet_stun_attr_vdata_update((tnet_stun_attr_vdata_t*)pc_attr, (const uint8_t*)pc_usr_name, tsk_strlen(pc_usr_name)))) {
goto bail;
}
}
else {
ret = tnet_stun_pkt_attrs_add(p_self,
TNET_STUN_PKT_ATTR_ADD_USERNAME_ZT(pc_usr_name),
TNET_STUN_PKT_ATTR_ADD_NULL());
if (ret) {
goto bail;
}
}
if (pc_usr_name) { // LONG-TERM, optional for SHORT-TERM
if ((ret = tnet_stun_pkt_attr_find_first(p_self, tnet_stun_attr_type_username, &pc_attr))) {
goto bail;
}
if (pc_attr) {
if ((ret = tnet_stun_attr_vdata_update((tnet_stun_attr_vdata_t*)pc_attr, (const uint8_t*)pc_usr_name, tsk_strlen(pc_usr_name)))) {
goto bail;
}
}
else {
ret = tnet_stun_pkt_attrs_add(p_self,
TNET_STUN_PKT_ATTR_ADD_USERNAME_ZT(pc_usr_name),
TNET_STUN_PKT_ATTR_ADD_NULL());
if (ret) {
goto bail;
}
}
}
// REALM
if ((ret = tnet_stun_pkt_attr_find_first(p_self, tnet_stun_attr_type_realm, &pc_attr))) {
goto bail;
}
if (pc_attr) {
if ((ret = tnet_stun_attr_vdata_update((tnet_stun_attr_vdata_t*)pc_attr, (const uint8_t*)pc_realm, tsk_strlen(pc_realm)))) {
if (pc_realm) { // LONG-TERM
if ((ret = tnet_stun_pkt_attr_find_first(p_self, tnet_stun_attr_type_realm, &pc_attr))) {
goto bail;
}
}
else {
ret = tnet_stun_pkt_attrs_add(p_self,
TNET_STUN_PKT_ATTR_ADD_REALM_ZT(pc_realm),
TNET_STUN_PKT_ATTR_ADD_NULL());
if (ret) {
goto bail;
if (pc_attr) {
if ((ret = tnet_stun_attr_vdata_update((tnet_stun_attr_vdata_t*)pc_attr, (const uint8_t*)pc_realm, tsk_strlen(pc_realm)))) {
goto bail;
}
}
else {
ret = tnet_stun_pkt_attrs_add(p_self,
TNET_STUN_PKT_ATTR_ADD_REALM_ZT(pc_realm),
TNET_STUN_PKT_ATTR_ADD_NULL());
if (ret) {
goto bail;
}
}
}
// NONCE
if ((ret = tnet_stun_pkt_attr_find_first(p_self, tnet_stun_attr_type_nonce, &pc_attr))) {
goto bail;
}
if (pc_attr) {
if ((ret = tnet_stun_attr_vdata_update((tnet_stun_attr_vdata_t*)pc_attr, (const uint8_t*)pc_nonce, tsk_strlen(pc_nonce)))) {
if (pc_nonce) { // LONG-TERM
if ((ret = tnet_stun_pkt_attr_find_first(p_self, tnet_stun_attr_type_nonce, &pc_attr))) {
goto bail;
}
}
else {
ret = tnet_stun_pkt_attrs_add(p_self,
TNET_STUN_PKT_ATTR_ADD_NONCE_ZT(pc_nonce),
TNET_STUN_PKT_ATTR_ADD_NULL());
if (ret) {
goto bail;
if (pc_attr) {
if ((ret = tnet_stun_attr_vdata_update((tnet_stun_attr_vdata_t*)pc_attr, (const uint8_t*)pc_nonce, tsk_strlen(pc_nonce)))) {
goto bail;
}
}
else {
ret = tnet_stun_pkt_attrs_add(p_self,
TNET_STUN_PKT_ATTR_ADD_NONCE_ZT(pc_nonce),
TNET_STUN_PKT_ATTR_ADD_NULL());
if (ret) {
goto bail;
}
}
}
// MESSAGE-INTEGRITY
@ -621,6 +678,50 @@ int tnet_stun_pkt_get_errorcode(const struct tnet_stun_pkt_s* pc_self, uint16_t*
return 0;
}
int tnet_stun_pkt_process_err420(struct tnet_stun_pkt_s *p_self, const struct tnet_stun_pkt_s *pc_pkt_resp420)
{
const tnet_stun_attr_vdata_t* pc_attr;
uint16_t u16;
int ret;
tsk_bool_t b_done = tsk_false;
if (!p_self || !pc_pkt_resp420) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if ((ret = tnet_stun_pkt_attr_find_first(pc_pkt_resp420, tnet_stun_attr_type_unknown_attrs, (const tnet_stun_attr_t**)&pc_attr))) {
goto bail;
}
if (!pc_attr || !pc_attr->p_data_ptr || (pc_attr->u_data_size & 1)) {
TSK_DEBUG_ERROR("UNKNOWN-ATTRIBUTES missing in 420");
ret = -3;
goto bail;
}
for (u16 = 0; u16 < pc_attr->u_data_size; u16+=2) {
switch (*((uint16_t*)&pc_attr->p_data_ptr[u16])) {
case tnet_stun_attr_type_dont_fragment: {
p_self->opt.dontfrag = 0;
b_done = tsk_true;
break;
}
case tnet_stun_attr_type_fingerprint: {
p_self->opt.fingerprint = 0;
b_done = tsk_true;
break;
}
}
}
if (b_done) {
// TRANSACTION-ID
if ((ret = tnet_stun_utils_transac_id_rand(&p_self->transac_id))) {
goto bail;
}
}
bail:
return ret;
}
static tsk_object_t* tnet_stun_pkt_ctor(tsk_object_t * self, va_list * app)
{
tnet_stun_pkt_t *p_pkt = (tnet_stun_pkt_t *)self;
@ -634,7 +735,9 @@ static tsk_object_t* tnet_stun_pkt_dtor(tsk_object_t * self)
{
tnet_stun_pkt_t *p_pkt = (tnet_stun_pkt_t *)self;
if (p_pkt) {
#if PRINT_DESTROYED_MSG
TSK_DEBUG_INFO("*** STUN pkt destroyed ***");
#endif
TSK_OBJECT_SAFE_FREE(p_pkt->p_list_attrs);
TSK_FREE(p_pkt->p_pwd);
}

View File

@ -24,6 +24,7 @@
#include "tsk_object.h"
#include "tsk_list.h"
#include "tsk_buffer.h"
TNET_BEGIN_DECLS
@ -45,7 +46,7 @@ TNET_BEGIN_DECLS
* Checks whether the STUN message is an error response or not.
*/
#define TNET_STUN_PKT_IS_REQ(p_self) ((p_self) && (((p_self)->e_type & 0x0110) == tnet_stun_mask_request))
#define TNET_STUN_PKT_IS_RESP(p_self) (TNET_STUN_PKT_RESP_IS_SUCCESS((p_self)) || TNET_STUN_PKT_RESP_IS_ERROR((self)))
#define TNET_STUN_PKT_IS_RESP(p_self) (TNET_STUN_PKT_RESP_IS_SUCCESS((p_self)) || TNET_STUN_PKT_RESP_IS_ERROR((p_self)))
#define TNET_STUN_PKT_IS_INDICATION(p_self) ((p_self) && (((p_self)->e_type & 0x0110) == tnet_stun_mask_indication))
#define TNET_STUN_PKT_RESP_IS_SUCCESS(p_self) ((p_self) && (((p_self)->e_type & 0x0110) == tnet_stun_mask_success))
#define TNET_STUN_PKT_RESP_IS_ERROR(p_self) ((p_self) && (((p_self)->e_type & 0x0110) == tnet_stun_mask_error))
@ -63,7 +64,7 @@ tnet_stun_pkt_attr_add_t;
#define TNET_STUN_PKT_ATTR_ADD_NULL() tnet_stun_pkt_attr_add_null
#define TNET_STUN_PKT_ATTR_ADD_VDATA(E_TYPE, P_DATA_PTR, U_DATA_SIZE) tnet_stun_pkt_attr_add_vdata, (enum tnet_stun_attr_type_e)(E_TYPE), (const uint8_t*)(P_DATA_PTR), (uint16_t)(U_DATA_SIZE)
#define TNET_STUN_PKT_ATTR_ADD_UINT0(E_TYPE) TNET_STUN_PKT_ATTR_ADD_VDATA(E_TYPE, 0, 0)
#define TNET_STUN_PKT_ATTR_ADD_UINT0(E_TYPE) TNET_STUN_PKT_ATTR_ADD_VDATA(E_TYPE, tsk_null, 0)
#define TNET_STUN_PKT_ATTR_ADD_UINT8(E_TYPE, U8) TNET_STUN_PKT_ATTR_ADD_VDATA(E_TYPE, &U8, 1)
#define TNET_STUN_PKT_ATTR_ADD_UINT16(E_TYPE, U16) TNET_STUN_PKT_ATTR_ADD_VDATA(E_TYPE, &U16, 2)
#define TNET_STUN_PKT_ATTR_ADD_UINT32(E_TYPE, U32) TNET_STUN_PKT_ATTR_ADD_VDATA(E_TYPE, &U32, 4)
@ -128,7 +129,14 @@ tnet_stun_pkt_attr_add_t;
// rfc5766(TURN) - 14.8. DONT-FRAGMENT
#define TNET_STUN_PKT_ATTR_ADD_DONT_FRAGMENT() TNET_STUN_PKT_ATTR_ADD_UINT0(tnet_stun_attr_type_dont_fragment)
// rfc5245(ICE) - 19.1. New Attributes (PRIORITY)
#define TNET_STUN_PKT_ATTR_ADD_ICE_PRIORITY(U32_PRIORITY) TNET_STUN_PKT_ATTR_ADD_UINT32(tnet_stun_attr_type_ice_priority, U32_PRIORITY)
// rfc5245(ICE) - 19.1. New Attributes (USE-CANDIDATE)
#define TNET_STUN_PKT_ATTR_ADD_ICE_USE_CANDIDATE() TNET_STUN_PKT_ATTR_ADD_UINT0(tnet_stun_attr_type_ice_use_candidate)
// rfc5245(ICE) - 19.1. New Attributes (ICE-CONTROLLED)
#define TNET_STUN_PKT_ATTR_ADD_ICE_CONTROLLED(U64_CONTROLLED) TNET_STUN_PKT_ATTR_ADD_UINT64(tnet_stun_attr_type_ice_controlled, U64_CONTROLLED)
// rfc5245(ICE) - 19.1. New Attributes (ICE-CONTROLLED)
#define TNET_STUN_PKT_ATTR_ADD_ICE_CONTROLLING(U64_CONTROLLING) TNET_STUN_PKT_ATTR_ADD_UINT64(tnet_stun_attr_type_ice_controlling, U64_CONTROLLING)
typedef struct tnet_stun_pkt_s {
TSK_DECLARE_OBJECT;
@ -152,18 +160,24 @@ TINYNET_API int tnet_stun_pkt_create(enum tnet_stun_pkt_type_e e_type, uint16_t
#define tnet_stun_pkt_create_empty(e_type, pp_attr) tnet_stun_pkt_create((e_type), 0, tsk_null, (pp_attr))
TINYNET_API int tnet_stun_pkt_attr_add(struct tnet_stun_pkt_s* p_self, struct tnet_stun_attr_s** pp_attr);
TINYNET_API int tnet_stun_pkt_attrs_add(struct tnet_stun_pkt_s* p_self, ...);
TINYNET_API int tnet_stun_pkt_attr_remove(struct tnet_stun_pkt_s* p_self, enum tnet_stun_attr_type_e e_type);
TINYNET_API int tnet_stun_pkt_attr_find(const struct tnet_stun_pkt_s* pc_self, enum tnet_stun_attr_type_e e_type, tsk_size_t u_index, const struct tnet_stun_attr_s** ppc_attr);
#define tnet_stun_pkt_attr_find_first(pc_self, e_type, ppc_attr) tnet_stun_pkt_attr_find((pc_self), (e_type), 0, (ppc_attr))
TINYNET_API tsk_bool_t tnet_stun_pkt_attr_exists(const struct tnet_stun_pkt_s* pc_self, enum tnet_stun_attr_type_e e_type);
TINYNET_API int tnet_stun_pkt_get_size_in_octetunits_without_padding(const struct tnet_stun_pkt_s* pc_self, tsk_size_t* p_size);
TINYNET_API int tnet_stun_pkt_get_size_in_octetunits_with_padding(const struct tnet_stun_pkt_s* pc_self, tsk_size_t* p_size);
TINYNET_API int tnet_stun_pkt_write_with_padding(const struct tnet_stun_pkt_s* pc_self, uint8_t* p_buff_ptr, tsk_size_t n_buff_size, tsk_size_t *p_written);
TINYNET_API int tnet_stun_pkt_write_with_padding_2(const struct tnet_stun_pkt_s* pc_self, struct tsk_buffer_s** pp_buff);
TINYNET_API int tnet_stun_pkt_is_complete(const uint8_t* pc_buff_ptr, tsk_size_t n_buff_size, tsk_bool_t *pb_is_complete);
TINYNET_API int tnet_stun_pkt_read(const uint8_t* pc_buff_ptr, tsk_size_t n_buff_size, struct tnet_stun_pkt_s** pp_pkt);
TINYNET_API int tnet_stun_pkt_auth_prepare(struct tnet_stun_pkt_s* p_self, const char* pc_usr_name, const char* pc_pwd, const char* pc_realm, const char* pc_nonce);
#define tnet_stun_pkt_auth_prepare_longterm(p_self, pc_usr_name, pc_pwd, pc_realm, pc_nonce) tnet_stun_pkt_auth_prepare((p_self), (pc_usr_name), (pc_pwd), (pc_realm), (pc_nonce))
#define tnet_stun_pkt_auth_prepare_shortterm(p_self, pc_usr_name, pc_pwd) tnet_stun_pkt_auth_prepare((p_self), (pc_usr_name), (pc_pwd), tsk_null, tsk_null)
#define tnet_stun_pkt_auth_prepare_shortterm_2(p_self, pc_pwd) tnet_stun_pkt_auth_prepare_shortterm((p_self), tsk_null, (pc_pwd))
TINYNET_API int tnet_stun_pkt_auth_prepare_2(struct tnet_stun_pkt_s* p_self, const char* pc_usr_name, const char* pc_pwd, const struct tnet_stun_pkt_s* pc_resp);
TINYNET_API int tnet_stun_pkt_auth_copy(struct tnet_stun_pkt_s* p_self, const char* pc_usr_name, const char* pc_pwd, const struct tnet_stun_pkt_s* pc_pkt);
TINYNET_API int tnet_stun_pkt_get_errorcode(const struct tnet_stun_pkt_s* pc_self, uint16_t* pu_code);
TINYNET_API int tnet_stun_pkt_process_err420(struct tnet_stun_pkt_s *p_self, const struct tnet_stun_pkt_s *pc_pkt_resp420);
TNET_END_DECLS

View File

@ -24,6 +24,8 @@
TNET_BEGIN_DECLS
typedef uint8_t tnet_stun_addr_t[16]; // IPv4(32bits) or IPv6(128bits)
typedef uint64_t tnet_stun_binding_id_t;
typedef long tnet_turn_peer_id_t;
/**@ingroup tnet_stun_group
* Checks if the pointer to the buffer hold a STUN header by checking that it starts with 0b00 and contain the magic cookie.
@ -34,7 +36,7 @@ typedef uint8_t tnet_stun_addr_t[16]; // IPv4(32bits) or IPv6(128bits)
*
* @param PU8 The pointer to the buffer holding the STUN raw data.
**/
#define TNET_STUN_PKT_IS_STUN2(PU8, SIZE) \
#define TNET_STUN_BUFF_IS_STUN2(PU8, SIZE) \
( \
((PU8)) && \
((SIZE) >= kStunPktHdrSizeInOctets) && \
@ -43,7 +45,7 @@ typedef uint8_t tnet_stun_addr_t[16]; // IPv4(32bits) or IPv6(128bits)
)
// rfc5766 - 11. Channels
#define TNET_STUN_PKT_IS_CHANNEL_DATA(PU8, SIZE) \
#define TNET_STUN_BUFF_IS_CHANNEL_DATA(PU8, SIZE) \
( \
((PU8)) && \
((SIZE) >= kStunChannelDataHdrSizeInOctets) && \
@ -58,6 +60,15 @@ typedef uint8_t tnet_stun_addr_t[16]; // IPv4(32bits) or IPv6(128bits)
#define kStunErrCodeStaleNonce 438
#define kStunErrCodeIceConflict 487
// Estimate of the round-trip time (RTT) in millisecond.
#define kStunRTO 500
// Number of retransmission for UDP retransmission in millisecond.
// 7.2.1. Sending over UDP
// Rc SHOULD be configurable and SHOULD have a default of 7.
#define kStunRC /*7*/4/* 7 is too hight */
#define kStunBindingInvalidId 0
#if !defined(kStunBuffMinPad)
# define kStunBuffMinPad 40 // to make the buffer kasher
@ -324,6 +335,14 @@ tnet_stun_pkt_type_t;
# define kStunChannelDataHdrSizeInOctets 4
#endif /* kStunChannelDataHdrSizeInOctets */
// Not part of the standard
typedef enum tnet_stun_state_e {
tnet_stun_state_none,
tnet_stun_state_trying,
tnet_stun_state_ok,
tnet_stun_state_nok
} tnet_stun_state_t;
TNET_END_DECLS
#endif /* TNET_STUN_TYPES_H */

View File

@ -17,9 +17,12 @@
*
*/
#include "stun/tnet_stun_utils.h"
#include "stun/tnet_stun_pkt.h"
#include "stun/tnet_stun_attr.h"
#include "tnet_utils.h"
#include "tsk_memory.h"
#include "tsk_debug.h"
int tnet_stun_utils_inet_pton(tsk_bool_t b_v6, const char* p_src, tnet_stun_addr_t* p_dst)
@ -83,4 +86,116 @@ int tnet_stun_utils_buff_cmp(const uint8_t* pc_buf1_ptr, tsk_size_t n_buff1_size
}
}
return 0;
}
}
int tnet_stun_utils_send_unreliably(tnet_fd_t localFD, uint16_t RTO, uint16_t Rc, const struct tnet_stun_pkt_s* pc_stun_req, struct sockaddr* p_addr_server, struct tnet_stun_pkt_s** pp_stun_resp)
{
int ret = -1;
uint16_t i, rto = RTO;
struct timeval tv;
fd_set set;
void* p_buff_ptr = tsk_null;
tsk_size_t u_buff_size;
if (!pc_stun_req || !p_addr_server || !pp_stun_resp) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
/* RFC 5389 - 7.2.1. Sending over UDP
STUN indications are not retransmitted; thus, indication transactions over UDP
are not reliable.
*/
*pp_stun_resp = tsk_null;
tv.tv_sec = 0;
tv.tv_usec = 0;
if ((ret = tnet_stun_pkt_get_size_in_octetunits_with_padding(pc_stun_req, &u_buff_size))) {
goto bail;
}
u_buff_size += kStunBuffMinPad;
if (!(p_buff_ptr = tsk_malloc(u_buff_size))) {
goto bail;
}
if ((ret = tnet_stun_pkt_write_with_padding(pc_stun_req, p_buff_ptr, u_buff_size, &u_buff_size))) {
goto bail;
}
/* RFC 5389 - 7.2.1. Sending over UDP
A client SHOULD retransmit a STUN request message starting with an
interval of RTO ("Retransmission TimeOut"), doubling after each
retransmission.
e.g. 0 ms, 500 ms, 1500 ms, 3500 ms, 7500ms, 15500 ms, and 31500 ms
*/
for (i = 0; i < Rc; i++) {
tv.tv_sec += rto/1000;
tv.tv_usec += (rto% 1000) * 1000;
if (tv.tv_usec >= 1000000) {
tv.tv_usec -= 1000000;
tv.tv_sec++;
}
FD_ZERO(&set);
FD_SET(localFD, &set);
if ((ret = tnet_sockfd_sendto(localFD, p_addr_server, p_buff_ptr, u_buff_size))) {
// do nothing... not an error
}
if ((ret = select(localFD+1, &set, NULL, NULL, &tv)) < 0) {
goto bail;
}
else if (ret == 0) {
/* timeout */
TSK_DEBUG_INFO("STUN request timedout at %d", i);
rto *= 2;
continue;
}
else if (FD_ISSET(localFD, &set)) {
/* there is data to read */
tsk_size_t len = 0;
void* data = 0;
TSK_DEBUG_INFO("STUN request got response");
/* Check how how many bytes are pending */
if ((ret = tnet_ioctlt(localFD, FIONREAD, &len)) < 0) {
goto bail;
}
if(len == 0) {
TSK_DEBUG_INFO("tnet_ioctlt() returent zero bytes");
continue;
}
/* Receive pending data */
data = tsk_malloc(len);
if ((ret = tnet_sockfd_recvfrom(localFD, data, len, 0, p_addr_server)) < 0) {
TSK_FREE(data);
TSK_DEBUG_ERROR("Recv STUN dgrams failed with error code:%d", tnet_geterrno());
goto bail;
}
/* Parse the incoming response. */
ret = tnet_stun_pkt_read(data, (tsk_size_t)ret, pp_stun_resp);
TSK_FREE(data);
if (*pp_stun_resp) {
if (tnet_stun_utils_transac_id_cmp((*pp_stun_resp)->transac_id, pc_stun_req->transac_id) != 0) {
/* Not same transaction id */
TSK_OBJECT_SAFE_FREE(*pp_stun_resp);
continue;
}
}
goto bail;
}
else {
continue;
}
}
bail:
TSK_FREE(p_buff_ptr);
return (*pp_stun_resp) ? 0 : -4;
}

View File

@ -24,6 +24,8 @@
#include "tnet_types.h"
struct tnet_stun_pkt_s;
TNET_BEGIN_DECLS
TINYNET_API int tnet_stun_utils_inet_pton(tsk_bool_t b_v6, const char* p_src, tnet_stun_addr_t* p_dst);
@ -35,7 +37,8 @@ TINYNET_API int tnet_stun_utils_inet_ntop(tsk_bool_t b_v6, const tnet_stun_addr_
TINYNET_API int tnet_stun_utils_transac_id_rand(tnet_stun_transac_id_t* p_transac_id);
TINYNET_API int tnet_stun_utils_buff_cmp(const uint8_t* pc_buf1_ptr, tsk_size_t n_buff1_size, const uint8_t* pc_buf2_ptr, tsk_size_t n_buff2_size);
#define tnet_stun_utils_transac_id_cmp(pc_tid1, pc_tid2) tnet_stun_utils_buff_cmp((pc_tid1), sizeof(tnet_stun_transac_id_t), (pc_tid2), sizeof(tnet_stun_transac_id_t))
#define tnet_stun_utils_transac_id_equals(pc_tid1, pc_tid2) (tnet_stun_utils_transac_id_cmp((pc_tid1), (pc_tid2)) == 0)
int tnet_stun_utils_send_unreliably(tnet_fd_t localFD, uint16_t RTO, uint16_t Rc, const struct tnet_stun_pkt_s* pc_stun_req, struct sockaddr* p_addr_server, struct tnet_stun_pkt_s** pp_stun_resp);
TNET_END_DECLS

View File

@ -110,7 +110,7 @@
#endif
/* Used in TURN/STUN2 attributes. */
#define TNET_SOFTWARE "IM-client/OMA1.0 doubango/v0.0.0"
#define TNET_SOFTWARE "IM-client/OMA1.0 doubango/v2.0.0"
#define TNET_IANA_PEN 35368 /**< PEN number assigned by the IANA.
The list of assigned numbers could be found here http://www.iana.org/assignments/enterprise-numbers. */
#define TNET_RESOLV_CONF_PATH "/etc/resolv.conf" /**< Path to "/resolv.conf". */

View File

@ -41,8 +41,15 @@ typedef struct tnet_dtls_socket_s
tsk_bool_t use_srtp;
tsk_bool_t handshake_completed;
tsk_bool_t handshake_started;
tsk_bool_t handshake_storedata; // whether to store handshaking data or to send it to the remote party
tnet_dtls_setup_t setup;
struct {
void* ptr;
tsk_size_t size;
tsk_size_t count;
} handshake_data;
struct{
const void* usrdata;
tnet_dtls_socket_cb_f func;
@ -108,10 +115,13 @@ static int _tnet_dtls_verify_cert(int preverify_ok, X509_STORE_CTX *ctx)
TSK_DEBUG_ERROR("Not expected");
return 0;
}
if(_tnet_dtls_is_fingerprint_matching(ctx->cert, &socket->remote.fp, socket->remote.hash) == tsk_false){
tsk_safeobj_lock(socket);
if (_tnet_dtls_is_fingerprint_matching(ctx->cert, &socket->remote.fp, socket->remote.hash) == tsk_false) {
TSK_DEBUG_ERROR("Failed to match fingerprint");
tsk_safeobj_unlock(socket);
return 0;
}
tsk_safeobj_unlock(socket);
return 1;
}
@ -323,6 +333,10 @@ tnet_dtls_socket_handle_t* tnet_dtls_socket_create(tnet_fd_t fd, struct ssl_ctx_
socket->verify_peer = tsk_true;
SSL_set_verify(socket->ssl, (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT), _tnet_dtls_verify_cert);
}
else {
// FIXME:
TSK_DEBUG_ERROR("????");
}
SSL_set_app_data(socket->ssl, socket);
}
@ -425,6 +439,27 @@ int tnet_dtls_socket_set_setup(tnet_dtls_socket_handle_t* handle, tnet_dtls_setu
#endif
}
int tnet_dtls_socket_set_store_handshakingdata(tnet_dtls_socket_handle_t* handle, tsk_bool_t handshake_storedata)
{
if (!handle) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
((tnet_dtls_socket_t*)handle)->handshake_storedata = handshake_storedata;
return 0;
}
int tnet_dtls_socket_get_handshakingdata(tnet_dtls_socket_handle_t* handle, const void** data, tsk_size_t *size)
{
if (!handle || !data || !size) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
*data = ((tnet_dtls_socket_t*)handle)->handshake_data.ptr;
*size = ((tnet_dtls_socket_t*)handle)->handshake_data.count;
return 0;
}
tsk_bool_t tnet_dtls_socket_is_remote_cert_fp_match(tnet_dtls_socket_handle_t* handle)
{
#if !HAVE_OPENSSL || !HAVE_OPENSSL_DTLS
@ -443,27 +478,30 @@ int tnet_dtls_socket_do_handshake(tnet_dtls_socket_handle_t* handle, const struc
#else
tnet_dtls_socket_t *socket = handle;
int ret, len;
int ret = 0, len;
void* out_data;
if(!socket){
if (!socket) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
tsk_safeobj_lock(socket);
// update remote address even if handshaking is completed
if(remote_addr){
if (remote_addr) {
socket->remote.addr = *remote_addr;
}
if(socket->handshake_completed){
if (socket->handshake_completed) {
TSK_DEBUG_INFO("Handshake completed");
return 0;
ret = 0;
goto bail;
}
if (!socket->handshake_started) {
if((ret = SSL_do_handshake(socket->ssl)) != 1){
switch((ret = SSL_get_error(socket->ssl, ret))){
if ((ret = SSL_do_handshake(socket->ssl)) != 1) {
switch ((ret = SSL_get_error(socket->ssl, ret))) {
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
case SSL_ERROR_NONE:
@ -471,43 +509,41 @@ int tnet_dtls_socket_do_handshake(tnet_dtls_socket_handle_t* handle, const struc
default:
TSK_DEBUG_ERROR("DTLS handshake failed [%s]", ERR_error_string(ERR_get_error(), tsk_null));
_tnet_dtls_socket_raise_event_dataless(socket, tnet_dtls_socket_event_type_handshake_failed);
return -2;
ret = -2;
goto bail;
}
}
socket->handshake_started = (ret == SSL_ERROR_NONE); // TODO: reset for renegotiation
}
#if 0
len = BIO_ctrl_pending(socket->wbio);
if (len > 0) {
tnet_port_t port;
tnet_ip_t ip;
out_data = malloc(len);
len = BIO_read(socket->wbio, out_data, len);
tnet_get_sockip_n_port((const struct sockaddr *)&socket->remote.addr, &ip, &port);
TSK_DEBUG_INFO("DTLS data handshake to send with len = %d, ip = %.*s and port = %d", len, sizeof(ip), ip, port);
len = tnet_sockfd_sendto(socket->fd, (const struct sockaddr *)&socket->remote.addr, out_data, len);
TSK_DEBUG_INFO("DTLS data handshake sent len = %d", len);
free(out_data);
if ((len = BIO_get_mem_data(socket->wbio, &out_data)) > 0 && out_data) {
if (socket->handshake_storedata) {
if ((int)socket->handshake_data.size < len) {
if (!(socket->handshake_data.ptr = tsk_realloc(socket->handshake_data.ptr, len))) {
socket->handshake_data.size = 0;
socket->handshake_data.count = 0;
ret = -5;
goto bail;
}
socket->handshake_data.size = len;
}
socket->handshake_data.count = len;
memcpy(socket->handshake_data.ptr, out_data, len);
}
else {
tnet_port_t port;
tnet_ip_t ip;
tnet_get_sockip_n_port((const struct sockaddr *)&socket->remote.addr, &ip, &port);
TSK_DEBUG_INFO("DTLS data handshake to send with len = %d, ip = %.*s and port = %d", len, sizeof(ip), ip, port);
len = tnet_sockfd_sendto(socket->fd, (const struct sockaddr *)&socket->remote.addr, out_data, len);
TSK_DEBUG_INFO("DTLS data handshake sent len = %d", len);
}
}
#else
if((len = BIO_get_mem_data(socket->wbio, &out_data)) && out_data){
tnet_port_t port;
tnet_ip_t ip;
tnet_get_sockip_n_port((const struct sockaddr *)&socket->remote.addr, &ip, &port);
TSK_DEBUG_INFO("DTLS data handshake to send with len = %d, ip = %.*s and port = %d", len, sizeof(ip), ip, port);
len = tnet_sockfd_sendto(socket->fd, (const struct sockaddr *)&socket->remote.addr, out_data, len);
TSK_DEBUG_INFO("DTLS data handshake sent len = %d", len);
}
#endif
BIO_reset(socket->rbio);
BIO_reset(socket->wbio);
if((socket->handshake_completed = SSL_is_init_finished(socket->ssl))){
if ((socket->handshake_completed = SSL_is_init_finished(socket->ssl))) {
TSK_DEBUG_INFO("DTLS handshake completed");
#if HAVE_OPENSSL_DTLS_SRTP
@ -525,9 +561,10 @@ int tnet_dtls_socket_do_handshake(tnet_dtls_socket_handle_t* handle, const struc
static const tsk_size_t keying_material_size = sizeof(keying_material);
/*if(socket->use_srtp)*/{
SRTP_PROTECTION_PROFILE *p = SSL_get_selected_srtp_profile(socket->ssl);
if(!p){
if (!p) {
TSK_DEBUG_ERROR("SSL_get_selected_srtp_profile() returned null [%s]", ERR_error_string(ERR_get_error(), tsk_null));
return -2;
ret = -2;
goto bail;
}
// alert user
_tnet_dtls_socket_raise_event(socket, tnet_dtls_socket_event_type_dtls_srtp_profile_selected, p->name, tsk_strlen(p->name));
@ -536,11 +573,12 @@ int tnet_dtls_socket_do_handshake(tnet_dtls_socket_handle_t* handle, const struc
// rfc5764 - 4.2. Key Derivation
ret = SSL_export_keying_material(socket->ssl, keying_material, sizeof(keying_material), EXTRACTOR_dtls_srtp_text, EXTRACTOR_dtls_srtp_text_len, tsk_null, 0, 0);
if(ret != 1){
if (ret != 1) {
// alert listener
_tnet_dtls_socket_raise_event_dataless(socket, tnet_dtls_socket_event_type_error);
TSK_DEBUG_ERROR("SSL_export_keying_material() failed [%s]", ERR_error_string(ERR_get_error(), tsk_null));
return -2;
ret = -2;
goto bail;
}
}
// alert listener
@ -549,8 +587,10 @@ int tnet_dtls_socket_do_handshake(tnet_dtls_socket_handle_t* handle, const struc
#endif /* HAVE_OPENSSL_DTLS_SRTP */
_tnet_dtls_socket_raise_event_dataless(socket, tnet_dtls_socket_event_type_handshake_succeed);
}
return 0;
ret = 0; // clear "ret", error will directly jump to "bail:"
bail:
tsk_safeobj_unlock(socket);
return ret;
#endif
}
@ -573,24 +613,35 @@ int tnet_dtls_socket_handle_incoming_data(tnet_dtls_socket_handle_t* handle, con
return -200;
#else
tnet_dtls_socket_t *socket = handle;
int ret;
int ret = 0;
if(!socket || !data || !size){
if (!socket || !data || !size) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
tsk_safeobj_lock(socket);
TSK_DEBUG_INFO("Receive DTLS data: %u", size);
// BIO_reset(socket->rbio);
// BIO_reset(socket->wbio);
ret = _tnet_dtls_socket_do_handshake(socket);
if (!socket->rbio || !socket->wbio) {
TSK_DEBUG_ERROR("BIO not initialized yet");
ret = -2;
goto bail;
}
if ((ret = _tnet_dtls_socket_do_handshake(socket))) {
goto bail;
}
if((ret = BIO_write(socket->rbio, data, size)) != size){
if ((ret = BIO_write(socket->rbio, data, size)) != size) {
ret = SSL_get_error(socket->ssl, ret);
TSK_DEBUG_ERROR("BIO_write(rbio, %u) failed [%s]", size, ERR_error_string(ERR_get_error(), tsk_null));
return -1;
ret = -1;
goto bail;
}
/*if((ret = SSL_read(socket->ssl, (void*)data, size)) <= 0){
@ -626,7 +677,11 @@ int tnet_dtls_socket_handle_incoming_data(tnet_dtls_socket_handle_t* handle, con
}
}*/
return _tnet_dtls_socket_do_handshake(socket);
ret = _tnet_dtls_socket_do_handshake(socket);
bail:
tsk_safeobj_unlock(socket);
return ret;
#endif
}
@ -648,19 +703,22 @@ static tsk_object_t* tnet_dtls_socket_dtor(tsk_object_t * self)
tnet_dtls_socket_t *socket = self;
if(socket){
#if HAVE_OPENSSL
if(socket->rbio){
if (socket->rbio) {
//BIO_free(socket->rbio);
//socket->rbio = tsk_null;
socket->rbio = tsk_null;
}
if(socket->wbio){
if (socket->wbio) {
//BIO_free(socket->wbio);
//socket->wbio = tsk_null;
socket->wbio = tsk_null;
}
if(socket->ssl){
if (socket->ssl) {
SSL_shutdown(socket->ssl);
// https://www.openssl.org/docs/crypto/BIO_s_bio.html
// implicitly frees internal_bio
SSL_free(socket->ssl);
}
#endif
TSK_FREE(socket->handshake_data.ptr);
tsk_safeobj_deinit(socket);
}
return self;

View File

@ -57,6 +57,8 @@ TINYNET_API tnet_fd_t tnet_dtls_socket_get_fd(const tnet_dtls_socket_handle_t* h
TINYNET_API const struct sockaddr_storage* tnet_dtls_socket_get_remote_addr(const tnet_dtls_socket_handle_t* handle);
TINYNET_API int tnet_dtls_socket_set_callback(tnet_dtls_socket_handle_t* handle, const void* usrdata, tnet_dtls_socket_cb_f func);
TINYNET_API int tnet_dtls_socket_set_remote_fingerprint(tnet_dtls_socket_handle_t* handle, const tnet_fingerprint_t* fingerprint, tnet_dtls_hash_type_t hash);
TINYNET_API int tnet_dtls_socket_set_store_handshakingdata(tnet_dtls_socket_handle_t* handle, tsk_bool_t handshake_storedata);
TINYNET_API int tnet_dtls_socket_get_handshakingdata(tnet_dtls_socket_handle_t* handle, const void** data, tsk_size_t *size);
TINYNET_API int tnet_dtls_socket_use_srtp(tnet_dtls_socket_handle_t* handle);
TINYNET_API int tnet_dtls_socket_set_setup(tnet_dtls_socket_handle_t* handle, tnet_dtls_setup_t setup);
TINYNET_API tsk_bool_t tnet_dtls_socket_is_remote_cert_fp_match(tnet_dtls_socket_handle_t* handle);

View File

@ -1,8 +1,6 @@
/*
* Copyright (C) 2010-2011 Mamadou Diop.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
@ -23,13 +21,16 @@
/**@file tnet_nat.c
* @brief NAT Traversal helper functions using STUN, TURN and ICE.
*
* @author Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
*/
#include "tnet_nat.h"
#include "stun/tnet_stun_types.h"
#include "stun/tnet_stun_utils.h"
#include "stun/tnet_stun_pkt.h"
#include "stun/tnet_stun_attr.h"
#include "stun/tnet_stun_binding.h"
#include "tnet_endianness.h"
#include "tnet_socket.h"
#include "tsk_string.h"
#include "tsk_memory.h"
@ -39,35 +40,56 @@
/**@defgroup tnet_nat_group NAT Traversal API (STUN, TURN and ICE).
*/
typedef struct tnet_nat_ctx_s
{
TSK_DECLARE_OBJECT;
tnet_socket_type_t socket_type;
char* username; /**< The username to use to authenticate against the TURN/STUN server. */
char* password; /**< The password to use to authenticate against the TURN/STUN server. */
char* server_address; /**< TURN/STUN server address (could be FQDN or IP) */
tnet_port_t server_port; /**< TURN/STUN server port. */
uint16_t RTO; /**< Estimate of the round-trip time (RTT) in millisecond. */
uint16_t Rc; /**< Number of retransmissions for UDP in millisecond. */
unsigned use_dnsquery:1; /**< Indicates whether to use DNS SRV query to find the stun/turn ip address. */
tnet_stun_bindings_L_t *stun_bindings; /**< List of all STUN2 bindings associated to this context. */
}
tnet_nat_ctx_t;
/**@ingroup tnet_nat_group
* Creates new NAT context.
*/
tnet_nat_context_handle_t* tnet_nat_context_create(tnet_socket_type_t socket_type, const char* username, const char* password)
struct tnet_nat_ctx_s* tnet_nat_context_create(tnet_socket_type_t socket_type, const char* pc_username, const char* pc_password)
{
return tsk_object_new(tnet_nat_context_def_t, socket_type, username, password);
}
extern const tsk_object_def_t *tnet_nat_context_def_t;
struct tnet_nat_ctx_s* p_ctx;
/**
* Predicate function to find turn allocation by id.
*
* @param [in,out] item The current list item.
* @param [in,out] id A pointer to the allocation identifier.
*
* @return Zero if current list item hold an allocation with the same id and -1 otherwise.
**/
int __pred_find_turn_allocation(const tsk_list_item_t* item, const void* id)
{
if(item)
{
tnet_turn_allocation_t *allocation = item->data;
if(allocation)
{
tnet_turn_allocation_id_t alloc_id = *((tnet_turn_allocation_id_t*)id);
return (allocation->id == alloc_id) ? 0 : -1;
}
if (!(p_ctx = tsk_object_new(tnet_nat_context_def_t)) || !(p_ctx->stun_bindings = tsk_list_create())) {
TSK_OBJECT_SAFE_FREE(p_ctx);
TSK_DEBUG_ERROR("Failed to create NAT context");
return tsk_null;
}
return -1;
p_ctx->socket_type = socket_type;
p_ctx->username = tsk_strdup(pc_username);
p_ctx->password = tsk_strdup(pc_password);
p_ctx->server_port = kStunPortDefaultTcpUdp;
/* 7.2.1. Sending over UDP
In fixed-line access links, a value of 500 ms is RECOMMENDED.
*/
p_ctx->RTO = kStunRTO;
/* 7.2.1. Sending over UDP
Rc SHOULD be configurable and SHOULD have a default of 7.
*/
p_ctx->Rc = kStunRC;
return p_ctx;
}
/** Predicate function to find stun binding by id.
@ -79,122 +101,54 @@ int __pred_find_turn_allocation(const tsk_list_item_t* item, const void* id)
**/
int __pred_find_stun_binding(const tsk_list_item_t* item, const void* id)
{
if(item)
{
tnet_stun_binding_t *binding = item->data;
if(binding)
{
if(item) {
tnet_stun_binding_t *p_bind = item->data;
if (p_bind) {
tnet_stun_binding_id_t binding_id = *((tnet_stun_binding_id_t*)id);
return (binding->id == binding_id) ? 0 : -1;
return (p_bind->id == binding_id) ? 0 : -1;
}
}
return -1;
}
/** Predicate function to find TURN channel binding by id.
*
* @param [in,out] item The current list item.
* @param [in,out] id A pointer to the TURN channel binding identifier.
*
* @return Zero if current list item hold a TURN channel binding with the same id and -1 otherwise.
**/
int __pred_find_turn_channel_binding(const tsk_list_item_t* item, const void* id)
{
if(item)
{
tnet_turn_channel_binding_t *binding = item->data;
if(binding)
{
tnet_turn_channel_binding_id_t binding_id = *((tnet_turn_channel_binding_id_t*)id);
return (binding->id == binding_id) ? 0 : -1;
}
}
return -1;
}
/**
* Formats binary IP address as string.
*
* @param in_ip The binary IP address to format (in Host byte order).
* @param family The address family.
* @param [in,out] out_ip The output string
*
* @return Zero if current list item hold a binding with the same id and -1 otherwise.
**/
int tnet_stun_address_tostring(const uint8_t in_ip[16], tnet_stun_addr_family_t family, char** out_ip)
{
/*if(family == stun_ipv6){
tsk_sprintf(out_ip, "%x:%x:%x:%x:%x:%x:%x:%x",
tnet_ntohs_2(&in_ip[0]), tnet_ntohs_2(&in_ip[2]), tnet_ntohs_2(&in_ip[4]), tnet_ntohs_2(&in_ip[6]),
tnet_ntohs_2(&in_ip[8]), tnet_ntohs_2(&in_ip[10]), tnet_ntohs_2(&in_ip[12]), tnet_ntohs_2(&in_ip[14]));
}
else if(family == stun_ipv4){
tsk_sprintf(out_ip, "%u.%u.%u.%u", (address>>24)&0xFF, (address>>16)&0xFF, (address>>8)&0xFF, (address>>0)&0xFF);
return 0;
}
else{
TSK_DEBUG_ERROR("Unsupported address family: %u.", family);
}*/
if(family == stun_ipv6){
tsk_sprintf(out_ip, "%x:%x:%x:%x:%x:%x:%x:%x",
TSK_TO_UINT16(&in_ip[0]), TSK_TO_UINT16(&in_ip[2]), TSK_TO_UINT16(&in_ip[4]), TSK_TO_UINT16(&in_ip[6]),
TSK_TO_UINT16(&in_ip[8]), TSK_TO_UINT16(&in_ip[10]), TSK_TO_UINT16(&in_ip[12]), TSK_TO_UINT16(&in_ip[14]));
}
else if(family == stun_ipv4){
tsk_sprintf(out_ip, "%u.%u.%u.%u", in_ip[0], in_ip[1], in_ip[2], in_ip[3]);
return 0;
}
else{
TSK_DEBUG_ERROR("Unsupported address family: %u.", family);
}
return -1;
}
/**@ingroup tnet_nat_group
*
* Sets the address of the STUN/TURN server.
*
* @param [in,out] self The NAT context.
* @param [in,out] server_address The address of server.
* @param [in,out] p_self The NAT context.
* @param [in,out] pc_server_address The address of server.
*
* @return Zero if succeed and non zero error code otherwise.
**/
int tnet_nat_set_server_address(tnet_nat_context_handle_t* self, const char* server_address)
int tnet_nat_set_server_address(struct tnet_nat_ctx_s* p_self, const char* pc_server_address)
{
tnet_nat_context_t* context = self;
if(context){
tsk_strupdate(&(context->server_address), server_address);
return 0;
if (!p_self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
return -1;
tsk_strupdate(&(p_self->server_address), pc_server_address);
return 0;
}
/**@ingroup tnet_nat_group
*
* Sets the address and port of the STUN/TURN server.
*
* @param [in,out] self The NAT context.
* @param [in,out] server_address The address of server.
* @param server_port The server port.
* @param [in,out] p_self The NAT context.
* @param [in,out] pc_server_address The address of server.
* @param u_server_port The server port.
*
* @return Zero if succeed and non zero error code otherwise.
**/
int tnet_nat_set_server(tnet_nat_context_handle_t* self, const char* server_address, tnet_port_t server_port)
int tnet_nat_set_server(struct tnet_nat_ctx_s* p_self, const char* pc_server_address, tnet_port_t u_server_port)
{
tnet_nat_context_t* context = self;
if(context){
tsk_strupdate(&(context->server_address), server_address);
context->server_port = server_port;
return 0;
if (!p_self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
return -1;
tsk_strupdate(&(p_self->server_address), pc_server_address);
p_self->server_port = u_server_port;
return 0;
}
/**@ingroup tnet_nat_group
@ -202,74 +156,179 @@ int tnet_nat_set_server(tnet_nat_context_handle_t* self, const char* server_addr
* Creates and sends a STUN2 binding request to the STUN/TURN server in order to get the server reflexive
* address associated to this file descriptor (or socket). The caller should call @ref tnet_nat_stun_unbind to destroy the binding.
*
* @param [in,out] self The NAT context.
* @param [in,out] p_self The NAT context.
* @param localFD The local file descriptor (or socket) for which to get the reflexive server address.
*
* @return A valid binding id if succeed and @ref TNET_STUN_INVALID_BINDING_ID otherwise. If the returned id is valid then
* @return A valid binding id if succeed and @ref kStunBindingInvalidId otherwise. If the returned id is valid then
* the newly created binding will contain the server-reflexive address associated to the local file descriptor.
*
* @sa @ref tnet_nat_stun_unbind.
**/
tnet_stun_binding_id_t tnet_nat_stun_bind(const tnet_nat_context_handle_t* self, const tnet_fd_t localFD)
tnet_stun_binding_id_t tnet_nat_stun_bind(const struct tnet_nat_ctx_s* p_self, const tnet_fd_t localFD)
{
const tnet_nat_context_t* context = self;
if(context){
return tnet_stun_bind(context, localFD);
tnet_stun_binding_id_t id = kStunBindingInvalidId;
tnet_stun_binding_t *p_binding = tsk_null;
int ret;
if (!p_self || localFD == TNET_INVALID_FD) {
TSK_DEBUG_ERROR("Invalid parameter");
goto bail;
}
return TNET_STUN_INVALID_BINDING_ID;
if ((ret = tnet_stun_binding_create(localFD, p_self->socket_type, p_self->server_address, p_self->server_port, p_self->username, p_self->password, &p_binding))) {
goto bail;
}
if ((ret = tnet_nat_stun_send_bind(p_self, p_binding))) {
goto bail;
}
id = p_binding->id;
tsk_list_push_back_data(p_self->stun_bindings, (void**)&p_binding);
bail:
TSK_OBJECT_SAFE_FREE(p_binding);
return id;
}
/**@ingroup tnet_nat_group
* Internal function to send a STUN2 binding request over the network.
*
* @param [in,out] p_self The NAT context holding the user preferences.
* @param [in,out] p_binding The STUN binding object used to create the message to send.
*
* @return Zero if succeed and non-zero error code otherwise.
**/
int tnet_nat_stun_send_bind(const struct tnet_nat_ctx_s* pc_self, struct tnet_stun_binding_s *p_binding)
{
int ret = -1;
tnet_stun_pkt_resp_t *p_pkt_resp = tsk_null;
tnet_stun_pkt_req_t *p_pkt_req = tsk_null;
if (!pc_self || !p_binding) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if (!TNET_SOCKET_TYPE_IS_DGRAM(p_binding->socket_type)) {
TSK_DEBUG_ERROR("Only DGRAM could be used for STUN transport");
return -2;
}
if ((ret = tnet_stun_binding_create_req(p_binding, &p_pkt_req))) {
goto bail;
}
/* RFC 5389 - 10.2.1.1. First Request
If the client has not completed a successful request/response
transaction with the server (as identified by hostname, if the DNS
procedures of Section 9 are used, else IP address if not), it SHOULD
omit the USERNAME, MESSAGE-INTEGRITY, REALM, and NONCE attributes.
In other words, the very first request is sent as if there were no
authentication or message integrity applied.
*/
stun_phase0: {
if ((ret = tnet_stun_utils_send_unreliably(p_binding->localFD, pc_self->RTO, pc_self->Rc, p_pkt_req, (struct sockaddr*)&p_binding->addr_server, &p_pkt_resp))) {
goto bail;
}
if (p_pkt_resp) {
if (TNET_STUN_PKT_RESP_IS_ERROR(p_pkt_resp)) {
uint16_t u_code;
if ((ret = tnet_stun_pkt_get_errorcode(p_pkt_resp, &u_code))) {
goto bail;
}
if (u_code == kStunErrCodeUnauthorized || u_code == kStunErrCodeStaleNonce) {
if (u_code == kStunErrCodeUnauthorized) {
// Make sure this is not an authentication failure (#2 401)
// Do not send another req to avoid endless messages
if ((tnet_stun_pkt_attr_exists(p_pkt_req, tnet_stun_attr_type_message_integrity))) { // already has a MESSAGE-INTEGRITY?
TSK_DEBUG_ERROR("STUN authentication failed");
goto bail;
}
}
if ((ret = tnet_stun_pkt_auth_prepare_2(p_pkt_req, p_binding->p_username, p_binding->p_password, p_pkt_resp))) {
goto bail;
}
// Try to send again now that authinfo is up2date
goto stun_phase0;
}
else if (u_code == kStunErrCodeUnknownAttributes) {
if((ret = tnet_stun_pkt_process_err420(p_pkt_req, p_pkt_resp))) {
goto bail;
}
// Try to send again now that authinfo is up2date
goto stun_phase0;
}
ret = -3;
}
else {
const tnet_stun_attr_address_t* pc_addr;
if ((ret = tnet_stun_pkt_attr_find_first(p_pkt_resp, tnet_stun_attr_type_xor_mapped_address, (const tnet_stun_attr_t**)&pc_addr)) == 0 && pc_addr) {
TSK_OBJECT_SAFE_FREE(p_binding->p_xmaddr);
p_binding->p_xmaddr = tsk_object_ref(TSK_OBJECT(pc_addr));
}
if ((ret = tnet_stun_pkt_attr_find_first(p_pkt_resp, tnet_stun_attr_type_mapped_address, (const tnet_stun_attr_t**)&pc_addr)) == 0 && pc_addr) {
TSK_OBJECT_SAFE_FREE(p_binding->p_maddr);
p_binding->p_maddr = tsk_object_ref(TSK_OBJECT(pc_addr));
}
}
}
}
/* END OF stun_phase0 */
bail:
TSK_OBJECT_SAFE_FREE(p_pkt_resp);
TSK_OBJECT_SAFE_FREE(p_pkt_req);
return ret;
}
/**@ingroup tnet_nat_group
* Gets the server reflexive address associated to this STUN2 binding.
*
*
* @param [in,out] self The NAT context.
* @param [in,out] p_self The NAT context.
* @param id The id of the STUN2 binding conetxt (obtained using @ref tnet_nat_stun_bind) holding the server-reflexive address.
* @param [in,out] ipaddress The reflexive IP address. It is up the the caller to free the returned string
* @param [in,out] port The reflexive port.
* @param [in,out] pp_ip The reflexive IP address. It is up the the caller to free the returned string
* @param [in,out] pu_port The reflexive port.
*
* @return Zero if succeed and non zero error code otherwise.
**/
int tnet_nat_stun_get_reflexive_address(const tnet_nat_context_handle_t* self, tnet_stun_binding_id_t id, char** ipaddress, tnet_port_t *port)
int tnet_nat_stun_get_reflexive_address(const struct tnet_nat_ctx_s* p_self, tnet_stun_binding_id_t id, char** pp_ip, tnet_port_t *pu_port)
{
const tnet_nat_context_t* context = self;
if(context){
const tsk_list_item_t* item = tsk_list_find_item_by_pred(context->stun_bindings, __pred_find_stun_binding, &id);
if(item && item->data){
tnet_stun_binding_t *binding = item->data;
/*STUN2: XOR-MAPPED-ADDRESS */
if(binding->xmaddr){
int ret = 0;
if(ipaddress){
ret = tnet_stun_address_tostring(binding->xmaddr->xaddress, binding->xmaddr->family, ipaddress);
}
if(port){
*port = /*tnet_ntohs*/(binding->xmaddr->xport);
}
const tsk_list_item_t* item;
if (!p_self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if (!pp_ip && !pu_port) {
return 0;
}
if ((item = tsk_list_find_item_by_pred(p_self->stun_bindings, __pred_find_stun_binding, &id)) && item->data) {
const tnet_stun_binding_t *pc_bind = (const tnet_stun_binding_t *)item->data;
const struct tnet_stun_attr_address_s *pc_addr = pc_bind->p_xmaddr ? pc_bind->p_xmaddr : pc_bind->p_maddr;
if (pc_addr) {
tnet_ip_t ip;
int ret;
if ((ret = tnet_stun_utils_inet_ntop((pc_addr->e_family == tnet_stun_address_family_ipv6), &pc_addr->address, &ip))) {
return ret;
}
/*STUN1: MAPPED-ADDRESS*/
if(binding->maddr){
int ret = 0;
if(ipaddress){
ret = tnet_stun_address_tostring(binding->maddr->address, binding->maddr->family, ipaddress);
}
if(port){
*port = /*tnet_ntohs*/(binding->maddr->port);
}
return ret;
if (pp_ip) {
tsk_strupdate(pp_ip, ip);
}
if (pu_port) {
*pu_port = pc_addr->u_port;
}
return 0;
}
}
return -1;
return -2;
}
/**@ingroup tnet_nat_group
*
* Removes a STUN2 binding from the NAT context.
*
* @param [in,out] self The NAT context from which to remove the STUN2 binding.
* @param [in,out] p_self The NAT context from which to remove the STUN2 binding.
* @param id The id of the STUN2 binding to remove.
*
* @return Zero if succeed and non zero error code otherwise.
@ -277,234 +336,14 @@ int tnet_nat_stun_get_reflexive_address(const tnet_nat_context_handle_t* self, t
*
* @sa @ref tnet_nat_stun_bind.
**/
int tnet_nat_stun_unbind(const tnet_nat_context_handle_t* self, tnet_stun_binding_id_t id)
int tnet_nat_stun_unbind(const struct tnet_nat_ctx_s* p_self, tnet_stun_binding_id_t id)
{
const tnet_nat_context_t* context = self;
if(context)
{
tsk_list_remove_item_by_pred(context->stun_bindings, __pred_find_stun_binding, &id);
return 0;
if (!p_self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
return -1;
}
/**@ingroup tnet_nat_group
*
* Creates TURN allocation as per draft-ietf-behave-turn-16 subclause 6. This function will also
* send an allocation request to the server (subclause 6.1).
*
* @param [in,out] self The NAT context.
* @param localFD The local file descriptor.
*
* @return A valid TURN allocation id if succeed and @ref TNET_TURN_INVALID_ALLOCATION_ID otherwise.
*
* @sa @ref tnet_nat_turn_unallocate.
**/
tnet_turn_allocation_id_t tnet_nat_turn_allocate(const tnet_nat_context_handle_t* self, const tnet_fd_t localFD)
{
const tnet_nat_context_t* context = self;
if(self)
{
return tnet_turn_allocate(self, localFD, context->socket_type);
}
return TNET_TURN_INVALID_ALLOCATION_ID;
}
/**@ingroup tnet_nat_group
* Gets the STUN server-refelexive IP address and port associated to this TURN allocation.
*
* @param [in,out] self The NAT context.
* @param id The id of the TURN allocation for which to to get server-reflexive IP address and port.
* @param [in,out] ipaddress The server-reflexive IP address.
* @param [in,out] port The server-reflexive port.
*
* @return Zero if succeed and non zero error code otherwise.
**/
int tnet_nat_turn_get_reflexive_address(const tnet_nat_context_handle_t* self, tnet_turn_allocation_id_t id, char** ipaddress, tnet_port_t *port)
{
const tnet_nat_context_t* context = self;
if(context)
{
const tsk_list_item_t* item = tsk_list_find_item_by_pred(context->allocations, __pred_find_turn_allocation, &id);
if(item && item->data)
{
tnet_turn_allocation_t *allocation = item->data;
/*STUN2: XOR-MAPPED-ADDRESS */
if(allocation->xmaddr)
{
int ret = tnet_stun_address_tostring(allocation->xmaddr->xaddress, allocation->xmaddr->family, ipaddress);
*port = /*tnet_ntohs*/(allocation->xmaddr->xport);
return ret;
}
/*STUN1: MAPPED-ADDRESS*/
if(allocation->maddr)
{
int ret = tnet_stun_address_tostring(allocation->maddr->address, allocation->maddr->family, ipaddress);
*port = /*tnet_ntohs*/(allocation->maddr->port);
return ret;
}
}
}
return -1;
}
/**@ingroup tnet_nat_group
*
* Refresh a TURN allocation previously created using @ref tnet_nat_turn_allocate.
*
* @param [in,out] self The NAT context.
* @param id The id of the TURN allocation to refresh.
*
* @return Zero if succeed and non zero error code otherwise.
**/
int tnet_nat_turn_allocation_refresh(const tnet_nat_context_handle_t* self, tnet_turn_allocation_id_t id)
{
const tnet_nat_context_t* context = self;
if(context)
{
const tsk_list_item_t* item = tsk_list_find_item_by_pred(context->allocations, __pred_find_turn_allocation, &id);
if(item && item->data)
{
tnet_turn_allocation_t *allocation = item->data;
return tnet_turn_allocation_refresh(self, allocation);
}
}
return -1;
}
/**@ingroup tnet_nat_group
*
* Unallocate/remove a TURN allocation from the server.
*
* @param [in,out] self The NAT context from which to remove the allocation.
* @param id The id of the TURN allocation to remove.
*
* @return Zero if succeed and non zero error code otherwise.
*
* @sa @ref tnet_nat_turn_allocate.
**/
int tnet_nat_turn_unallocate(const tnet_nat_context_handle_t* self, tnet_turn_allocation_id_t id)
{
const tnet_nat_context_t* context = self;
if(context)
{
const tsk_list_item_t* item = tsk_list_find_item_by_pred(context->allocations, __pred_find_turn_allocation, &id);
if(item && item->data)
{
tnet_turn_allocation_t *allocation = item->data;
return tnet_turn_unallocate(self, allocation);
}
}
return -1;
}
/**@ingroup tnet_nat_group
* Creates TURN channel binding as per draft-ietf-behave-turn-16 sublause 11 and send it to the
* server as per subclause 11.1.
*
*
* @param [in,out] self The NAT context.
* @param id The id of the TURN allocation associated to this binding.
* @param [in,out] peer The XOR remote peer for the channel binding.
*
* @return A valid TURN channel binding id if succeed and @ref TNET_TURN_INVALID_CHANNEL_BINDING_ID otherwise.
**/
tnet_turn_channel_binding_id_t tnet_nat_turn_channel_bind(const tnet_nat_context_handle_t* self, tnet_turn_allocation_id_t id, struct sockaddr_storage *peer)
{
const tnet_nat_context_t* context = self;
if(context)
{
const tsk_list_item_t* item = tsk_list_find_item_by_pred(context->allocations, __pred_find_turn_allocation, &id);
if(item && item->data)
{
tnet_turn_allocation_t *allocation = item->data;
return tnet_turn_channel_bind(self, allocation, peer);
}
}
return TNET_TURN_INVALID_CHANNEL_BINDING_ID;
}
/**@ingroup tnet_nat_group
*/
int tnet_nat_turn_channel_refresh(const tnet_nat_context_handle_t* self, tnet_turn_channel_binding_id_t id)
{
const tnet_nat_context_t* context = self;
if(context)
{
tsk_list_item_t* curr;
tsk_list_foreach(curr, context->allocations)
{
const tsk_list_item_t* item = tsk_list_find_item_by_pred(((tnet_turn_allocation_t *)curr->data)->channel_bindings, __pred_find_turn_channel_binding, &id);
if(item && item->data)
{
return tnet_turn_channel_refresh(context, (tnet_turn_channel_binding_t *)item->data);
}
}
}
return -1;
}
/**@ingroup tnet_nat_group
*/
int tnet_nat_turn_channel_send(const tnet_nat_context_handle_t* self, tnet_turn_channel_binding_id_t id, const void* data, tsk_size_t size, int indication)
{
const tnet_nat_context_t* context = self;
if(context && data && size)
{
tsk_list_item_t* curr;
tsk_list_foreach(curr, context->allocations)
{
const tsk_list_item_t* item = tsk_list_find_item_by_pred(((tnet_turn_allocation_t *)curr->data)->channel_bindings, __pred_find_turn_channel_binding, &id);
if(item && item->data)
{
return tnet_turn_channel_senddata(context, (tnet_turn_channel_binding_t *)item->data, data, size, indication);
}
}
}
return -1;
}
/**@ingroup tnet_nat_group
*/
int tnet_nat_turn_add_permission(const tnet_nat_context_handle_t* self, tnet_turn_allocation_id_t id, const char* ipaddress, uint32_t timeout)
{
const tnet_nat_context_t* context = self;
if(self)
{
const tsk_list_item_t* item = tsk_list_find_item_by_pred(context->allocations, __pred_find_turn_allocation, &id);
if(item && item->data)
{
tnet_turn_allocation_t *allocation = item->data;
return tnet_turn_add_permission(self, allocation, ipaddress, timeout);
}
}
return -1;
tsk_list_remove_item_by_pred(p_self->stun_bindings, __pred_find_stun_binding, &id);
return 0;
}
@ -513,56 +352,28 @@ int tnet_nat_turn_add_permission(const tnet_nat_context_handle_t* self, tnet_tur
//
static tsk_object_t* tnet_nat_context_ctor(tsk_object_t * self, va_list * app)
{
tnet_nat_context_t *context = self;
if(context){
context->socket_type = va_arg(*app, tnet_socket_type_t);
context->username = tsk_strdup(va_arg(*app, const char*));
context->password = tsk_strdup(va_arg(*app, const char*));
context->server_port = TNET_NAT_TCP_UDP_DEFAULT_PORT;
/* 7.2.1. Sending over UDP
In fixed-line access links, a value of 500 ms is RECOMMENDED.
*/
context->RTO = TNET_NAT_DEFAULT_RTO;
/* 7.2.1. Sending over UDP
Rc SHOULD be configurable and SHOULD have a default of 7.
*/
context->Rc = TNET_NAT_DEFAULT_RC;
context->software = tsk_strdup(TNET_SOFTWARE);
//context->enable_evenport = 1;
//context->enable_fingerprint = 1;
context->enable_integrity = 0;
context->enable_dontfrag = 0;//TNET_SOCKET_TYPE_IS_DGRAM(context->socket_type) ? 1 : 0;
context->allocations = tsk_list_create();
context->stun_bindings = tsk_list_create();
tnet_nat_ctx_t *p_ctx = (tnet_nat_ctx_t*)self;
if (p_ctx) {
}
return self;
}
static tsk_object_t* tnet_nat_context_dtor(tsk_object_t * self)
{
tnet_nat_context_t *context = self;
if(context){
TSK_FREE(context->username);
TSK_FREE(context->password);
TSK_FREE(context->software);
TSK_FREE(context->server_address);
tnet_nat_ctx_t *p_ctx = (tnet_nat_ctx_t*)self;
if (p_ctx) {
TSK_FREE(p_ctx->username);
TSK_FREE(p_ctx->password);
TSK_FREE(p_ctx->server_address);
TSK_OBJECT_SAFE_FREE(context->allocations);
TSK_OBJECT_SAFE_FREE(context->stun_bindings);
TSK_OBJECT_SAFE_FREE(p_ctx->stun_bindings);
TSK_DEBUG_INFO("*** NAT context destroyed ***");
}
return self;
}
static const tsk_object_def_t tnet_nat_context_def_s =
{
sizeof(tnet_nat_context_t),
sizeof(tnet_nat_ctx_t),
tnet_nat_context_ctor,
tnet_nat_context_dtor,
tsk_null,

View File

@ -1,8 +1,5 @@
/*
* Copyright (C) 2010-2011 Mamadou Diop.
/* Copyright (C) 2010-2014 Mamadou DIOP.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
@ -19,101 +16,27 @@
* along with DOUBANGO.
*
*/
/**@file tnet_nat.h
* @brief NAT Traversal helper functions using STUN, TURN and ICE.
*
* @author Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
*/
#ifndef TNET_NAT_H
#define TNET_NAT_H
#include "tinynet_config.h"
#include "tnet_socket.h"
#include "stun/tnet_stun.h"
#include "turn/tnet_turn.h"
#include "tnet_proto.h"
#include "tnet_types.h"
#include "tsk_object.h"
#include "stun/tnet_stun_types.h"
TNET_BEGIN_DECLS
/**@ingroup tnet_nat_group
* Estimate of the round-trip time (RTT) in millisecond.
*/
#define TNET_NAT_DEFAULT_RTO 500
/**@ingroup tnet_nat_group
* Number of retransmission for UDP retransmission in millisecond.
* 7.2.1. Sending over UDP
Rc SHOULD be configurable and SHOULD have a default of 7.
*/
#define TNET_NAT_DEFAULT_RC /*7*/3/* 7 is too hight */
/**@ingroup tnet_nat_group
*/
#define TNET_NAT_TCP_UDP_DEFAULT_PORT 3478
struct tnet_nat_ctx_s;
struct tnet_stun_binding_s;
enum tnet_socket_type_e;
/**@ingroup tnet_nat_group
* NAT context.
**/
typedef struct tnet_nat_context_s
{
TSK_DECLARE_OBJECT;
//tnet_fd_t localFD; /**< Local file descriptor. */
tnet_socket_type_t socket_type;
char* username; /**< The username to use to authenticate against the TURN/STUN server. */
char* password; /**< The password to use to authenticate against the TURN/STUN server. */
char* software; /**< The turn/stun client name. */
char* server_address; /**< TURN/STUN server address (could be FQDN or IP) */
tnet_port_t server_port; /**< TURN/STUN server port. */
uint16_t RTO; /**< Estimate of the round-trip time (RTT) in millisecond. */
uint16_t Rc; /**< Number of retransmissions for UDP in millisecond. */
unsigned enable_dontfrag:1;
unsigned enable_integrity:1;
unsigned enable_evenport:1;
unsigned enable_fingerprint:1; /**< Indicates whether to add the 'fingerprint' attribute in all outgoing stun/turn requests. */
unsigned use_dnsquery:1; /**< Indicates whether to use DNS SRV query to find the stun/turn ip address. */
tnet_turn_allocations_L_t *allocations; /**< List of all allocations associated to this context. */
tnet_stun_bindings_L_t *stun_bindings; /**< List of all STUN2 bindings associated to this context. */
}
tnet_nat_context_t;
/**@ingroup tnet_nat_group
* Handle to the NAT context(@ref tnet_nat_context_t).
**/
typedef void tnet_nat_context_handle_t;
TINYNET_API int tnet_nat_set_server_address(tnet_nat_context_handle_t* self, const char* server_address);
TINYNET_API int tnet_nat_set_server(tnet_nat_context_handle_t* self, const char* server_address, tnet_port_t server_port);
TINYNET_API tnet_stun_binding_id_t tnet_nat_stun_bind(const tnet_nat_context_handle_t* self, const tnet_fd_t localFD);
TINYNET_API int tnet_nat_stun_get_reflexive_address(const tnet_nat_context_handle_t* self, tnet_stun_binding_id_t id, char** ipaddress, tnet_port_t *port);
TINYNET_API int tnet_nat_stun_unbind(const tnet_nat_context_handle_t* self, tnet_stun_binding_id_t id);
TINYNET_API tnet_turn_allocation_id_t tnet_nat_turn_allocate(const tnet_nat_context_handle_t* self, const tnet_fd_t localFD);
TINYNET_API int tnet_nat_turn_get_reflexive_address(const tnet_nat_context_handle_t* self, tnet_turn_allocation_id_t id, char** ipaddress, tnet_port_t *port);
TINYNET_API int tnet_nat_turn_allocation_refresh(const tnet_nat_context_handle_t* self, tnet_turn_allocation_id_t id);
TINYNET_API int tnet_nat_turn_unallocate(const tnet_nat_context_handle_t* self, tnet_turn_allocation_id_t id);
TINYNET_API tnet_turn_channel_binding_id_t tnet_nat_turn_channel_bind(const tnet_nat_context_handle_t* self, tnet_turn_allocation_id_t id, struct sockaddr_storage *peer);
TINYNET_API int tnet_nat_turn_channel_refresh(const tnet_nat_context_handle_t* self, tnet_turn_channel_binding_id_t id);
TINYNET_API int tnet_nat_turn_channel_send(const tnet_nat_context_handle_t* self, tnet_turn_channel_binding_id_t id, const void* data, tsk_size_t size, int indication);
#define tnet_nat_turn_channel_sendindication(context, channel_id, data, size) tnet_nat_turn_channel_send(context, channel_id, data, size, 1)
#define tnet_nat_turn_channel_senddata(context, channel_id, data, size) tnet_nat_turn_channel_send(context, channel_id, data, size, 0)
TINYNET_API int tnet_nat_turn_add_permission(const tnet_nat_context_handle_t* self, tnet_turn_allocation_id_t id, const char* ipaddress, uint32_t timeout);
TINYNET_API tnet_nat_context_handle_t* tnet_nat_context_create(tnet_socket_type_t socket_type, const char* username, const char* password);
TINYNET_GEXTERN const tsk_object_def_t *tnet_nat_context_def_t;
TINYNET_API int tnet_nat_set_server_address(struct tnet_nat_ctx_s* p_self, const char* pc_srv_addr);
TINYNET_API int tnet_nat_set_server(struct tnet_nat_ctx_s* p_self, const char* pc_srv_addr, tnet_port_t u_srv_port);
TINYNET_API tnet_stun_binding_id_t tnet_nat_stun_bind(const struct tnet_nat_ctx_s* p_self, const tnet_fd_t localFD);
TINYNET_API int tnet_nat_stun_send_bind(const struct tnet_nat_ctx_s* pc_self, struct tnet_stun_binding_s *p_binding);
TINYNET_API int tnet_nat_stun_get_reflexive_address(const struct tnet_nat_ctx_s* p_self, tnet_stun_binding_id_t id, char** pp_ip, tnet_port_t *pu_port);
TINYNET_API int tnet_nat_stun_unbind(const struct tnet_nat_ctx_s* p_self, tnet_stun_binding_id_t id);
TINYNET_API struct tnet_nat_ctx_s* tnet_nat_context_create(enum tnet_socket_type_e socket_type, const char* pc_username, const char* pc_password);
TNET_END_DECLS

View File

@ -155,19 +155,9 @@ tnet_socket_t* tnet_socket_create_2(const char* host, tnet_port_t port_, tnet_so
*/
//
if (TNET_SOCKET_TYPE_IS_STREAM(sock->type)) {
#if defined(SOLARIS)
static const char yes = '1';
#else
static const int yes = 1;
#endif
if(setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&yes, sizeof(int)) == -1){
TNET_PRINT_LAST_ERROR("setsockopt(SO_REUSEADDR) have failed");
}
#if defined(SO_REUSEPORT)
if(setsockopt(sock->fd, SOL_SOCKET, SO_REUSEPORT, (char*)&yes, sizeof(int)) == -1){
TNET_PRINT_LAST_ERROR("setsockopt(SO_REUSEPORT) have failed");
}
#endif
if ((status = tnet_sockfd_reuseaddr(sock->fd, 1))) {
// do not break...continue
}
}
if(bindsocket){

View File

@ -35,6 +35,8 @@
#include "tls/tnet_tls.h"
#include "tls/tnet_dtls.h"
#include "stun/tnet_stun_types.h"
#include "tsk_memory.h"
#include "tsk_string.h"
#include "tsk_debug.h"
@ -107,6 +109,7 @@ static int _tnet_transport_ssl_init(tnet_transport_t* transport)
TSK_DEBUG_ERROR("SSL_CTX_set_cipher_list failed [%s]", ERR_error_string(ERR_get_error(), tsk_null));
return -6;
}
transport->dtls.activated = tsk_true;
}
#endif /* HAVE_OPENSSL_DTLS */
}
@ -364,7 +367,7 @@ int tnet_transport_get_ip_n_port_2(const tnet_transport_handle_t *handle, tnet_i
}
}
int tnet_transport_set_natt_ctx(tnet_transport_handle_t *handle, tnet_nat_context_handle_t* natt_ctx)
int tnet_transport_set_natt_ctx(tnet_transport_handle_t *handle, struct tnet_nat_ctx_s* natt_ctx)
{
if (!handle) {
TSK_DEBUG_ERROR("Invalid parameter");
@ -378,15 +381,15 @@ int tnet_transport_set_natt_ctx(tnet_transport_handle_t *handle, tnet_nat_contex
int tnet_transport_get_public_ip_n_port(const tnet_transport_handle_t *handle, tnet_fd_t fd, tnet_ip_t *ip, tnet_port_t *port)
{
tsk_bool_t stun_ok = tsk_false;
tnet_nat_context_handle_t* natt_ctx;
struct tnet_nat_ctx_s* natt_ctx;
const tnet_transport_t *transport = handle;
if(!transport){
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if(TNET_SOCKET_TYPE_IS_DGRAM(transport->type) && (natt_ctx = tsk_object_ref(transport->natt_ctx))){
tnet_stun_binding_id_t bind_id = TNET_STUN_INVALID_BINDING_ID;
if (TNET_SOCKET_TYPE_IS_DGRAM(transport->type) && (natt_ctx = tsk_object_ref(transport->natt_ctx))) {
tnet_stun_binding_id_t bind_id = kStunBindingInvalidId;
// if the socket is already monitored by the transport we should pause because both the transport and
// NAT binder will try to read from it
@ -397,7 +400,7 @@ int tnet_transport_get_public_ip_n_port(const tnet_transport_handle_t *handle, t
// Resume the socket
tnet_transport_pause_socket(transport, fd, tsk_false);
if(TNET_STUN_IS_VALID_BINDING_ID(bind_id)){
if (bind_id != kStunBindingInvalidId) {
char* public_ip = tsk_null;
if(tnet_nat_stun_get_reflexive_address(transport->natt_ctx, bind_id, &public_ip, port) == 0){
if(ip && public_ip){
@ -600,19 +603,19 @@ int tnet_transport_dtls_set_setup(tnet_transport_handle_t* handle, tnet_dtls_set
{
tnet_transport_t *transport = handle;
if(!transport){
if (!transport) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if(!transport->dtls.enabled){
if (!transport->dtls.enabled) {
TSK_DEBUG_ERROR("DTLS not enabled on this transport");
return -2;
}
if(sockets && sockets_count){
if (sockets && sockets_count) {
tsk_size_t i;
for(i = 0; i < sockets_count; ++i){
if(!sockets[i] || !sockets[i]->dtlshandle){
for (i = 0; i < sockets_count; ++i) {
if (!sockets[i] || !sockets[i]->dtlshandle) {
continue;
}
tnet_dtls_socket_set_setup(sockets[i]->dtlshandle, setup);
@ -621,26 +624,51 @@ int tnet_transport_dtls_set_setup(tnet_transport_handle_t* handle, tnet_dtls_set
return 0;
}
int tnet_transport_dtls_set_store_handshakingdata(tnet_transport_handle_t* handle, tsk_bool_t handshake_storedata, struct tnet_socket_s** sockets, tsk_size_t sockets_count)
{
tnet_transport_t *transport = handle;
if (!transport) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if (!transport->dtls.enabled) {
TSK_DEBUG_ERROR("DTLS not enabled on this transport");
return -2;
}
if (sockets && sockets_count) {
tsk_size_t i;
for (i = 0; i < sockets_count; ++i) {
if (!sockets[i] || !sockets[i]->dtlshandle) {
continue;
}
tnet_dtls_socket_set_store_handshakingdata(sockets[i]->dtlshandle, handshake_storedata);
}
}
return 0;
}
int tnet_transport_dtls_do_handshake(tnet_transport_handle_t *handle, struct tnet_socket_s** sockets, tsk_size_t sockets_count, const struct sockaddr_storage** remote_addrs, tsk_size_t remote_addrs_count)
{
tnet_transport_t *transport = handle;
tsk_size_t i;
if(!transport || !sockets){
if (!transport || !sockets) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if(!transport->dtls.enabled){
if (!transport->dtls.enabled) {
TSK_DEBUG_ERROR("DTLS not enabled on this transport");
return -2;
}
if(sockets){
if (sockets) {
int ret;
for(i = 0; i < sockets_count; ++i){
if(sockets[i] && sockets[i]->dtlshandle){
if((ret = tnet_dtls_socket_do_handshake(sockets[i]->dtlshandle,
for (i = 0; i < sockets_count; ++i) {
if (sockets[i] && sockets[i]->dtlshandle) {
if ((ret = tnet_dtls_socket_do_handshake(sockets[i]->dtlshandle,
(remote_addrs && i < remote_addrs_count) ? remote_addrs[i] : tsk_null)) != 0){
return ret;
}
@ -651,6 +679,39 @@ int tnet_transport_dtls_do_handshake(tnet_transport_handle_t *handle, struct tne
return 0;
}
int tnet_transport_dtls_get_handshakingdata(tnet_transport_handle_t* handle, const struct tnet_socket_s** sockets, tsk_size_t sockets_count, const void* data[], tsk_size_t size[])
{
tnet_transport_t *transport = handle;
tsk_size_t i;
if (!transport || !sockets) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if (!transport->dtls.enabled) {
TSK_DEBUG_ERROR("DTLS not enabled on this transport");
return -2;
}
if (sockets) {
int ret;
for (i = 0; i < sockets_count; ++i) {
if (sockets[i] && sockets[i]->dtlshandle) {
if ((ret = tnet_dtls_socket_get_handshakingdata(sockets[i]->dtlshandle, &data[i], &size[i])) != 0){
return ret;
}
}
else {
data[i] = tsk_null;
size[i] = 0;
}
}
}
return 0;
}
tnet_socket_type_t tnet_transport_get_type(const tnet_transport_handle_t *handle)
{
if(!handle){
@ -795,13 +856,13 @@ int tnet_transport_shutdown(tnet_transport_handle_t* handle)
static int _tnet_transport_dtls_cb(const void* usrdata, tnet_dtls_socket_event_type_t dtls_e, const tnet_dtls_socket_handle_t* handle, const void* data, tsk_size_t size)
{
tnet_transport_t *transport = (tnet_transport_t*)usrdata;
if(transport){
if (transport) {
tnet_transport_event_type_t t_e;
const struct sockaddr_storage* remote_addr;
tnet_fd_t fd;
tnet_transport_event_t* e;
switch(dtls_e){
switch (dtls_e) {
case tnet_dtls_socket_event_type_handshake_started: t_e = event_dtls_handshake_started; break;
case tnet_dtls_socket_event_type_handshake_succeed: t_e = event_dtls_handshake_succeed; break;
case tnet_dtls_socket_event_type_handshake_failed: t_e = event_dtls_handshake_failed; break;
@ -813,15 +874,25 @@ static int _tnet_transport_dtls_cb(const void* usrdata, tnet_dtls_socket_event_t
}
remote_addr = tnet_dtls_socket_get_remote_addr(handle);
fd = tnet_dtls_socket_get_fd(handle);
if((e = tnet_transport_event_create(t_e, transport->callback_data, fd))){
if(data && size && (e ->data = tsk_malloc(size))){
if ((e = tnet_transport_event_create(t_e, transport->callback_data, fd))) {
if (data && size && (e ->data = tsk_malloc(size))) {
memcpy(e ->data, data, size);
e->size = size;
}
if(remote_addr){
if (remote_addr) {
e->remote_addr = *remote_addr;
}
TSK_RUNNABLE_ENQUEUE_OBJECT_SAFE(TSK_RUNNABLE(transport), e);
if (TSK_RUNNABLE(transport)->initialized && TSK_RUNNABLE(transport)->running && TSK_RUNNABLE(transport)->started) {
TSK_RUNNABLE_ENQUEUE_OBJECT_SAFE(TSK_RUNNABLE(transport), e);
}
else {
TSK_DEBUG_INFO("Delivering network event synchronously.");
// network transport not started (happens when TURN is using the sockets instead of the RTP manager)
if (transport->callback) {
transport->callback(e);
}
TSK_OBJECT_SAFE_FREE(e);
}
return 0;
}
}
@ -858,7 +929,7 @@ static void* TSK_STDCALL run(void* self)
if((curr = TSK_RUNNABLE_POP_FIRST_SAFE(TSK_RUNNABLE(transport)))){
const tnet_transport_event_t *e = (const tnet_transport_event_t*)curr->data;
if(transport->callback){
if (transport->callback) {
transport->callback(e);
}
tsk_object_unref(curr);

View File

@ -85,7 +85,7 @@ TINYNET_API int tnet_transport_issecure(const tnet_transport_handle_t *handle);
TINYNET_API const char* tnet_transport_get_description(const tnet_transport_handle_t *handle);
TINYNET_API int tnet_transport_get_ip_n_port(const tnet_transport_handle_t *handle, tnet_fd_t fd, tnet_ip_t *ip, tnet_port_t *port);
TINYNET_API int tnet_transport_get_ip_n_port_2(const tnet_transport_handle_t *handle, tnet_ip_t *ip, tnet_port_t *port);
TINYNET_API int tnet_transport_set_natt_ctx(tnet_transport_handle_t *handle, tnet_nat_context_handle_t* natt_ctx);
TINYNET_API int tnet_transport_set_natt_ctx(tnet_transport_handle_t *handle, struct tnet_nat_ctx_s* natt_ctx);
TINYNET_API int tnet_transport_get_public_ip_n_port(const tnet_transport_handle_t *handle, tnet_fd_t fd, tnet_ip_t *ip, tnet_port_t *port);
TINYNET_API int tnet_transport_isconnected(const tnet_transport_handle_t *handle, tnet_fd_t fd);
@ -109,7 +109,9 @@ TINYNET_API int tnet_transport_dtls_set_remote_fingerprint(tnet_transport_handle
TINYNET_API tsk_bool_t tnet_transport_dtls_is_enabled(const tnet_transport_handle_t *handle);
TINYNET_API int tnet_transport_dtls_set_enabled(tnet_transport_handle_t *handle, tsk_bool_t enabled, struct tnet_socket_s** sockets, tsk_size_t sockets_count);
TINYNET_API int tnet_transport_dtls_set_setup(tnet_transport_handle_t* handle, tnet_dtls_setup_t setup, struct tnet_socket_s** sockets, tsk_size_t sockets_count);
TINYNET_API int tnet_transport_dtls_set_store_handshakingdata(tnet_transport_handle_t* handle, tsk_bool_t handshake_storedata, struct tnet_socket_s** sockets, tsk_size_t sockets_count);
TINYNET_API int tnet_transport_dtls_do_handshake(tnet_transport_handle_t *handle, struct tnet_socket_s** sockets, tsk_size_t sockets_count, const struct sockaddr_storage** remote_addrs, tsk_size_t remote_addrs_count);
TINYNET_API int tnet_transport_dtls_get_handshakingdata(tnet_transport_handle_t* handle, const struct tnet_socket_s** sockets, tsk_size_t sockets_count, const void* data[], tsk_size_t size[]);
TINYNET_API tnet_socket_type_t tnet_transport_get_type(const tnet_transport_handle_t *handle);
TINYNET_API tnet_fd_t tnet_transport_get_master_fd(const tnet_transport_handle_t *handle);
@ -124,7 +126,7 @@ typedef struct tnet_transport_s
char* local_host;
tnet_port_t req_local_port; // user requested local port
tnet_port_t bind_local_port; // local port on which we are listening (same as master socket)
tnet_nat_context_handle_t* natt_ctx;
struct tnet_nat_ctx_s* natt_ctx;
tnet_socket_t *master;
tsk_object_t *context;
@ -152,6 +154,7 @@ typedef struct tnet_transport_s
/* DTLS */
struct{
tsk_bool_t enabled;
tsk_bool_t activated;
tsk_bool_t use_srtp;
struct ssl_ctx_st *ctx;
tnet_fingerprint_t fingerprints[TNET_DTLS_HASH_TYPE_MAX];

View File

@ -714,15 +714,16 @@ void* TSK_STDCALL tnet_transport_mainthread(void *param)
if(ret){
ret = WSAGetLastError();
if(ret == WSAEWOULDBLOCK){
if (ret == WSAEWOULDBLOCK) {
// Doesn't (always) mean congestion but... another thread is also poll()ing the FD. For example, when TURN session has a reference to the fd.
TSK_DEBUG_WARN("WSAEWOULDBLOCK error for READ SSESSION");
}
else if(ret == WSAECONNRESET && TNET_SOCKET_TYPE_IS_DGRAM(transport->master->type)){
else if (ret == WSAECONNRESET && TNET_SOCKET_TYPE_IS_DGRAM(transport->master->type)) {
/* For DGRAM ==> The sent packet gernerated "ICMP Destination/Port unreachable" result. */
TSK_FREE(wsaBuffer.buf);
goto done; // ignore and retry.
}
else{
else {
TSK_FREE(wsaBuffer.buf);
removeSocket(index, context);

View File

@ -1,8 +1,6 @@
/*
* Copyright (C) 2010-2011 Mamadou Diop.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
@ -23,9 +21,6 @@
/**@file tnet_types.h
* @brief ????.
*
* @author Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
*/
#ifndef TNET_TYPES_H
#define TNET_TYPES_H

View File

@ -1273,13 +1273,13 @@ int tnet_inet_pton(int af, const char* src, void* dst)
# if (_WIN32_WINNT <= 0x0501)
{
struct sockaddr_storage addr = { 0 };
int addr_len = sizeof(addr);
int addr_len = (af == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
if (WSAStringToAddressA((LPSTR)src, af, NULL, (struct sockaddr *)&addr, &addr_len) == 0) {
if (af == AF_INET6) {
*((struct in6_addr *)dst) = ((struct sockaddr_in6 *)&addr)->sin6_addr;
memcpy(dst, &((struct sockaddr_in6 *)&addr)->sin6_addr, 16);
}
else {
*((struct in_addr *)dst) = ((struct sockaddr_in *)&addr)->sin_addr;
memcpy(dst, &((struct sockaddr_in *)&addr)->sin_addr, 4);
}
return 1;
}
@ -1287,7 +1287,7 @@ int tnet_inet_pton(int af, const char* src, void* dst)
return -2;
}
# else
return InetPton(af, src, dst);
return InetPtonA(af, src, dst);
# endif // TNET_UNDER_WINDOWS
#else
{
@ -1329,16 +1329,16 @@ const char *tnet_inet_ntop(int af, const void *src, char *dst, int size)
TSK_DEBUG_ERROR("Destination size too short(%d)", size);
return tsk_null;
}
addr.ss_family = AF_INET6;
((struct sockaddr_in6 *)&addr)->sin6_addr = *((struct in6_addr *)src);
((struct sockaddr_in6 *)&addr)->sin6_family = AF_INET6;
memcpy(&((struct sockaddr_in6 *)&addr)->sin6_addr, src, 16);
}
else {
if (size < INET_ADDRSTRLEN) {
TSK_DEBUG_ERROR("Destination size too short(%d)", size);
return tsk_null;
}
addr.ss_family = AF_INET;
((struct sockaddr_in *)&addr)->sin_addr = *((struct in_addr *)src);
((struct sockaddr_in *)&addr)->sin_family = AF_INET;
memcpy(&((struct sockaddr_in *)&addr)->sin_addr, src, 4);
}
if (WSAAddressToStringA((struct sockaddr*)&addr, addr_len, NULL, dst, &size) == 0) {
return dst;
@ -1347,7 +1347,7 @@ const char *tnet_inet_ntop(int af, const void *src, char *dst, int size)
return tsk_null;
}
# else
return InetNtop(af, src, dst, size);
return InetNtopA(af, (PVOID)src, dst, size);
# endif // TNET_UNDER_WINDOWS
#else
{
@ -1637,6 +1637,34 @@ int tnet_sockfd_set_mode(tnet_fd_t fd, int nonBlocking)
return 0;
}
/**@ingroup tnet_utils_group
*/
int tnet_sockfd_reuseaddr(tnet_fd_t fd, int reuseAddr)
{
if (fd != TNET_INVALID_FD) {
int ret;
#if defined(SOLARIS)
static const char yes = '1';
static const char no = '0';
#else
static const int yes = 1;
static const int no = 0;
#endif
if ((ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char*)(reuseAddr ? &yes : &no), sizeof(int)))) {
TNET_PRINT_LAST_ERROR("setsockopt(SO_REUSEADDR, fd=%d) have failed", fd);
return ret;
}
#if defined(SO_REUSEPORT)
if ((ret = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (char*)(reuseAddr ? &yes : &no), sizeof(int)))) {
TNET_PRINT_LAST_ERROR("setsockopt(SO_REUSEPORT, fd=%d) have failed", fd);
return ret;
}
#endif
return 0;
}
return -1;
}
/**@ingroup tnet_utils_group
* Sends data to a specific destination.
* @param fd The source socket.

View File

@ -146,6 +146,7 @@ TINYNET_API int tnet_sockaddr_init(const char *host, tnet_port_t port, tnet_sock
TINYNET_API int tnet_sockfd_init(const char *host, tnet_port_t port, tnet_socket_type_t type, tnet_fd_t *fd);
TINYNET_API int tnet_sockfd_set_mode(tnet_fd_t fd, int nonBlocking);
TINYNET_API int tnet_sockfd_reuseaddr(tnet_fd_t fd, int reuseAddr);
#define tnet_sockfd_set_nonblocking(fd) tnet_sockfd_set_mode(fd, 1)
#define tnet_sockfd_set_blocking(fd) tnet_sockfd_set_mode(fd, 0)

File diff suppressed because it is too large Load Diff

View File

@ -1,175 +1,175 @@
/*
* Copyright (C) 2010-2011 Mamadou Diop.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
*/
/**@file tnet_turn.h
* @brief Traversal Using Relays around NAT (TURN) implementation as per 'draft-ietf-behave-turn-16', 'draft-ietf-behave-turn-tcp-05'
* and 'draft-ietf-behave-turn-ipv6'.
* http://tools.ietf.org/html/draft-ietf-behave-turn-16
* http://tools.ietf.org/html/draft-ietf-behave-turn-tcp-05
* http://tools.ietf.org/html/draft-ietf-behave-turn-ipv6-07
*
* @author Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
*/
#ifndef TNET_TURN_H
#define TNET_TURN_H
#include "tinynet_config.h"
#include "turn/tnet_turn_attribute.h"
#include "tnet_proto.h"
#include "tnet_socket.h"
#include "tnet_types.h"
#include "tsk_object.h"
/**@ingroup tnet_turn_group
* @def TNET_TURN_PERMISSION_TIMEOUT_DEFAULT
*/
/**@ingroup tnet_turn_group
* @def TNET_TURN_CHANBIND_TIMEOUT_DEFAULT
*/
TNET_BEGIN_DECLS
#define TNET_TURN_PERMISSION_TIMEOUT_DEFAULT 300 /* draft-ietf-behave-turn-16 subclause 8 */
#define TNET_TURN_CHANBIND_TIMEOUT_DEFAULT 600 /* draft-ietf-behave-turn-16 subclause 11 */
/**@ingroup tnet_turn_group
* @def tnet_turn_allocation_id_t.
*/
/**@ingroup tnet_turn_group
* @def TNET_TURN_INVALID_ALLOCATION_ID.
*/
/**@ingroup tnet_turn_group
* @def TNET_TURN_IS_VALID_ALLOCATION_ID.
*/
typedef uint64_t tnet_turn_allocation_id_t;
#define TNET_TURN_INVALID_ALLOCATION_ID 0
#define TNET_TURN_IS_VALID_ALLOCATION_ID(id) (id != TNET_TURN_INVALID_ALLOCATION_ID)
/**@ingroup tnet_turn_group
* @def tnet_turn_channel_binding_id_t.
*/
/**@ingroup tnet_turn_group
* @def TNET_TURN_INVALID_CHANNEL_BINDING_ID.
*/
/**@ingroup tnet_turn_group
* @def TNET_TURN_IS_VALID_CHANNEL_BINDING_ID.
*/
typedef uint16_t tnet_turn_channel_binding_id_t;
#define TNET_TURN_INVALID_CHANNEL_BINDING_ID 0x00
#define TNET_TURN_IS_VALID_CHANNEL_BINDING_ID(id) ( (0x4000 <= id) && (id <= 0x7FFF) ) /* see draft-ietf-behave-turn-16 subcaluse 11. */
/**@ingroup tnet_turn_group
*/
typedef struct tnet_turn_permission_s
{
TSK_DECLARE_OBJECT;
tnet_turn_attribute_xpeer_addr_t *xpeer;
uint32_t timeout; /**< Timeout value in seconds. Default is 300s(5 minutes). */
}
tnet_turn_permission_t;
typedef tsk_list_t tnet_turn_permissions_L_t; /**< List of @ref tnet_turn_permission_t elements. */
/**@ingroup tnet_turn_group
*/
typedef struct tnet_turn_channel_binding_s
{
TSK_DECLARE_OBJECT;
tnet_turn_channel_binding_id_t id;
const struct tnet_turn_allocation_s *allocation;
tnet_turn_attribute_xpeer_addr_t *xpeer;
uint32_t timeout; /**< Timeout value in seconds. Default is 600s(10 minutes). */
}
tnet_turn_channel_binding_t;
typedef tsk_list_t tnet_turn_channel_bindings_L_t; /**< List of @ref tnet_turn_channel_binding_t elements. */
/**@ingroup tnet_turn_group
*/
typedef struct tnet_turn_allocation_s
{
TSK_DECLARE_OBJECT;
tnet_turn_allocation_id_t id; /**< Unique id. */
char* relay_address; /**< the relayed transport address */
//! Server reflexive address of the local socket(STUN1 as per RFC 3489).
tnet_stun_attribute_mapped_addr_t *maddr;
//! XORed server reflexive address (STUN2 as per RFC 5389).
tnet_stun_attribute_xmapped_addr_t *xmaddr;
/* 5-tuple */
tnet_fd_t localFD;
tnet_socket_type_t socket_type;
struct sockaddr_storage server;
/*---*/
/* the authentication information */
char* username;
char* password;
char* realm;
char* nonce;
/*---*/
/* the time-to-expiry */
uint32_t timeout; /**< Timeout value in seconds. Default is 600s(10 minutes). */
/*---*/
/* A list of permissions */
/* A list of channel to peer bindings */
char* software;
tnet_turn_channel_bindings_L_t *channel_bindings;
tnet_turn_permissions_L_t *permissions;
}
tnet_turn_allocation_t;
typedef tsk_list_t tnet_turn_allocations_L_t; /**< List of @ref tnet_turn_allocation_t elements. */
TINYNET_GEXTERN const tsk_object_def_t *tnet_turn_permission_def_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_turn_channel_binding_def_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_turn_allocation_def_t;
//#if defined(__SYMBIAN32__) || ANDROID /* Forward declaration */
struct tnet_nat_context_s;
//#endif
tnet_turn_allocation_id_t tnet_turn_allocate(const struct tnet_nat_context_s* nat_context, const tnet_fd_t localFD, tnet_socket_type_t socket_type);
int tnet_turn_allocation_refresh(const struct tnet_nat_context_s* nat_context, tnet_turn_allocation_t *allocation);
int tnet_turn_unallocate(const struct tnet_nat_context_s* nat_context, tnet_turn_allocation_t *allocation);
tnet_turn_channel_binding_id_t tnet_turn_channel_bind(const struct tnet_nat_context_s* nat_context, tnet_turn_allocation_t *allocation, struct sockaddr_storage *peer);
int tnet_turn_channel_refresh(const struct tnet_nat_context_s* nat_context, const tnet_turn_channel_binding_t * channel_bind);
int tnet_turn_channel_senddata(const struct tnet_nat_context_s* nat_context, const tnet_turn_channel_binding_t * channel_bind, const void* data, tsk_size_t size, int indication);
int tnet_turn_add_permission(const struct tnet_nat_context_s* nat_context, tnet_turn_allocation_t *allocation, const char* ipaddress, uint32_t timeout);
TNET_END_DECLS
#endif /* TNET_TURN_H */
///*
//* Copyright (C) 2010-2011 Mamadou Diop.
//*
//* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
//*
//* This file is part of Open Source Doubango Framework.
//*
//* DOUBANGO is free software: you can redistribute it and/or modify
//* it under the terms of the GNU General Public License as published by
//* the Free Software Foundation, either version 3 of the License, or
//* (at your option) any later version.
//*
//* DOUBANGO is distributed in the hope that it will be useful,
//* but WITHOUT ANY WARRANTY; without even the implied warranty of
//* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//* GNU General Public License for more details.
//*
//* You should have received a copy of the GNU General Public License
//* along with DOUBANGO.
//*
//*/
//
///**@file tnet_turn.h
// * @brief Traversal Using Relays around NAT (TURN) implementation as per 'draft-ietf-behave-turn-16', 'draft-ietf-behave-turn-tcp-05'
// * and 'draft-ietf-behave-turn-ipv6'.
// * http://tools.ietf.org/html/draft-ietf-behave-turn-16
// * http://tools.ietf.org/html/draft-ietf-behave-turn-tcp-05
// * http://tools.ietf.org/html/draft-ietf-behave-turn-ipv6-07
// *
// * @author Mamadou Diop <diopmamadou(at)doubango[dot]org>
// *
//
// */
//#ifndef TNET_TURN_H
//#define TNET_TURN_H
//
//#include "tinynet_config.h"
//
//#include "turn/tnet_turn_attribute.h"
//
//#include "tnet_proto.h"
//#include "tnet_socket.h"
//#include "tnet_types.h"
//
//#include "tsk_object.h"
//
///**@ingroup tnet_turn_group
//* @def TNET_TURN_PERMISSION_TIMEOUT_DEFAULT
//*/
///**@ingroup tnet_turn_group
//* @def TNET_TURN_CHANBIND_TIMEOUT_DEFAULT
//*/
//TNET_BEGIN_DECLS
//
//#define TNET_TURN_PERMISSION_TIMEOUT_DEFAULT 300 /* draft-ietf-behave-turn-16 subclause 8 */
//#define TNET_TURN_CHANBIND_TIMEOUT_DEFAULT 600 /* draft-ietf-behave-turn-16 subclause 11 */
//
//
///**@ingroup tnet_turn_group
//* @def tnet_turn_allocation_id_t.
//*/
///**@ingroup tnet_turn_group
//* @def TNET_TURN_INVALID_ALLOCATION_ID.
//*/
///**@ingroup tnet_turn_group
//* @def TNET_TURN_IS_VALID_ALLOCATION_ID.
//*/
//typedef uint64_t tnet_turn_allocation_id_t;
//#define TNET_TURN_INVALID_ALLOCATION_ID 0
//#define TNET_TURN_IS_VALID_ALLOCATION_ID(id) (id != TNET_TURN_INVALID_ALLOCATION_ID)
//
///**@ingroup tnet_turn_group
//* @def tnet_turn_channel_binding_id_t.
//*/
///**@ingroup tnet_turn_group
//* @def TNET_TURN_INVALID_CHANNEL_BINDING_ID.
//*/
///**@ingroup tnet_turn_group
//* @def TNET_TURN_IS_VALID_CHANNEL_BINDING_ID.
//*/
//typedef uint16_t tnet_turn_channel_binding_id_t;
//#define TNET_TURN_INVALID_CHANNEL_BINDING_ID 0x00
//#define TNET_TURN_IS_VALID_CHANNEL_BINDING_ID(id) ( (0x4000 <= id) && (id <= 0x7FFF) ) /* see draft-ietf-behave-turn-16 subcaluse 11. */
//
///**@ingroup tnet_turn_group
//*/
//typedef struct tnet_turn_permission_s
//{
// TSK_DECLARE_OBJECT;
//
// tnet_turn_attribute_xpeer_addr_t *xpeer;
// uint32_t timeout; /**< Timeout value in seconds. Default is 300s(5 minutes). */
//}
//tnet_turn_permission_t;
//typedef tsk_list_t tnet_turn_permissions_L_t; /**< List of @ref tnet_turn_permission_t elements. */
//
///**@ingroup tnet_turn_group
//*/
//typedef struct tnet_turn_channel_binding_s
//{
// TSK_DECLARE_OBJECT;
//
// tnet_turn_channel_binding_id_t id;
// const struct tnet_turn_allocation_s *allocation;
// tnet_turn_attribute_xpeer_addr_t *xpeer;
// uint32_t timeout; /**< Timeout value in seconds. Default is 600s(10 minutes). */
//}
//tnet_turn_channel_binding_t;
//typedef tsk_list_t tnet_turn_channel_bindings_L_t; /**< List of @ref tnet_turn_channel_binding_t elements. */
//
///**@ingroup tnet_turn_group
//*/
//typedef struct tnet_turn_allocation_s
//{
// TSK_DECLARE_OBJECT;
//
// tnet_turn_allocation_id_t id; /**< Unique id. */
//
// char* relay_address; /**< the relayed transport address */
// //! Server reflexive address of the local socket(STUN1 as per RFC 3489).
// tnet_stun_attribute_mapped_addr_t *maddr;
// //! XORed server reflexive address (STUN2 as per RFC 5389).
// tnet_stun_attribute_xmapped_addr_t *xmaddr;
//
// /* 5-tuple */
// tnet_fd_t localFD;
// tnet_socket_type_t socket_type;
//
// struct sockaddr_storage server;
//
// /*---*/
//
// /* the authentication information */
// char* username;
// char* password;
// char* realm;
// char* nonce;
// /*---*/
//
// /* the time-to-expiry */
// uint32_t timeout; /**< Timeout value in seconds. Default is 600s(10 minutes). */
// /*---*/
//
// /* A list of permissions */
// /* A list of channel to peer bindings */
//
// char* software;
//
// tnet_turn_channel_bindings_L_t *channel_bindings;
// tnet_turn_permissions_L_t *permissions;
//}
//tnet_turn_allocation_t;
//typedef tsk_list_t tnet_turn_allocations_L_t; /**< List of @ref tnet_turn_allocation_t elements. */
//
//TINYNET_GEXTERN const tsk_object_def_t *tnet_turn_permission_def_t;
//TINYNET_GEXTERN const tsk_object_def_t *tnet_turn_channel_binding_def_t;
//TINYNET_GEXTERN const tsk_object_def_t *tnet_turn_allocation_def_t;
//
////#if defined(__SYMBIAN32__) || ANDROID /* Forward declaration */
//struct struct tnet_nat_ctx_s;
////#endif
//
//tnet_turn_allocation_id_t tnet_turn_allocate(const struct struct tnet_nat_ctx_s* nat_context, const tnet_fd_t localFD, tnet_socket_type_t socket_type);
//int tnet_turn_allocation_refresh(const struct struct tnet_nat_ctx_s* nat_context, tnet_turn_allocation_t *allocation);
//int tnet_turn_unallocate(const struct struct tnet_nat_ctx_s* nat_context, tnet_turn_allocation_t *allocation);
//tnet_turn_channel_binding_id_t tnet_turn_channel_bind(const struct struct tnet_nat_ctx_s* nat_context, tnet_turn_allocation_t *allocation, struct sockaddr_storage *peer);
//int tnet_turn_channel_refresh(const struct struct tnet_nat_ctx_s* nat_context, const tnet_turn_channel_binding_t * channel_bind);
//int tnet_turn_channel_senddata(const struct struct tnet_nat_ctx_s* nat_context, const tnet_turn_channel_binding_t * channel_bind, const void* data, tsk_size_t size, int indication);
//int tnet_turn_add_permission(const struct struct tnet_nat_ctx_s* nat_context, tnet_turn_allocation_t *allocation, const char* ipaddress, uint32_t timeout);
//
//
//TNET_END_DECLS
//
//#endif /* TNET_TURN_H */
//

View File

@ -1,21 +1,21 @@
/* Copyright (C) 2014 Mamadou DIOP.
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
*/
#include "turn/tnet_turn_attr.h"
#include "tsk_debug.h"
///* Copyright (C) 2014 Mamadou DIOP.
//*
//* This file is part of Open Source Doubango Framework.
//*
//* DOUBANGO is free software: you can redistribute it and/or modify
//* it under the terms of the GNU General Public License as published by
//* the Free Software Foundation, either version 3 of the License, or
//* (at your option) any later version.
//*
//* DOUBANGO is distributed in the hope that it will be useful,
//* but WITHOUT ANY WARRANTY; without even the implied warranty of
//* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//* GNU Lesser General Public License for more details.
//*
//* You should have received a copy of the GNU General Public License
//* along with DOUBANGO.
//*
//*/
//#include "turn/tnet_turn_attr.h"
//
//#include "tsk_debug.h"

View File

@ -1,32 +1,32 @@
/* Copyright (C) 2014 Mamadou DIOP.
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
*/
#ifndef TNET_TURN_ATTR_H
#define TNET_TURN_ATTR_H
#include "tinynet_config.h"
#include "stun/tnet_stun_types.h"
#include "tsk_object.h"
#include "tsk_list.h"
TNET_BEGIN_DECLS
TNET_END_DECLS
#endif /* TNET_TURN_ATTR_H */
///* Copyright (C) 2014 Mamadou DIOP.
//*
//* This file is part of Open Source Doubango Framework.
//*
//* DOUBANGO is free software: you can redistribute it and/or modify
//* it under the terms of the GNU General Public License as published by
//* the Free Software Foundation, either version 3 of the License, or
//* (at your option) any later version.
//*
//* DOUBANGO is distributed in the hope that it will be useful,
//* but WITHOUT ANY WARRANTY; without even the implied warranty of
//* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//* GNU Lesser General Public License for more details.
//*
//* You should have received a copy of the GNU General Public License
//* along with DOUBANGO.
//*
//*/
//#ifndef TNET_TURN_ATTR_H
//#define TNET_TURN_ATTR_H
//
//#include "tinynet_config.h"
//#include "stun/tnet_stun_types.h"
//
//#include "tsk_object.h"
//#include "tsk_list.h"
//
//TNET_BEGIN_DECLS
//
//TNET_END_DECLS
//
//#endif /* TNET_TURN_ATTR_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,196 +1,196 @@
/*
* Copyright (C) 2010-2011 Mamadou Diop.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
*/
/**@file tnet_turn_attribute.h
* @brief New STUN Attributes as per draft-ietf-behave-turn-16 subclause 14.
*
* @author Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
*/
#ifndef TNET_TURN_ATTRIBUTE_H
#define TNET_TURN_ATTRIBUTE_H
#include "tinynet_config.h"
#include "tnet_proto.h"
#include "stun/tnet_stun_attribute.h"
TNET_BEGIN_DECLS
typedef tnet_stun_attribute_t tnet_turn_attribute_t;
/* draft-ietf-behave-turn-16 - 14.1. CHANNEL-NUMBER
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Channel Number | RFFU = 0 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**@ingroup tnet_turn_group
*/
typedef struct tnet_turn_attribute_channelnum_s
{
TNET_STUN_DECLARE_ATTRIBUTE;
uint16_t number;
uint16_t rffu;
}
tnet_turn_attribute_channelnum_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_turn_attribute_channelnum_def_t;
/**@ingroup tnet_turn_group
* draft-ietf-behave-turn-16 - 14.2. LIFETIME
*/
typedef struct tnet_turn_attribute_lifetime_s
{
TNET_STUN_DECLARE_ATTRIBUTE;
uint32_t value;
}
tnet_turn_attribute_lifetime_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_turn_attribute_lifetime_def_t;
/**@ingroup tnet_turn_group
* draft-ietf-behave-turn-16 - 14.3. XOR-PEER-ADDRESS
*/
typedef struct tnet_turn_attribute_xpeer_addr_s
{
TNET_STUN_DECLARE_ATTRIBUTE;
tnet_stun_addr_family_t family;
uint16_t xport;
uint8_t xaddress[16];
}
tnet_turn_attribute_xpeer_addr_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_turn_attribute_xpeer_addr_def_t;
/**@ingroup tnet_turn_group
* draft-ietf-behave-turn-16 - 14.4. DATA
*/
typedef struct tnet_turn_attribute_data_s
{
TNET_STUN_DECLARE_ATTRIBUTE;
tsk_buffer_t* value;
}
tnet_turn_attribute_data_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_turn_attribute_data_def_t;
/**@ingroup tnet_turn_group
* draft-ietf-behave-turn-16 - 14.5. XOR-RELAYED-ADDRESS
*/
typedef struct tnet_turn_attribute_xrelayed_addr_s
{
TNET_STUN_DECLARE_ATTRIBUTE;
tnet_stun_addr_family_t family;
uint16_t xport;
uint8_t xaddress[16];
}
tnet_turn_attribute_xrelayed_addr_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_turn_attribute_xrelayed_addr_def_t;
/**@ingroup tnet_turn_group
* draft-ietf-behave-turn-16 - 14.6. EVEN-PORT
*/
typedef struct tnet_turn_attribute_even_port_s
{
TNET_STUN_DECLARE_ATTRIBUTE;
/*
0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
|R| RFFU |
+-+-+-+-+-+-+-+-+
*/
unsigned R:1;
unsigned rffu:7;
}
tnet_turn_attribute_even_port_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_turn_attribute_even_port_def_t;
/**@ingroup tnet_turn_group
*/
typedef struct tnet_turn_attribute_reqtrans_s
{
TNET_STUN_DECLARE_ATTRIBUTE;
/*
draft-ietf-behave-turn-16 - 14.7. REQUESTED-TRANSPORT
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Protocol | RFFU |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
tnet_proto_t protocol;
uint8_t rffu[3];
}
tnet_turn_attribute_reqtrans_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_turn_attribute_reqtrans_def_t;
/**@ingroup tnet_turn_group
* draft-ietf-behave-turn-16 - 14.8. DONT-FRAGMENT
*/
typedef struct tnet_turn_attribute_dontfrag_s
{
TNET_STUN_DECLARE_ATTRIBUTE;
}
tnet_turn_attribute_dontfrag_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_turn_attribute_dontfrag_def_t;
/**@ingroup tnet_turn_group
* draft-ietf-behave-turn-16 - 14.9. RESERVATION-TOKEN
*/
typedef struct tnet_turn_attribute_restoken_s
{
TNET_STUN_DECLARE_ATTRIBUTE;
uint8_t value[8];
}
tnet_turn_attribute_restoken_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_turn_attribute_restoken_def_t;
tnet_stun_attribute_t* tnet_turn_attribute_deserialize(tnet_stun_attribute_type_t type, uint16_t length, const void* payload, tsk_size_t payload_size);
int tnet_turn_attribute_serialize(const tnet_stun_attribute_t* attribute, tsk_buffer_t *output);
tnet_turn_attribute_channelnum_t* tnet_turn_attribute_channelnum_create(uint16_t number);
tnet_turn_attribute_lifetime_t* tnet_turn_attribute_lifetime_create(uint32_t lifetime);
tnet_turn_attribute_xpeer_addr_t* tnet_turn_attribute_xpeer_addr_create(const void* payload, tsk_size_t payload_size);
tnet_turn_attribute_xpeer_addr_t* tnet_turn_attribute_xpeer_addr_create_null();
tnet_turn_attribute_data_t* tnet_turn_attribute_data_create(const void* payload, tsk_size_t payload_size);
tnet_turn_attribute_xrelayed_addr_t* tnet_turn_attribute_xrelayed_addr_create(const void* payload, tsk_size_t payload_size);
tnet_turn_attribute_even_port_t* tnet_turn_attribute_even_port_create(unsigned R);
tnet_turn_attribute_reqtrans_t* tnet_turn_attribute_reqtrans_create(tnet_proto_t protocol);
tnet_turn_attribute_dontfrag_t* tnet_turn_attribute_dontfrag_create();
tnet_turn_attribute_restoken_t* tnet_turn_attribute_restoken_create(const void* payload, tsk_size_t payload_size);
TNET_END_DECLS
#endif /* TNET_TURN_ATTRIBUTE_H */
///*
//* Copyright (C) 2010-2011 Mamadou Diop.
//*
//* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
//*
//* This file is part of Open Source Doubango Framework.
//*
//* DOUBANGO is free software: you can redistribute it and/or modify
//* it under the terms of the GNU General Public License as published by
//* the Free Software Foundation, either version 3 of the License, or
//* (at your option) any later version.
//*
//* DOUBANGO is distributed in the hope that it will be useful,
//* but WITHOUT ANY WARRANTY; without even the implied warranty of
//* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//* GNU General Public License for more details.
//*
//* You should have received a copy of the GNU General Public License
//* along with DOUBANGO.
//*
//*/
//
///**@file tnet_turn_attribute.h
// * @brief New STUN Attributes as per draft-ietf-behave-turn-16 subclause 14.
// *
// * @author Mamadou Diop <diopmamadou(at)doubango[dot]org>
// *
//
// */
//#ifndef TNET_TURN_ATTRIBUTE_H
//#define TNET_TURN_ATTRIBUTE_H
//
//#include "tinynet_config.h"
//#include "tnet_proto.h"
//#include "stun/tnet_stun_attribute.h"
//
//TNET_BEGIN_DECLS
//
//typedef tnet_stun_attr_t tnet_turn_attribute_t;
//
///* draft-ietf-behave-turn-16 - 14.1. CHANNEL-NUMBER
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Channel Number | RFFU = 0 |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//*/
///**@ingroup tnet_turn_group
//*/
//typedef struct tnet_turn_attribute_channelnum_s
//{
// TNET_STUN_DECLARE_ATTRIBUTE;
//
// uint16_t number;
// uint16_t rffu;
//}
//tnet_turn_attribute_channelnum_t;
//TINYNET_GEXTERN const tsk_object_def_t *tnet_turn_attribute_channelnum_def_t;
//
//
///**@ingroup tnet_turn_group
//* draft-ietf-behave-turn-16 - 14.2. LIFETIME
//*/
//typedef struct tnet_turn_attribute_lifetime_s
//{
// TNET_STUN_DECLARE_ATTRIBUTE;
//
// uint32_t value;
//}
//tnet_turn_attribute_lifetime_t;
//TINYNET_GEXTERN const tsk_object_def_t *tnet_turn_attribute_lifetime_def_t;
//
//
///**@ingroup tnet_turn_group
//* draft-ietf-behave-turn-16 - 14.3. XOR-PEER-ADDRESS
//*/
//typedef struct tnet_turn_attribute_xpeer_addr_s
//{
// TNET_STUN_DECLARE_ATTRIBUTE;
//
// tnet_stun_addr_family_t family;
// uint16_t xport;
// uint8_t xaddress[16];
//}
//tnet_turn_attribute_xpeer_addr_t;
//TINYNET_GEXTERN const tsk_object_def_t *tnet_turn_attribute_xpeer_addr_def_t;
//
///**@ingroup tnet_turn_group
//* draft-ietf-behave-turn-16 - 14.4. DATA
//*/
//typedef struct tnet_turn_attribute_data_s
//{
// TNET_STUN_DECLARE_ATTRIBUTE;
//
// tsk_buffer_t* value;
//}
//tnet_turn_attribute_data_t;
//TINYNET_GEXTERN const tsk_object_def_t *tnet_turn_attribute_data_def_t;
//
///**@ingroup tnet_turn_group
//* draft-ietf-behave-turn-16 - 14.5. XOR-RELAYED-ADDRESS
//*/
//typedef struct tnet_turn_attribute_xrelayed_addr_s
//{
// TNET_STUN_DECLARE_ATTRIBUTE;
//
// tnet_stun_addr_family_t family;
// uint16_t xport;
// uint8_t xaddress[16];
//}
//tnet_turn_attribute_xrelayed_addr_t;
//TINYNET_GEXTERN const tsk_object_def_t *tnet_turn_attribute_xrelayed_addr_def_t;
//
///**@ingroup tnet_turn_group
//* draft-ietf-behave-turn-16 - 14.6. EVEN-PORT
//*/
//typedef struct tnet_turn_attribute_even_port_s
//{
// TNET_STUN_DECLARE_ATTRIBUTE;
//
///*
// 0 1 2 3 4 5 6 7
// +-+-+-+-+-+-+-+-+
// |R| RFFU |
// +-+-+-+-+-+-+-+-+
//*/
// unsigned R:1;
// unsigned rffu:7;
//}
//tnet_turn_attribute_even_port_t;
//TINYNET_GEXTERN const tsk_object_def_t *tnet_turn_attribute_even_port_def_t;
//
//
///**@ingroup tnet_turn_group
//*/
//typedef struct tnet_turn_attribute_reqtrans_s
//{
// TNET_STUN_DECLARE_ATTRIBUTE;
///*
// draft-ietf-behave-turn-16 - 14.7. REQUESTED-TRANSPORT
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Protocol | RFFU |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//*/
// tnet_proto_t protocol;
// uint8_t rffu[3];
//}
//tnet_turn_attribute_reqtrans_t;
//TINYNET_GEXTERN const tsk_object_def_t *tnet_turn_attribute_reqtrans_def_t;
//
//
//
///**@ingroup tnet_turn_group
//* draft-ietf-behave-turn-16 - 14.8. DONT-FRAGMENT
//*/
//typedef struct tnet_turn_attribute_dontfrag_s
//{
// TNET_STUN_DECLARE_ATTRIBUTE;
//}
//tnet_turn_attribute_dontfrag_t;
//TINYNET_GEXTERN const tsk_object_def_t *tnet_turn_attribute_dontfrag_def_t;
//
//
///**@ingroup tnet_turn_group
//* draft-ietf-behave-turn-16 - 14.9. RESERVATION-TOKEN
//*/
//typedef struct tnet_turn_attribute_restoken_s
//{
// TNET_STUN_DECLARE_ATTRIBUTE;
//
// uint8_t value[8];
//}
//tnet_turn_attribute_restoken_t;
//TINYNET_GEXTERN const tsk_object_def_t *tnet_turn_attribute_restoken_def_t;
//
//
//tnet_stun_attr_t* tnet_turn_attribute_deserialize(tnet_stun_attr_type_t type, uint16_t length, const void* payload, tsk_size_t payload_size);
//int tnet_turn_attribute_serialize(const tnet_stun_attr_t* attribute, tsk_buffer_t *output);
//
//tnet_turn_attribute_channelnum_t* tnet_turn_attribute_channelnum_create(uint16_t number);
//tnet_turn_attribute_lifetime_t* tnet_turn_attribute_lifetime_create(uint32_t lifetime);
//tnet_turn_attribute_xpeer_addr_t* tnet_turn_attribute_xpeer_addr_create(const void* payload, tsk_size_t payload_size);
//tnet_turn_attribute_xpeer_addr_t* tnet_turn_attribute_xpeer_addr_create_null();
//tnet_turn_attribute_data_t* tnet_turn_attribute_data_create(const void* payload, tsk_size_t payload_size);
//tnet_turn_attribute_xrelayed_addr_t* tnet_turn_attribute_xrelayed_addr_create(const void* payload, tsk_size_t payload_size);
//tnet_turn_attribute_even_port_t* tnet_turn_attribute_even_port_create(unsigned R);
//tnet_turn_attribute_reqtrans_t* tnet_turn_attribute_reqtrans_create(tnet_proto_t protocol);
//tnet_turn_attribute_dontfrag_t* tnet_turn_attribute_dontfrag_create();
//tnet_turn_attribute_restoken_t* tnet_turn_attribute_restoken_create(const void* payload, tsk_size_t payload_size);
//
//TNET_END_DECLS
//
//#endif /* TNET_TURN_ATTRIBUTE_H */
//

View File

@ -1,163 +1,163 @@
/*
* Copyright (C) 2010-2011 Mamadou Diop.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
*/
/**@file tnet_turn_message.c
* @brief Traversal Using Relays around NAT (TURN) messages.
*
* @author Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
*/
#include "tnet_turn_message.h"
#include "../tnet_types.h"
#include "../tnet_endianness.h"
#include "tsk_memory.h"
#include <string.h>
tnet_turn_channel_data_t* tnet_turn_channel_data_create(uint16_t number, uint16_t length, const void* data)
{
return tsk_object_new(tnet_turn_channel_data_def_t, number, length, data);
}
tnet_turn_channel_data_t* tnet_turn_channel_data_create_null()
{
return tnet_turn_channel_data_create(0, 0, tsk_null);
}
/**@ingroup tnet_turn_group
*/
tsk_buffer_t* tnet_turn_channel_data_serialize(const tnet_turn_channel_data_t *message)
{
tsk_buffer_t *output = 0;
if(!message) goto bail;
output = tsk_buffer_create_null();
/* draft-ietf-behave-turn-16 11.4. The ChannelData Message
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Channel Number | Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
/ Application Data /
/ /
| |
| +-------------------------------+
| |
+-------------------------------+
*/
/* Channel Number
*/
{
uint16_t number = tnet_htons(message->chanel_number);
tsk_buffer_append(output, &(number), 2);
}
/* Length
*/
{
uint16_t length = tnet_htons(message->length);
tsk_buffer_append(output, &(length), 2);
}
/* Application Data
*/
{
tsk_buffer_append(output, message->data, message->length);
/* === Padding:
Over stream transports, the ChannelData message MUST be padded to a
multiple of four bytes in order to ensure the alignment of subsequent
messages. The padding is not reflected in the length field of the
ChannelData message, so the actual size of a ChannelData message
(including padding) is (4 + Length) rounded up to the nearest
multiple of 4. Over UDP, the padding is not required but MAY be included.
*/
if(message->length%4)
{
static uint32_t zeros = 0x00000000;
tsk_buffer_append(output, &zeros, 4-(message->length%4));
}
}
bail:
return output;
}
//=================================================================================================
// TURN CHANNEL-DATA message object definition
///*
//* Copyright (C) 2010-2011 Mamadou Diop.
//*
//* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
//*
//* This file is part of Open Source Doubango Framework.
//*
//* DOUBANGO is free software: you can redistribute it and/or modify
//* it under the terms of the GNU General Public License as published by
//* the Free Software Foundation, either version 3 of the License, or
//* (at your option) any later version.
//*
//* DOUBANGO is distributed in the hope that it will be useful,
//* but WITHOUT ANY WARRANTY; without even the implied warranty of
//* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//* GNU General Public License for more details.
//*
//* You should have received a copy of the GNU General Public License
//* along with DOUBANGO.
//*
//*/
//
static tsk_object_t* tnet_turn_channel_data_ctor(tsk_object_t * self, va_list * app)
{
tnet_turn_channel_data_t *message = self;
if(message){
const void* data;
message->chanel_number = tsk_va_arg_u16(*app);
message->length = tsk_va_arg_u16(*app);
data = va_arg(*app, const void*);
if(data && message->length){
if((message->data = tsk_calloc(message->length, sizeof(uint8_t)))){
memcpy(message->data, data, message->length);
}
}
}
return self;
}
static tsk_object_t* tnet_turn_channel_data_dtor(tsk_object_t * self)
{
tnet_turn_channel_data_t *message = self;
if(message){
TSK_FREE(message->data);
}
return self;
}
static const tsk_object_def_t tnet_turn_channel_data_def_s =
{
sizeof(tnet_turn_channel_data_t),
tnet_turn_channel_data_ctor,
tnet_turn_channel_data_dtor,
tsk_null,
};
const tsk_object_def_t *tnet_turn_channel_data_def_t = &tnet_turn_channel_data_def_s;
///**@file tnet_turn_message.c
// * @brief Traversal Using Relays around NAT (TURN) messages.
// *
// * @author Mamadou Diop <diopmamadou(at)doubango[dot]org>
// *
//
// */
//#include "tnet_turn_message.h"
//
//#include "../tnet_types.h"
//#include "../tnet_endianness.h"
//
//#include "tsk_memory.h"
//
//#include <string.h>
//
//tnet_turn_channel_data_t* tnet_turn_channel_data_create(uint16_t number, uint16_t length, const void* data)
//{
// return tsk_object_new(tnet_turn_channel_data_def_t, number, length, data);
//}
//
//tnet_turn_channel_data_t* tnet_turn_channel_data_create_null()
//{
// return tnet_turn_channel_data_create(0, 0, tsk_null);
//}
//
///**@ingroup tnet_turn_group
//*/
//tsk_buffer_t* tnet_turn_channel_data_serialize(const tnet_turn_channel_data_t *message)
//{
// tsk_buffer_t *output = 0;
//
// if(!message) goto bail;
//
// output = tsk_buffer_create_null();
//
// /* draft-ietf-behave-turn-16 11.4. The ChannelData Message
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Channel Number | Length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | |
// / Application Data /
// / /
// | |
// | +-------------------------------+
// | |
// +-------------------------------+
// */
//
// /* Channel Number
// */
// {
// uint16_t number = tnet_htons(message->chanel_number);
// tsk_buffer_append(output, &(number), 2);
// }
//
// /* Length
// */
// {
// uint16_t length = tnet_htons(message->length);
// tsk_buffer_append(output, &(length), 2);
// }
//
// /* Application Data
// */
// {
// tsk_buffer_append(output, message->data, message->length);
//
// /* === Padding:
// Over stream transports, the ChannelData message MUST be padded to a
// multiple of four bytes in order to ensure the alignment of subsequent
// messages. The padding is not reflected in the length field of the
// ChannelData message, so the actual size of a ChannelData message
// (including padding) is (4 + Length) rounded up to the nearest
// multiple of 4. Over UDP, the padding is not required but MAY be included.
// */
// if(message->length%4)
// {
// static uint32_t zeros = 0x00000000;
// tsk_buffer_append(output, &zeros, 4-(message->length%4));
// }
// }
//
//bail:
// return output;
//}
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
////=================================================================================================
//// TURN CHANNEL-DATA message object definition
////
//static tsk_object_t* tnet_turn_channel_data_ctor(tsk_object_t * self, va_list * app)
//{
// tnet_turn_channel_data_t *message = self;
// if(message){
// const void* data;
// message->chanel_number = tsk_va_arg_u16(*app);
// message->length = tsk_va_arg_u16(*app);
// data = va_arg(*app, const void*);
// if(data && message->length){
// if((message->data = tsk_calloc(message->length, sizeof(uint8_t)))){
// memcpy(message->data, data, message->length);
// }
// }
// }
// return self;
//}
//
//static tsk_object_t* tnet_turn_channel_data_dtor(tsk_object_t * self)
//{
// tnet_turn_channel_data_t *message = self;
// if(message){
// TSK_FREE(message->data);
// }
//
// return self;
//}
//
//static const tsk_object_def_t tnet_turn_channel_data_def_s =
//{
// sizeof(tnet_turn_channel_data_t),
// tnet_turn_channel_data_ctor,
// tnet_turn_channel_data_dtor,
// tsk_null,
//};
//const tsk_object_def_t *tnet_turn_channel_data_def_t = &tnet_turn_channel_data_def_s;

View File

@ -1,75 +1,75 @@
/*
* Copyright (C) 2010-2011 Mamadou Diop.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
*/
/**@file tnet_turn_message.h
* @brief Traversal Using Relays around NAT (TURN) messages.
*
* @author Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
*/
#ifndef TNET_TURN_MESSAGE_H
#define TNET_TURN_MESSAGE_H
#include "../tinynet_config.h"
#include "tsk_buffer.h"
TNET_BEGIN_DECLS
/**@ingroup tnet_turn_group
* TURN channel data message as per draft-ietf-behave-turn-16 subclause 11.4.
*/
typedef struct tnet_turn_channel_data_s
{
TSK_DECLARE_OBJECT;
/* draft-ietf-behave-turn-16 11.4. The ChannelData Message
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Channel Number | Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
/ Application Data /
/ /
| |
| +-------------------------------+
| |
+-------------------------------+
*/
uint16_t chanel_number;
uint16_t length;
void* data;
}
tnet_turn_channel_data_t;
tsk_buffer_t* tnet_turn_channel_data_serialize(const tnet_turn_channel_data_t *message);
tnet_turn_channel_data_t* tnet_turn_channel_data_create(uint16_t number, uint16_t length, const void* data);
tnet_turn_channel_data_t* tnet_turn_channel_data_create_null();
TINYNET_GEXTERN const tsk_object_def_t *tnet_turn_channel_data_def_t;
TNET_END_DECLS
#endif /* TNET_TURN_MESSAGE_H */
///*
//* Copyright (C) 2010-2011 Mamadou Diop.
//*
//* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
//*
//* This file is part of Open Source Doubango Framework.
//*
//* DOUBANGO is free software: you can redistribute it and/or modify
//* it under the terms of the GNU General Public License as published by
//* the Free Software Foundation, either version 3 of the License, or
//* (at your option) any later version.
//*
//* DOUBANGO is distributed in the hope that it will be useful,
//* but WITHOUT ANY WARRANTY; without even the implied warranty of
//* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//* GNU General Public License for more details.
//*
//* You should have received a copy of the GNU General Public License
//* along with DOUBANGO.
//*
//*/
//
///**@file tnet_turn_message.h
// * @brief Traversal Using Relays around NAT (TURN) messages.
// *
// * @author Mamadou Diop <diopmamadou(at)doubango[dot]org>
// *
//
// */
//#ifndef TNET_TURN_MESSAGE_H
//#define TNET_TURN_MESSAGE_H
//
//#include "../tinynet_config.h"
//
//#include "tsk_buffer.h"
//
//TNET_BEGIN_DECLS
//
///**@ingroup tnet_turn_group
// * TURN channel data message as per draft-ietf-behave-turn-16 subclause 11.4.
//*/
//typedef struct tnet_turn_channel_data_s
//{
// TSK_DECLARE_OBJECT;
//
// /* draft-ietf-behave-turn-16 11.4. The ChannelData Message
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Channel Number | Length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | |
// / Application Data /
// / /
// | |
// | +-------------------------------+
// | |
// +-------------------------------+
// */
// uint16_t chanel_number;
// uint16_t length;
// void* data;
//}
//tnet_turn_channel_data_t;
//
//tsk_buffer_t* tnet_turn_channel_data_serialize(const tnet_turn_channel_data_t *message);
//
//tnet_turn_channel_data_t* tnet_turn_channel_data_create(uint16_t number, uint16_t length, const void* data);
//tnet_turn_channel_data_t* tnet_turn_channel_data_create_null();
//
//TINYNET_GEXTERN const tsk_object_def_t *tnet_turn_channel_data_def_t;
//
//TNET_END_DECLS
//
//#endif /* TNET_TURN_MESSAGE_H */

File diff suppressed because it is too large Load Diff

View File

@ -29,6 +29,7 @@ TNET_BEGIN_DECLS
struct tnet_turn_session_s;
struct tnet_socket_s;
enum tnet_socket_type_e;
#define kTurnPeerIdInvalid -1
typedef enum tnet_turn_session_event_type_e
{
@ -46,7 +47,10 @@ tnet_turn_session_event_type_t;
typedef struct tnet_turn_session_event_xs {
enum tnet_turn_session_event_type_e e_type;
tnet_turn_peer_id_t u_peer_id;
const void* pc_usr_data;
const struct tnet_transport_event_s* pc_enet;
struct tnet_turn_session_s* pc_session;
struct {
const void* pc_data_ptr;
tsk_size_t u_data_size;
@ -68,9 +72,13 @@ TINYNET_API int tnet_turn_session_start(struct tnet_turn_session_s* p_self);
TINYNET_API int tnet_turn_session_allocate(struct tnet_turn_session_s* p_self);
TINYNET_API int tnet_turn_session_get_relayed_addr(const struct tnet_turn_session_s* p_self, char** pp_ip, uint16_t *pu_port, tsk_bool_t *pb_ipv6);
TINYNET_API int tnet_turn_session_get_srflx_addr(const struct tnet_turn_session_s* p_self, char** pp_ip, uint16_t *pu_port, tsk_bool_t *pb_ipv6);
TINYNET_API int tnet_turn_session_createpermission(struct tnet_turn_session_s* p_self, const char* pc_peer_addr, uint16_t u_peer_port);
TINYNET_API int tnet_turn_session_chanbind(struct tnet_turn_session_s* p_self);
TINYNET_API int tnet_turn_session_send_data(struct tnet_turn_session_s* p_self, const void* pc_data_ptr, uint16_t u_data_size);
TINYNET_API int tnet_turn_session_get_state_alloc(const struct tnet_turn_session_s* pc_self, enum tnet_stun_state_e *pe_state);
TINYNET_API int tnet_turn_session_get_state_createperm(const struct tnet_turn_session_s* pc_self, tnet_turn_peer_id_t u_peer_id, enum tnet_stun_state_e *pe_state);
TINYNET_API int tnet_turn_session_createpermission(struct tnet_turn_session_s* p_self, const char* pc_peer_addr, uint16_t u_peer_port, tnet_turn_peer_id_t* pu_peer_id);
TINYNET_API int tnet_turn_session_deletepermission(struct tnet_turn_session_s* p_self, tnet_turn_peer_id_t u_peer_id);
TINYNET_API int tnet_turn_session_chanbind(struct tnet_turn_session_s* p_self, tnet_turn_peer_id_t u_peer_id);
TINYNET_API int tnet_turn_session_send_data(struct tnet_turn_session_s* p_self, tnet_turn_peer_id_t u_peer_id, const void* pc_data_ptr, uint16_t u_data_size);
TINYNET_API int tnet_turn_session_is_active(const struct tnet_turn_session_s* pc_self, tnet_turn_peer_id_t u_peer_id, tsk_bool_t *pb_active);
TINYNET_API int tnet_turn_session_stop(struct tnet_turn_session_s* p_self);
TNET_END_DECLS

View File

@ -42,8 +42,8 @@
#define RUN_TEST_SOCKETS 0 /* FIXME: Android */
#define RUN_TEST_TRANSPORT 0
#define RUN_TEST_AUTH 0
#define RUN_TEST_STUN 1
#define RUN_TEST_ICE 0
#define RUN_TEST_STUN 0
#define RUN_TEST_ICE 1
#define RUN_TEST_NAT 0
#define RUN_TEST_IFACES 0
#define RUN_TEST_DNS 0

View File

@ -20,125 +20,194 @@
#ifndef TNET_TEST_ICE_H
#define TNET_TEST_ICE_H
#define ICE_CANDIDATES "1 1 udp 1 192.168.196.1 57806 typ host name video_rtcp network_name {0C0137CC-DB78-46B6-9B6C-7E097FFA79FE} username StFEVThMK2DHThkv password qkhKUDr4WqKRwZTo generation 0\r\n" \
"1 2 udp 1 192.168.211.1 57808 typ srflx name video_rtcp network_name {F53974D9-C92C-4644-AF7A-EA09D29BD5A5} username 9ONjPsYvSFh0JvAc password rDHSkokdvp9dyXqQ generation 0\r\n" \
"1 1 udp 1 192.168.196.1 57809 typ prflx name video_rtp network_name {0C0137CC-DB78-46B6-9B6C-7E097FFA79FE} username S1vDZTVVky3r0pT+ password XgLb+H9uofxuWg7G generation 0\r\n" \
"1 2 udp 1 192.168.211.1 57811 typ relay name video_rtp network_name {F53974D9-C92C-4644-AF7A-EA09D29BD5A5} username x64BhO4BXjBFkpz2 password ZwHhRhu0KU9R6iWd generation 0\r\n" \
"1 1 udp 1 192.168.211.1 57811 typ token name video_rtp network_name {F53974D9-C92C-4644-AF7A-EA09D29BD5A5} username x64BhO4BXjBFkpz2 password ZwHhRhu0KU9R6iWd generation 0\r\n"
#define kStunUsrName "bossiel@yahoo.fr"
#define kStunPwd "tinynet"
#define kStunServerIP "ns313841.ovh.net" /*"numb.viagenie.ca"*/ /*stun.ekiga.net*/
static int tnet_ice_callback(const tnet_ice_event_t *e)
#define kSkipHosts 0
#define kSkipReflexives 1 // server reflexive: STUN
#define kSkipPeers 1 // peer reflexive
#define kSkipRelays 0 // relays: TURN
static struct tnet_ice_ctx_s *p_ice_ctx1 = tsk_null;
static struct tnet_ice_ctx_s *p_ice_ctx2 = tsk_null;
static void test_ice_print_local_candidates(const struct tnet_ice_ctx_s *pc_ctx)
{
TSK_DEBUG_INFO("ICE callback: %s", e->phrase);
tsk_size_t index = 0;
const tnet_ice_candidate_t* candidate;
char* p_str = tsk_null;
while ((candidate = tnet_ice_ctx_get_local_candidate_at(pc_ctx, index++))) {
tsk_strcat_2(&p_str, "%s\r\n", tnet_ice_candidate_tostring((tnet_ice_candidate_t*)candidate));
}
TSK_DEBUG_INFO("ICE LOCAL CANDIDATES:\n%s", p_str);
TSK_FREE(p_str);
}
static char* test_ice_get_local_candidates(const struct tnet_ice_ctx_s *pc_ctx)
{
tsk_size_t index = 0;
const tnet_ice_candidate_t* candidate;
char* p_str = tsk_null;
while ((candidate = tnet_ice_ctx_get_local_candidate_at(pc_ctx, index++))) {
if (kSkipHosts && candidate->type_e == tnet_ice_cand_type_host) {
continue;
}
if (kSkipReflexives && candidate->type_e == tnet_ice_cand_type_srflx) {
continue;
}
if (kSkipRelays && candidate->type_e == tnet_ice_cand_type_relay) {
continue;
}
if (kSkipPeers && candidate->type_e == tnet_ice_cand_type_prflx) {
continue;
}
tsk_strcat_2(&p_str, "%s\r\n", tnet_ice_candidate_tostring((tnet_ice_candidate_t*)candidate));
}
return p_str;
}
static int test_ice_rtp_callback(const void* callback_data, const uint8_t* data_ptr, tsk_size_t data_size, tnet_fd_t local_fd, const struct sockaddr_storage* remote_addr)
{
struct tnet_ice_ctx_s *p_ice_ctx = (struct tnet_ice_ctx_s *)callback_data;
TSK_DEBUG_INFO("\n\nICE rtp callback: %.*s\n\n", data_size, data_ptr);
return 0;
}
static int test_ice_state_callback(const tnet_ice_event_t *e)
{
struct tnet_ice_ctx_s *p_ice_ctx = (struct tnet_ice_ctx_s *)e->ctx;
int ret = 0;
TSK_DEBUG_INFO("ICE state callback: %s", e->phrase);
switch(e->type)
{
case tnet_ice_event_type_gathering_completed:
{
struct tnet_ice_ctx_s *ctx;
if((ctx = (struct tnet_ice_ctx_s *)e->userdata)){
tnet_ice_ctx_set_remote_candidates(ctx, ICE_CANDIDATES, "ice-ufrag", "ice-pwd", tsk_true, tsk_false);
test_ice_print_local_candidates(p_ice_ctx);
if (p_ice_ctx == p_ice_ctx1) {
if ((ret = tnet_ice_ctx_start(p_ice_ctx2))) {
goto bail;
}
}
else {
const tnet_ice_candidate_t* candidate;
char* p_cand;
p_cand = test_ice_get_local_candidates(p_ice_ctx2);
candidate = tnet_ice_ctx_get_local_candidate_first(p_ice_ctx2);
ret = tnet_ice_ctx_set_remote_candidates(p_ice_ctx1, p_cand, candidate->ufrag, candidate->pwd, tsk_true, tsk_false);
if (ret == 0) {
TSK_FREE(p_cand);
p_cand = test_ice_get_local_candidates(p_ice_ctx1);
candidate = tnet_ice_ctx_get_local_candidate_first(p_ice_ctx1);
ret = tnet_ice_ctx_set_remote_candidates(p_ice_ctx2, p_cand, candidate->ufrag, candidate->pwd, tsk_false, tsk_false);
TSK_FREE(p_cand);
}
}
break;
}
case tnet_ice_event_type_conncheck_succeed:
{
const char kTurnData[] = "TURN data to send for testing";
const tnet_ice_candidate_t *candidate_offer, *candidate_answer_src, *candidate_answer_dest;
ret = tnet_ice_ctx_get_nominated_symetric_candidates(p_ice_ctx, TNET_ICE_CANDIDATE_COMPID_RTP, &candidate_offer, &candidate_answer_src, &candidate_answer_dest);
if (ret == 0) {
TSK_DEBUG_INFO("Nominated candidate(RTP): Offer=[[%s]], AnswerSrc=[[%s]], AnswerDest=[[%s]]",
tnet_ice_candidate_tostring((tnet_ice_candidate_t*)candidate_offer),
tnet_ice_candidate_tostring((tnet_ice_candidate_t*)candidate_answer_src),
tnet_ice_candidate_tostring((tnet_ice_candidate_t*)candidate_answer_dest));
if (tnet_ice_ctx_is_turn_rtp_active(p_ice_ctx)) {
tnet_ice_ctx_send_turn_rtp(p_ice_ctx, kTurnData, sizeof(kTurnData));
}
}
ret = tnet_ice_ctx_get_nominated_symetric_candidates(p_ice_ctx, TNET_ICE_CANDIDATE_COMPID_RTCP, &candidate_offer, &candidate_answer_src, &candidate_answer_dest);
if (ret == 0) {
TSK_DEBUG_INFO("Nominated candidate(RTCP): Offer=[[%s]], AnswerSrc=[[%s]], AnswerDest=[[%s]]",
tnet_ice_candidate_tostring((tnet_ice_candidate_t*)candidate_offer),
tnet_ice_candidate_tostring((tnet_ice_candidate_t*)candidate_answer_src),
tnet_ice_candidate_tostring((tnet_ice_candidate_t*)candidate_answer_dest));
if (tnet_ice_ctx_is_turn_rtcp_active(p_ice_ctx)) {
tnet_ice_ctx_send_turn_rtcp(p_ice_ctx, kTurnData, sizeof(kTurnData));
}
}
break;
}
}
return 0;
bail:
return ret;
}
void test_ice()
{
struct tnet_ice_ctx_s *ctx;
int ret;
static const tsk_bool_t use_ipv6 = tsk_false;
static const tsk_bool_t use_rtcp = tsk_true;
static const tsk_bool_t use_ice_jingle = tsk_false;
static const tsk_bool_t use_video = tsk_false;
long a = tnet_htonl(0x6b0c76a7);
long b = tnet_htonl(0x034aa76b);
long c = tnet_htonl(0x510da598);
ctx = tnet_ice_ctx_create(use_ice_jingle, use_ipv6, use_rtcp, use_video, tnet_ice_callback, tsk_null);
tnet_ice_ctx_set_userdata(ctx, ctx);
ret = tnet_ice_ctx_set_stun(ctx, "numb.viagenie.ca", 3478, "Doubango", "bossiel@yahoo.fr", "stun-password");
ret = tnet_ice_ctx_start(ctx);
// ret = tnet_ice_ctx_set_remote_candidates(ctx, ICE_CANDIDATES);
getchar();
ret = tnet_ice_ctx_stop(ctx);
TSK_OBJECT_SAFE_FREE(ctx);
}
#endif /* TNET_TEST_ICE_H */
/*
* Copyright (C) 2012 Doubango Telecom <http://www.doubango.org>
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*/
#ifndef TNET_TEST_ICE_H
#define TNET_TEST_ICE_H
#define ICE_CANDIDATES "1 1 udp 1 192.168.196.1 57806 typ host name video_rtcp network_name {0C0137CC-DB78-46B6-9B6C-7E097FFA79FE} username StFEVThMK2DHThkv password qkhKUDr4WqKRwZTo generation 0\r\n" \
"1 2 udp 1 192.168.211.1 57808 typ srflx name video_rtcp network_name {F53974D9-C92C-4644-AF7A-EA09D29BD5A5} username 9ONjPsYvSFh0JvAc password rDHSkokdvp9dyXqQ generation 0\r\n" \
"1 1 udp 1 192.168.196.1 57809 typ prflx name video_rtp network_name {0C0137CC-DB78-46B6-9B6C-7E097FFA79FE} username S1vDZTVVky3r0pT+ password XgLb+H9uofxuWg7G generation 0\r\n" \
"1 2 udp 1 192.168.211.1 57811 typ relay name video_rtp network_name {F53974D9-C92C-4644-AF7A-EA09D29BD5A5} username x64BhO4BXjBFkpz2 password ZwHhRhu0KU9R6iWd generation 0\r\n" \
"1 1 udp 1 192.168.211.1 57811 typ token name video_rtp network_name {F53974D9-C92C-4644-AF7A-EA09D29BD5A5} username x64BhO4BXjBFkpz2 password ZwHhRhu0KU9R6iWd generation 0\r\n"
static int tnet_ice_callback(const tnet_ice_event_t *e)
{
TSK_DEBUG_INFO("ICE callback: %s", e->phrase);
switch(e->type)
{
case tnet_ice_event_type_gathering_completed:
{
struct tnet_ice_ctx_s *ctx;
if((ctx = (struct tnet_ice_ctx_s *)e->userdata)){
tnet_ice_ctx_set_remote_candidates(ctx, ICE_CANDIDATES);
}
break;
}
if (!(p_ice_ctx1 = tnet_ice_ctx_create(use_ice_jingle, use_ipv6, use_rtcp, use_video, test_ice_state_callback, tsk_null))) {
goto bail;
}
return 0;
}
void test_ice()
{
struct tnet_ice_ctx_s *ctx;
int ret;
static const tsk_bool_t use_ipv6 = tsk_false;
static const tsk_bool_t use_rtcp = tsk_true;
ctx = tnet_ice_ctx_create(use_ipv6, use_rtcp, tnet_ice_callback, tsk_null);
tnet_ice_ctx_set_userdata(ctx, ctx);
ret = tnet_ice_ctx_stun_configure(ctx, "numb.viagenie.ca", 3478, "Doubango", "bossiel@yahoo.fr", "stun-password");
ret = tnet_ice_ctx_start(ctx);
// ret = tnet_ice_ctx_set_remote_candidates(ctx, ICE_CANDIDATES);
if (!(p_ice_ctx2 = tnet_ice_ctx_create(use_ice_jingle, use_ipv6, use_rtcp, use_video, test_ice_state_callback, tsk_null))) {
goto bail;
}
if ((ret = tnet_ice_ctx_set_turn_enabled(p_ice_ctx1, 1))) {
goto bail;
}
if ((ret = tnet_ice_ctx_set_turn_enabled(p_ice_ctx2, 1))) {
goto bail;
}
if ((ret = tnet_ice_ctx_set_stun_enabled(p_ice_ctx1, 1))) {
goto bail;
}
if ((ret = tnet_ice_ctx_set_stun_enabled(p_ice_ctx2, 1))) {
goto bail;
}
if ((ret = tnet_ice_ctx_set_userdata(p_ice_ctx1, p_ice_ctx1))) {
goto bail;
}
if ((ret = tnet_ice_ctx_set_userdata(p_ice_ctx2, p_ice_ctx2))) {
goto bail;
}
if ((ret = tnet_ice_ctx_rtp_callback(p_ice_ctx1, test_ice_rtp_callback, p_ice_ctx1))) {
goto bail;
}
if ((ret = tnet_ice_ctx_rtp_callback(p_ice_ctx2, test_ice_rtp_callback, p_ice_ctx2))) {
goto bail;
}
if ((ret = tnet_ice_ctx_set_stun(p_ice_ctx1, kStunServerIP, 3478, kStunSoftware, kStunUsrName, kStunPwd))) {
goto bail;
}
if ((ret = tnet_ice_ctx_set_stun(p_ice_ctx2, kStunServerIP, 3478, kStunSoftware, kStunUsrName, kStunPwd))) {
goto bail;
}
if ((ret = tnet_ice_ctx_start(p_ice_ctx1))) {
goto bail;
}
// start ctx2 when we finish gathering ctx1's candidates
//if ((ret = tnet_ice_ctx_start(p_ice_ctx2))) {
// goto bail;
//}
getchar();
ret = tnet_ice_ctx_stop(ctx);
// ret = tnet_ice_ctx_stop(p_ice_ctx1);
// ret = tnet_ice_ctx_stop(p_ice_ctx2);
TSK_OBJECT_SAFE_FREE(ctx);
bail:
TSK_OBJECT_SAFE_FREE(p_ice_ctx1);
TSK_OBJECT_SAFE_FREE(p_ice_ctx2);
}
#endif /* TNET_TEST_ICE_H */

View File

@ -19,9 +19,7 @@
#ifndef TNET_TEST_NAT_H
#define TNET_TEST_NAT_H
//stun.ekiga.net
//#define STUN_SERVER_IP "numb.viagenie.ca"
#define STUN_SERVER_IP "numb.viagenie.ca"
#define STUN_SERVER_IP "ns313841.ovh.net" // "numb.viagenie.ca" /* stun.ekiga.net, */
#define STUN_USERNAME "bossiel@yahoo.fr"
#define STUN_PASSWORD "tinynet"
#define STUN_SERVER_PORT TNET_STUN_TCP_UDP_DEFAULT_PORT
@ -30,7 +28,7 @@
void test_nat_stun()
{
tnet_socket_t *socket1 = 0, *socket2 = 0;
tnet_nat_context_handle_t *context = 0;
struct tnet_nat_ctx_s *context = 0;
tnet_stun_binding_id_t bind_id1, bind_id2;
@ -38,42 +36,35 @@ void test_nat_stun()
tnet_port_t public_port1 = 0, public_port2 = 0;
if(!(socket1 = tnet_socket_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, STUN_SERVER_PROTO))
|| !(socket2 = tnet_socket_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, STUN_SERVER_PROTO)))
{
|| !(socket2 = tnet_socket_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, STUN_SERVER_PROTO))) {
goto bail;
}
context = tnet_nat_context_create(STUN_SERVER_PROTO, STUN_USERNAME, STUN_PASSWORD);
if(tnet_nat_set_server_address(context, STUN_SERVER_IP))
{
if(tnet_nat_set_server_address(context, STUN_SERVER_IP)) {
TSK_DEBUG_ERROR("Failed to set STUN/TURN address.");
goto bail;
}
/* == BIND
*/
// == BIND == //
bind_id1 = tnet_nat_stun_bind(context, socket1->fd);
bind_id2 = tnet_nat_stun_bind(context, socket2->fd);
if(!TNET_STUN_IS_VALID_BINDING_ID(bind_id1) ||!TNET_STUN_IS_VALID_BINDING_ID(bind_id2))
{
if(!bind_id1 || !bind_id2) {
TSK_DEBUG_ERROR("Failed to get public IP/port using stun");
goto bail;
}
if(!tnet_nat_stun_get_reflexive_address(context, bind_id1, &public_ip1, &public_port1))
{
if (tnet_nat_stun_get_reflexive_address(context, bind_id1, &public_ip1, &public_port1) == 0) {
TSK_DEBUG_INFO("Public IP1/Port1 ==> %s:%u", public_ip1, public_port1);
}
if(!tnet_nat_stun_get_reflexive_address(context, bind_id2, &public_ip2, &public_port2))
{
if (tnet_nat_stun_get_reflexive_address(context, bind_id2, &public_ip2, &public_port2) == 0) {
TSK_DEBUG_INFO("Public IP2/Port2 ==> %s:%u", public_ip2, public_port2);
}
/* == UNBIND
*/
// == UNBIND == //
tnet_nat_stun_unbind(context, bind_id1);
tnet_nat_stun_unbind(context, bind_id2);
@ -89,129 +80,129 @@ bail:
void test_nat_turn()
{
tnet_socket_t *socket1 = 0, *socket2 = 0;
tnet_nat_context_handle_t *context = 0;
tnet_turn_allocation_id_t alloc_id1, alloc_id2;
char* public_ip1 = 0, *public_ip2 = 0;
tnet_port_t public_port1 = 0, public_port2 = 0;
tnet_turn_channel_binding_id_t channel_id;
int ret;
if(!(socket1 = tnet_socket_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, STUN_SERVER_PROTO))
|| !(socket2 = tnet_socket_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, STUN_SERVER_PROTO)))
{
goto bail;
}
context = tnet_nat_context_create(STUN_SERVER_PROTO, STUN_USERNAME, STUN_PASSWORD);
((tnet_nat_context_t*)context)->enable_evenport = 0;
((tnet_nat_context_t*)context)->enable_fingerprint = 0;
((tnet_nat_context_t*)context)->enable_dontfrag = 0;
((tnet_nat_context_t*)context)->enable_integrity = 0;
if(tnet_nat_set_server_address(context, STUN_SERVER_IP))
{
TSK_DEBUG_ERROR("Failed to set STUN/TURN address.");
goto bail;
}
/* == ALLOC
*/
alloc_id1 = tnet_nat_turn_allocate(context, socket1->fd);
alloc_id2 = tnet_nat_turn_allocate(context, socket2->fd);
if(!TNET_TURN_IS_VALID_ALLOCATION_ID(alloc_id1) || !TNET_TURN_IS_VALID_ALLOCATION_ID(alloc_id2))
{
TSK_DEBUG_ERROR("TURN allocation failed.");
goto bail;
}
else
{
TSK_DEBUG_INFO("TURN allocation succeeded and id1=%llu and id2=%llu", alloc_id1, alloc_id2);
}
tsk_thread_sleep(2000);
/* == RETRIEVE STUN SERVER REFLEXIVE ADDRESSES
*/
if(!tnet_nat_turn_get_reflexive_address(context, alloc_id1, &public_ip1, &public_port1))
{
TSK_DEBUG_INFO("Public IP1/Port1 ==> %s:%u", public_ip1, public_port1);
}
if(!tnet_nat_turn_get_reflexive_address(context, alloc_id2, &public_ip2, &public_port2))
{
TSK_DEBUG_INFO("Public IP2/Port2 ==> %s:%u", public_ip2, public_port2);
}
/* == CREATE PERMISSION
*/
//tnet_nat_turn_add_permission(context, alloc_id1, "192.168.0.11", 300);
/* == CHANNEL BINDING
*/
{
/* Try to bind (channel binding) to the socket1 to socket2 */
struct sockaddr_storage peer;
if((ret = tnet_sockaddr_init(public_ip2, public_port2, STUN_SERVER_PROTO, &peer)))
{
TSK_DEBUG_ERROR("Failed to init peer with error code %d.", ret);
}
else
{
channel_id = tnet_nat_turn_channel_bind(context, alloc_id1,&peer);
if(TNET_TURN_IS_VALID_CHANNEL_BINDING_ID(channel_id))
{
TSK_DEBUG_INFO("TURN channel binding succeeded.");
/* Try to send data using the newly create channel */
if(tnet_nat_turn_channel_senddata(context, channel_id, "Doubango", strlen("Doubango")))
{
TSK_DEBUG_ERROR("Failed to send data using channel id [%u].", channel_id);
}
else
{
TSK_DEBUG_INFO("Data successfuly sent using channel if[%u].", channel_id);
}
}
else
{
TSK_DEBUG_ERROR("TURN channel binding failed.");
}
}
}
tsk_thread_sleep(2000);
/* == UNALLOC
*/
if((ret = tnet_nat_turn_unallocate(context, alloc_id1)) || (ret = tnet_nat_turn_unallocate(context, alloc_id2)))
{
TSK_DEBUG_ERROR("TURN unallocation failed with error code: %d.", ret);
goto bail;
}
else
{
TSK_DEBUG_INFO("TURN unallocation succeeded.");
}
bail:
TSK_OBJECT_SAFE_FREE(socket1);
TSK_OBJECT_SAFE_FREE(socket2);
TSK_FREE(public_ip1);
TSK_FREE(public_ip1);
TSK_OBJECT_SAFE_FREE(context);
// tnet_socket_t *socket1 = 0, *socket2 = 0;
// struct tnet_nat_ctx_s *context = 0;
// tnet_turn_allocation_id_t alloc_id1, alloc_id2;
//
// char* public_ip1 = 0, *public_ip2 = 0;
// tnet_port_t public_port1 = 0, public_port2 = 0;
//
// tnet_turn_channel_binding_id_t channel_id;
//
// int ret;
//
// if(!(socket1 = tnet_socket_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, STUN_SERVER_PROTO))
// || !(socket2 = tnet_socket_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, STUN_SERVER_PROTO)))
// {
// goto bail;
// }
//
// context = tnet_nat_context_create(STUN_SERVER_PROTO, STUN_USERNAME, STUN_PASSWORD);
// ((tnet_nat_context_t*)context)->enable_evenport = 0;
// ((tnet_nat_context_t*)context)->enable_fingerprint = 0;
// ((tnet_nat_context_t*)context)->enable_dontfrag = 0;
// ((tnet_nat_context_t*)context)->enable_integrity = 0;
//
// if(tnet_nat_set_server_address(context, STUN_SERVER_IP))
// {
// TSK_DEBUG_ERROR("Failed to set STUN/TURN address.");
// goto bail;
// }
//
// /* == ALLOC
// */
// alloc_id1 = tnet_nat_turn_allocate(context, socket1->fd);
// alloc_id2 = tnet_nat_turn_allocate(context, socket2->fd);
// if(!TNET_TURN_IS_VALID_ALLOCATION_ID(alloc_id1) || !TNET_TURN_IS_VALID_ALLOCATION_ID(alloc_id2))
// {
// TSK_DEBUG_ERROR("TURN allocation failed.");
// goto bail;
// }
// else
// {
// TSK_DEBUG_INFO("TURN allocation succeeded and id1=%llu and id2=%llu", alloc_id1, alloc_id2);
// }
//
// tsk_thread_sleep(2000);
//
// /* == RETRIEVE STUN SERVER REFLEXIVE ADDRESSES
// */
// if(!tnet_nat_turn_get_reflexive_address(context, alloc_id1, &public_ip1, &public_port1))
// {
// TSK_DEBUG_INFO("Public IP1/Port1 ==> %s:%u", public_ip1, public_port1);
// }
//
// if(!tnet_nat_turn_get_reflexive_address(context, alloc_id2, &public_ip2, &public_port2))
// {
// TSK_DEBUG_INFO("Public IP2/Port2 ==> %s:%u", public_ip2, public_port2);
// }
//
// /* == CREATE PERMISSION
// */
// //tnet_nat_turn_add_permission(context, alloc_id1, "192.168.0.11", 300);
//
// /* == CHANNEL BINDING
// */
// {
// /* Try to bind (channel binding) to the socket1 to socket2 */
// struct sockaddr_storage peer;
// if((ret = tnet_sockaddr_init(public_ip2, public_port2, STUN_SERVER_PROTO, &peer)))
// {
// TSK_DEBUG_ERROR("Failed to init peer with error code %d.", ret);
// }
// else
// {
// channel_id = tnet_nat_turn_channel_bind(context, alloc_id1,&peer);
// if(TNET_TURN_IS_VALID_CHANNEL_BINDING_ID(channel_id))
// {
// TSK_DEBUG_INFO("TURN channel binding succeeded.");
//
// /* Try to send data using the newly create channel */
// if(tnet_nat_turn_channel_senddata(context, channel_id, "Doubango", strlen("Doubango")))
// {
// TSK_DEBUG_ERROR("Failed to send data using channel id [%u].", channel_id);
// }
// else
// {
// TSK_DEBUG_INFO("Data successfuly sent using channel if[%u].", channel_id);
// }
// }
// else
// {
// TSK_DEBUG_ERROR("TURN channel binding failed.");
// }
// }
// }
//
// tsk_thread_sleep(2000);
//
// /* == UNALLOC
// */
// if((ret = tnet_nat_turn_unallocate(context, alloc_id1)) || (ret = tnet_nat_turn_unallocate(context, alloc_id2)))
// {
// TSK_DEBUG_ERROR("TURN unallocation failed with error code: %d.", ret);
// goto bail;
// }
// else
// {
// TSK_DEBUG_INFO("TURN unallocation succeeded.");
// }
//
//bail:
// TSK_OBJECT_SAFE_FREE(socket1);
// TSK_OBJECT_SAFE_FREE(socket2);
//
// TSK_FREE(public_ip1);
// TSK_FREE(public_ip1);
//
// TSK_OBJECT_SAFE_FREE(context);
}
void test_nat()
{
//test_nat_stun();
test_nat_turn();
test_nat_stun();
//test_nat_turn();
//tsk_thread_sleep(1000);
}

View File

@ -63,16 +63,6 @@ static int test_stun_buff_cmp(const uint8_t* pc_buf1_ptr, tsk_size_t n_buff1_siz
return 0;
}
static void test_stun_dump_transacid(tnet_stun_transacid_t transcid)
{
char transac_idstriing[TNET_STUN_TRANSACID_SIZE*2+1];
tsk_str_from_hex(transcid, TNET_STUN_TRANSACID_SIZE, transac_idstriing);
transac_idstriing[sizeof(transac_idstriing)-1] = '\0';
TSK_DEBUG_INFO("STUN transac id:%s", transac_idstriing);
}
static void test_stun_parser()
{
tnet_stun_pkt_t* p_pkt = tsk_null;
@ -155,9 +145,11 @@ static struct tnet_turn_session_s* __pc_ss2 = tsk_null;
static char* __p_rel_ip_ss1 = tsk_null;
static uint16_t __u_rel_port_ss1 = 0;
static tsk_bool_t __b_rel_ipv6_ss1 = 0;
static tnet_turn_peer_id_t __u_peer_id1 = kTurnPeerIdInvalid;
static char* __p_rel_ip_ss2 = tsk_null;
static uint16_t __u_rel_port_ss2 = 0;
static tsk_bool_t __b_rel_ipv6_ss2 = 0;
static tnet_turn_peer_id_t __u_peer_id2 = kTurnPeerIdInvalid;
static int _test_turn_session_callback(const struct tnet_turn_session_event_xs *e)
{
@ -169,10 +161,11 @@ static int _test_turn_session_callback(const struct tnet_turn_session_event_xs *
uint16_t *pu_port = (pc_ss == __pc_ss2) ? &__u_rel_port_ss1 : &__u_rel_port_ss2;
char** pp_ip = (pc_ss == __pc_ss2) ? &__p_rel_ip_ss1 : &__p_rel_ip_ss2;
tsk_bool_t *pb_ipv6 = (pc_ss == __pc_ss2) ? &__b_rel_ipv6_ss1 : &__b_rel_ipv6_ss2;
tnet_turn_peer_id_t *pu_peer_id = (pc_ss == __pc_ss2) ? &__u_peer_id2 : &__u_peer_id1;
BAIL_IF_ERR(tnet_turn_session_get_relayed_addr(pc_ss, pp_ip, pu_port, pb_ipv6));
// BAIL_IF_ERR(tnet_turn_session_get_srflx_addr(pc_ss, pu_port, &u_port, &b_ipv6)); // get my own server reflexive address (in order to send data to myself)
BAIL_IF_ERR(tnet_turn_session_createpermission((struct tnet_turn_session_s*)pc_ss, *pp_ip, *pu_port)); // Input = ADDR(remote.candidate.relay)
BAIL_IF_ERR(tnet_turn_session_createpermission((struct tnet_turn_session_s*)pc_ss, *pp_ip, *pu_port, pu_peer_id)); // Input = ADDR(remote.candidate.relay)
break;
}
case tnet_turn_session_event_type_alloc_nok:
@ -184,11 +177,12 @@ static int _test_turn_session_callback(const struct tnet_turn_session_event_xs *
{
static const char __pc_data[] = { "TURN Sample Data (Send Indication)" };
int i;
tnet_turn_peer_id_t u_peer_id = (pc_ss == __pc_ss2) ? __u_peer_id2 : __u_peer_id1;
// Bind a channel (not required). If succeed, will be used to save data.
tnet_turn_session_chanbind((struct tnet_turn_session_s*)pc_ss);
tnet_turn_session_chanbind((struct tnet_turn_session_s*)pc_ss, u_peer_id);
// Send data (will use channel if one is active. Otherwise (no channel), SendIndications will be used)
for (i = 0; i < 10; ++i) {
BAIL_IF_ERR(tnet_turn_session_send_data((struct tnet_turn_session_s*)pc_ss, __pc_data, sizeof(__pc_data)));
BAIL_IF_ERR(tnet_turn_session_send_data((struct tnet_turn_session_s*)pc_ss, u_peer_id, __pc_data, sizeof(__pc_data)));
}
break;
}
@ -201,8 +195,9 @@ static int _test_turn_session_callback(const struct tnet_turn_session_event_xs *
{
static const char __pc_data[] = { "TURN Sample Data (ChannelData)" };
int i;
tnet_turn_peer_id_t u_peer_id = (pc_ss == __pc_ss2) ? __u_peer_id2 : __u_peer_id1;
for (i = 0; i < 10; ++i) {
BAIL_IF_ERR(tnet_turn_session_send_data((struct tnet_turn_session_s*)pc_ss, __pc_data, sizeof(__pc_data)));
BAIL_IF_ERR(tnet_turn_session_send_data((struct tnet_turn_session_s*)pc_ss, u_peer_id, __pc_data, sizeof(__pc_data)));
}
break;
}

View File

@ -119,7 +119,7 @@
Optimization="3"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="src;&quot;..\thirdparties\win32\include&quot;;&quot;..\tinySAK\src&quot;"
PreprocessorDefinitions="DEBUG_LEVEL=DEBUG_LEVEL_ERROR;HAVE_OPENSSL=1;WIN32;NDEBUG;_WINDOWS;_USRDLL;TINYNET_EXPORTS"
PreprocessorDefinitions="DEBUG_LEVEL=DEBUG_LEVEL_ERROR;HAVE_OPENSSL=1;WIN32;_WIN32_WINNT=0x0501;NDEBUG;_WINDOWS;_USRDLL;TINYNET_EXPORTS"
RuntimeLibrary="2"
EnableFunctionLevelLinking="false"
UsePrecompiledHeader="0"
@ -236,6 +236,10 @@
RelativePath=".\src\stun\tnet_stun_attribute.c"
>
</File>
<File
RelativePath=".\src\stun\tnet_stun_binding.c"
>
</File>
<File
RelativePath=".\src\stun\tnet_stun_message.c"
>
@ -488,6 +492,10 @@
RelativePath=".\src\stun\tnet_stun_attribute.h"
>
</File>
<File
RelativePath=".\src\stun\tnet_stun_binding.h"
>
</File>
<File
RelativePath=".\src\stun\tnet_stun_message.h"
>

View File

@ -40,10 +40,12 @@ TRTP_BEGIN_DECLS
struct trtp_rtcp_packet_s;
struct trtp_rtp_packet_s;
struct tnet_ice_ctx_s;
typedef int (*trtp_rtcp_cb_f)(const void* callback_data, const struct trtp_rtcp_packet_s* packet);
struct trtp_rtcp_session_s* trtp_rtcp_session_create(uint32_t ssrc, const char* cname);
struct trtp_rtcp_session_s* trtp_rtcp_session_create_2(struct tnet_ice_ctx_s* ice_ctx, uint32_t ssrc, const char* cname);
int trtp_rtcp_session_set_callback(struct trtp_rtcp_session_s* self, trtp_rtcp_cb_f callback, const void* callback_data);
#if HAVE_SRTP
int trtp_rtcp_session_set_srtp_sess(struct trtp_rtcp_session_s* self, const srtp_t* session);

View File

@ -50,6 +50,7 @@ typedef struct trtp_manager_s
tsk_bool_t use_rtcpmux;
tsk_bool_t is_socket_disabled;
tsk_bool_t is_ice_neg_ok;
tsk_bool_t is_ice_turn_active;
tsk_bool_t is_force_symetric_rtp;
tsk_bool_t is_symetric_rtp_checked;
tsk_bool_t is_symetric_rtcp_checked;
@ -189,7 +190,7 @@ TINYRTP_API int trtp_manager_set_srtp_type_remote(trtp_manager_t* self, enum tme
TINYRTP_API int trtp_manager_set_srtp_type_local(trtp_manager_t* self, enum tmedia_srtp_type_e srtp_type, enum tmedia_srtp_mode_e srtp_mode);
#endif /* HAVE_SRTP */
TINYRTP_API tsk_bool_t trtp_manager_is_ready(trtp_manager_t* self);
TINYRTP_API int trtp_manager_set_natt_ctx(trtp_manager_t* self, tnet_nat_context_handle_t* natt_ctx);
TINYRTP_API int trtp_manager_set_natt_ctx(trtp_manager_t* self, struct tnet_nat_ctx_s* natt_ctx);
TINYRTP_API int trtp_manager_set_rtp_callback(trtp_manager_t* self, trtp_rtp_cb_f fun, const void* usrdata);
TINYRTP_API int trtp_manager_set_rtcp_callback(trtp_manager_t* self, trtp_rtcp_cb_f fun, const void* usrdata);
TINYRTP_API int trtp_manager_set_rtp_dscp(trtp_manager_t* self, int32_t dscp);

View File

@ -36,6 +36,9 @@
#include "tinyrtp/rtcp/trtp_rtcp_report_fb.h"
#include "tinyrtp/rtp/trtp_rtp_packet.h"
#include "ice/tnet_ice_ctx.h"
#include "turn/tnet_turn_session.h"
#include "tnet_utils.h"
#include "tsk_string.h"
@ -263,9 +266,11 @@ typedef struct trtp_rtcp_session_s
{
TSK_DECLARE_OBJECT;
tsk_bool_t started;
tsk_bool_t is_started;
tnet_fd_t local_fd;
const struct sockaddr * remote_addr;
struct tnet_ice_ctx_s* ice_ctx;
tsk_bool_t is_ice_turn_active;
const void* callback_data;
trtp_rtcp_cb_f callback;
@ -350,6 +355,7 @@ static tsk_object_t* trtp_rtcp_session_dtor(tsk_object_t * self)
TSK_OBJECT_SAFE_FREE(session->sources);
TSK_OBJECT_SAFE_FREE(session->source_local);
TSK_OBJECT_SAFE_FREE(session->sdes);
TSK_OBJECT_SAFE_FREE(session->ice_ctx);
TSK_FREE(session->cname);
// release the handle for the global timer manager
tsk_timer_mgr_global_unref(&session->timer.handle_global);
@ -375,6 +381,7 @@ static int _trtp_rtcp_session_add_source(trtp_rtcp_session_t* self, trtp_rtcp_so
static int _trtp_rtcp_session_add_source_2(trtp_rtcp_session_t* self, uint32_t ssrc, uint16_t seq, uint32_t ts, tsk_bool_t *added);
static int _trtp_rtcp_session_remove_source(trtp_rtcp_session_t* self, uint32_t ssrc, tsk_bool_t *removed);
static tsk_size_t _trtp_rtcp_session_send_pkt(trtp_rtcp_session_t* self, trtp_rtcp_packet_t* pkt);
static tsk_size_t _trtp_rtcp_session_send_raw(trtp_rtcp_session_t* self, const void* data, tsk_size_t size);
static int _trtp_rtcp_session_timer_callback(const void* arg, tsk_timer_id_t timer_id);
static void Schedule(trtp_rtcp_session_t* session, double tn, event_ e);
@ -409,6 +416,17 @@ bail:
return session;
}
struct trtp_rtcp_session_s* trtp_rtcp_session_create_2(struct tnet_ice_ctx_s* ice_ctx, uint32_t ssrc, const char* cname)
{
struct trtp_rtcp_session_s* session = trtp_rtcp_session_create(ssrc, cname);
if (session) {
if ((session->ice_ctx = tsk_object_ref(ice_ctx))) {
session->is_ice_turn_active = tnet_ice_ctx_is_turn_rtcp_active(session->ice_ctx);
}
}
return session;
}
int trtp_rtcp_session_set_callback(trtp_rtcp_session_t* self, trtp_rtcp_cb_f callback, const void* callback_data)
{
if(!self){
@ -451,7 +469,7 @@ int trtp_rtcp_session_set_app_bandwidth_max(trtp_rtcp_session_t* self, int32_t b
self->app_bw_max_upload = bw_upload_kbps;
self->app_bw_max_download = bw_download_kbps;
if(self->started && self->source_local && self->app_bw_max_download > 0 && self->app_bw_max_download != INT_MAX){ // INT_MAX or <=0 means undefined
if(self->is_started && self->source_local && self->app_bw_max_download > 0 && self->app_bw_max_download != INT_MAX){ // INT_MAX or <=0 means undefined
tsk_list_item_t* item;
uint32_t media_ssrc_list[256] = {0};
uint32_t media_ssrc_list_count = 0;
@ -492,7 +510,7 @@ int trtp_rtcp_session_start(trtp_rtcp_session_t* self, tnet_fd_t local_fd, const
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if(self->started){
if(self->is_started){
TSK_DEBUG_WARN("Already started");
return 0;
}
@ -512,7 +530,7 @@ int trtp_rtcp_session_start(trtp_rtcp_session_t* self, tnet_fd_t local_fd, const
// set start time
self->time_start = tsk_time_now();
self->started = tsk_true;
self->is_started = tsk_true;
return ret;
}
@ -526,7 +544,7 @@ int trtp_rtcp_session_stop(trtp_rtcp_session_t* self)
return -1;
}
if(self->started){
if(self->is_started){
// send BYE synchronous way
SendBYEPacket(self, EVENT_REPORT);
@ -542,7 +560,7 @@ int trtp_rtcp_session_stop(trtp_rtcp_session_t* self)
self->timer.id_report = TSK_INVALID_TIMER_ID;
}
tsk_safeobj_unlock(self);
self->started = tsk_false;
self->is_started = tsk_false;
}
return ret;
@ -557,7 +575,7 @@ int trtp_rtcp_session_process_rtp_out(trtp_rtcp_session_t* self, const trtp_rtp_
return -1;
}
if(!self->started){
if(!self->is_started){
TSK_DEBUG_ERROR("Not started");
return -2;
}
@ -612,7 +630,7 @@ int trtp_rtcp_session_process_rtp_in(trtp_rtcp_session_t* self, const trtp_rtp_p
return -1;
}
if(!self->started){
if(!self->is_started){
TSK_DEBUG_INFO("RTCP session not started");
return -2;
}
@ -648,7 +666,7 @@ int trtp_rtcp_session_process_rtcp_in(trtp_rtcp_session_t* self, const void* buf
return -1;
}
if(!self->started){
if(!self->is_started){
TSK_DEBUG_ERROR("Not started");
return -2;
}
@ -690,7 +708,7 @@ int trtp_rtcp_session_signal_pkt_loss(trtp_rtcp_session_t* self, uint32_t ssrc_m
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if(!self->started){
if(!self->is_started){
TSK_DEBUG_ERROR("Not started");
return -1;
}
@ -720,7 +738,7 @@ int trtp_rtcp_session_signal_frame_corrupted(trtp_rtcp_session_t* self, uint32_t
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if(!self->started){
if(!self->is_started){
TSK_DEBUG_ERROR("Not started");
return -1;
}
@ -889,15 +907,31 @@ static tsk_size_t _trtp_rtcp_session_send_pkt(trtp_rtcp_session_t* self, trtp_rt
}
}
#endif
if(tnet_sockfd_sendto(self->local_fd, self->remote_addr, data, size) > 0){
ret = size;
}
ret = _trtp_rtcp_session_send_raw(self, data, size);
TSK_OBJECT_SAFE_FREE(buffer);
}
return ret;
}
static tsk_size_t _trtp_rtcp_session_send_raw(trtp_rtcp_session_t* self, const void* data, tsk_size_t size)
{
tsk_size_t ret = 0;
if (!self || !data || !size) {
TSK_DEBUG_ERROR("Invalid parameter");
return 0;
}
if (self->is_ice_turn_active) {
ret = (tnet_ice_ctx_send_turn_rtcp(self->ice_ctx, data, size) == 0) ? size : 0; // returns #0 if ok
}
else {
if (tnet_sockfd_sendto(self->local_fd, self->remote_addr, data, size) == size){ // returns number of sent bytes
ret = size;
}
}
return ret;
}
static int _trtp_rtcp_session_timer_callback(const void* arg, tsk_timer_id_t timer_id)
{
trtp_rtcp_session_t* session = (trtp_rtcp_session_t*)arg;
@ -1150,7 +1184,7 @@ static void SendBYEPacket(trtp_rtcp_session_t* session, event_ e)
}
}
#endif
tnet_sockfd_sendto(session->local_fd, session->remote_addr, data, size);
_trtp_rtcp_session_send_raw(session, data, size);
TSK_OBJECT_SAFE_FREE(buffer);
}
TSK_OBJECT_SAFE_FREE(bye);

View File

@ -28,6 +28,7 @@
#include "tinyrtp/rtcp/trtp_rtcp_packet.h"
#include "tinyrtp/rtcp/trtp_rtcp_session.h"
#include "turn/tnet_turn_session.h"
#include "ice/tnet_ice_candidate.h"
#include "tsk_string.h"
@ -92,28 +93,18 @@ static int _trtp_transport_layer_cb(const tnet_transport_event_t* e)
/* DTLS - SRTP events */
case event_dtls_handshake_succeed:
{
const tnet_socket_t* socket = manager->transport->master && (manager->transport->master->fd == e->local_fd)
const tnet_socket_t* socket = manager->transport && manager->transport->master && (manager->transport->master->fd == e->local_fd)
? manager->transport->master
: ((manager->rtcp.local_socket && manager->rtcp.local_socket->fd == e->local_fd) ? manager->rtcp.local_socket : tsk_null);
if(!socket){
TSK_DEBUG_ERROR("DTLS data from unknown socket");
break;
}
// cancel handshaking timer when both SRTP and SRTCP are connected
tsk_safeobj_lock(manager);
if(manager->dtls.srtp_connected && manager->dtls.srtcp_connected){
if(manager->dtls.timer_hanshaking.id != TSK_INVALID_TIMER_ID){
tsk_timer_manager_cancel(manager->timer_mgr_global, manager->dtls.timer_hanshaking.id);
manager->dtls.timer_hanshaking.id = TSK_INVALID_TIMER_ID; // invalidate timer id (not required but should be done by good citizen)
manager->dtls.timer_hanshaking.timeout = TRTP_DTLS_HANDSHAKING_TIMEOUT; // reset timeout
}
}
tsk_safeobj_unlock(manager);
if(!manager->dtls.srtp_handshake_succeed){
if (!manager->dtls.srtp_handshake_succeed) {
manager->dtls.srtp_handshake_succeed = (socket == manager->transport->master);
}
if(!manager->dtls.srtcp_handshake_succeed){
if (!manager->dtls.srtcp_handshake_succeed) {
manager->dtls.srtcp_handshake_succeed = (socket == manager->rtcp.local_socket) || _trtp_manager_is_rtcpmux_active(manager);
}
@ -249,26 +240,43 @@ static int _trtp_transport_dtls_handshaking_timer_cb(const void* arg, tsk_timer_
{
#if HAVE_SRTP
trtp_manager_t* manager = (trtp_manager_t*)arg;
int ret = 0;
tsk_safeobj_lock(manager);
if(manager->is_started && manager->dtls.timer_hanshaking.id == timer_id && manager->srtp_state == trtp_srtp_state_activated && manager->srtp_type == tmedia_srtp_type_dtls){
if (manager->is_started && manager->dtls.timer_hanshaking.id == timer_id && manager->srtp_state == trtp_srtp_state_activated && manager->srtp_type == tmedia_srtp_type_dtls) {
// retry DTLS-SRTP handshaking if srtp-type is DTLS-SRTP and the engine is activated
struct tnet_socket_s* sockets[] = { manager->transport->master , manager->rtcp.local_socket };
struct tnet_socket_s* sockets[] = { manager->dtls.srtp_connected ? tsk_null : manager->transport->master , manager->dtls.srtcp_connected ? tsk_null : manager->rtcp.local_socket };
const struct sockaddr_storage* remote_addrs[] = { &manager->rtp.remote_addr, &manager->rtcp.remote_addr };
TSK_DEBUG_INFO("_trtp_transport_dtls_handshaking_timer_cb(timeout=%llu)", manager->dtls.timer_hanshaking.timeout);
tnet_transport_dtls_do_handshake(manager->transport, sockets, 2, remote_addrs, 2);
if (manager->is_ice_turn_active) {
// means TURN is active and handshaking data must be sent using the channel
const void* data[] = { tsk_null, tsk_null };
tsk_size_t size[] = { 0, 0 };
if ((ret = tnet_transport_dtls_get_handshakingdata(manager->transport, sockets, 2, data, size))) {
return ret;
}
if (data[0] && size[0]) {
ret = tnet_ice_ctx_send_turn_rtp(manager->ice_ctx, data[0], size[0]);
}
if (data[1] && size[1]) {
ret = tnet_ice_ctx_send_turn_rtcp(manager->ice_ctx, data[1], size[1]);
}
}
// increase timeout
manager->dtls.timer_hanshaking.timeout += (TRTP_DTLS_HANDSHAKING_TIMEOUT >> 1);
if(manager->dtls.timer_hanshaking.timeout < TRTP_DTLS_HANDSHAKING_TIMEOUT_MAX){
if ((manager->dtls.timer_hanshaking.timeout < TRTP_DTLS_HANDSHAKING_TIMEOUT_MAX) && !(manager->dtls.srtp_connected && manager->dtls.srtcp_connected)) {
manager->dtls.timer_hanshaking.id = tsk_timer_manager_schedule(manager->timer_mgr_global, manager->dtls.timer_hanshaking.timeout, _trtp_transport_dtls_handshaking_timer_cb, manager);
}
else{
manager->dtls.timer_hanshaking.id = TSK_INVALID_TIMER_ID; // not required but we're good citizen
else {
manager->dtls.timer_hanshaking.id = TSK_INVALID_TIMER_ID; // invalidate timer id (not required but should be done by good citizen)
manager->dtls.timer_hanshaking.timeout = TRTP_DTLS_HANDSHAKING_TIMEOUT; // reset timeout
}
}
tsk_safeobj_unlock(manager);
#endif
return 0;
return ret;
}
#if 0
@ -333,6 +341,11 @@ static int _trtp_manager_recv_data(const trtp_manager_t* self, const uint8_t* da
{
tsk_bool_t is_rtp_rtcp, is_rtcp = tsk_false, is_rtp = tsk_false, is_stun, is_dtls;
if (!self->is_started) {
TSK_DEBUG_INFO("RTP manager not started yet");
return 0;
}
// defined when RTCP-MUX is disabled and RTCP port is equal to "RTP Port + 1"
// rfc5764 - 5.1.2. Reception
@ -356,16 +369,30 @@ static int _trtp_manager_recv_data(const trtp_manager_t* self, const uint8_t* da
}
else{
is_dtls = !is_rtp_rtcp && (19 < *data_ptr && *data_ptr < 64);
is_stun = !is_dtls && TNET_IS_STUN2_MSG(data_ptr, data_size); /* MUST NOT USE: "(*data_ptr < 2)" beacause of "Old VAT" which starts with "0x00" */;
is_stun = !is_dtls && TNET_STUN_BUFF_IS_STUN2(data_ptr, data_size); /* MUST NOT USE: "(*data_ptr < 2)" beacause of "Old VAT" which starts with "0x00" */;
}
if(is_dtls){
tnet_socket_t* socket = (self->transport->master && self->transport->master->fd == local_fd)
tnet_socket_t* socket = (self->transport && self->transport->master && self->transport->master->fd == local_fd)
? self->transport->master
: ((self->rtcp.local_socket && self->rtcp.local_socket->fd == local_fd) ? self->rtcp.local_socket : tsk_null);
if(socket){
if (socket && socket->dtlshandle) {
TSK_DEBUG_INFO("Receive %s-DTLS data on ip=%s and port=%d", (socket == self->transport->master) ? "RTP" : "RTCP", socket->ip, socket->port);
return tnet_dtls_socket_handle_incoming_data(socket->dtlshandle, data_ptr, data_size);
// Handle incoming data then do handshaking
tnet_dtls_socket_handle_incoming_data(socket->dtlshandle, data_ptr, data_size);
if (self->is_ice_turn_active) {
// means TURN is active and handshaking data must be sent using the channel
const void* data = tsk_null;
tsk_size_t size = 0;
if (tnet_transport_dtls_get_handshakingdata(self->transport, &socket, 1, &data, &size) == 0) {
if (self->rtcp.local_socket == socket) {
/*ret = */tnet_ice_ctx_send_turn_rtcp(self->ice_ctx, data, size);
}
else {
/*ret = */tnet_ice_ctx_send_turn_rtp(self->ice_ctx, data, size);
}
}
}
}
return 0;
}
@ -543,6 +570,7 @@ static int _trtp_manager_srtp_activate(trtp_manager_t* self, tmedia_srtp_type_t
*/
struct tnet_socket_s* sockets[] = { self->transport->master , self->rtcp.local_socket };
const struct sockaddr_storage* remote_addrs[] = { &self->rtp.remote_addr, &self->rtcp.remote_addr };
tsk_bool_t store_handshakingdata[] = { self->is_ice_turn_active, self->is_ice_turn_active };
// check if DTLS-SRTP enabling was postponed because the net transport was not ready (could happen if ICE is ON)
if(self->dtls.enable_postponed){
@ -575,10 +603,28 @@ static int _trtp_manager_srtp_activate(trtp_manager_t* self, tmedia_srtp_type_t
if((ret = tnet_transport_dtls_set_setup(self->transport, self->dtls.local.setup, sockets, 2))){
return ret;
}
// start handshaking process (will do nothing if already completed)
if((ret = tnet_transport_dtls_do_handshake(self->transport, sockets, 2, remote_addrs, 2))){
// whether to send DTLS handshaking data using the provided sockets or TURN session
if ((ret = tnet_transport_dtls_set_store_handshakingdata(self->transport, store_handshakingdata[0], sockets, 2))) {
return ret;
}
// start handshaking process (will do nothing if already completed)
if ((ret = tnet_transport_dtls_do_handshake(self->transport, sockets, 2, remote_addrs, 2))) {
return ret;
}
if (store_handshakingdata[0]) {
// means TURN is active and handshaking data must be sent using the channel
const void* data[] = { tsk_null, tsk_null };
tsk_size_t size[] = { 0, 0 };
if ((ret = tnet_transport_dtls_get_handshakingdata(self->transport, sockets, 2, data, size))) {
return ret;
}
if (data[0] && size[0]) {
ret = tnet_ice_ctx_send_turn_rtp(self->ice_ctx, data[0], size[0]);
}
if (data[1] && size[1]) {
ret = tnet_ice_ctx_send_turn_rtcp(self->ice_ctx, data[1], size[1]);
}
}
self->dtls.state = trtp_srtp_state_activated;
}
@ -586,7 +632,7 @@ static int _trtp_manager_srtp_activate(trtp_manager_t* self, tmedia_srtp_type_t
self->srtp_state = trtp_srtp_state_activated;
// SDES-SRTP could be started right now while DTLS requires the handshaking to terminate
if(srtp_type & tmedia_srtp_type_sdes){
if (srtp_type & tmedia_srtp_type_sdes) {
return _trtp_manager_srtp_start(self, self->srtp_type);
}
}
@ -656,21 +702,22 @@ static int _trtp_manager_ice_init(trtp_manager_t* self)
int ret;
const tnet_ice_candidate_t *candidate_offer, *candidate_answer_src, *candidate_answer_dest;
if(!self || !self->ice_ctx){
if (!self || !self->ice_ctx) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if(!self->transport){
if (!self->transport) {
// get rtp nominated symetric candidates
ret = tnet_ice_ctx_get_nominated_symetric_candidates(self->ice_ctx, TNET_ICE_CANDIDATE_COMPID_RTP,
&candidate_offer, &candidate_answer_src, &candidate_answer_dest);
self->is_ice_neg_ok = (ret == 0 && candidate_offer && candidate_answer_src && candidate_answer_dest);
if(!self->is_ice_neg_ok){
self->is_ice_turn_active = self->is_ice_neg_ok && tnet_ice_ctx_is_turn_rtp_active(self->ice_ctx);
if (!self->is_ice_neg_ok) {
// If this code is called this means that ICE negotiation has failed
// This is not really an error because it could happen if the remote peer is not an ICE agent or is an ICE-lite
// in this case, use the first offered candidate which is the best one and already used in the "c=" line
if(!(candidate_offer = tnet_ice_ctx_get_local_candidate_at(self->ice_ctx, 0))){
if (!(candidate_offer = tnet_ice_ctx_get_local_candidate_first(self->ice_ctx))) {
// Must never happen as we always have at least one local "host" candidate
TSK_DEBUG_ERROR("ICE context not ready");
return -3;
@ -678,12 +725,12 @@ static int _trtp_manager_ice_init(trtp_manager_t* self)
}
// create transport
if(!(self->transport = tnet_transport_create_2(candidate_offer->socket, TRTP_TRANSPORT_NAME))){
if (!(self->transport = tnet_transport_create_2(candidate_offer->socket, TRTP_TRANSPORT_NAME))) {
TSK_DEBUG_ERROR("Failed to create transport(%s:%u)", candidate_offer->socket->ip, candidate_offer->socket->port);
return -4;
}
// set rtp local and remote IPs and ports
if(candidate_answer_dest){ // could be "null" if remote peer is ICE-lite
if (candidate_answer_dest) { // could be "null" if remote peer is ICE-lite
tsk_strupdate(&self->rtp.remote_ip, candidate_answer_dest->connection_addr);
self->rtp.remote_port = candidate_answer_dest->port;
tsk_strupdate(&self->rtp.public_ip, candidate_offer->connection_addr);
@ -691,10 +738,10 @@ static int _trtp_manager_ice_init(trtp_manager_t* self)
}
// get rtp nominated symetric candidates
if(self->use_rtcp){
if (self->use_rtcp) {
ret = tnet_ice_ctx_get_nominated_symetric_candidates(self->ice_ctx, TNET_ICE_CANDIDATE_COMPID_RTCP,
&candidate_offer, &candidate_answer_src, &candidate_answer_dest);
if(ret == 0 && candidate_offer && candidate_answer_src && candidate_answer_dest){
if (ret == 0 && candidate_offer && candidate_answer_src && candidate_answer_dest) {
// set rtp local and remote IPs and ports
tsk_strupdate(&self->rtcp.remote_ip, candidate_answer_dest->connection_addr);
self->rtcp.remote_port = candidate_answer_dest->port;
@ -1046,7 +1093,7 @@ tsk_bool_t trtp_manager_is_ready(trtp_manager_t* self)
}
/** Sets NAT Traversal context */
int trtp_manager_set_natt_ctx(trtp_manager_t* self, tnet_nat_context_handle_t* natt_ctx)
int trtp_manager_set_natt_ctx(trtp_manager_t* self, struct tnet_nat_ctx_s* natt_ctx)
{
int ret;
@ -1196,12 +1243,12 @@ int trtp_manager_start(trtp_manager_t* self)
tsk_safeobj_lock(self);
if(self->is_started){
if (self->is_started) {
goto bail;
}
// Initialize transport with ICE context
if(self->ice_ctx && (ret = _trtp_manager_ice_init(self)) != 0){
if (self->ice_ctx && (ret = _trtp_manager_ice_init(self)) != 0) {
TSK_DEBUG_ERROR("_trtp_manager_ice_init() failed");
goto bail;
}
@ -1300,7 +1347,7 @@ int trtp_manager_start(trtp_manager_t* self)
}
/* create and start RTCP session */
if(!self->rtcp.session && ret == 0){
self->rtcp.session = trtp_rtcp_session_create(self->rtp.ssrc.local, self->rtcp.cname);
self->rtcp.session = trtp_rtcp_session_create_2(self->ice_ctx, self->rtp.ssrc.local, self->rtcp.cname);
}
if(self->rtcp.session){
ret = trtp_rtcp_session_set_callback(self->rtcp.session, self->rtcp.cb.fun, self->rtcp.cb.usrdata);
@ -1322,7 +1369,7 @@ int trtp_manager_start(trtp_manager_t* self)
}
/* DTLS handshaking Timer */
if(self->timer_mgr_global && self->srtp_state == trtp_srtp_state_activated && (self->srtp_type & tmedia_srtp_type_dtls) == tmedia_srtp_type_dtls){
if (self->timer_mgr_global && self->srtp_state == trtp_srtp_state_activated && (self->srtp_type & tmedia_srtp_type_dtls) == tmedia_srtp_type_dtls) {
ret = tsk_timer_manager_start(self->timer_mgr_global);
self->dtls.timer_hanshaking.timeout = TRTP_DTLS_HANDSHAKING_TIMEOUT;
// start handshaking timer
@ -1333,8 +1380,8 @@ int trtp_manager_start(trtp_manager_t* self)
#endif /* HAVE_SRTP */
/* start the transport */
if((ret = tnet_transport_start(self->transport))){
/* start the transport if TURN is not active (otherwise TURN data will be received directly on RTP manager with channel headers) */
if (!self->is_ice_turn_active && (ret = tnet_transport_start(self->transport))) {
TSK_DEBUG_ERROR("Failed to start the RTP/RTCP transport");
goto bail;
}
@ -1452,9 +1499,9 @@ tsk_size_t trtp_manager_send_rtp_packet(trtp_manager_t* self, const struct trtp_
}
}
#endif
if(/* number of bytes sent */(ret = tnet_sockfd_sendto(self->transport->master->fd, (const struct sockaddr *)&self->rtp.remote_addr, data_ptr, data_size)) > 0){
if (/* number of bytes sent */(ret = trtp_manager_send_rtp_raw(self, data_ptr, data_size)) > 0) {
// forward packet to the RTCP session
if(self->rtcp.session){
if (self->rtcp.session) {
trtp_rtcp_session_process_rtp_out(self->rtcp.session, packet, data_size);
}
}
@ -1479,9 +1526,14 @@ tsk_size_t trtp_manager_send_rtp_raw(trtp_manager_t* self, const void* data, tsk
return 0;
}
tsk_safeobj_lock(self);
ret = tnet_sockfd_sendto(self->transport->master->fd, (const struct sockaddr *)&self->rtp.remote_addr, data, size);
if (self->is_ice_turn_active) {
ret = (tnet_ice_ctx_send_turn_rtp(self->ice_ctx, data, size) == 0) ? size : 0; // returns #0 if ok
}
else {
ret = tnet_sockfd_sendto(self->transport->master->fd, (const struct sockaddr *)&self->rtp.remote_addr, data, size); // returns number of sent bytes
}
tsk_safeobj_unlock(self);
return 0;
return ret;
}
int trtp_manager_set_app_bandwidth_max(trtp_manager_t* self, int32_t bw_upload_kbps, int32_t bw_download_kbps)
@ -1536,6 +1588,14 @@ int trtp_manager_stop(trtp_manager_t* self)
// ret = tnet_ice_ctx_stop(self->ice_ctx);
//}
// callbacks
if (self->transport) {
ret = tnet_transport_set_callback(self->transport, tsk_null, tsk_null);
}
if (self->ice_ctx) {
ret = tnet_ice_ctx_rtp_callback(self->ice_ctx, tsk_null, tsk_null);
}
// Stop the RTCP session first (will send BYE)
if(self->rtcp.session){
ret = trtp_rtcp_session_stop(self->rtcp.session);
@ -1562,6 +1622,7 @@ int trtp_manager_stop(trtp_manager_t* self)
// reset default values
self->is_symetric_rtp_checked = self->is_symetric_rtcp_checked = tsk_false;
self->is_ice_neg_ok = tsk_false;
self->is_ice_turn_active = tsk_false;
self->is_socket_disabled = tsk_false;
self->is_started = tsk_false;
@ -1622,8 +1683,16 @@ static tsk_object_t* trtp_manager_dtor(tsk_object_t * self)
{
trtp_manager_t *manager = self;
if(manager){
/* callbacks */
if (manager->ice_ctx) {
tnet_ice_ctx_rtp_callback(manager->ice_ctx, tsk_null, tsk_null);
}
if (manager->transport) {
}
/* stop */
if(manager->is_started){
if (manager->is_started) {
trtp_manager_stop(manager);
}
@ -1673,8 +1742,7 @@ static tsk_object_t* trtp_manager_dtor(tsk_object_t * self)
}
/* ICE */
if(manager->ice_ctx){
tnet_ice_ctx_rtp_callback(manager->ice_ctx, tsk_null, tsk_null);
if (manager->ice_ctx) {
TSK_OBJECT_SAFE_FREE(manager->ice_ctx);
}

View File

@ -188,6 +188,7 @@ int tsip_dialog_getCKIK(tsip_dialog_t *self, AKA_CK_T *ck, AKA_IK_T *ik);
int tsip_dialog_init(tsip_dialog_t *self, tsip_dialog_type_t type, const char* call_id, tsip_ssession_t* ss, tsk_fsm_state_id curr, tsk_fsm_state_id term);
int tsip_dialog_fsm_act(tsip_dialog_t* self, tsk_fsm_action_id , const tsip_message_t* , const tsip_action_handle_t*);
#define tsip_dialog_fsm_act_2(self, action_id) tsip_dialog_fsm_act((self), (action_id), tsk_null, tsk_null)
tsk_bool_t tsip_dialog_keep_action(const tsip_dialog_t* self, const tsip_response_t *response);
int tsip_dialog_set_connected_fd(tsip_dialog_t* self, tnet_fd_t fd);
int tsip_dialog_set_curr_action(tsip_dialog_t* self, const tsip_action_t* action);

View File

@ -117,6 +117,10 @@ typedef enum tsip_msession_param_type_e
mstype_set_rtcp,
mstype_set_rtcpmux,
mstype_set_ice,
mstype_set_ice_stun,
mstype_set_ice_turn,
mstype_set_stun_server,
mstype_set_stun_cred,
mstype_set_qos,
mstype_unset_qos,
@ -142,6 +146,10 @@ tsip_msession_param_type_t;
#define TSIP_MSESSION_SET_RTCP(ENABLED_BOOL) mstype_set_rtcp, (tsk_bool_t)ENABLED_BOOL
#define TSIP_MSESSION_SET_RTCPMUX(ENABLED_BOOL) mstype_set_rtcpmux, (tsk_bool_t)ENABLED_BOOL
#define TSIP_MSESSION_SET_ICE(ENABLED_BOOL) mstype_set_ice, (tsk_bool_t)ENABLED_BOOL
#define TSIP_MSESSION_SET_ICE_STUN(ENABLED_BOOL) mstype_set_ice_stun, (tsk_bool_t)ENABLED_BOOL
#define TSIP_MSESSION_SET_ICE_TURN(ENABLED_BOOL) mstype_set_ice_turn, (tsk_bool_t)ENABLED_BOOL
#define TSIP_MSESSION_SET_STUN_SERVER(HOSTNAME, PORT) mstype_set_stun_server, (const char*)HOSTNAME, (uint16_t)PORT
#define TSIP_MSESSION_SET_STUN_CRED(USERNAME, PASSWORD) mstype_set_stun_cred, (const char*)USERNAME, (const char*)PASSWORD
#define TSIP_MSESSION_SET_QOS(TYPE_ENUM, STRENGTH_ENUM) mstype_set_qos, (tmedia_qos_stype_t)TYPE_ENUM, (tmedia_qos_strength_t)STRENGTH_ENUM
#define TSIP_MSESSION_UNSET_QOS() mstype_unset_qos
#define TSIP_MSESSION_SET_TIMERS(TIMEOUT_UINT, REFRESHER_STR) mstype_set_timers, (unsigned)TIMEOUT_UINT, (const char*)REFRESHER_STR
@ -230,10 +238,19 @@ typedef struct tsip_ssession_s
struct{
tmedia_session_msrp_cb_f callback;
} msrp;
/* STUN */
struct{
char* username;
char* password;
char* hostname;
uint16_t port;
} stun;
/* Features */
unsigned enable_100rel:1;
unsigned enable_ice:1;
unsigned enable_icestun:1;
unsigned enable_iceturn:1;
unsigned enable_rtcp:1;
unsigned enable_rtcpmux:1;
} media;

View File

@ -111,7 +111,6 @@ typedef enum tsip_stack_param_type_e
tsip_pname_header,
/* Nat Traversal */
tsip_pname_icestun_enabled,
tsip_pname_stun_enabled,
tsip_pname_stun_server,
tsip_pname_stun_cred,
@ -523,7 +522,6 @@ int ret = tsip_stack_set(stack,
#define TSIP_STACK_SET_STUN_SERVER(IP_STR, PORT_UINT) tsip_pname_stun_server, (const char*)IP_STR, (unsigned)PORT_UINT
#define TSIP_STACK_SET_STUN_CRED(USR_STR, PASSORD_STR) tsip_pname_stun_cred, (const char*)USR_STR, (const char*)PASSORD_STR
#define TSIP_STACK_SET_STUN_ENABLED(ENABLED_BOOL) tsip_pname_stun_enabled, (tsk_bool_t)ENABLED_BOOL
#define TSIP_STACK_SET_ICE_STUN_ENABLED(ENABLED_BOOL) tsip_pname_icestun_enabled, (tsk_bool_t)ENABLED_BOOL
/* === User Data === */
/**@ingroup tsip_stack_group
@ -649,12 +647,7 @@ typedef struct tsip_stack_s
char* pwd;
tsk_bool_t enabled;
} stun;
struct{
tsk_bool_t stun_enabled;
} ice;
// TURN
// ICE
tnet_nat_context_handle_t* ctx;
struct tnet_nat_ctx_s* ctx;
} natt;
/* DHCP context */

View File

@ -28,6 +28,7 @@
#include "tinysdp/headers/tsdp_header_S.h"
#include "tinysdp/headers/tsdp_header_O.h"
#include "stun/tnet_stun_types.h"
#include "ice/tnet_ice_ctx.h"
#include "tsk_debug.h"
@ -131,45 +132,46 @@ int tsip_dialog_invite_ice_timers_set(tsip_dialog_invite_t *self, int64_t timeou
static int tsip_dialog_invite_ice_create_ctx(tsip_dialog_invite_t * self, tmedia_type_t media_type)
{
int32_t transport_idx;
int ret = 0;
if(!self){
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
transport_idx = TSIP_DIALOG_GET_STACK(self)->network.transport_idx_default;
if(!self->ice.ctx_audio && (media_type & tmedia_audio)){
if (!self->ice.ctx_audio && (media_type & tmedia_audio)) {
self->ice.ctx_audio = tnet_ice_ctx_create(self->ice.is_jingle, TNET_SOCKET_TYPE_IS_IPV6(TSIP_DIALOG_GET_STACK(self)->network.proxy_cscf_type[transport_idx]),
self->use_rtcp, tsk_false, tsip_dialog_invite_ice_audio_callback, self);
if(!self->ice.ctx_audio){
if (!self->ice.ctx_audio) {
TSK_DEBUG_ERROR("Failed to create ICE audio context");
return -2;
}
if(TSIP_DIALOG_GET_STACK(self)->natt.ice.stun_enabled){
tnet_ice_ctx_set_stun(self->ice.ctx_audio, TSIP_DIALOG_GET_STACK(self)->natt.stun.ip, TSIP_DIALOG_GET_STACK(self)->natt.stun.port, "Doubango", TSIP_DIALOG_GET_STACK(self)->natt.stun.login, TSIP_DIALOG_GET_STACK(self)->natt.stun.pwd);
}
tnet_ice_ctx_set_rtcpmux(self->ice.ctx_audio, self->use_rtcpmux);
ret = tnet_ice_ctx_set_stun(self->ice.ctx_audio, TSIP_DIALOG_GET_SS(self)->media.stun.hostname, TSIP_DIALOG_GET_SS(self)->media.stun.port, kStunSoftware, TSIP_DIALOG_GET_STACK(self)->natt.stun.login, TSIP_DIALOG_GET_SS(self)->media.stun.password);
ret = tnet_ice_ctx_set_stun_enabled(self->ice.ctx_audio, TSIP_DIALOG_GET_SS(self)->media.enable_icestun);
ret = tnet_ice_ctx_set_turn_enabled(self->ice.ctx_audio, TSIP_DIALOG_GET_SS(self)->media.enable_iceturn);
ret = tnet_ice_ctx_set_rtcpmux(self->ice.ctx_audio, self->use_rtcpmux);
}
if(!self->ice.ctx_video && (media_type & tmedia_video)){
if (!self->ice.ctx_video && (media_type & tmedia_video)) {
self->ice.ctx_video = tnet_ice_ctx_create(self->ice.is_jingle, TNET_SOCKET_TYPE_IS_IPV6(TSIP_DIALOG_GET_STACK(self)->network.proxy_cscf_type[transport_idx]),
self->use_rtcp, tsk_true, tsip_dialog_invite_ice_video_callback, self);
if(!self->ice.ctx_video){
if (!self->ice.ctx_video) {
TSK_DEBUG_ERROR("Failed to create ICE video context");
return -2;
}
if(TSIP_DIALOG_GET_STACK(self)->natt.ice.stun_enabled){
tnet_ice_ctx_set_stun(self->ice.ctx_video, TSIP_DIALOG_GET_STACK(self)->natt.stun.ip, TSIP_DIALOG_GET_STACK(self)->natt.stun.port, "Doubango", TSIP_DIALOG_GET_STACK(self)->natt.stun.login, TSIP_DIALOG_GET_STACK(self)->natt.stun.pwd);
}
tnet_ice_ctx_set_rtcpmux(self->ice.ctx_video, self->use_rtcpmux);
ret = tnet_ice_ctx_set_stun(self->ice.ctx_video, TSIP_DIALOG_GET_SS(self)->media.stun.hostname, TSIP_DIALOG_GET_SS(self)->media.stun.port, kStunSoftware, TSIP_DIALOG_GET_STACK(self)->natt.stun.login, TSIP_DIALOG_GET_SS(self)->media.stun.password);
ret = tnet_ice_ctx_set_stun_enabled(self->ice.ctx_video, TSIP_DIALOG_GET_SS(self)->media.enable_icestun);
ret = tnet_ice_ctx_set_turn_enabled(self->ice.ctx_video, TSIP_DIALOG_GET_SS(self)->media.enable_iceturn);
ret = tnet_ice_ctx_set_rtcpmux(self->ice.ctx_video, self->use_rtcpmux);
}
// set media type
tsip_dialog_invite_ice_set_media_type(self, media_type);
ret = tsip_dialog_invite_ice_set_media_type(self, media_type);
// update session manager with the right ICE contexts
if(self->msession_mgr){
tmedia_session_mgr_set_ice_ctx(self->msession_mgr, self->ice.ctx_audio, self->ice.ctx_video);
if (self->msession_mgr) {
ret = tmedia_session_mgr_set_ice_ctx(self->msession_mgr, self->ice.ctx_audio, self->ice.ctx_video);
}
return 0;
return ret;
}
int tsip_dialog_invite_ice_set_media_type(tsip_dialog_invite_t * self, tmedia_type_t _media_type)
@ -548,7 +550,7 @@ static int tsip_dialog_invite_ice_callback(const tnet_ice_event_t *e)
{
if(dialog->ice.last_action_id != tsk_fsm_state_none){
if(tsip_dialog_invite_ice_got_local_candidates(dialog)){
tsip_dialog_fsm_act(TSIP_DIALOG(dialog), dialog->ice.last_action_id, dialog->ice.last_message, dialog->ice.last_action);
ret = tsip_dialog_fsm_act(TSIP_DIALOG(dialog), dialog->ice.last_action_id, dialog->ice.last_message, dialog->ice.last_action);
dialog->ice.last_action_id = tsk_fsm_state_none;
}
}
@ -560,13 +562,20 @@ static int tsip_dialog_invite_ice_callback(const tnet_ice_event_t *e)
// fatal errors which discard ICE process
case tnet_ice_event_type_gathering_host_candidates_failed:
case tnet_ice_event_type_gathering_reflexive_candidates_failed:
case tnet_ice_event_type_gathering_relay_candidates_failed:
{
if(dialog->ice.last_action_id != tsk_fsm_state_none){
tsip_dialog_fsm_act(TSIP_DIALOG(dialog), dialog->ice.last_action_id, dialog->ice.last_message, dialog->ice.last_action);
if (dialog->ice.last_action_id != tsk_fsm_state_none) {
ret = tsip_dialog_fsm_act(TSIP_DIALOG(dialog), dialog->ice.last_action_id, dialog->ice.last_message, dialog->ice.last_action);
dialog->ice.last_action_id = tsk_fsm_state_none;
}
break;
}
// TURN session disconnected while we're in call
case tnet_ice_event_type_turn_connection_broken:
{
ret = tsip_dialog_fsm_act_2(TSIP_DIALOG(dialog), _fsm_action_oBYE);
break;
}
default: break;
}

View File

@ -439,12 +439,6 @@ static int __tsip_stack_set(tsip_stack_t *self, va_list* app)
self->natt.stun.enabled = va_arg(*app, tsk_bool_t);
break;
}
case tsip_pname_icestun_enabled:
{ /* (tsk_bool_t)ENABLED_BOOL */
self->natt.ice.stun_enabled = va_arg(*app, tsk_bool_t);
break;
}
/* === User Data === */
case tsip_pname_userdata:
{ /* (const void*)DATA_PTR */
@ -558,12 +552,13 @@ tsip_stack_handle_t* tsip_stack_create(tsip_stack_callback_f callback, const cha
const char *server_ip, *usr_name, *usr_pwd;
uint16_t server_port;
stack->natt.stun.enabled = tmedia_defaults_get_stun_enabled();
stack->natt.ice.stun_enabled = tmedia_defaults_get_icestun_enabled();
if(tmedia_defaults_get_stun_server(&server_ip, &server_port, &usr_name, &usr_pwd) == 0){
if(tmedia_defaults_get_stun_server(&server_ip, &server_port) == 0){
tsk_strupdate(&stack->natt.stun.ip, server_ip);
stack->natt.stun.port = server_port;
}
if(tmedia_defaults_get_stun_cred(&usr_name, &usr_pwd) == 0){
tsk_strupdate(&stack->natt.stun.login, usr_name);
tsk_strupdate(&stack->natt.stun.pwd, usr_pwd);
stack->natt.stun.port = server_port;
}
}
@ -754,7 +749,7 @@ int tsip_stack_start(tsip_stack_handle_t *self)
if(stack->natt.stun.enabled && !tsk_strnullORempty(stack->natt.stun.ip)){
if(stack->natt.stun.port == 0){
/* FIXME: for now only UDP(IPv4/IPv6) is supported */
stack->natt.stun.port = TNET_STUN_TCP_UDP_DEFAULT_PORT;
stack->natt.stun.port = kStunPortDefaultTcpUdp;
}
TSK_DEBUG_INFO("STUN server = %s:%u", stack->natt.stun.ip, stack->natt.stun.port);
stack->natt.ctx = tnet_nat_context_create(TNET_SOCKET_TYPE_IS_IPV6(tx_values[stack->network.transport_idx_default])? tnet_socket_type_udp_ipv6: tnet_socket_type_udp_ipv4,

View File

@ -288,6 +288,8 @@ int __tsip_ssession_set(tsip_ssession_t *self, va_list *app)
break;
case mstype_set_100rel: self->media.enable_100rel = va_arg(*app, tsk_bool_t); break;
case mstype_set_ice: self->media.enable_ice = va_arg(*app, tsk_bool_t); break;
case mstype_set_ice_stun: self->media.enable_icestun = va_arg(*app, tsk_bool_t); break;
case mstype_set_ice_turn: self->media.enable_iceturn = va_arg(*app, tsk_bool_t); break;
case mstype_set_rtcp: self->media.enable_rtcp = va_arg(*app, tsk_bool_t); break;
case mstype_set_rtcpmux: self->media.enable_rtcpmux = va_arg(*app, tsk_bool_t); break;
case mstype_set_qos:
@ -350,6 +352,22 @@ int __tsip_ssession_set(tsip_ssession_t *self, va_list *app)
self->media.msrp.callback = va_arg(*app, tmedia_session_msrp_cb_f);
break;
}
case mstype_set_stun_server:
{ /* (const char*)HOSTNAME, (uint16_t)PORT */
const char* HOSTNAME = va_arg(*app, const char*);
uint16_t PORT = tsk_va_arg_u16(*app);
tsk_strupdate(&self->media.stun.hostname, HOSTNAME);
self->media.stun.port = PORT;
break;
}
case mstype_set_stun_cred:
{ /* (const char*)USERNAME, (const char*)PASSWORD */
const char* USERNAME = va_arg(*app, const char*);
const char* PASSWORD = va_arg(*app, const char*);
tsk_strupdate(&self->media.stun.username, USERNAME);
tsk_strupdate(&self->media.stun.password, PASSWORD);
break;
}
default:{
/* va_list will be unsafe => exit */
TSK_DEBUG_ERROR("%d NOT a valid MEDIA pname", mscurr);
@ -644,7 +662,7 @@ static tsk_object_t* tsip_ssession_ctor(tsk_object_t * self, va_list * app)
// default parentid: not parent -> no pending transfer
ss->id_parent = TSIP_SSESSION_INVALID_ID;
// default SigComp compId (will be updated by session_set())
if(ss->stack->sigcomp.handle){
if (ss->stack->sigcomp.handle) {
ss->sigcomp_id = tsk_strdup(tsip_sigcomp_handler_fixme_getcompid(ss->stack->sigcomp.handle));
}
// default media values
@ -653,6 +671,8 @@ static tsk_object_t* tsip_ssession_ctor(tsk_object_t * self, va_list * app)
ss->media.avpf_mode = tmedia_defaults_get_avpf_mode();
ss->media.enable_100rel = tmedia_defaults_get_100rel_enabled();
ss->media.enable_ice = tmedia_defaults_get_ice_enabled();
ss->media.enable_icestun = tmedia_defaults_get_icestun_enabled();
ss->media.enable_iceturn = tmedia_defaults_get_iceturn_enabled();
ss->media.enable_rtcp = tmedia_defaults_get_rtcp_enabled();
ss->media.enable_rtcpmux = tmedia_defaults_get_rtcpmux_enabled();
ss->media.type = tmedia_none;
@ -663,6 +683,18 @@ static tsk_object_t* tsip_ssession_ctor(tsk_object_t * self, va_list * app)
ss->media.codecs = tmedia_codec_id_all;
ss->media.bypass_encoding = tmedia_defaults_get_bypass_encoding();
ss->media.bypass_decoding = tmedia_defaults_get_bypass_decoding();
{
const char *stun_hostname, *stun_username, *stun_password;
uint16_t stun_port;
if(tmedia_defaults_get_stun_server(&stun_hostname, &stun_port) == 0){
ss->media.stun.hostname = tsk_strdup(stun_hostname);
ss->media.stun.port = stun_port;
}
if(tmedia_defaults_get_stun_cred(&stun_username, &stun_password) == 0){
ss->media.stun.username = tsk_strdup(stun_username);
ss->media.stun.password = tsk_strdup(stun_password);
}
}
/* add the session to the stack */
if(ss->stack){
@ -699,6 +731,9 @@ static tsk_object_t* tsip_ssession_dtor(tsk_object_t * self)
// Media
//=======
TSK_FREE(ss->media.timers.refresher);
TSK_FREE(ss->media.stun.username);
TSK_FREE(ss->media.stun.password);
TSK_FREE(ss->media.stun.hostname);
//=======
// WebSocket