/*
 * Functions operating on SOCK_STREAM and buffers.
 *
 * Copyright 2000-2007 Willy Tarreau <w@1wt.eu>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 *
 */

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>

#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>

#include <common/compat.h>
#include <common/config.h>
#include <common/time.h>

#include <types/buffers.h>
#include <types/global.h>
#include <types/polling.h>

#include <proto/client.h>
#include <proto/fd.h>
#include <proto/stream_sock.h>
#include <proto/task.h>


/*
 * this function is called on a read event from a stream socket.
 * It returns 0.
 */
int stream_sock_read(int fd) {
	struct buffer *b = fdtab[fd].cb[DIR_RD].b;
	int ret, max;
	int read_poll = MAX_READ_POLL_LOOPS;

#ifdef DEBUG_FULL
	fprintf(stderr,"stream_sock_read : fd=%d, owner=%p\n", fd, fdtab[fd].owner);
#endif

	if (fdtab[fd].state != FD_STERROR) {
		while (read_poll-- > 0)
		{
			if (b->l == 0) { /* let's realign the buffer to optimize I/O */
				b->r = b->w = b->lr  = b->data;
				max = b->rlim - b->data;
			}
			else if (b->r > b->w) {
				max = b->rlim - b->r;
			}
			else {
				max = b->w - b->r;
				/* FIXME: theorically, if w>0, we shouldn't have rlim < data+size anymore
				 * since it means that the rewrite protection has been removed. This
				 * implies that the if statement can be removed.
				 */
				if (max > b->rlim - b->data)
					max = b->rlim - b->data;
			}
	    
			if (max == 0) {  /* not anymore room to store data */
				EV_FD_CLR(fd, DIR_RD);
				break;
			}

#ifndef MSG_NOSIGNAL
			{
				int skerr;
				socklen_t lskerr = sizeof(skerr);
	
				ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &skerr, &lskerr);
				if (ret == -1 || skerr)
					ret = -1;
				else
					ret = recv(fd, b->r, max, 0);
			}
#else
			ret = recv(fd, b->r, max, MSG_NOSIGNAL);
#endif
			if (ret > 0) {
				b->r += ret;
				b->l += ret;
				b->flags |= BF_PARTIAL_READ;
	
				if (b->r == b->data + BUFSIZE) {
					b->r = b->data; /* wrap around the buffer */
				}

				b->total += ret;

				/* generally if we read something smaller than the 1 or 2 MSS,
				 * it means that it's not worth trying to read again.
				 */
				if (ret < MIN_RET_FOR_READ_LOOP)
					break;
				if (!read_poll)
					break;

				/* we hope to read more data or to get a close on next round */
				continue;
			}
			else if (ret == 0) {
				b->flags |= BF_READ_NULL;
				break;
			}
			else if (errno == EAGAIN) {/* ignore EAGAIN */
				break;
			}
			else {
				b->flags |= BF_READ_ERROR;
				fdtab[fd].state = FD_STERROR;
				break;
			}
		} /* while(1) */
	}
	else {
		b->flags |= BF_READ_ERROR;
		fdtab[fd].state = FD_STERROR;
	}

	if (b->flags & BF_READ_STATUS) {
		if (b->rto && EV_FD_ISSET(fd, DIR_RD))
			tv_delayfrom(&b->rex, &now, b->rto);
		else
			tv_eternity(&b->rex);
	
		task_wakeup(&rq, fdtab[fd].owner);
	}

	return 0;
}


/*
 * this function is called on a write event from a stream socket.
 * It returns 0.
 */
int stream_sock_write(int fd) {
	struct buffer *b = fdtab[fd].cb[DIR_WR].b;
	int ret, max;

#ifdef DEBUG_FULL
	fprintf(stderr,"stream_sock_write : fd=%d, owner=%p\n", fd, fdtab[fd].owner);
#endif

	if (b->l == 0) { /* let's realign the buffer to optimize I/O */
		b->r = b->w = b->lr  = b->data;
		max = 0;
	}
	else if (b->r > b->w) {
		max = b->r - b->w;
	}
	else
		max = b->data + BUFSIZE - b->w;
    
	if (fdtab[fd].state != FD_STERROR) {
		if (max == 0) {
			/* may be we have received a connection acknowledgement in TCP mode without data */
			if (fdtab[fd].state == FD_STCONN) {
				int skerr;
				socklen_t lskerr = sizeof(skerr);
				ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &skerr, &lskerr);
				if (ret == -1 || skerr) {
					b->flags |= BF_WRITE_ERROR;
					fdtab[fd].state = FD_STERROR;
					task_wakeup(&rq, fdtab[fd].owner);
					tv_eternity(&b->wex);
					EV_FD_CLR(fd, DIR_WR);
					return 0;
				}
			}

			b->flags |= BF_WRITE_NULL;
			task_wakeup(&rq, fdtab[fd].owner);
			fdtab[fd].state = FD_STREADY;
			tv_eternity(&b->wex);
			EV_FD_CLR(fd, DIR_WR);
			return 0;
		}

#ifndef MSG_NOSIGNAL
		{
			int skerr;
			socklen_t lskerr = sizeof(skerr);

			ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &skerr, &lskerr);
			if (ret == -1 || skerr)
				ret = -1;
			else
				ret = send(fd, b->w, max, MSG_DONTWAIT);
		}
#else
		ret = send(fd, b->w, max, MSG_DONTWAIT | MSG_NOSIGNAL);
#endif

		if (ret > 0) {
			b->l -= ret;
			b->w += ret;
	    
			b->flags |= BF_PARTIAL_WRITE;
	    
			if (b->w == b->data + BUFSIZE) {
				b->w = b->data; /* wrap around the buffer */
			}
		}
		else if (ret == 0) {
			/* nothing written, just pretend we were never called */
			// b->flags |= BF_WRITE_NULL;
			return 0;
		}
		else if (errno == EAGAIN) /* ignore EAGAIN */
			return 0;
		else {
			b->flags |= BF_WRITE_ERROR;
			fdtab[fd].state = FD_STERROR;
		}
	}
	else {
		b->flags |= BF_WRITE_ERROR;
		fdtab[fd].state = FD_STERROR;
	}

	if (b->wto) {
		tv_delayfrom(&b->wex, &now, b->wto);
		/* FIXME: to prevent the client from expiring read timeouts during writes,
		 * we refresh it. A solution would be to merge read+write timeouts into a
		 * unique one, although that needs some study particularly on full-duplex
		 * TCP connections. */
		b->rex = b->wex;
	}
	else
		tv_eternity(&b->wex);

	task_wakeup(&rq, fdtab[fd].owner);
	return 0;
}



/*
 * Local variables:
 *  c-indent-level: 8
 *  c-basic-offset: 8
 * End:
 */
