-void *tcpserverwr(void *arg) {
- int cnt;
- struct client *client = (struct client *)arg;
- struct queue *replyq;
- struct request *reply;
-
- debug(DBG_DBG, "tcpserverwr: starting for %s", addr2string(client->addr));
- replyq = client->replyq;
- for (;;) {
- pthread_mutex_lock(&replyq->mutex);
- while (!list_first(replyq->entries)) {
- if (client->sock >= 0) {
- debug(DBG_DBG, "tcpserverwr: waiting for signal");
- pthread_cond_wait(&replyq->cond, &replyq->mutex);
- debug(DBG_DBG, "tcpserverwr: got signal");
- }
- if (client->sock < 0) {
- /* s might have changed while waiting */
- pthread_mutex_unlock(&replyq->mutex);
- debug(DBG_DBG, "tcpserverwr: exiting as requested");
- pthread_exit(NULL);
- }
- }
- reply = (struct request *)list_shift(replyq->entries);
- pthread_mutex_unlock(&replyq->mutex);
- cnt = write(client->sock, reply->replybuf, RADLEN(reply->replybuf));
- if (cnt > 0)
- debug(DBG_DBG, "tcpserverwr: sent %d bytes, Radius packet of length %d to %s",
- cnt, RADLEN(reply->replybuf), addr2string(client->addr));
- else
- debug(DBG_ERR, "tcpserverwr: write error for %s", addr2string(client->addr));
- freerq(reply);
- }
+/* The read callback for TCP.
+
+ Read exactly one RADIUS message from BEV and store it in struct
+ rs_packet passed in USER_DATA.
+
+ Inform upper layer about successful reception of received RADIUS
+ message by invoking conn->callbacks.recevied_cb(), if !NULL. */
+void
+tcp_read_cb (struct bufferevent *bev, void *user_data)
+{
+ struct rs_packet *pkt = (struct rs_packet *) user_data;
+
+ assert (pkt);
+ assert (pkt->conn);
+ assert (pkt->rpkt);
+
+ pkt->rpkt->sockfd = pkt->conn->fd;
+ pkt->rpkt->vps = NULL; /* FIXME: can this be done when initializing pkt? */
+
+ /* Read a message header if not already read, return if that
+ fails. Read a message and have it dispatched to the user
+ registered callback.
+
+ Room for improvement: Peek inside buffer (evbuffer_copyout()) to
+ avoid the extra copying. */
+ if ((pkt->flags & RS_PACKET_HEADER_READ) == 0)
+ if (_read_header (pkt))
+ return; /* Error. */
+ _read_packet (pkt);