-#include "list.h"
-#include "util.h"
-#include "radsecproxy.h"
-#include "tls.h"
-
-static int client4_sock = -1;
-static int client6_sock = -1;
-static struct queue *server_replyq = NULL;
-
-/* exactly one of client and server must be non-NULL */
-/* return who we received from in *client or *server */
-/* return from in sa if not NULL */
-unsigned char *radudpget(int s, struct client **client, struct server **server, uint16_t *port) {
- int cnt, len;
- unsigned char buf[4], *rad = NULL;
- struct sockaddr_storage from;
- struct sockaddr *fromcopy;
- socklen_t fromlen = sizeof(from);
- struct clsrvconf *p;
- struct list_node *node;
- fd_set readfds;
- struct client *c = NULL;
-
- for (;;) {
- if (rad) {
- free(rad);
- rad = NULL;
- }
- FD_ZERO(&readfds);
- FD_SET(s, &readfds);
- if (select(s + 1, &readfds, NULL, NULL, NULL) < 1)
- continue;
- cnt = recvfrom(s, buf, 4, MSG_PEEK | MSG_TRUNC, (struct sockaddr *)&from, &fromlen);
- if (cnt == -1) {
- debug(DBG_WARN, "radudpget: recv failed");
- continue;
- }
- if (cnt < 20) {
- debug(DBG_WARN, "radudpget: length too small");
- recv(s, buf, 4, 0);
- continue;
- }
-
- p = client
- ? find_clconf(RAD_UDP, (struct sockaddr *)&from, NULL)
- : find_srvconf(RAD_UDP, (struct sockaddr *)&from, NULL);
- if (!p) {
- debug(DBG_WARN, "radudpget: got packet from wrong or unknown UDP peer %s, ignoring", addr2string((struct sockaddr *)&from));
- recv(s, buf, 4, 0);
- continue;
- }
-
- len = RADLEN(buf);
- if (len < 20) {
- debug(DBG_WARN, "radudpget: length too small");
- recv(s, buf, 4, 0);
- continue;
- }
-
- rad = malloc(len);
- if (!rad) {
- debug(DBG_ERR, "radudpget: malloc failed");
- recv(s, buf, 4, 0);
- continue;
- }
-
- cnt = recv(s, rad, len, MSG_TRUNC);
- debug(DBG_DBG, "radudpget: got %d bytes from %s", cnt, addr2string((struct sockaddr *)&from));
-
- if (cnt < len) {
- debug(DBG_WARN, "radudpget: packet smaller than length field in radius header");
- continue;
- }
- if (cnt > len)
- debug(DBG_DBG, "radudpget: packet was padded with %d bytes", cnt - len);
-
- if (client) {
- pthread_mutex_lock(p->lock);
- for (node = list_first(p->clients); node; node = list_next(node)) {
- c = (struct client *)node->data;
- if (s == c->sock && addr_equal((struct sockaddr *)&from, c->addr))
- break;
- }
- if (!node) {
- fromcopy = addr_copy((struct sockaddr *)&from);
- if (!fromcopy) {
- pthread_mutex_unlock(p->lock);
- continue;
- }
- c = addclient(p, 0);
- if (!c) {
- free(fromcopy);
- pthread_mutex_unlock(p->lock);
- continue;
- }
- c->sock = s;
- c->addr = fromcopy;
- }
- *client = c;
- pthread_mutex_unlock(p->lock);
- } else if (server)
- *server = p->servers;
- break;
+#include "event.h"
+#include "compat.h"
+#include "udp.h"
+
+/* Send one packet, the first in queue. */
+static int
+_send (struct rs_connection *conn, int fd)
+{
+ ssize_t r = 0;
+ struct rs_packet *pkt = conn->out_queue;
+
+ assert (pkt->rpkt);
+ assert (pkt->rpkt->data);
+
+ /* Send. */
+ r = compat_send (fd, pkt->rpkt->data, pkt->rpkt->length, 0);
+ if (r == -1)
+ {
+ int sockerr = evutil_socket_geterror (pkt->conn->fd);
+ if (sockerr != EAGAIN)
+ return rs_err_conn_push_fl (pkt->conn, RSE_SOCKERR, __FILE__, __LINE__,
+ "%d: send: %d (%s)", fd, sockerr,
+ evutil_socket_error_to_string (sockerr));