1 /* Copyright 2011,2013 NORDUnet A/S. All rights reserved.
2 See LICENSE for licensing information. */
4 #if defined HAVE_CONFIG_H
9 #include <event2/event.h>
10 #include <event2/bufferevent.h>
11 #include <radsec/radsec.h>
12 #include <radsec/radsec-impl.h>
22 _conn_open (struct rs_connection *conn, struct rs_message *msg)
24 if (event_init_eventbase (TO_BASE_CONN (conn)))
27 if (!conn->active_peer)
28 peer_pick_peer (conn);
29 if (!conn->active_peer)
30 return rs_err_conn_push_fl (conn, RSE_NOPEER, __FILE__, __LINE__, NULL);
32 if (event_init_socket (&conn->base_, conn->active_peer))
35 if (conn->base_.realm->type == RS_CONN_TYPE_TCP
36 || conn->base_.realm->type == RS_CONN_TYPE_TLS)
38 if (tcp_init_connect_timer (conn))
40 if (event_init_bufferevent (conn))
45 if (udp_init (conn, msg))
47 if (udp_init_retransmit_timer (conn))
51 if (conn->state != RS_CONN_STATE_CONNECTED
52 && conn->state != RS_CONN_STATE_CONNECTING)
53 event_do_connect (conn);
59 _conn_is_open_p (struct rs_connection *conn)
61 return conn->state == RS_CONN_STATE_CONNECTED
62 && conn->active_peer != NULL;
65 /* User callback used when we're dispatching for user. */
67 _wcb (void *user_data)
69 struct rs_message *msg = (struct rs_message *) user_data;
71 msg->flags |= RS_MESSAGE_SENT;
72 if (msg->conn->base_.bev)
73 bufferevent_disable (msg->conn->base_.bev, EV_WRITE|EV_READ);
75 event_del (msg->conn->base_.wev);
79 rs_message_send (struct rs_message *msg)
81 struct rs_connection *conn = NULL;
88 if (_conn_is_open_p (conn))
89 message_do_send (msg);
91 if (_conn_open (conn, msg))
94 assert (conn->base_.ctx);
95 assert (conn->base_.ctx->evb);
96 assert (conn->active_peer);
97 assert (conn->base_.fd >= 0);
99 if (conn->base_.bev) /* TCP */
101 bufferevent_setcb (conn->base_.bev, NULL, tcp_write_cb, tcp_event_cb,
103 bufferevent_enable (conn->base_.bev, EV_WRITE);
107 event_assign (conn->base_.wev, conn->base_.ctx->evb,
108 event_get_fd (conn->base_.wev),
109 EV_WRITE, event_get_callback (conn->base_.wev), msg);
110 err = event_add (conn->base_.wev, NULL);
112 return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
114 evutil_gai_strerror (err));
117 /* Do dispatch, unless the user wants to do it herself. */
118 if (!conn_user_dispatch_p (conn))
121 conn->callbacks.sent_cb = _wcb;
122 conn->base_.user_data = msg;
123 rs_debug (("%s: entering event loop\n", __func__));
124 err = event_base_dispatch (conn->base_.ctx->evb);
126 return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
127 "event_base_dispatch: %s",
128 evutil_gai_strerror (err));
129 rs_debug (("%s: event loop done\n", __func__));
130 conn->callbacks.sent_cb = NULL;
131 conn->base_.user_data = NULL;
133 if ((msg->flags & RS_MESSAGE_SENT) == 0)
135 assert (rs_err_conn_peek_code (conn));
136 return rs_err_conn_peek_code (conn);