X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=lib%2Fconn.c;h=c6692a263b03978fdd407f204925d019970cd819;hb=937144b230752ac640e611cabb57387f613997bc;hp=85cd7d5543735a8112e735375c21cc37d93a2afd;hpb=fac0219dad91c574417f78ec674aa0dd10949e15;p=radsecproxy.git diff --git a/lib/conn.c b/lib/conn.c index 85cd7d5..c6692a2 100644 --- a/lib/conn.c +++ b/lib/conn.c @@ -1,11 +1,13 @@ /* Copyright 2010, 2011 NORDUnet A/S. All rights reserved. - See the file COPYING for licensing information. */ + See LICENSE for licensing information. */ #if defined HAVE_CONFIG_H #include #endif #include +#include +#include #include #include #include @@ -20,11 +22,12 @@ int conn_close (struct rs_connection **connp) { - int r; + int r = 0; assert (connp); assert (*connp); - r = rs_conn_destroy (*connp); - if (!r) + if ((*connp)->is_connected) + r = rs_conn_disconnect (*connp); + if (r == RSE_OK) *connp = NULL; return r; } @@ -41,7 +44,8 @@ conn_user_dispatch_p (const struct rs_connection *conn) } int -rs_conn_create (struct rs_context *ctx, struct rs_connection **conn, +rs_conn_create (struct rs_context *ctx, + struct rs_connection **conn, const char *config) { struct rs_connection *c; @@ -91,8 +95,10 @@ rs_conn_set_type (struct rs_connection *conn, rs_conn_type_t type) } int -rs_conn_add_listener (struct rs_connection *conn, rs_conn_type_t type, - const char *hostname, int port) +rs_conn_add_listener (struct rs_connection *conn, + rs_conn_type_t type, + const char *hostname, + int port) { return rs_err_conn_push_fl (conn, RSE_NOSYS, __FILE__, __LINE__, NULL); } @@ -122,15 +128,26 @@ rs_conn_destroy (struct rs_connection *conn) if (conn->is_connected) err = rs_conn_disconnect (conn); + +#if defined (RS_ENABLE_TLS) + if (conn->tls_ssl) /* FIXME: Free SSL strucxt in rs_conn_disconnect? */ + SSL_free (conn->tls_ssl); + if (conn->tls_ctx) + SSL_CTX_free (conn->tls_ctx); +#endif + if (conn->tev) event_free (conn->tev); if (conn->bev) bufferevent_free (conn->bev); + if (conn->rev) + event_free (conn->rev); + if (conn->wev) + event_free (conn->wev); if (conn->evb) event_base_free (conn->evb); - /* TODO: free tls_ctx */ - /* TODO: free tls_ssl */ + rs_free (conn->ctx, conn); return err; } @@ -169,7 +186,8 @@ rs_conn_select_peer (struct rs_connection *conn, const char *name) } int -rs_conn_get_current_peer (struct rs_connection *conn, const char *name, +rs_conn_get_current_peer (struct rs_connection *conn, + const char *name, size_t buflen) { return rs_err_conn_push_fl (conn, RSE_NOSYS, __FILE__, __LINE__, NULL); @@ -196,22 +214,6 @@ _rcb (struct rs_packet *packet, void *user_data) event_del (pkt->conn->rev); } -/* Special function used in libradsec blocking dispatching mode, - i.e. with socket set to block on read/write and with no libradsec - callbacks registered. - - For any other use of libradsec, a the received_cb callback should - be registered in the callbacks member of struct rs_connection. - - On successful reception of a RADIUS message it will be verified - against REQ_MSG, if !NULL. - - If PKT_OUT is !NULL it will upon return point at a pointer to a - struct rs_packet containing the message. - - If anything goes wrong or if the read times out (TODO: explain), - PKT_OUT will not be changed and one or more errors are pushed on - the connection (available through rs_err_conn_pop()). */ int rs_conn_receive_packet (struct rs_connection *conn, struct rs_packet *req_msg, @@ -222,36 +224,39 @@ rs_conn_receive_packet (struct rs_connection *conn, assert (conn); assert (conn->realm); - assert (!conn_user_dispatch_p (conn)); /* Dispatching mode only. */ + assert (!conn_user_dispatch_p (conn)); /* Blocking mode only. */ if (rs_packet_create (conn, &pkt)) return -1; - pkt->conn = conn; assert (conn->evb); - assert (conn->bev); - assert (conn->active_peer); assert (conn->fd >= 0); conn->callbacks.received_cb = _rcb; conn->user_data = pkt; pkt->flags &= ~rs_packet_received_flag; - if (conn->bev) + if (conn->bev) /* TCP. */ { bufferevent_setwatermark (conn->bev, EV_READ, RS_HEADER_LEN, 0); bufferevent_setcb (conn->bev, tcp_read_cb, NULL, tcp_event_cb, pkt); bufferevent_enable (conn->bev, EV_READ); } - else + else /* UDP. */ { + /* Put fresh packet in user_data for the callback and enable the + read event. */ + event_assign (conn->rev, conn->evb, event_get_fd (conn->rev), + EV_READ, event_get_callback (conn->rev), pkt); err = event_add (conn->rev, NULL); if (err < 0) return rs_err_conn_push_fl (pkt->conn, RSE_EVENT, __FILE__, __LINE__, "event_add: %s", evutil_gai_strerror (err)); - } + /* Activate retransmission timer. */ + conn_activate_timeout (pkt->conn); + } rs_debug (("%s: entering event loop\n", __func__)); err = event_base_dispatch (conn->evb); @@ -266,7 +271,10 @@ rs_conn_receive_packet (struct rs_connection *conn, || (req_msg && packet_verify_response (pkt->conn, pkt, req_msg) != RSE_OK)) { - assert (rs_err_conn_peek_code (pkt->conn)); + if (rs_err_conn_peek_code (pkt->conn) == RSE_OK) + /* No packet and no error on the stack _should_ mean that the + server hung up on us. */ + rs_err_conn_push (pkt->conn, RSE_DISCO, "no response"); return rs_err_conn_peek_code (conn); } @@ -282,3 +290,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; +}