1 /* Copyright 2011 NORDUnet A/S. All rights reserved.
2 See the file COPYING for licensing information. */
4 #if defined HAVE_CONFIG_H
9 #include <event2/event.h>
10 #include <event2/bufferevent.h>
11 #if defined (RS_ENABLE_TLS)
12 #include <event2/bufferevent_ssl.h>
13 #include <openssl/err.h>
15 #include <radsec/radsec.h>
16 #include <radsec/radsec-impl.h>
19 #if defined (RS_ENABLE_TLS)
28 extern int _event_debug_mode_on;
32 _evlog_cb (int severity, const char *msg)
37 case _EVENT_LOG_DEBUG:
38 #if !defined (DEBUG_LEVENT)
56 fprintf (stderr, "libevent: [%s] %s\n", sevstr, msg); /* FIXME: stderr? */
60 event_conn_timeout_cb (int fd, short event, void *data)
62 struct rs_connection *conn = NULL;
65 conn = (struct rs_connection *) data;
67 if (event & EV_TIMEOUT)
69 rs_debug (("%s: connection timeout on %p (fd %d) connecting to %p\n",
70 __func__, conn, conn->fd, conn->active_peer));
71 conn->is_connecting = 0;
72 rs_err_conn_push_fl (conn, RSE_TIMEOUT_CONN, __FILE__, __LINE__, NULL);
73 event_loopbreak (conn);
78 event_retransmit_timeout_cb (int fd, short event, void *data)
80 struct rs_connection *conn = NULL;
83 conn = (struct rs_connection *) data;
85 if (event & EV_TIMEOUT)
87 rs_debug (("%s: retransmission timeout on %p (fd %d) sending to %p\n",
88 __func__, conn, conn->fd, conn->active_peer));
89 rs_err_conn_push_fl (conn, RSE_TIMEOUT_IO, __FILE__, __LINE__, NULL);
90 event_loopbreak (conn);
95 event_init_socket (struct rs_connection *conn, struct rs_peer *p)
101 conn->fd = socket (p->addr->ai_family, p->addr->ai_socktype,
102 p->addr->ai_protocol);
104 return rs_err_conn_push_fl (conn, RSE_SOCKERR, __FILE__, __LINE__,
106 errno, strerror (errno));
107 if (evutil_make_socket_nonblocking (conn->fd) < 0)
109 evutil_closesocket (conn->fd);
111 return rs_err_conn_push_fl (conn, RSE_SOCKERR, __FILE__, __LINE__,
112 "evutil_make_socket_nonblocking: %d (%s)",
113 errno, strerror (errno));
119 event_init_bufferevent (struct rs_connection *conn, struct rs_peer *peer)
124 if (conn->realm->type == RS_CONN_TYPE_TCP)
126 conn->bev = bufferevent_socket_new (conn->evb, conn->fd, 0);
128 return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
129 "bufferevent_socket_new");
131 #if defined (RS_ENABLE_TLS)
132 else if (conn->realm->type == RS_CONN_TYPE_TLS)
134 if (rs_tls_init (conn))
136 /* Would be convenient to pass BEV_OPT_CLOSE_ON_FREE but things
137 seem to break when be_openssl_ctrl() (in libevent) calls
138 SSL_set_bio() after BIO_new_socket() with flag=1. */
140 bufferevent_openssl_socket_new (conn->evb, conn->fd, conn->tls_ssl,
141 BUFFEREVENT_SSL_CONNECTING, 0);
143 return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
144 "bufferevent_openssl_socket_new");
146 #endif /* RS_ENABLE_TLS */
149 return rs_err_conn_push_fl (conn, RSE_INTERNAL, __FILE__, __LINE__,
150 "%s: unknown connection type: %d", __func__,
158 event_do_connect (struct rs_connection *conn)
164 assert (conn->active_peer);
165 p = conn->active_peer;
169 char host[80], serv[80];
171 getnameinfo (p->addr->ai_addr,
173 host, sizeof(host), serv, sizeof(serv),
174 0 /* NI_NUMERICHOST|NI_NUMERICSERV*/);
175 rs_debug (("%s: connecting to %s:%s\n", __func__, host, serv));
179 if (p->conn->bev) /* TCP */
181 conn_activate_timeout (conn); /* Connect timeout. */
182 err = bufferevent_socket_connect (p->conn->bev, p->addr->ai_addr,
183 p->addr->ai_addrlen);
185 rs_err_conn_push_fl (p->conn, RSE_EVENT, __FILE__, __LINE__,
186 "bufferevent_socket_connect: %s",
187 evutil_gai_strerror (err));
189 p->conn->is_connecting = 1;
193 err = connect (p->conn->fd, p->addr->ai_addr, p->addr->ai_addrlen);
196 sockerr = evutil_socket_geterror (p->conn->fd);
197 rs_debug (("%s: %d: connect: %d (%s)\n", __func__, p->conn->fd,
198 sockerr, evutil_socket_error_to_string (sockerr)));
199 rs_err_conn_push_fl (p->conn, RSE_SOCKERR, __FILE__, __LINE__,
200 "%d: connect: %d (%s)", p->conn->fd, sockerr,
201 evutil_socket_error_to_string (sockerr));
207 event_loopbreak (struct rs_connection *conn)
209 int err = event_base_loopbreak (conn->evb);
211 rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
212 "event_base_loopbreak: %s",
213 evutil_gai_strerror (err));
219 event_on_disconnect (struct rs_connection *conn)
221 conn->is_connecting = 0;
222 conn->is_connected = 0;
223 rs_debug (("%s: %p disconnected\n", __func__, conn->active_peer));
224 if (conn->callbacks.disconnected_cb)
225 conn->callbacks.disconnected_cb (conn->user_data);
229 event_on_connect (struct rs_connection *conn, struct rs_packet *pkt)
231 assert (!conn->is_connecting);
232 conn->is_connected = 1;
233 rs_debug (("%s: %p connected\n", __func__, conn->active_peer));
235 if (conn->callbacks.connected_cb)
236 conn->callbacks.connected_cb (conn->user_data);
239 packet_do_send (pkt);
243 event_init_eventbase (struct rs_connection *conn)
250 if (!_event_debug_mode_on)
251 event_enable_debug_mode ();
253 event_set_log_callback (_evlog_cb);
254 conn->evb = event_base_new ();
256 return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,