diff options
| author | Linus Nordberg <linus@nordu.net> | 2010-09-29 15:52:39 +0200 | 
|---|---|---|
| committer | Linus Nordberg <linus@nordu.net> | 2010-09-29 15:52:39 +0200 | 
| commit | b10a02e5f3a7dd184ada869015e438e63bca52bf (patch) | |
| tree | 70c74d012d2a89c1a1efefa5afc0787de0b84368 | |
| parent | e2633633030e62994ca41ff62006e3e40517c73a (diff) | |
WIP -- connecting and sending a packet using libevent.
| -rw-r--r-- | lib/err.c | 4 | ||||
| -rw-r--r-- | lib/examples/Makefile | 2 | ||||
| -rw-r--r-- | lib/examples/client.c | 12 | ||||
| -rw-r--r-- | lib/libradsec-impl.h | 1 | ||||
| -rw-r--r-- | lib/libradsec.h | 6 | ||||
| -rw-r--r-- | lib/packet.c | 88 | ||||
| -rw-r--r-- | lib/radsec.c | 22 | 
7 files changed, 108 insertions, 27 deletions
| @@ -13,8 +13,8 @@ const char *_errtxt[] = {    "FreeRadius error"		/* 6 RSE_FR */    "bad hostname or port"	/* 7 RSE_BADADDR */    "no peer configured"		/* 8 RSE_NOPEER */ -  "ERR 9"			/*  RSE_ */ -  "ERR 10"			/*  RSE_ */ +  "libevent error"		/* 9 RSE_EVENT */ +  "connection error"		/* 10 RSE_CONNERR */    "ERR 11"			/*  RSE_ */    "ERR 12"			/*  RSE_ */    "ERR 13"			/*  RSE_ */ diff --git a/lib/examples/Makefile b/lib/examples/Makefile index a9876da..f9f2ee1 100644 --- a/lib/examples/Makefile +++ b/lib/examples/Makefile @@ -6,7 +6,7 @@ blocking.o: blocking.c blocking.h ../libradsec-base.h ../libradsec.h  	$(CC) $(CFLAGS) -c -I .. $^  client: client.c ../libradsec.a ../libradsec.h ../libradsec-impl.h -	$(CC) $(CFLAGS) -o $@ $< -L /usr/lib/freeradius -lfreeradius-radius -L .. -lradsec -L /usr/local/lib -levent +	$(CC) $(CFLAGS) -o $@ $< -L /usr/lib/freeradius -lfreeradius-radius -L .. -lradsec -L /usr/local/lib -levent_core  clean:  	-rm *.o client diff --git a/lib/examples/client.c b/lib/examples/client.c index a6b7999..2304e49 100644 --- a/lib/examples/client.c +++ b/lib/examples/client.c @@ -4,6 +4,7 @@  #include <string.h>  #include <unistd.h>  #include <stdlib.h> +#include <event2/event.h>  #include "../libradsec.h"  #include "../debug.h" @@ -18,14 +19,13 @@ rsx_client (const char *srvname, int srvport)    struct rs_connection *conn;    struct rs_peer *server;    struct rs_packet *req; -  //struct rs_packet  *resp;    if (rs_context_create (&h, "/usr/share/freeradius/dictionary"))      return NULL;    if (rs_conn_create (h, &conn))      return rs_conn_err_pop (conn); -  if (rs_conn_add_server (conn, &server, RS_CONN_TYPE_UDP, srvname, srvport)) +  if (rs_conn_add_server (conn, &server, RS_CONN_TYPE_TCP, srvname, srvport))      return rs_conn_err_pop (conn);    rs_server_set_timeout (server, 10);    rs_server_set_tries (server, 3); @@ -38,14 +38,6 @@ rsx_client (const char *srvname, int srvport)      return rs_conn_err_pop (conn);    req = NULL; -#if 0 -  printf ("waiting for response\n"); -  if (rs_packet_recv (conn, &resp)) -    return rs_conn_err_pop (conn); -  printf ("got response\n"); -  rs_dump_packet (resp); -#endif -    rs_conn_destroy (conn);    rs_context_destroy (h);    return 0; diff --git a/lib/libradsec-impl.h b/lib/libradsec-impl.h index 939cdd9..e51c54c 100644 --- a/lib/libradsec-impl.h +++ b/lib/libradsec-impl.h @@ -79,6 +79,7 @@ struct rs_peer {  struct rs_connection {      struct rs_handle *ctx; +    struct event_base *evb;      enum rs_conn_type type;      struct rs_credentials transport_credentials;      struct rs_conn_callbacks callbacks; diff --git a/lib/libradsec.h b/lib/libradsec.h index 255c0f5..2ccafe2 100644 --- a/lib/libradsec.h +++ b/lib/libradsec.h @@ -14,6 +14,8 @@ enum rs_err_code {      RSE_FR = 6,      RSE_BADADDR = 7,      RSE_NOPEER = 8, +    RSE_EVENT = 9, +    RSE_CONNERR = 10,      RSE_SOME_ERROR = 21,  }; @@ -48,7 +50,7 @@ int rs_context_config_read(struct rs_handle *ctx, const char *config_file);  int rs_conn_create(struct rs_handle *ctx, struct rs_connection **conn);  int rs_conn_add_server(struct rs_connection *conn, struct rs_peer **server, rs_conn_type_t type, const char *hostname, int port);  int rs_conn_add_listener(struct rs_connection  *conn, rs_conn_type_t type, const char *hostname, int port); -void rs_conn_destroy(struct rs_connection  *conn); +void rs_conn_destroy(struct rs_connection *conn);  int rs_conn_set_eventbase(struct rs_connection *conn, struct event_base *eb);  int rs_conn_set_callbacks(struct rs_connection *conn, struct rs_conn_callbacks *cb);  int rs_conn_select_server(struct rs_connection *conn, const char *name); @@ -69,7 +71,7 @@ void rs_packet_add_attr(struct rs_packet *pkt, struct rs_attr *attr);  int rs_attr_create(struct rs_connection *conn, struct rs_attr **attr, const char *type, const char *val);  void rs_attr_destroy(struct rs_attr *attr); -int rs_packet_send(struct rs_connection *conn, const struct rs_packet *pkt, void *user_data); +int rs_packet_send(struct rs_connection *conn, struct rs_packet *pkt, void *data);  int rs_packet_recv(struct rs_connection *conn, struct rs_packet **pkt);  int rs_ctx_err_push(struct rs_handle *ctx, int code, const char *fmt, ...); 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) diff --git a/lib/radsec.c b/lib/radsec.c index 97f62e6..82576e1 100644 --- a/lib/radsec.c +++ b/lib/radsec.c @@ -5,6 +5,7 @@  #include <libgen.h>  #include <freeradius/libradius.h> +#include <event2/event.h>  #include <event2/util.h>  #include "libradsec.h"  #include "libradsec-impl.h" @@ -202,6 +203,9 @@ rs_conn_destroy(struct rs_connection *conn)        if (p->secret)  	rs_free (conn->ctx, p->secret);      } + +  if (conn->evb) +    event_base_free (conn->evb);  }  int rs_conn_set_eventbase(struct rs_connection *conn, struct event_base *eb) @@ -245,6 +249,7 @@ rs_conn_open(struct rs_connection *conn)    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).  */ @@ -252,6 +257,23 @@ rs_conn_open(struct rs_connection *conn)        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; | 
