From 727af5678906c03eedff8d8262d39fad788973a6 Mon Sep 17 00:00:00 2001 From: Linus Nordberg Date: Wed, 29 Sep 2010 21:53:43 +0200 Subject: Refactoring in preparation for handling more cases than client sending one packet. --- lib/err.c | 14 +++++- lib/examples/client.c | 20 ++++++-- lib/libradsec-impl.h | 6 +-- lib/packet.c | 130 ++++++++++++++++++++++++++++++++++++++++++-------- lib/radsec.c | 93 +++++++++++++----------------------- 5 files changed, 171 insertions(+), 92 deletions(-) (limited to 'lib') diff --git a/lib/err.c b/lib/err.c index 74edeb0..4c88ce1 100644 --- a/lib/err.c +++ b/lib/err.c @@ -1,4 +1,5 @@ #include +#include #include #include "libradsec.h" #include "libradsec-impl.h" @@ -27,6 +28,7 @@ const char *_errtxt[] = { "ERR " /* RSE_ */ "some error" /* 21 RSE_SOME_ERROR */ }; +#define ERRTXT_SIZE (sizeof(_errtxt) / sizeof(*_errtxt)) static struct rs_error * _err_new (unsigned int code, const char *file, int line, const char *fmt, va_list args) @@ -39,8 +41,16 @@ _err_new (unsigned int code, const char *file, int line, const char *fmt, va_lis int n; memset (err, 0, sizeof(struct rs_error)); err->code = code; - n = vsnprintf (err->buf, sizeof(err->buf), fmt, args); - if (n > 0) + if (fmt) + n = vsnprintf (err->buf, sizeof(err->buf), fmt, args); + else + { + strncpy (err->buf, + err->code < ERRTXT_SIZE ? _errtxt[err->code] : "", + sizeof(err->buf)); + n = strlen (err->buf); + } + if (n >= 0) { char *sep = strrchr (file, '/'); if (sep) diff --git a/lib/examples/client.c b/lib/examples/client.c index 14555c7..d7e7270 100644 --- a/lib/examples/client.c +++ b/lib/examples/client.c @@ -38,9 +38,17 @@ rsx_client (const char *srvname, int srvport) return rs_conn_err_pop (conn); req = NULL; +#if 0 + if (rs_packet_recv (conn, &resp)) + return rs_conn_err_pop (conn); +#if defined (DEBUG) + rs_dump_packet (resp); +#endif +#endif + rs_conn_destroy (conn); rs_context_destroy (h); - return 0; + return NULL; } int @@ -53,8 +61,10 @@ main (int argc, char *argv[]) host = strsep (argv + 1, ":"); port = atoi (argv[1]); err = rsx_client (host, port); - if (!err) - return -1; - fprintf (stderr, "%s\n", rs_err_msg (err, 0)); - return rs_err_code (err, 1); + if (err) + { + fprintf (stderr, "%s\n", rs_err_msg (err, 0)); + return rs_err_code (err, 1); + } + return 0; } diff --git a/lib/libradsec-impl.h b/lib/libradsec-impl.h index e51c54c..a4ce7c2 100644 --- a/lib/libradsec-impl.h +++ b/lib/libradsec-impl.h @@ -71,6 +71,8 @@ struct rs_peer { struct rs_connection *conn; struct evutil_addrinfo *addr; int s; /* Socket. */ + char is_connecting; + char is_connected; char *secret; int timeout; /* client only */ int tries; /* client only */ @@ -80,6 +82,7 @@ struct rs_peer { struct rs_connection { struct rs_handle *ctx; struct event_base *evb; + struct bufferevent *bev; enum rs_conn_type type; struct rs_credentials transport_credentials; struct rs_conn_callbacks callbacks; @@ -98,9 +101,6 @@ struct rs_attr { VALUE_PAIR *vp; }; -/* Internal functions. */ -int rs_conn_open(struct rs_connection *conn); - /* Convenience macros. */ #define rs_calloc(h, nmemb, size) \ (h->alloc_scheme.calloc ? h->alloc_scheme.calloc : calloc)(nmemb, size) diff --git a/lib/packet.c b/lib/packet.c index 652c495..90c8c31 100644 --- a/lib/packet.c +++ b/lib/packet.c @@ -66,11 +66,19 @@ static void _event_cb (struct bufferevent *bev, short events, void *ctx) { struct rs_packet *pkt = (struct rs_packet *) ctx; + struct rs_connection *conn; + struct rs_peer *p; assert (pkt); assert (pkt->conn); + assert (pkt->conn->active_peer); + conn = pkt->conn; + p = conn->active_peer; + + p->is_connecting = 0; if (events & BEV_EVENT_CONNECTED) { + p->is_connected = 1; #if defined (DEBUG) fprintf (stderr, "%s: connected\n", __func__); #endif @@ -110,32 +118,107 @@ _write_cb (struct bufferevent *bev, void *ctx) rs_packet_destroy (pkt); } -int -rs_packet_send (struct rs_connection *conn, struct rs_packet *pkt, void *data) +static int +_init_evb (struct rs_connection *conn) { - struct bufferevent *bev; - struct rs_peer *p; + if (!conn->evb) + { +#if defined (DEBUG) + event_enable_debug_mode (); +#endif + conn->evb = event_base_new (); + if (!conn->evb) + return rs_conn_err_push_fl (conn, RSE_EVENT, __FILE__, __LINE__, + "event_base_new"); + } + return RSE_OK; +} - assert (pkt->rpkt); +static int +_init_socket (struct rs_connection *conn, struct rs_peer *p) +{ + if (p->s < 0) + { + assert (p->addr); + p->s = socket (p->addr->ai_family, p->addr->ai_socktype, + p->addr->ai_protocol); + if (p->s < 0) + return rs_conn_err_push_fl (conn, RSE_SOME_ERROR, __FILE__, __LINE__, + strerror (errno)); + } + return RSE_OK; +} - if (rs_conn_open (conn)) - return -1; - p = conn->active_peer; - assert (p); +static struct rs_peer * +_pick_peer (struct rs_connection *conn) +{ + if (!conn->active_peer) + conn->active_peer = conn->peers; + return conn->active_peer; +} - assert (conn->active_peer->s >= 0); - bev = bufferevent_socket_new (conn->evb, conn->active_peer->s, 0); - if (!bev) - return rs_conn_err_push_fl (conn, RSE_EVENT, __FILE__, __LINE__, - "bufferevent_socket_new"); - if (bufferevent_socket_connect (bev, p->addr->ai_addr, p->addr->ai_addrlen) < 0) +static int +_init_bev (struct rs_connection *conn, struct rs_peer *peer, + struct rs_packet *pkt) +{ + if (!conn->bev) { - bufferevent_free (bev); - return rs_conn_err_push_fl (conn, RSE_EVENT, __FILE__, __LINE__, - "bufferevent_socket_connect"); + conn->bev = bufferevent_socket_new (conn->evb, peer->s, 0); + if (!conn->bev) + return rs_conn_err_push_fl (conn, RSE_EVENT, __FILE__, __LINE__, + "bufferevent_socket_new"); + bufferevent_setcb (conn->bev, NULL, _write_cb, _event_cb, pkt); } + return RSE_OK; +} + +static void +_do_connect (struct rs_peer *p) +{ + if (bufferevent_socket_connect (p->conn->bev, p->addr->ai_addr, + p->addr->ai_addrlen) < 0) + rs_conn_err_push_fl (p->conn, RSE_EVENT, __FILE__, __LINE__, + "bufferevent_socket_connect"); + else + p->is_connecting = 1; +} + +static int +_conn_open(struct rs_connection *conn, struct rs_packet *pkt) +{ + struct rs_peer *p; + + if (_init_evb (conn)) + return -1; + + p = _pick_peer (conn); + if (!p) + return rs_conn_err_push_fl (conn, RSE_NOPEER, __FILE__, __LINE__, NULL); + + if (_init_socket (conn, p)) + return -1; + + if (_init_bev (conn, p, pkt)) + return -1; - bufferevent_setcb (bev, NULL, _write_cb, _event_cb, pkt); + if (!p->is_connected) + if (!p->is_connecting) + _do_connect (p); + + return RSE_OK; +} + +int +rs_packet_send (struct rs_connection *conn, struct rs_packet *pkt, void *data) +{ + assert (conn); + assert (pkt->rpkt); + if (_conn_open (conn, pkt)) + return -1; + assert (conn->evb); + assert (conn->bev); + assert (conn->active_peer); + assert (conn->active_peer->s >= 0); event_base_dispatch (conn->evb); #if defined (DEBUG) fprintf (stderr, "%s: event loop done\n", __func__); @@ -147,13 +230,18 @@ rs_packet_send (struct rs_connection *conn, struct rs_packet *pkt, void *data) int rs_packet_receive(struct rs_connection *conn, struct rs_packet **pkt) { - return rs_conn_err_push_fl (conn, RSE_NOSYS, __FILE__, __LINE__, - "%s: NYI", __func__); + //struct bufferevent *bev; + + //skalleper; + //bufferevent_enable(bev, EV_READ); + return 0; /* FIXME */ } + void rs_packet_add_attr(struct rs_packet *pkt, struct rs_attr *attr) { pairadd (&pkt->rpkt->vps, attr->vp); attr->pkt = pkt; } + diff --git a/lib/radsec.c b/lib/radsec.c index 82576e1..72d7f5f 100644 --- a/lib/radsec.c +++ b/lib/radsec.c @@ -128,35 +128,53 @@ _resolv (struct rs_connection *conn, const char *hostname, int port) return res; /* Simply use first result. */ } +static struct rs_peer * +_peer_new (struct rs_connection *conn, const char *hostname, int port) +{ + struct rs_peer *p; + struct evutil_addrinfo *addr; + + addr = _resolv (conn, hostname, port); + if (!addr) + return NULL; + + p = (struct rs_peer *) malloc (sizeof(*p)); + if (p) + { + memset (p, 0, sizeof(struct rs_peer)); + p->conn = conn; + p->s = -1; + p->addr = addr; + p->next = conn->peers; + if (conn->peers) + conn->peers->next = p; + else + conn->peers = p; + } + else + { + evutil_freeaddrinfo (addr); + rs_conn_err_push_fl (conn, RSE_NOMEM, __FILE__, __LINE__, NULL); + } + return p; +} + int rs_conn_add_server(struct rs_connection *conn, struct rs_peer **server, rs_conn_type_t type, const char *hostname, int port) { struct rs_peer *srv; - struct evutil_addrinfo *addr; if (conn->type == RS_CONN_TYPE_NONE) conn->type = type; else if (conn->type != type) return rs_conn_err_push (conn, RSE_CONN_TYPE_MISMATCH, NULL); - addr = _resolv (conn, hostname, port); - if (!addr) - return -1; - - srv = (struct rs_peer *) malloc (sizeof(struct rs_peer)); + srv = _peer_new (conn, hostname, port); if (srv) { - memset (srv, 0, sizeof(struct rs_peer)); - srv->conn = conn; - srv->addr = addr; srv->timeout = 10; srv->tries = 3; - srv->next = conn->peers; - if (conn->peers) - conn->peers->next = srv; - else - conn->peers = srv; } if (*server) *server = srv; @@ -188,7 +206,6 @@ int rs_conn_add_listener(struct rs_connection *conn, rs_conn_type_t type, const "%s: NYI", __func__); } - void rs_conn_destroy(struct rs_connection *conn) { @@ -232,49 +249,3 @@ int rs_conn_get_current_server(struct rs_connection *conn, const char *name, siz "%s: NYI", __func__); } -/* Non-public. */ -int -rs_conn_open(struct rs_connection *conn) -{ - int s; - struct rs_peer *p; - - if (conn->active_peer) - return RSE_OK; - p = conn->peers; - if (!p) - return rs_conn_err_push_fl (conn, RSE_NOPEER, __FILE__, __LINE__, NULL); - - s = socket (p->addr->ai_family, p->addr->ai_socktype, p->addr->ai_protocol); - if (s < 0) - return rs_conn_err_push_fl (conn, RSE_SOME_ERROR, __FILE__, __LINE__, - strerror (errno)); -#if 0 /* let librevent do this in rs_packet_send() */ - if (connect (s, p->addr->ai_addr, p->addr->ai_addrlen)) - { - /* TODO: handle nonblocking sockets (EINTR, EAGAIN). */ - EVUTIL_CLOSESOCKET (s); - return rs_conn_err_push_fl (conn, RSE_SOME_ERROR, __FILE__, __LINE__, - strerror (errno)); - } -#endif - - if (!conn->evb) - { -#if defined (DEBUG) - event_enable_debug_mode (); -#endif - conn->evb = event_base_new (); - } - - if (!conn->evb) - { - EVUTIL_CLOSESOCKET (s); - return rs_conn_err_push_fl (conn, RSE_EVENT, __FILE__, __LINE__, - "event_base_new"); - } - - p->s = s; - conn->active_peer = p; - return RSE_OK; -} -- cgit v1.1