Commit f42ad91b authored by Martti Mela's avatar Martti Mela

updated STUN API, tport-stun-http mods in progress

darcs-hash:20060322111238-1b897-9ad14e959d072aa765a92afbfd1f56411dc9e8c5.gz
parent a95d68f5
......@@ -1936,7 +1936,7 @@ void agent_tp_error(nta_agent_t *agent,
/** Handle updated transport addresses */
static void agent_update_tport(nta_agent_t *self, tport_t *tport)
{
/* Initialize non-natted Vias first */
/* Initialize local Vias first */
agent_init_via(self, tport_primaries(self->sa_tports), 0);
/* Initialize natted Vias */
......
......@@ -155,58 +155,73 @@ typedef void (*stun_dns_lookup_f)(stun_dns_lookup_t *self,
/* -------------------------------------------------------------------
* Functions for managing STUN handles. */
char const *stun_str_state(stun_state_t state);
/** Check if a STUN handle should be created. */
stun_handle_t *stun_handle_create(stun_magic_t *context,
su_root_t *root,
stun_event_f cb,
tag_type_t tag, tag_value_t value, ...);
int stun_handle_release(stun_handle_t *sh, su_socket_t s);
void stun_handle_destroy(stun_handle_t *sh);
su_root_t *stun_handle_root(stun_handle_t *sh);
int stun_handle_process_message(stun_handle_t *sh, su_socket_t s,
su_sockaddr_t *sa, socklen_t salen,
void *data, int len);
int stun_process_request(su_socket_t s, stun_msg_t *req,
int sid, su_sockaddr_t *from_addr,
int from_len);
char const *stun_str_state(stun_state_t state);
su_root_t *stun_root(stun_handle_t *sh);
int stun_is_requested(tag_type_t tag, tag_value_t value, ...);
/* -------------------------------------------------------------------
* Functions for 'Binding Discovery' usage (RFC3489bis) */
int stun_request_shared_secret(stun_handle_t *sh);
int stun_handle_bind(stun_handle_t *sh,
/** Bind a socket using STUN. */
int stun_bind(stun_handle_t *sh,
stun_discovery_f,
stun_discovery_magic_t *magic,
/* su_localinfo_t *my_addr, */
tag_type_t tag, tag_value_t value,
...);
int stun_get_nattype(stun_handle_t *sh,
stun_discovery_f,
stun_discovery_magic_t *magic,
/* su_localinfo_t *my_addr, */
tag_type_t tag, tag_value_t value,
...);
int stun_handle_get_nattype(stun_handle_t *sh,
stun_discovery_f,
stun_discovery_magic_t *magic,
tag_type_t tag, tag_value_t value,
...);
char const *stun_nattype(stun_discovery_t *sd);
su_sockaddr_t *stun_discovery_get_address(stun_discovery_t *sd);
su_socket_t stun_discovery_get_socket(stun_discovery_t *sd);
/* -------------------------------------------------------------------
* Functions for binding lifetime discovery (orig. RFC3489) */
int stun_handle_get_lifetime(stun_handle_t *sh,
stun_discovery_f,
stun_discovery_magic_t *magic,
tag_type_t tag, tag_value_t value,
...);
int stun_get_lifetime(stun_handle_t *sh,
stun_discovery_f,
stun_discovery_magic_t *magic,
tag_type_t tag, tag_value_t value,
...);
int stun_lifetime(stun_discovery_t *sd);
/* -------------------------------------------------------------------
* Functions for 'Connectivity Check' and 'NAT Keepalives' usages (RFC3489bis) */
/* other functions */
int stun_set_uname_pwd(stun_handle_t *sh,
const char *uname,
int len_uname,
const char *pwd,
int len_pwd);
int stun_msg_is_keepalive(uint16_t data);
int stun_message_length(void *data, int len, int end_of_message);
/** Process incoming message */
int stun_process_message(stun_handle_t *sh, su_socket_t s,
su_sockaddr_t *sa, socklen_t salen,
void *data, int len);
int stun_process_request(su_socket_t s, stun_msg_t *req,
int sid, su_sockaddr_t *from_addr,
int from_len);
/* Create a keepalive dispatcher for bound SIP sockets */
int stun_keepalive(stun_handle_t *sh,
su_sockaddr_t *sa,
tag_type_t tag, tag_value_t value,
......@@ -216,6 +231,41 @@ int stun_keepalive_destroy(stun_handle_t *sh, su_socket_t s);
/* -------------------------------------------------------------------
* Functions for 'Short-Term password' usage (RFC3489bis) */
/* Return socket attached to discovery object */
su_socket_t stun_discovery_get_socket(stun_discovery_t *sd);
/*********************************************************/
/* Deprecated functions. These are supported with limited
compatibility. */
su_root_t *stun_handle_root(stun_handle_t *sh);
int stun_handle_request_shared_secret(stun_handle_t *sh);
/** Bind a socket using STUN. */
int stun_handle_bind(stun_handle_t *sh,
/* su_localinfo_t *my_addr, */
tag_type_t tag, tag_value_t value,
...);
int stun_handle_get_nattype(stun_handle_t *sh,
tag_type_t tag, tag_value_t value,
...);
int stun_handle_get_lifetime(stun_handle_t *sh,
tag_type_t tag, tag_value_t value,
...);
int stun_handle_set_uname_pwd(stun_handle_t *sh,
const char *uname,
int len_uname,
const char *pwd,
int len_pwd);
int stun_handle_process_message(stun_handle_t *sh,
su_socket_t s,
su_sockaddr_t *sa,
socklen_t salen,
void *data,
int len);
int stun_handle_request_shared_secret(stun_handle_t *sh);
int stun_handle_set_uname_pwd(stun_handle_t *sh,
const char *uname,
......
......@@ -313,13 +313,19 @@ void stun_keepalive_timer_cb(su_root_magic_t *magic,
su_timer_arg_t *arg);
/* Deprecated. Use stun_root(). */
su_root_t *stun_handle_root(stun_handle_t *self)
{
return stun_root(self);
}
/**
* Return su_root_t assigned to stun_handle_t.
*
* @param self stun_handle_t object
* @return su_root_t object, NULL if self not given.
*/
su_root_t *stun_handle_root(stun_handle_t *self)
su_root_t *stun_root(stun_handle_t *self)
{
return self ? self->sh_root : NULL;
}
......@@ -452,13 +458,22 @@ stun_handle_t *stun_handle_create(stun_magic_t *context,
return stun;
}
/* Deprecated. Use stun_request_shared_secret() */
int stun_handle_request_shared_secret(stun_handle_t *sh)
{
return stun_request_shared_secret(sh);
}
/**
* Performs shared secret request/response processing.
* Result will be trigged in STUN handle callback (state
* one of stun_tls_*).
**/
#if defined(HAVE_OPENSSL)
int stun_handle_request_shared_secret(stun_handle_t *sh)
/** Shared secret request/response processing */
int stun_request_shared_secret(stun_handle_t *sh)
{
int events = -1;
int one, err = -1;
......@@ -549,7 +564,7 @@ int stun_handle_request_shared_secret(stun_handle_t *sh)
return 0;
}
#else
int stun_handle_request_shared_secret(stun_handle_t *sh)
int stun_request_shared_secret(stun_handle_t *sh)
{
return 0;
}
......@@ -811,6 +826,20 @@ static int get_localinfo(su_localinfo_t *clientinfo)
}
#endif
/* Deprecated. Use stun_bind() */
int stun_handle_bind(stun_handle_t *sh,
tag_type_t tag, tag_value_t value,
...)
{
int err;
ta_list ta;
ta_start(ta, tag, value);
err = stun_bind(sh, NULL, NULL, ta_tags(ta));
ta_end(ta);
return err;
}
/** Bind a socket using STUN client.
*
* The function stun_bind() obtains a global address for a UDP socket using
......@@ -842,11 +871,11 @@ static int get_localinfo(su_localinfo_t *clientinfo)
* the socket.
*
*/
int stun_handle_bind(stun_handle_t *sh,
stun_discovery_f sdf,
stun_discovery_magic_t *magic,
tag_type_t tag, tag_value_t value,
...)
int stun_bind(stun_handle_t *sh,
stun_discovery_f sdf,
stun_discovery_magic_t *magic,
tag_type_t tag, tag_value_t value,
...)
{
su_socket_t s = -1;
stun_request_t *req = NULL;
......@@ -963,6 +992,21 @@ int stun_discovery_destroy(stun_discovery_t *sd)
return 0;
}
/* Deprecated. Use stun_get_nattype() */
int stun_handle_get_nattype(stun_handle_t *sh,
tag_type_t tag, tag_value_t value,
...)
{
int err;
ta_list ta;
ta_start(ta, tag, value);
err = stun_get_nattype(sh, NULL, NULL, ta_tags(ta));
ta_end(ta);
return err;
}
/**
* Initiates STUN discovery proces to find out NAT
* characteristics.
......@@ -973,11 +1017,11 @@ int stun_discovery_destroy(stun_discovery_t *sd)
* @TAG STUNTAG_SERVER() stun server hostname or dotted IPv4 address
*
*/
int stun_handle_get_nattype(stun_handle_t *sh,
stun_discovery_f sdf,
stun_discovery_magic_t *magic,
tag_type_t tag, tag_value_t value,
...)
int stun_get_nattype(stun_handle_t *sh,
stun_discovery_f sdf,
stun_discovery_magic_t *magic,
tag_type_t tag, tag_value_t value,
...)
{
int err = 0, index = 0, s_reg = 0;
ta_list ta;
......@@ -2268,15 +2312,26 @@ int stun_process_error_response(stun_msg_t *msg)
return 0;
}
/**
* Sets values for USERNAME and PASSWORD stun fields
* for the handle.
*/
/* Deprecated. Use stun_set_uname_pwd(). */
int stun_handle_set_uname_pwd(stun_handle_t *sh,
const char *uname,
int len_uname,
const char *pwd,
int len_pwd)
{
return stun_set_uname_pwd(sh, uname, len_uname,
pwd, len_pwd);
}
/**
* Sets values for USERNAME and PASSWORD stun fields
* for the handle.
*/
int stun_set_uname_pwd(stun_handle_t *sh,
const char *uname,
int len_uname,
const char *pwd,
int len_pwd)
{
enter;
......@@ -2357,6 +2412,20 @@ int stun_atoaddr(int ai_family,
}
/* Deprecated. Use stun_get_lifetime() */
int stun_handle_get_lifetime(stun_handle_t *sh,
tag_type_t tag, tag_value_t value,
...)
{
int err;
ta_list ta;
ta_start(ta, tag, value);
err = stun_get_lifetime(sh, NULL, NULL, ta_tags(ta));
ta_end(ta);
return err;
}
/**
* Initiates STUN discovery proces to find out NAT
* binding life-time settings.
......@@ -2367,11 +2436,11 @@ int stun_atoaddr(int ai_family,
* @TAG STUNTAG_SERVER() stun server hostname or dotted IPv4 address
*
*/
int stun_handle_get_lifetime(stun_handle_t *sh,
stun_discovery_f sdf,
stun_discovery_magic_t *magic,
tag_type_t tag, tag_value_t value,
...)
int stun_get_lifetime(stun_handle_t *sh,
stun_discovery_f sdf,
stun_discovery_magic_t *magic,
tag_type_t tag, tag_value_t value,
...)
{
stun_request_t *req = NULL;
stun_discovery_t *sd = NULL;
......@@ -2535,10 +2604,19 @@ int stun_message_length(void *data, int len, int end_of_message)
return -1;
}
/** Process incoming message */
/* Deprecated. Use stun_process_message() */
int stun_handle_process_message(stun_handle_t *sh, su_socket_t s,
su_sockaddr_t *sa, socklen_t salen,
void *data, int len)
{
return stun_process_message(sh, s, sa, salen,
data, len);
}
/** Process incoming message */
int stun_process_message(stun_handle_t *sh, su_socket_t s,
su_sockaddr_t *sa, socklen_t salen,
void *data, int len)
{
int retval = -1;
stun_msg_t msg;
......
......@@ -85,7 +85,7 @@ void stunc_callback(stunc_t *stunc, stun_handle_t *sh,
case stun_tls_connection_failed:
case stun_tls_connection_timeout:
SU_DEBUG_0(("%s: TLS query done, start binding process.\n", __func__));
if (stun_handle_bind(sh, NULL, NULL, STUNTAG_SOCKET(s), TAG_NULL()) < 0) {
if (stun_handle_bind(sh, STUNTAG_SOCKET(s), TAG_NULL()) < 0) {
SU_DEBUG_0(("%s: %s failed\n", __func__, "stun_handle_bind()"));
su_root_break(stun_handle_root(sh));
}
......@@ -112,12 +112,12 @@ void stunc_callback(stunc_t *stunc, stun_handle_t *sh,
(unsigned) ntohs(sa->su_port)));
/* su_root_break(stun_handle_root(sh)); */
if (stun_handle_get_nattype(sh, NULL, NULL, STUNTAG_SOCKET(s), TAG_NULL()) < 0) {
if (stun_handle_get_nattype(sh, STUNTAG_SOCKET(s), TAG_NULL()) < 0) {
SU_DEBUG_0(("%s: %s failed\n", __func__, "stun_handle_get_nattype()"));
su_root_break(stun_handle_root(sh));
}
if (stun_handle_get_lifetime(sh, NULL, NULL, STUNTAG_SOCKET(s), TAG_NULL()) < 0) {
if (stun_handle_get_lifetime(sh, STUNTAG_SOCKET(s), TAG_NULL()) < 0) {
SU_DEBUG_0(("%s: %s failed\n", __func__, "stun_handle_get_lifetime()"));
su_root_break(stun_handle_root(sh));
}
......@@ -186,7 +186,7 @@ int main(int argc, char *argv[])
}
/* If no TSL query, start bind here */
if (stun_handle_bind(sh, NULL, NULL, STUNTAG_SOCKET(s), TAG_NULL()) < 0) {
if (stun_handle_bind(sh, STUNTAG_SOCKET(s), TAG_NULL()) < 0) {
SU_DEBUG_0(("%s: %s failed\n", __func__, "stun_handle_bind()"));
return -1;
}
......
......@@ -900,6 +900,7 @@ static tport_primary_t *tport_listen(tport_master_t *mr,
su_addrinfo_t const *ai,
char const *canon, char const *protoname,
int port,
int try_http,
tagi_t *tags);
static void tport_zap_primary(tport_primary_t *);
......@@ -1179,35 +1180,110 @@ tport_primary_t *tport_alloc_public_primary(tport_master_t *mr)
}
#if 0
int tport_tcp_socket_http_connect(su_home_t *home, su_socket_t s,
su_sockaddr_t *sa, url_t const *srv)
/** Process events for socket waiting to be connected
*/
static int tport_http_connected(su_root_magic_t *magic, su_wait_t *w, tport_t *self)
{
int events = su_wait_events(w, self->tp_socket);
tport_master_t *mr = self->tp_master;
su_wait_t wait[1] = { SU_WAIT_INIT };
int error;
SU_DEBUG_7(("%s(%p): events%s%s\n", __func__, self,
events & SU_WAIT_CONNECT ? " CONNECTED" : "",
events & SU_WAIT_ERR ? " ERR" : ""));
#if HAVE_POLL
assert(w->fd == self->tp_socket);
#endif
if (events & SU_WAIT_ERR)
tport_error_event(self, events);
if (!(events & SU_WAIT_CONNECT) || self->tp_closed) {
return 0;
}
error = su_soerror(self->tp_socket);
if (error) {
tport_error_report(self, error, NULL);
return 0;
}
su_root_deregister(mr->mr_root, self->tp_index);
self->tp_index = -1;
self->tp_events = SU_WAIT_IN | SU_WAIT_ERR;
if (su_wait_create(wait, self->tp_socket, self->tp_events) == -1 ||
(self->tp_index = su_root_register(mr->mr_root,
wait, tport_recv, self, 0))
== -1) {
tport_close(self);
}
else if (self->tp_queue && self->tp_queue[self->tp_qhead]) {
tport_send_event(self, events);
}
return 0;
}
int tport_tcp_socket_http_connect(su_socket_t s, const char *httpd,
tagi_t *tags)
{
char ua[] = "sofia-sip-1.11.6";
char *str;
int len;
url_string_t *url;
url_string_t *url_string;
url_t const *url;
su_addrinfo_t *res = NULL, *ai, hints[1] = {{ 0 }};
su_sockaddr_t sa[1];
su_home_t autohome[SU_HOME_AUTO_SIZE(2048)];
su_home_auto(autohome, sizeof autohome);
/* Get the SIP proxy address */
tl_gets(tags,
URLTAG_URL_REF(url_string),
TAG_END());
str = su_sprintf(autohome, "CONNECT %s HTTP/1.1\nUser-agent: %s\n\n",
url_string->us_str, ua);
if ((err = su_getaddrinfo(httpd, NULL, hints, &res)) != 0) {
STUN_ERROR(err, su_getaddrinfo);
return -1;
}
memset(sa, 0, sizeof(*sa));
for (ai = res; ai; ai = ai->ai_next) {
if (ai->ai_family != AF_INET)
continue;
/* info->ai_flags = ai->ai_flags; */
sa->su_family = ai->ai_family;
sa->su_len = ai->ai_addrlen;
memcpy(sa->su_sa, ai->ai_addr, sizeof(struct su_sockaddr_t));
break;
}
len = url_len(srv);
url = su_zalloc(home, len);
url_e(url, len, srv);
/* If no port specified, use default */
if (!sa->su_port)
sa->su_port = htons(443);
str = su_sprintf(home, "CONNECT %s HTTP/1.1\nUser-agent: %s\n\n", (char *) url, ua);
su_free(home, url);
if (res)
su_freeaddrinfo(res);
if (connect(s, sa->su_sa, sa->su_len) == SOCKET_ERROR) {
err = su_errno();
if (err != EINPROGRESS && err != EAGAIN && err != EWOULDBLOCK)
TPORT_CONNECT_ERROR(err, connect);
events = SU_WAIT_CONNECT | SU_WAIT_ERR;
wakeup = tport_http_connected;
}
if (su_wait_create(wait, s, events) == -1)
TPORT_CONNECT_ERROR(su_errno(), su_wait_create);
/* Register receiving function with events specified above */
if ((index = su_root_register(mr->mr_root, wait, wakeup, self, 0)) == -1)
TPORT_CONNECT_ERROR(su_errno(), su_root_register);
su_home_deinit(autohome);
return 0;
}
......@@ -1228,6 +1304,7 @@ tport_primary_t *tport_listen(tport_master_t *mr,
su_addrinfo_t const *ainfo,
char const *canon, char const *protoname,
int port,
int try_http_connect,
tagi_t *tags)
{
tport_primary_t *pri = NULL;
......@@ -1345,8 +1422,23 @@ tport_primary_t *tport_listen(tport_master_t *mr,
}
#endif
}
if (ai->ai_socktype == SOCK_STREAM ||
if (try_http_connect) {
/* tport_tcp_socket_http_connect(s, httpd, sip_registrar); */
/* wakeup = tport_http_connected; */
events = SU_WAIT_CONNECT | SU_WAIT_ERR;
#if !defined(__linux__)
/* Allow reusing TCP sockets
*
* On Solaris & BSD, call setreuseaddr() after bind in order to avoid
* binding to a port owned by an existing server.
*/
su_setreuseaddr(s, 1);
#endif
}
else if (ai->ai_socktype == SOCK_STREAM ||
ai->ai_socktype == SOCK_SEQPACKET) {
/* Connection-oriented protocols listen and accept connections */
wakeup = tport_accept; /* accepting function will be registered */
......@@ -2106,7 +2198,7 @@ int tport_bind_server(tport_master_t *mr,
{
char hostname[256];
char const *canon = NULL, *host, *service;
int error = 0, not_supported, family = 0, natted = 0;
int error = 0, not_supported, family = 0, natted = 0, http_enabled = 0;
tport_primary_t *pri = NULL, *pub = NULL, **tbf, **tbf_pub;
su_addrinfo_t *ai, *res = NULL;
unsigned port, port0, port1, old;
......@@ -2187,7 +2279,7 @@ int tport_bind_server(tport_master_t *mr,
((su_sockaddr_t *)ai->ai_addr)->su_port = htons(port);
pri = tport_listen(mr, ai, canon, ai->ai_canonname, port, tags);
pri = tport_listen(mr, ai, canon, ai->ai_canonname, port, 0, tags);
if (!pri) {
switch (error = su_errno()) {
case EADDRNOTAVAIL: /* Not our address */
......@@ -2201,7 +2293,7 @@ int tport_bind_server(tport_master_t *mr,
}
/* Launch NAT discovery requests */
if (!natted && ai->ai_protocol == IPPROTO_UDP && ai->ai_family == AF_INET) {
if (!natted && ai->ai_family == AF_INET) {
pub = tport_start_public_listen(mr, pri, ai, canon, ai->ai_canonname, port, tags);
if (!pub) {
SU_DEBUG_3(("%s(%p): cannot start NAT traversal discovery\n", __func__, mr));
......@@ -3928,8 +4020,8 @@ int tport_recv_stun_dgram(tport_t const *self, int N)
if ((!error || dgram[0] == 1) && self->tp_master->mr_nat->stun) {
#if HAVE_SOFIA_STUN
if (n > N) n = N; /* Truncated? */
stun_handle_process_message(self->tp_master->mr_nat->stun, self->tp_socket,
from, fromlen, (void *)dgram, n);
stun_process_message(self->tp_master->mr_nat->stun, self->tp_socket,
from, fromlen, (void *)dgram, n);
if (dgram != buffer)
free(dgram);
return 0;
......@@ -7648,9 +7740,9 @@ tport_nat_initialize_nat_traversal(tport_master_t *mr,
if (!nat->stun)
return NULL;
if (stun_handle_request_shared_secret(nat->stun) < 0) {
if (stun_request_shared_secret(nat->stun) < 0) {
SU_DEBUG_3(("%s: %s failed\n", __func__,
"stun_handle_request_shared_secret()"));
"stun_request_shared_secret()"));
}
nat->try_stun = 1;
......@@ -7717,13 +7809,13 @@ int tport_nat_stun_bind(tport_primary_t *pub,
/* Do not register socket to stun's event loop */
reg_socket = 0;
nat_bound = stun_handle_bind(sh, tport_stun_bind_cb, pub,
STUNTAG_SOCKET(s),
STUNTAG_REGISTER_SOCKET(reg_socket),
TAG_NULL());
nat_bound = stun_bind(sh, tport_stun_bind_cb, pub,
STUNTAG_SOCKET(s),
STUNTAG_REGISTER_SOCKET(reg_socket),
TAG_NULL());
if (nat_bound < 0) {
SU_DEBUG_9(("%s: %s failed.\n", __func__, "stun_handle_bind()"));
SU_DEBUG_9(("%s: %s failed.\n", __func__, "stun_bind()"));
return nat_bound;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment