Commit 75cba9f6 authored by Martti Mela's avatar Martti Mela
Browse files

updated stunc with cool features & cleanup. Removed stun_request_t from public callbacks

darcs-hash:20060328120527-1b897-af1a5d9e4acede3a12aa2506b336476cd3485e14.gz
parent b836a3d1
......@@ -133,7 +133,6 @@ typedef enum stun_state_e {
/* Per discovery */
typedef void (*stun_discovery_f)(stun_discovery_magic_t *magic,
stun_handle_t *sh,
stun_request_t *req,
stun_discovery_t *sd,
stun_action_t action,
stun_state_t event);
......@@ -255,7 +254,6 @@ void stun_mini_request(stun_mini_t *server, int socket,
/* Used if no stun_discovery_f specified for a discovery */
typedef void (*stun_event_f)(stun_magic_t *magic,
stun_handle_t *sh,
stun_request_t *req,
stun_discovery_t *sd,
stun_action_t action,
stun_state_t event);
......
......@@ -1409,10 +1409,13 @@ static int stun_tls_callback(su_root_magic_t *m, su_wait_t *w, su_wakeup_arg_t *
sd->sd_state = stun_tls_connection_failed;
if (sd->sd_callback)
sd->sd_callback(sd->sd_magic, self, NULL, sd, sd->sd_action, sd->sd_state);
sd->sd_callback(sd->sd_magic, self, sd, sd->sd_action, sd->sd_state);
#if 0
else
self->sh_callback(self->sh_context, self, NULL, sd,
self->sh_callback(self->sh_context, self, sd,
sd->sd_action, sd->sd_state);
#endif
return 0;
}
......@@ -1484,10 +1487,12 @@ static int stun_tls_callback(su_root_magic_t *m, su_wait_t *w, su_wakeup_arg_t *
sd->sd_state = stun_tls_connection_failed;
if (sd->sd_callback)
sd->sd_callback(sd->sd_magic, self, NULL, sd, sd->sd_action, sd->sd_state);
sd->sd_callback(sd->sd_magic, self, sd, sd->sd_action, sd->sd_state);
#if 0
else
self->sh_callback(self->sh_context, self, NULL, sd,
self->sh_callback(self->sh_context, self, sd,
sd->sd_action, sd->sd_state);
#endif
return -1;
}
......@@ -1613,11 +1618,13 @@ static int stun_tls_callback(su_root_magic_t *m, su_wait_t *w, su_wakeup_arg_t *
sd->sd_state = stun_tls_done;
if (sd->sd_callback)
sd->sd_callback(sd->sd_magic, self, NULL, sd, sd->sd_action, sd->sd_state);
sd->sd_callback(sd->sd_magic, self, sd, sd->sd_action, sd->sd_state);
#if 0
else
self->sh_callback(self->sh_context, self, NULL, sd,
self->sh_callback(self->sh_context, self, sd,
sd->sd_action, sd->sd_state);
#endif
break;
default:
......@@ -1660,7 +1667,7 @@ static void stun_tls_connect_timer_cb(su_root_magic_t *magic,
sd->sd_index = -1; /* mark index as deregistered */
sd->sd_state = stun_tls_connection_timeout;
sh->sh_callback(sh->sh_context, sh, NULL, sd, sd->sd_action, sd->sd_state);
sd->sd_callback(sd->sd_magic, sh, sd, sd->sd_action, sd->sd_state);
return;
}
......@@ -1773,8 +1780,10 @@ static int stun_bind_callback(stun_magic_t *m, su_wait_t *w, su_wakeup_arg_t *ar
/* su_wait_destroy(w); */
/* su_root_deregister(self->sh_root, self->ss_root_index); */
/* self->sh_state = stun_bind_error; */
self->sh_callback(self->sh_context, self, NULL, NULL,
#if 0
self->sh_callback(self->sh_context, self, NULL,
stun_action_no_action, stun_bind_error);
#endif
return 0;
}
......@@ -1864,16 +1873,20 @@ static int do_action(stun_handle_t *sh, stun_msg_t *msg)
case stun_action_no_action:
SU_DEBUG_3(("%s: Unknown response. No matching request found.\n", __func__));
req->sr_state = stun_request_not_found;
sh->sh_callback(sh->sh_context, sh, req, NULL,
#if 0
sh->sh_callback(sh->sh_context, sh, NULL,
stun_action_no_action, req->sr_state);
#endif
req->sr_state = stun_dispose_me;
break;
default:
SU_DEBUG_3(("%s: bad action.\n", __func__));
req->sr_state = stun_error;
sh->sh_callback(sh->sh_context, sh, req, NULL,
#if 0
sh->sh_callback(sh->sh_context, sh, NULL,
stun_action_no_action, req->sr_state);
#endif
req->sr_state = stun_dispose_me;
break;
}
......@@ -1983,9 +1996,12 @@ static int process_test_lifetime(stun_request_t *req, stun_msg_t *binding_respon
/* Use per discovery specific callback */
if (sd->sd_callback)
sd->sd_callback(sd->sd_magic, sh, req, sd, action, sd->sd_state);
sd->sd_callback(sd->sd_magic, sh, sd, action, sd->sd_state);
#if 0
else
sh->sh_callback(sh->sh_context, sh, req, sd, action, sd->sd_state);
sh->sh_callback(sh->sh_context, sh, sd, action, sd->sd_state);
#endif
req->sr_state = stun_dispose_me;
return 0;
......@@ -1996,9 +2012,11 @@ static int process_test_lifetime(stun_request_t *req, stun_msg_t *binding_respon
/* Use per discovery specific callback */
if (sd->sd_callback)
sd->sd_callback(sd->sd_magic, sh, req, sd, action, sd->sd_state);
sd->sd_callback(sd->sd_magic, sh, sd, action, sd->sd_state);
#if 0
else
sh->sh_callback(sh->sh_context, sh, req, sd, action, sd->sd_state);
sh->sh_callback(sh->sh_context, sh, sd, action, sd->sd_state);
#endif
req->sr_state = stun_dispose_me;
return 0;
......@@ -2089,9 +2107,11 @@ static int action_bind(stun_request_t *req, stun_msg_t *binding_response)
sd->sd_state = stun_bind_done;
if (sd->sd_callback)
sd->sd_callback(sd->sd_magic, sh, req, sd, action, sd->sd_state);
sd->sd_callback(sd->sd_magic, sh, sd, action, sd->sd_state);
#if 0
else
sh->sh_callback(sh->sh_context, sh, req, sd, action, sd->sd_state);
sh->sh_callback(sh->sh_context, sh, sd, action, sd->sd_state);
#endif
req->sr_state = stun_dispose_me;
......@@ -2149,9 +2169,11 @@ static int action_determine_nattype(stun_request_t *req, stun_msg_t *binding_res
/* Use per discovery specific callback */
if (sd->sd_callback)
sd->sd_callback(sd->sd_magic, sh, req, sd, action, sd->sd_state);
sd->sd_callback(sd->sd_magic, sh, sd, action, sd->sd_state);
#if 0
else
sh->sh_callback(sh->sh_context, sh, req, sd, action, sd->sd_state);
sh->sh_callback(sh->sh_context, sh, sd, action, sd->sd_state);
#endif
req->sr_state = stun_dispose_me;
/* stun_request_destroy(req); */
......@@ -2165,9 +2187,11 @@ static int action_determine_nattype(stun_request_t *req, stun_msg_t *binding_res
/* Use per discovery specific callback */
if (sd->sd_callback)
sd->sd_callback(sd->sd_magic, sh, req, sd, action, sd->sd_state);
sd->sd_callback(sd->sd_magic, sh, sd, action, sd->sd_state);
#if 0
else
sh->sh_callback(sh->sh_context, sh, req, sd, action, sd->sd_state);
sh->sh_callback(sh->sh_context, sh, sd, action, sd->sd_state);
#endif
req->sr_state = stun_dispose_me;
/* stun_request_destroy(req); */
......@@ -2181,9 +2205,11 @@ static int action_determine_nattype(stun_request_t *req, stun_msg_t *binding_res
/* Use per discovery specific callback */
if (sd->sd_callback)
sd->sd_callback(sd->sd_magic, sh, req, sd, action, sd->sd_state);
sd->sd_callback(sd->sd_magic, sh, sd, action, sd->sd_state);
#if 0
else
sh->sh_callback(sh->sh_context, sh, req, sd, action, sd->sd_state);
sh->sh_callback(sh->sh_context, sh, sd, action, sd->sd_state);
#endif
req->sr_state = stun_dispose_me;
/* stun_request_destroy(req); */
......@@ -2215,9 +2241,11 @@ static int action_determine_nattype(stun_request_t *req, stun_msg_t *binding_res
/* Use per discovery specific callback */
if (sd->sd_callback)
sd->sd_callback(sd->sd_magic, sh, req, sd, action, sd->sd_state);
sd->sd_callback(sd->sd_magic, sh, sd, action, sd->sd_state);
#if 0
else
sh->sh_callback(sh->sh_context, sh, req, sd, action, sd->sd_state);
sh->sh_callback(sh->sh_context, sh, sd, action, sd->sd_state);
#endif
req->sr_state = stun_dispose_me;
/* stun_request_destroy(req); */
......@@ -2239,9 +2267,11 @@ static int action_determine_nattype(stun_request_t *req, stun_msg_t *binding_res
/* Use per discovery specific callback */
if (sd->sd_callback)
sd->sd_callback(sd->sd_magic, sh, req, sd, action, sd->sd_state);
sd->sd_callback(sd->sd_magic, sh, sd, action, sd->sd_state);
#if 0
else
sh->sh_callback(sh->sh_context, sh, req, sd, action, sd->sd_state);
sh->sh_callback(sh->sh_context, sh, sd, action, sd->sd_state);
#endif
req->sr_state = stun_dispose_me;
/* stun_request_destroy(req); */
......@@ -2258,9 +2288,11 @@ static int action_determine_nattype(stun_request_t *req, stun_msg_t *binding_res
/* Use per discovery specific callback */
if (sd->sd_callback)
sd->sd_callback(sd->sd_magic, sh, req, sd, action, sd->sd_state);
sd->sd_callback(sd->sd_magic, sh, sd, action, sd->sd_state);
#if 0
else
sh->sh_callback(sh->sh_context, sh, req, sd, action, sd->sd_state);
sh->sh_callback(sh->sh_context, sh, sd, action, sd->sd_state);
#endif
req->sr_state = stun_dispose_me;
/* stun_request_destroy(req); */
......@@ -2320,9 +2352,11 @@ static void stun_sendto_timer_cb(su_root_magic_t *magic,
/* Use per discovery specific callback */
if (sd->sd_callback)
sd->sd_callback(sd->sd_magic, sh, req, sd, action, sd->sd_state);
sd->sd_callback(sd->sd_magic, sh, sd, action, sd->sd_state);
#if 0
else
sh->sh_callback(sh->sh_context, sh, req, sd, action, sd->sd_state);
sh->sh_callback(sh->sh_context, sh, sd, action, sd->sd_state);
#endif
req->sr_state = stun_dispose_me;
break;
......@@ -2340,9 +2374,11 @@ static void stun_sendto_timer_cb(su_root_magic_t *magic,
/* Use per discovery specific callback */
if (sd->sd_callback)
sd->sd_callback(sd->sd_magic, sh, req, sd, action, sd->sd_state);
sd->sd_callback(sd->sd_magic, sh, sd, action, sd->sd_state);
#if 0
else
sh->sh_callback(sh->sh_context, sh, req, sd, action, sd->sd_state);
sh->sh_callback(sh->sh_context, sh, sd, action, sd->sd_state);
#endif
stun_keepalive_destroy(sh, sd->sd_socket);
......
......@@ -26,6 +26,7 @@
#define STUN_INTERNAL_H
/**@file stun_internal.h STUN client interface
*
* @author Martti Mela <martti.mela@nokia.com>
* @author Tat Chan <Tat.Chan@nokia.com>
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
* @author Kai Vehmanen <kai.vehmanen@nokia.com>
......
......@@ -45,6 +45,13 @@ typedef struct stunc_s stunc_t;
#include "sofia-sip/stun_tag.h"
#include <sofia-sip/su.h>
enum {
do_secret = 1,
do_bind = 2,
do_nat_check = 4,
do_life_check = 8,
};
#ifndef SU_DEBUG
#define SU_DEBUG 0
......@@ -52,24 +59,28 @@ typedef struct stunc_s stunc_t;
#define SU_LOG (stun_log)
#include <sofia-sip/su_debug.h>
char const *name = "stunc";
void usage(int exitcode)
void usage(char *name)
{
fprintf(stderr, "usage: %s server <use message integrity> <determine NAT type>\n", name);
exit(exitcode);
fprintf(stderr, "usage: %s <server> [-s] [-b] [-n] [-l]\n", name);
exit(1);
}
struct stunc_s {
su_socket_t sc_socket;
int sc_test_nattype;
int sc_flags;
};
static
void stunc_lifetime_cb(stunc_t *stunc,
stun_handle_t *sh,
stun_discovery_t *sd,
stun_action_t action,
stun_state_t event);
static
void stunc_nattype_cb(stunc_t *stunc,
stun_handle_t *sh,
stun_request_t *req,
stun_discovery_t *sd,
stun_action_t action,
stun_state_t event);
......@@ -77,7 +88,6 @@ void stunc_nattype_cb(stunc_t *stunc,
static
void stunc_bind_cb(stunc_t *stunc,
stun_handle_t *sh,
stun_request_t *req,
stun_discovery_t *sd,
stun_action_t action,
stun_state_t event);
......@@ -85,7 +95,6 @@ void stunc_bind_cb(stunc_t *stunc,
static
void stunc_ss_cb(stunc_t *stunc,
stun_handle_t *sh,
stun_request_t *req,
stun_discovery_t *sd,
stun_action_t action,
stun_state_t event)
......@@ -93,50 +102,39 @@ void stunc_ss_cb(stunc_t *stunc,
int err;
SU_DEBUG_3(("%s: %s\n", __func__, stun_str_state(event)));
stunc->sc_flags &= ~do_secret;
if (!stunc->sc_flags)
su_root_break(stun_handle_root(sh));
switch (event) {
case stun_tls_done:
err = stun_bind(sh, stunc_bind_cb, stunc,
STUNTAG_SOCKET(stunc->sc_socket),
STUNTAG_REGISTER_EVENTS(1),
TAG_NULL());
if (err < 0) {
SU_DEBUG_0(("%s: %s failed\n", __func__, "stun_handle_bind()"));
su_root_break(stun_handle_root(sh));
if (stunc->sc_flags & do_bind) {
err = stun_bind(sh, stunc_bind_cb, stunc,
STUNTAG_SOCKET(stunc->sc_socket),
STUNTAG_REGISTER_EVENTS(1),
TAG_NULL());
if (err < 0) {
SU_DEBUG_0(("%s: %s failed\n", __func__, "stun_handle_bind()"));
su_root_break(stun_handle_root(sh));
}
}
break;
case stun_tls_connection_failed:
SU_DEBUG_0(("%s: Obtaining shared secret failed, starting binding process.\n",
SU_DEBUG_0(("%s: Obtaining shared secret failed.\n",
__func__));
stunc->sc_flags &= ~do_bind;
err = stun_bind(sh, stunc_bind_cb, stunc,
STUNTAG_SOCKET(stunc->sc_socket),
STUNTAG_REGISTER_EVENTS(1),
TAG_NULL());
if (err < 0) {
SU_DEBUG_0(("%s: %s failed\n", __func__, "stun_handle_bind()"));
su_root_break(stun_handle_root(sh));
}
break;
case stun_tls_connection_timeout:
SU_DEBUG_0(("%s: Timeout when obtaining shared secret, starting binding process.\n",
SU_DEBUG_0(("%s: Timeout when obtaining shared secret.\n",
__func__));
err = stun_bind(sh, stunc_bind_cb, stunc,
STUNTAG_SOCKET(stunc->sc_socket),
STUNTAG_REGISTER_EVENTS(1),
TAG_NULL());
if (err < 0) {
SU_DEBUG_0(("%s: %s failed\n", __func__, "stun_handle_bind()"));
su_root_break(stun_handle_root(sh));
}
stunc->sc_flags &= ~do_bind;
break;
default:
su_root_break(stun_handle_root(sh));
break;
}
......@@ -147,19 +145,21 @@ void stunc_ss_cb(stunc_t *stunc,
static
void stunc_bind_cb(stunc_t *stunc,
stun_handle_t *sh,
stun_request_t *req,
stun_discovery_t *sd,
stun_action_t action,
stun_state_t event)
{
su_sockaddr_t sa[1];
char ipaddr[48];
char const *nattype;
int lifetime, err;
socklen_t addrlen;
SU_DEBUG_3(("%s: %s\n", __func__, stun_str_state(event)));
stunc->sc_flags &= ~do_bind;
if (!stunc->sc_flags)
su_root_break(stun_handle_root(sh));
switch (event) {
case stun_bind_done:
addrlen = sizeof(*sa);
......@@ -175,19 +175,6 @@ void stunc_bind_cb(stunc_t *stunc,
ipaddr, sizeof(ipaddr)),
(unsigned) ntohs(sa->su_port)));
if (stunc->sc_test_nattype) {
err = stun_test_nattype(sh, stunc_nattype_cb, stunc,
STUNTAG_REGISTER_EVENTS(1),
STUNTAG_SOCKET(stunc->sc_socket),
TAG_NULL());
if (err < 0) {
SU_DEBUG_0(("%s: %s failed\n", __func__, "stun_handle_test_nattype()"));
su_root_break(stun_handle_root(sh));
}
}
else
su_root_break(stun_handle_root(sh));
#if 0
if (stun_handle_test_lifetime(sh, STUNTAG_SOCKET(s), TAG_NULL()) < 0) {
......@@ -199,18 +186,10 @@ void stunc_bind_cb(stunc_t *stunc,
break;
case stun_discovery_timeout:
if (action == stun_action_binding_request) {
su_root_break(stun_handle_root(sh));
}
break;
case stun_bind_error:
case stun_error:
/* su_root_break(stun_handle_root(sh)); */
case stun_bind_timeout:
default:
su_root_break(stun_handle_root(sh));
break;
}
......@@ -221,33 +200,60 @@ void stunc_bind_cb(stunc_t *stunc,
static
void stunc_nattype_cb(stunc_t *stunc,
stun_handle_t *sh,
stun_request_t *req,
stun_discovery_t *sd,
stun_action_t action,
stun_state_t event)
{
su_sockaddr_t sa[1];
char ipaddr[48];
char const *nattype;
int lifetime;
socklen_t addrlen;
SU_DEBUG_3(("%s: %s\n", __func__, stun_str_state(event)));
switch (event) {
stunc->sc_flags &= ~do_nat_check;
if (!stunc->sc_flags)
su_root_break(stun_handle_root(sh));
switch (event) {
case stun_discovery_timeout:
if (action == stun_action_binding_request) {
su_root_break(stun_handle_root(sh));
}
SU_DEBUG_3(("%s: NAT type determination timeout.\n", __func__));
break;
case stun_discovery_done:
SU_DEBUG_3(("%s: NAT type determined to be %s.\n", __func__, stun_nattype(sd)));
break;
case stun_error:
default:
break;
}
return;
}
static
void stunc_lifetime_cb(stunc_t *stunc,
stun_handle_t *sh,
stun_discovery_t *sd,
stun_action_t action,
stun_state_t event)
{
SU_DEBUG_3(("%s: %s\n", __func__, stun_str_state(event)));
stunc->sc_flags &= ~do_life_check;
if (!stunc->sc_flags)
su_root_break(stun_handle_root(sh));
switch (event) {
case stun_discovery_timeout:
SU_DEBUG_3(("%s: Lifetime determination timeout.\n", __func__));
break;
case stun_discovery_done:
SU_DEBUG_3(("%s: Lifetime determined to be %d.\n", __func__, stun_lifetime(sd)));
break;
case stun_error:
default:
break;
}
......@@ -257,25 +263,33 @@ void stunc_nattype_cb(stunc_t *stunc,
int main(int argc, char *argv[])
{
int param_integrity, param_nattype, err;
int err, i, sflags = 0;
stunc_t stunc[1];
su_root_t *root = su_root_create(stunc);
stun_handle_t *sh;
/* Our UDP socket */
su_sockaddr_t sa[1];
su_socket_t s;
if (argc != 4)
usage(1);
param_integrity = atoi(argv[2]);
param_nattype = atoi(argv[3]);
if (!argv[1] || !argv[2] || inet_pton(AF_INET, argv[1], sa) < 1)
usage(argv[0]);
for (i = 2; argv[i]; i++) {
if (strcmp(argv[i], "-s") == 0)
sflags |= do_secret;
else if (strcmp(argv[i], "-b") == 0)
sflags |= do_bind;
else if (strcmp(argv[i], "-n") == 0)
sflags |= do_nat_check;
else if (strcmp(argv[i], "-l") == 0)
sflags |= do_life_check;
else
usage(argv[0]);
}
/* Running this test requires a local STUN server on default port */
sh = stun_handle_init(root,
STUNTAG_SERVER(argv[1]),
STUNTAG_REQUIRE_INTEGRITY(param_integrity),
STUNTAG_REQUIRE_INTEGRITY(sflags & do_secret),
TAG_NULL());
if (!sh) {
......@@ -285,33 +299,60 @@ int main(int argc, char *argv[])
s = su_socket(AF_INET, SOCK_DGRAM, 0);
if (s == -1) {
SU_DEBUG_0(("%s: %s failed: %s\n", __func__, "su_socket()", su_gli_strerror(errno)));
SU_DEBUG_0(("%s: %s failed: %s\n", __func__,
"su_socket()", su_gli_strerror(errno)));
return -1;
}
stunc->sc_socket = s;
stunc->sc_test_nattype = param_nattype;
stunc->sc_flags = sflags;
if (param_integrity == 1) {
if (sflags & do_secret) {
if (stun_obtain_shared_secret(sh, stunc_ss_cb, stunc, TAG_NULL()) < 0) {
SU_DEBUG_3(("%s: %s failed\n", __func__, "stun_handle_request_shared_secret()"));
SU_DEBUG_3(("%s: %s failed\n", __func__,
"stun_handle_request_shared_secret()"));
return -1;
}
su_root_run(root);
stun_handle_destroy(sh);
return 0;
}
/* If no TSL query, start bind here */
err = stun_bind(sh, stunc_bind_cb, stunc,
STUNTAG_SOCKET(s),
STUNTAG_REGISTER_EVENTS(1),
TAG_NULL());
if (err < 0) {
SU_DEBUG_0(("%s: %s failed\n", __func__, "stun_bind()"));
return -1;
/* If we want to bind and no integrity required */
if ((sflags & do_bind) && !(sflags & do_secret)) {
err = stun_bind(sh, stunc_bind_cb, stunc,
STUNTAG_SOCKET(s),
STUNTAG_REGISTER_EVENTS(1),
TAG_NULL());
if (err < 0) {