diff options
| author | Linus Nordberg <linus@nordu.net> | 2010-09-29 21:53:43 +0200 | 
|---|---|---|
| committer | Linus Nordberg <linus@nordu.net> | 2010-09-29 21:53:43 +0200 | 
| commit | 727af5678906c03eedff8d8262d39fad788973a6 (patch) | |
| tree | f9192ecc6b6590d79c356106004f14f2f46b7c2d | |
| parent | de906e3721e19d9d8b2c61f834d8057bcce47af1 (diff) | |
Refactoring in preparation for handling more cases than client sending one packet.
| -rw-r--r-- | lib/err.c | 14 | ||||
| -rw-r--r-- | lib/examples/client.c | 20 | ||||
| -rw-r--r-- | lib/libradsec-impl.h | 6 | ||||
| -rw-r--r-- | lib/packet.c | 130 | ||||
| -rw-r--r-- | lib/radsec.c | 93 | 
5 files changed, 171 insertions, 92 deletions
| @@ -1,4 +1,5 @@  #include <stdio.h> +#include <string.h>  #include <assert.h>  #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; -} | 
