diff options
Diffstat (limited to 'lib/packet.c')
-rw-r--r-- | lib/packet.c | 88 |
1 files changed, 76 insertions, 12 deletions
diff --git a/lib/packet.c b/lib/packet.c index eefb5eb..652c495 100644 --- a/lib/packet.c +++ b/lib/packet.c @@ -1,6 +1,8 @@ #include <string.h> #include <assert.h> #include <freeradius/libradius.h> +#include <event2/event.h> +#include <event2/bufferevent.h> #include "libradsec.h" #include "libradsec-impl.h" #if defined DEBUG @@ -29,6 +31,7 @@ _packet_create (struct rs_connection *conn, struct rs_packet **pkt_out, return rs_conn_err_push (conn, RSE_NOMEM, __func__); } memset (p, 0, sizeof (struct rs_packet)); + p->conn = conn; p->rpkt = rpkt; *pkt_out = p; @@ -59,26 +62,87 @@ rs_packet_create_acc_request (struct rs_connection *conn, return RSE_OK; } +static void +_event_cb (struct bufferevent *bev, short events, void *ctx) +{ + struct rs_packet *pkt = (struct rs_packet *) ctx; + + assert (pkt); + assert (pkt->conn); + if (events & BEV_EVENT_CONNECTED) + { +#if defined (DEBUG) + fprintf (stderr, "%s: connected\n", __func__); +#endif + rad_encode (pkt->rpkt, NULL, pkt->conn->active_peer->secret); +#if defined (DEBUG) + fprintf (stderr, "%s: about to send this to %s:\n", __func__, "<fixme>"); + rs_dump_packet (pkt); +#endif + if (bufferevent_write(bev, pkt->rpkt->data, pkt->rpkt->data_len)) + rs_conn_err_push_fl (pkt->conn, RSE_EVENT, __FILE__, __LINE__, + "bufferevent_write"); + /* Packet will be freed in write callback. */ + } + else if (events & BEV_EVENT_ERROR) + rs_conn_err_push_fl (pkt->conn, RSE_CONNERR, __FILE__, __LINE__, NULL); +} + +void +rs_packet_destroy(struct rs_packet *pkt) +{ + rad_free (&pkt->rpkt); + rs_free (pkt->conn->ctx, pkt); +} + +static void +_write_cb (struct bufferevent *bev, void *ctx) +{ + struct rs_packet *pkt = (struct rs_packet *) ctx; + + assert (pkt); + assert (pkt->conn); +#if defined (DEBUG) + fprintf (stderr, "%s: packet written, breaking event loop\n", __func__); +#endif + if (event_base_loopbreak (pkt->conn->evb) < 0) + abort (); /* FIXME */ + rs_packet_destroy (pkt); +} + int -rs_packet_send (struct rs_connection *conn, const struct rs_packet *pkt, - void *user_data) +rs_packet_send (struct rs_connection *conn, struct rs_packet *pkt, void *data) { + struct bufferevent *bev; + struct rs_peer *p; + assert (pkt->rpkt); - if (!conn->active_peer) + if (rs_conn_open (conn)) + return -1; + p = conn->active_peer; + assert (p); + + 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) { - int err = rs_conn_open (conn); - if (err) - return err; - } - rad_encode (pkt->rpkt, NULL, conn->active_peer->secret); + bufferevent_free (bev); + return rs_conn_err_push_fl (conn, RSE_EVENT, __FILE__, __LINE__, + "bufferevent_socket_connect"); + } + + bufferevent_setcb (bev, NULL, _write_cb, _event_cb, pkt); + event_base_dispatch (conn->evb); #if defined (DEBUG) - fprintf (stderr, "%s: about to send this to %s:\n", __func__, "<fixme>"); - rs_dump_packet (pkt); + fprintf (stderr, "%s: event loop done\n", __func__); + assert (event_base_got_break(conn->evb)); #endif - return rs_conn_err_push_fl (conn, RSE_NOSYS, __FILE__, __LINE__, - "%s: NYI", __func__); + return RSE_OK; } int rs_packet_receive(struct rs_connection *conn, struct rs_packet **pkt) |