summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorLinus Nordberg <linus@nordu.net>2011-03-09 10:18:06 +0100
committerLinus Nordberg <linus@nordu.net>2011-03-09 10:18:06 +0100
commitce4d6dfe1728e5633a8f49fc4b16c36df0d23521 (patch)
tree679a007b7897e03e9105a0902a84a8df1356e8c7 /lib
parentc4e2bd206bb9248843a8a4d9a945c5e49a188474 (diff)
Add retransmission timer support (UDP).
Diffstat (limited to 'lib')
-rw-r--r--lib/conn.c17
-rw-r--r--lib/event.c43
-rw-r--r--lib/event.h2
-rw-r--r--lib/packet.c6
-rw-r--r--lib/peer.h1
-rw-r--r--lib/radsec.c49
-rw-r--r--lib/send.c4
-rw-r--r--lib/tcp.c31
-rw-r--r--lib/tcp.h2
-rw-r--r--lib/udp.c15
-rw-r--r--lib/udp.h1
11 files changed, 129 insertions, 42 deletions
diff --git a/lib/conn.c b/lib/conn.c
index 85cd7d5..3981f6a 100644
--- a/lib/conn.c
+++ b/lib/conn.c
@@ -282,3 +282,20 @@ rs_conn_set_timeout(struct rs_connection *conn, struct timeval *tv)
assert (tv);
conn->timeout = *tv;
}
+
+int
+conn_activate_timeout (struct rs_connection *conn)
+{
+ assert (conn);
+ assert (conn->tev);
+ assert (conn->evb);
+ if (conn->timeout.tv_sec || conn->timeout.tv_usec)
+ {
+ rs_debug (("%s: activating timer: %d.%d\n", __func__,
+ conn->timeout.tv_sec, conn->timeout.tv_usec));
+ if (evtimer_add (conn->tev, &conn->timeout))
+ return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
+ "evtimer_add: %d", errno);
+ }
+ return RSE_OK;
+}
diff --git a/lib/event.c b/lib/event.c
index 55a7e6b..5afba98 100644
--- a/lib/event.c
+++ b/lib/event.c
@@ -21,6 +21,7 @@
#endif
#include "event.h"
#include "packet.h"
+#include "conn.h"
#include "debug.h"
static void
@@ -51,6 +52,41 @@ _evlog_cb (int severity, const char *msg)
fprintf (stderr, "libevent: [%s] %s\n", sevstr, msg); /* FIXME: stderr? */
}
+void
+event_conn_timeout_cb (int fd, short event, void *data)
+{
+ struct rs_connection *conn = NULL;
+
+ assert (data);
+ conn = (struct rs_connection *) data;
+
+ if (event & EV_TIMEOUT)
+ {
+ rs_debug (("%s: connection timeout on %p (fd %d) connecting to %p\n",
+ __func__, conn, conn->fd, conn->active_peer));
+ conn->is_connecting = 0;
+ rs_err_conn_push_fl (conn, RSE_TIMEOUT_CONN, __FILE__, __LINE__, NULL);
+ event_loopbreak (conn);
+ }
+}
+
+void
+event_retransmit_timeout_cb (int fd, short event, void *data)
+{
+ struct rs_connection *conn = NULL;
+
+ assert (data);
+ conn = (struct rs_connection *) data;
+
+ if (event & EV_TIMEOUT)
+ {
+ rs_debug (("%s: retransmission timeout on %p (fd %d) sending to %p\n",
+ __func__, conn, conn->fd, conn->active_peer));
+ rs_err_conn_push_fl (conn, RSE_TIMEOUT_IO, __FILE__, __LINE__, NULL);
+ event_loopbreak (conn);
+ }
+}
+
int
event_init_socket (struct rs_connection *conn, struct rs_peer *p)
{
@@ -138,7 +174,7 @@ event_do_connect (struct rs_connection *conn)
if (p->conn->bev) /* TCP */
{
- tcp_set_connect_timeout (conn);
+ conn_activate_timeout (conn); /* Connect timeout. */
err = bufferevent_socket_connect (p->conn->bev, p->addr->ai_addr,
p->addr->ai_addrlen);
if (err < 0)
@@ -191,10 +227,10 @@ event_on_connect (struct rs_connection *conn, struct rs_packet *pkt)
assert (!conn->is_connecting);
conn->is_connected = 1;
rs_debug (("%s: %p connected\n", __func__, conn->active_peer));
- if (conn->tev)
- evtimer_del (conn->tev);
+
if (conn->callbacks.connected_cb)
conn->callbacks.connected_cb (conn->user_data);
+
if (pkt)
packet_do_send (pkt);
}
@@ -202,6 +238,7 @@ event_on_connect (struct rs_connection *conn, struct rs_packet *pkt)
int
event_init_eventbase (struct rs_connection *conn)
{
+ assert (conn);
if (conn->evb)
return RSE_OK;
diff --git a/lib/event.h b/lib/event.h
index e5ea90c..e042599 100644
--- a/lib/event.h
+++ b/lib/event.h
@@ -8,3 +8,5 @@ int event_init_eventbase (struct rs_connection *conn);
int event_init_socket (struct rs_connection *conn, struct rs_peer *p);
int event_init_bufferevent (struct rs_connection *conn, struct rs_peer *peer);
void event_do_connect (struct rs_connection *conn);
+void event_conn_timeout_cb (int fd, short event, void *data);
+void event_retransmit_timeout_cb (int fd, short event, void *data);
diff --git a/lib/packet.c b/lib/packet.c
index 799234f..2611b46 100644
--- a/lib/packet.c
+++ b/lib/packet.c
@@ -88,7 +88,7 @@ packet_do_send (struct rs_packet *pkt)
}
#endif
- if (pkt->conn->bev)
+ if (pkt->conn->bev) /* TCP. */
{
int err = bufferevent_write (pkt->conn->bev, pkt->rpkt->data,
pkt->rpkt->data_len);
@@ -97,13 +97,15 @@ packet_do_send (struct rs_packet *pkt)
"bufferevent_write: %s",
evutil_gai_strerror (err));
}
- else
+ else /* UDP. */
{
struct rs_packet **pp = &pkt->conn->out_queue;
while (*pp && (*pp)->next)
*pp = (*pp)->next;
*pp = pkt;
+
+ conn_activate_timeout (pkt->conn); /* Retransmission timer. */
}
return RSE_OK;
diff --git a/lib/peer.h b/lib/peer.h
index f430bb2..a326325 100644
--- a/lib/peer.h
+++ b/lib/peer.h
@@ -1,4 +1,5 @@
/* Copyright 2011 NORDUnet A/S. All rights reserved.
See the file COPYING for licensing information. */
+struct rs_peer *peer_create (struct rs_context *ctx, struct rs_peer **rootp);
struct rs_peer *peer_pick_peer (struct rs_connection *conn);
diff --git a/lib/radsec.c b/lib/radsec.c
index ddd4edd..ec43b2f 100644
--- a/lib/radsec.c
+++ b/lib/radsec.c
@@ -20,6 +20,7 @@
#if defined (RS_ENABLE_TLS)
#include <regex.h>
#include "debug.h"
+#include "err.h"
#include "rsp_list.h"
#include "../radsecproxy.h"
#endif
@@ -91,24 +92,44 @@ rs_context_create (struct rs_context **ctx, const char *dict)
return err;
}
-struct rs_peer *
-_rs_peer_create (struct rs_context *ctx, struct rs_peer **rootp)
+struct rs_error * /* FIXME: Return int as all the others? */
+rs_resolv (struct evutil_addrinfo **addr,
+ rs_conn_type_t type,
+ const char *hostname,
+ const char *service)
{
- struct rs_peer *p;
+ int err;
+ struct evutil_addrinfo hints, *res = NULL;
- p = (struct rs_peer *) rs_malloc (ctx, sizeof(*p));
- if (p)
+ memset (&hints, 0, sizeof(struct evutil_addrinfo));
+ hints.ai_family = AF_INET; /* IPv4 only. TODO: Set AF_UNSPEC. */
+ hints.ai_flags = AI_ADDRCONFIG;
+ switch (type)
{
- memset (p, 0, sizeof(struct rs_peer));
- if (*rootp)
- {
- p->next = (*rootp)->next;
- (*rootp)->next = p;
- }
- else
- *rootp = p;
+ case RS_CONN_TYPE_NONE:
+ return err_create (RSE_INVALID_CONN, __FILE__, __LINE__, NULL, NULL);
+ case RS_CONN_TYPE_TCP:
+ /* Fall through. */
+ case RS_CONN_TYPE_TLS:
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ break;
+ case RS_CONN_TYPE_UDP:
+ /* Fall through. */
+ case RS_CONN_TYPE_DTLS:
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+ break;
+ default:
+ return err_create (RSE_INVALID_CONN, __FILE__, __LINE__, NULL, NULL);
}
- return p;
+ err = evutil_getaddrinfo (hostname, service, &hints, &res);
+ if (err)
+ return err_create (RSE_BADADDR, __FILE__, __LINE__,
+ "%s:%s: bad host name or service name (%s)",
+ hostname, service, evutil_gai_strerror(err));
+ *addr = res; /* Simply use first result. */
+ return NULL;
}
static void
diff --git a/lib/send.c b/lib/send.c
index f169ff9..0872471 100644
--- a/lib/send.c
+++ b/lib/send.c
@@ -35,6 +35,8 @@ _conn_open (struct rs_connection *conn, struct rs_packet *pkt)
if (conn->realm->type == RS_CONN_TYPE_TCP
|| conn->realm->type == RS_CONN_TYPE_TLS)
{
+ if (tcp_init_connect_timer (conn))
+ return -1;
if (event_init_bufferevent (conn, conn->active_peer))
return -1;
}
@@ -42,6 +44,8 @@ _conn_open (struct rs_connection *conn, struct rs_packet *pkt)
{
if (udp_init (conn, pkt))
return -1;
+ if (udp_init_retransmit_timer (conn))
+ return -1;
}
if (!conn->is_connected)
diff --git a/lib/tcp.c b/lib/tcp.c
index 063e9b2..ce071cd 100644
--- a/lib/tcp.c
+++ b/lib/tcp.c
@@ -24,24 +24,6 @@
#include <event2/buffer.h>
#endif
-static void
-_conn_timeout_cb (int fd, short event, void *data)
-{
- struct rs_connection *conn;
-
- assert (data);
- conn = (struct rs_connection *) data;
-
- if (event & EV_TIMEOUT)
- {
- rs_debug (("%s: connection timeout on %p (fd %d) connecting to %p\n",
- __func__, conn, conn->fd, conn->active_peer));
- conn->is_connecting = 0;
- rs_err_conn_push_fl (conn, RSE_TIMEOUT_CONN, __FILE__, __LINE__, NULL);
- event_loopbreak (conn);
- }
-}
-
/* Read one RADIUS packet header. Return !0 on error. A return value
of 0 means that we need more data. */
static int
@@ -191,6 +173,8 @@ tcp_event_cb (struct bufferevent *bev, short events, void *user_data)
conn->is_connecting = 0;
if (events & BEV_EVENT_CONNECTED)
{
+ if (conn->tev)
+ evtimer_del (conn->tev); /* Cancel connect timer. */
event_on_connect (conn, pkt);
}
else if (events & BEV_EVENT_EOF)
@@ -255,13 +239,16 @@ tcp_write_cb (struct bufferevent *bev, void *ctx)
}
int
-tcp_set_connect_timeout (struct rs_connection *conn)
+tcp_init_connect_timer (struct rs_connection *conn)
{
- if (!conn->tev)
- conn->tev = evtimer_new (conn->evb, _conn_timeout_cb, conn);
+ assert (conn);
+
+ if (conn->tev)
+ event_free (conn->tev);
+ conn->tev = evtimer_new (conn->evb, event_conn_timeout_cb, conn);
if (!conn->tev)
return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
"evtimer_new");
- evtimer_add (conn->tev, &conn->timeout);
+
return RSE_OK;
}
diff --git a/lib/tcp.h b/lib/tcp.h
index 8f519bb..fc2c4df 100644
--- a/lib/tcp.h
+++ b/lib/tcp.h
@@ -4,4 +4,4 @@
void tcp_event_cb (struct bufferevent *bev, short events, void *user_data);
void tcp_read_cb (struct bufferevent *bev, void *user_data);
void tcp_write_cb (struct bufferevent *bev, void *ctx);
-int tcp_set_connect_timeout (struct rs_connection *conn);
+int tcp_init_connect_timer (struct rs_connection *conn);
diff --git a/lib/udp.c b/lib/udp.c
index c602cbd..ac4e487 100644
--- a/lib/udp.c
+++ b/lib/udp.c
@@ -107,3 +107,18 @@ udp_init (struct rs_connection *conn, struct rs_packet *pkt)
}
return RSE_OK;
}
+
+int
+udp_init_retransmit_timer (struct rs_connection *conn)
+{
+ assert (conn);
+
+ if (conn->tev)
+ event_free (conn->tev);
+ conn->tev = evtimer_new (conn->evb, event_retransmit_timeout_cb, conn);
+ if (!conn->tev)
+ return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
+ "evtimer_new");
+
+ return RSE_OK;
+}
diff --git a/lib/udp.h b/lib/udp.h
index a2a7228..338e7c2 100644
--- a/lib/udp.h
+++ b/lib/udp.h
@@ -2,3 +2,4 @@
See the file COPYING for licensing information. */
int udp_init (struct rs_connection *conn, struct rs_packet *pkt);
+int udp_init_retransmit_timer (struct rs_connection *conn);