/*
 * Copyright (c) 2002, 2004, 2005 Sendmail, Inc. and its suppliers.
 *	All rights reserved.
 *
 * By using this file, you agree to the terms and conditions set
 * forth in the LICENSE file which can be found at the top level of
 * the sendmail distribution.
 */

#include "sm/generic.h"
SM_RCSID("@(#)$Id: t-net-1.c,v 1.8 2005/05/31 21:00:28 ca Exp $")
#include "sm/assert.h"
#include "sm/error.h"
#include "sm/test.h"
#include "sm/io.h"
#include "sm/ctype.h"
#include "sm/net.h"
#include "sm/unixsock.h"
#include "timing.h"

#include <stdio.h>
#include "t-net-common.c"

/*
**  CLIENT -- write wr characters to localhost:port
**
**	Parameters:
**		port -- port
**		wr -- number of chars to send
**		delay -- sleep time before close
**		bsize -- buffer size to use
**		timeout -- timeout
**		both -- if >0: do write and read ("both" times)
**			sets double buffering
**		iter -- number of iterations (writing data)
**
**	Returns:
**		none
*/

static void
client(int port, int wr, int delay, int bsize, int timeout, int both, int iter)
{
	int fd;
	sm_ret_T ret;

	if (Verbose > 1)
		fprintf(stderr, "clt: connect\n");
	(void) net_client_connect("127.0.0.1", port, &fd);
	if (Verbose > 1)
		fprintf(stderr, "clt: connected=%d\n", fd);
	SM_TEST(fd >= 0);
	if (fd < 0)
		return;
	while (iter-- > 0)
	{
		ret = write_sock(fd, wr, delay, bsize, timeout, both);
		SM_TEST(sm_is_success(ret));
		if (!sm_is_success(ret))
		{
			if (Verbose > 0)
				fprintf(stderr, "client: error %x\n", ret);
			return;
		}
	}
}

/*
**  SERVER -- receive rd characters on localhost:port
**
**	Parameters:
**		port -- port
**		rd -- number of chars to receive
**		rep -- loop through all of this rep times
**		delay -- sleep time before close
**		bsize -- buffer size to use
**		backlog -- size of listen queue
**		timeout -- timeout
**		both -- if >0: do write and read ("both" times)
**			sets double buffering
**		iter -- number of iterations (reading data)
**
**	Returns:
**		none
*/

static void
server(int port, int rd, int rep, int delay, int bsize, int backlog, int timeout, int both, int iter)
{
	int fd, lfd;
	sm_ret_T res;
	struct sockaddr addr;
	sockaddr_len_T addrlen;

	lfd = fd = -1;
	lfd = net_server_listen("127.0.0.1", port, backlog);
	SM_TEST(lfd >= 0);
	if (lfd < 0)
		return;
	res = SM_SUCCESS;
	while (rep-- > 0)
	{
		addrlen = sizeof(addr);
		if (Verbose > 1)
			fprintf(stderr, "srv: accept\n");
		fd = net_server_accept(lfd, &addr, &addrlen);
		SM_TEST(fd >= 0);
		if (fd < 0)
			goto err;
		while (iter-- > 0)
		{
			res = read_sock(fd, rd, delay, bsize, timeout, both);
			if (sm_is_err(res))
				goto err;
		}
		fd = -1;
		if (Verbose > 0)
			fprintf(stderr, "srv: read_sock done=%x\n", res);
		if (sm_is_err(res))
			goto err;
	}
  err:
	if (fd >= 0)
		close(fd);
	if (lfd >= 0)
		close(lfd);
}

int
main(int argc, char *argv[])
{
	bool clt, any;
	int c, port, rd, wr, rep, delay, backlog, bsize, timeout, both, iter;

	opterr = 0;
	clt = true;
	any = false;
	port = SM_DEFPORT;
	rd = wr = 0;
	rep = 1;
	delay = 0;
	bsize = 0;
	backlog = 20;
	timeout = 5;
	Verbose = 0;
	both = 0;
	iter = 1;
	while ((c = getopt(argc, argv, "b:c:d:i:l:r:s:t:p:BR:STV")) != -1)
	{
		any = true;
		switch (c)
		{
		  case 'B':
			both++;
			break;
		  case 'R':
			both = atoi(optarg);
			break;
		  case 'b':
			bsize = atoi(optarg);
			break;
		  case 'c':
			clt = true;
			wr = atoi(optarg);
			break;
		  case 'd':
			delay = atoi(optarg);
			break;
		  case 'i':
			iter = atoi(optarg);
			break;
		  case 'l':
			backlog = atoi(optarg);
			break;
		  case 'p':
			port = atoi(optarg);
			break;
		  case 'r':
			rep = atoi(optarg);
			break;
		  case 's':
			clt = false;
			rd = atoi(optarg);
			break;
		  case 't':
			timeout = atoi(optarg);
			break;
		  case 'S':
			fprintf(stderr, "sizeof sm_file_T: %d\n",
				(int) sizeof(sm_file_T));
			fprintf(stderr, "sizeof sm_stream_T: %d\n",
				(int) sizeof(sm_stream_T));
			fprintf(stderr, "sizeof smbuf_T: %d\n",
				(int) sizeof(smbuf_T));
			break;
		  case 'T':
			Timing = true;
			break;
		  case 'V':
			++Verbose;
			break;
		  default:
			usage(argv[0]);
			return(1);
		}
	}
	sm_test_begin(argc, argv, "test net 1");
	if (!any)
		goto end;

	if (clt)
		client(port, wr, delay, bsize, timeout, both, iter);
	else
	{
		server(port, rd, rep, delay, bsize, backlog, timeout, both, iter);
	}
  end:
	return sm_test_end();
}


syntax highlighted by Code2HTML, v. 0.9.1