Exemplo n.º 1
0
static void
listen_connect_drop(void)
{
	struct sockaddr_in sin;
	int slisten, sconnect, sv[2];
	int inflight, openfiles;
	socklen_t len;

	test = "listen_connect_drop";
	printf("%s\n", test);
	save_sysctls(&inflight, &openfiles);

	slisten = my_socket(PF_INET, SOCK_STREAM, 0);
	my_bind(slisten, (struct sockaddr *)&sin, sizeof(sin));
	my_listen(slisten, -1);

	my_socketpair(sv);

	len = sizeof(sin);
	my_getsockname(slisten, (struct sockaddr *)&sin, &len);

	sconnect = my_socket(PF_INET, SOCK_STREAM, 0);
	setnonblock(sconnect);
	my_connect(sconnect, (struct sockaddr *)&sin, len);

	sleep(1);
	sendfd(sv[0], slisten);
	close3(slisten, sv[0], sv[1]);
	sleep(1);
	close(sconnect);

	test_sysctls(inflight, openfiles);
}
Exemplo n.º 2
0
void parent_init(int reqfd, int msgfd, pid_t child) {

    // events
    struct event ev_cmd, ev_msg;
    struct event ev_sigchld, ev_sigint, ev_sigterm,  ev_sighup;

#ifdef HAVE_LIBCAP
    // capabilities
    cap_t caps;
#endif /* HAVE_LIBCAP */

    // init the queues
    TAILQ_INIT(&rawfds);

    // proctitle
    setproctitle("parent [priv]");

    // setup global sockets
    sock = my_socket(AF_INET, SOCK_DGRAM, 0);
    mfd = msgfd;

    // debug
    if (options & OPT_DEBUG) {
	dfd = STDOUT_FILENO;
	my_pcap_init(dfd);
#if HAVE_LIBCAP_NG
    } else {
	capng_clear(CAPNG_SELECT_BOTH);
	capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED, CAP_KILL,
		    CAP_NET_ADMIN, CAP_NET_RAW, CAP_NET_BROADCAST, -1);
	if (capng_apply(CAPNG_SELECT_BOTH) == -1)
	    my_fatal("unable to set capabilities");
#elif HAVE_LIBCAP
    } else {
Exemplo n.º 3
0
int				reopen_socket()
{
  struct	protoent	*pe;
  int		s_fd;

  pe = my_getprotobyname("tcp");
  s_fd = my_socket(PF_INET, SOCK_STREAM, pe->p_proto);
  return (s_fd);
}
Exemplo n.º 4
0
/*
 * Listen sockets can also be passed over UNIX domain sockets, so test
 * various cases, including ones where listen sockets have waiting sockets
 * hanging off them...
 */
static void
listen_nothing(void)
{
	struct sockaddr_un sun;
	struct sockaddr_in sin;
	int inflight, openfiles;
	int s;

	test = "listen_nothing_unp";
	printf("%s\n", test);
	bzero(&sun, sizeof(sun));
	sun.sun_family = AF_LOCAL;
	sun.sun_len = sizeof(sun);
	snprintf(sun.sun_path, sizeof(sun.sun_path), "%s/%s", dpath, test);
	save_sysctls(&inflight, &openfiles);
	s = my_socket(PF_LOCAL, SOCK_STREAM, 0);
	my_bind(s, (struct sockaddr *)&sun, sizeof(sun));
	my_listen(s, -1);
	close(s);
	(void)unlink(sun.sun_path);
	test_sysctls(inflight, openfiles);

	test = "listen_nothing_inet";
	printf("%s\n", test);
	bzero(&sin, sizeof(sin));
	sin.sin_family = AF_INET;
	sin.sin_len = sizeof(sin);
	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
	sin.sin_port = htons(0);
	save_sysctls(&inflight, &openfiles);
	s = my_socket(PF_INET, SOCK_STREAM, 0);
	my_bind(s, (struct sockaddr *)&sin, sizeof(sin));
	my_listen(s, -1);
	close(s);
	test_sysctls(inflight, openfiles);
}
Exemplo n.º 5
0
static VALUE
my_connect(VALUE klass, int io_wait, int domain,
	const void *addr, socklen_t addrlen)
{
	int fd = my_socket(domain);

	if (connect(fd, addr, addrlen) < 0) {
		if (errno == EINPROGRESS) {
			VALUE io = sock_for_fd(klass, fd);

			if (io_wait) {
				errno = EAGAIN;
				(void)kgio_call_wait_writable(io);
			}
			return io;
		}
		close_fail(fd, "connect");
	}
	return sock_for_fd(klass, fd);
}
Exemplo n.º 6
0
int main(int argc, char **argv)
{
    int     listenfd = 0;
    int     connfd = 0;
    pid_t   childpid ;
    socklen_t   clilen;
    struct  sockaddr_in     cliaddr;
    struct  sockaddr_in     servaddr;

    listenfd = my_socket(AF_INET, SOCK_STREAM, 0);
	
	signal(SIGCHLD, tu5_11sig_chld);						///
	
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(SERV_PORT);

    my_bind(listenfd, (SA *)&servaddr, sizeof(servaddr));
    my_listen(listenfd, LISTENQ);

    while(1)
    {
        clilen = sizeof(cliaddr);
        if ( (connfd = my_accept(listenfd, (SA*)&cliaddr, &clilen)) < 0)
        {
        
        }

        if ((childpid = my_fork()) == 0)
        {
            my_close(listenfd);
            tu5_17str_echo(connfd);
            exit(0);
        }
        my_close(connfd);
    }

    return 0;
}
Exemplo n.º 7
0
int main(int argc, char **argv)
{
     int    sockfd = 0;
     struct sockaddr_in     servaddr;

     if (argc < 2)
     {
          err_quit("usage: ./a.out <IPaddress>");
     }

     bzero(&servaddr, sizeof(servaddr));
     servaddr.sin_family = AF_INET;
     servaddr.sin_port = htons(SERV_PORT); //将一个无符号短整型的主机数值转换为网络字节顺序
     my_inet_pton(AF_INET, MCAST_IP, &servaddr.sin_addr); //十进制IP转二进制

     //创建一个套接字
     sockfd = my_socket(AF_INET, SOCK_DGRAM, 0);

     dg_cli(stdin, sockfd, (SA *) &servaddr, sizeof(servaddr));

     exit(0);
}
Exemplo n.º 8
0
int main(int argc, char **argv)
{
    int    sockfd = 0;
    struct sockaddr_in     servaddr;

    if (argc != 2)
    {
        err_quit("usage: ./udpcli <IPaddress>");
    }

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family  = AF_INET;
    servaddr.sin_port    = htons(SERV_PORT);
    my_inet_pton(AF_INET, argv[1], &servaddr.sin_addr);
//    servaddr.sin_addr.s_addr = htonl(argv[1]);

    sockfd = my_socket(AF_INET, SOCK_DGRAM, 0);

    tu8_19dg_cli(stdin, sockfd, (SA *)&servaddr, sizeof(servaddr));

    exit(0);

}
Exemplo n.º 9
0
void netif_init() {
    if (sockfd == -1)
	sockfd = my_socket(AF_INET, SOCK_DGRAM, 0);
}
Exemplo n.º 10
0
struct ifi_info *
get_ifi_info(int family, int doaliases)
{
	struct ifi_info		*ifi, *ifihead, **ifipnext;
	int					sockfd, len, lastlen, flags, myflags, idx = 0, hlen = 0;
	char				*ptr, *buf, lastname[IFNAMSIZ], *cptr, *haddr, *sdlname;
	struct ifconf		ifc;
	struct ifreq		*ifr, ifrcopy;
	struct sockaddr_in	*sinptr;
	struct sockaddr_in6	*sin6ptr;

	sockfd = my_socket(AF_INET, SOCK_DGRAM, 0);

	lastlen = 0;
	len = 100 * sizeof(struct ifreq);	/* initial buffer size guess */
	for ( ; ; ) {
		buf = my_malloc(len);
		ifc.ifc_len = len;
		ifc.ifc_buf = buf;
		if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
			if (errno != EINVAL || lastlen != 0)
				err_sys("ioctl error");
		} else {
			if (ifc.ifc_len == lastlen)
				break;		/* success, len has not changed */
			lastlen = ifc.ifc_len;
		}
		len += 10 * sizeof(struct ifreq);	/* increment */
		free(buf);
	}
	ifihead = NULL;
	ifipnext = &ifihead;
	lastname[0] = 0;
	sdlname = NULL;
/* end get_ifi_info1 */

/* include get_ifi_info2 */
	for (ptr = buf; ptr < buf + ifc.ifc_len; ) {
		ifr = (struct ifreq *) ptr;

#ifdef	HAVE_SOCKADDR_SA_LEN
		len = max(sizeof(struct sockaddr), ifr->ifr_addr.sa_len);
#else
		switch (ifr->ifr_addr.sa_family) {
#ifdef	IPV6
		case AF_INET6:	
			len = sizeof(struct sockaddr_in6);
			break;
#endif
		case AF_INET:	
		default:	
			len = sizeof(struct sockaddr);
			break;
		}
#endif	/* HAVE_SOCKADDR_SA_LEN */
		ptr += sizeof(ifr->ifr_name) + len;	/* for next one in buffer */

#ifdef	HAVE_SOCKADDR_DL_STRUCT
		/* assumes that AF_LINK precedes AF_INET or AF_INET6 */
		if (ifr->ifr_addr.sa_family == AF_LINK) {
			struct sockaddr_dl *sdl = (struct sockaddr_dl *)&ifr->ifr_addr;
			sdlname = ifr->ifr_name;
			idx = sdl->sdl_index;
			haddr = sdl->sdl_data + sdl->sdl_nlen;
			hlen = sdl->sdl_alen;
		}
#endif

		if (ifr->ifr_addr.sa_family != family)
			continue;	/* ignore if not desired address family */

		myflags = 0;
		if ( (cptr = strchr(ifr->ifr_name, ':')) != NULL)
			*cptr = 0;		/* replace colon with null */
		if (strncmp(lastname, ifr->ifr_name, IFNAMSIZ) == 0) {
			if (doaliases == 0)
				continue;	/* already processed this interface */
			myflags = IFI_ALIAS;
		}
		memcpy(lastname, ifr->ifr_name, IFNAMSIZ);

		ifrcopy = *ifr;
		my_ioctl(sockfd, SIOCGIFFLAGS, &ifrcopy);
		flags = ifrcopy.ifr_flags;
		if ((flags & IFF_UP) == 0)
			continue;	/* ignore if interface not up */
/* end get_ifi_info2 */

/* include get_ifi_info3 */
		ifi = my_calloc(1, sizeof(struct ifi_info));
		*ifipnext = ifi;			/* prev points to this new one */
		ifipnext = &ifi->ifi_next;	/* pointer to next one goes here */

		ifi->ifi_flags = flags;		/* IFF_xxx values */
		ifi->ifi_myflags = myflags;	/* IFI_xxx values */
#if defined(SIOCGIFMTU) && defined(HAVE_STRUCT_IFREQ_IFR_MTU)
		Ioctl(sockfd, SIOCGIFMTU, &ifrcopy);
		ifi->ifi_mtu = ifrcopy.ifr_mtu;
#else
		ifi->ifi_mtu = 0;
#endif
		memcpy(ifi->ifi_name, ifr->ifr_name, IFI_NAME);
		ifi->ifi_name[IFI_NAME-1] = '\0';
		/* If the sockaddr_dl is from a different interface, ignore it */
		if (sdlname == NULL || strcmp(sdlname, ifr->ifr_name) != 0)
			idx = hlen = 0;
		ifi->ifi_index = idx;
		ifi->ifi_hlen = hlen;
		if (ifi->ifi_hlen > IFI_HADDR)
			ifi->ifi_hlen = IFI_HADDR;
		if (hlen)
			memcpy(ifi->ifi_haddr, haddr, ifi->ifi_hlen);
/* end get_ifi_info3 */
/* include get_ifi_info4 */
		switch (ifr->ifr_addr.sa_family) {
		case AF_INET:
			sinptr = (struct sockaddr_in *) &ifr->ifr_addr;
			ifi->ifi_addr = my_calloc(1, sizeof(struct sockaddr_in));
			memcpy(ifi->ifi_addr, sinptr, sizeof(struct sockaddr_in));

#ifdef	SIOCGIFBRDADDR
			if (flags & IFF_BROADCAST) {
				my_ioctl(sockfd, SIOCGIFBRDADDR, &ifrcopy);
				sinptr = (struct sockaddr_in *) &ifrcopy.ifr_broadaddr;
				ifi->ifi_brdaddr = my_calloc(1, sizeof(struct sockaddr_in));
				memcpy(ifi->ifi_brdaddr, sinptr, sizeof(struct sockaddr_in));
			}
#endif

#ifdef	SIOCGIFDSTADDR
			if (flags & IFF_POINTOPOINT) {
				my_ioctl(sockfd, SIOCGIFDSTADDR, &ifrcopy);
				sinptr = (struct sockaddr_in *) &ifrcopy.ifr_dstaddr;
				ifi->ifi_dstaddr = my_calloc(1, sizeof(struct sockaddr_in));
				memcpy(ifi->ifi_dstaddr, sinptr, sizeof(struct sockaddr_in));
			}
#endif
			break;

		case AF_INET6:
			sin6ptr = (struct sockaddr_in6 *) &ifr->ifr_addr;
			ifi->ifi_addr = my_calloc(1, sizeof(struct sockaddr_in6));
			memcpy(ifi->ifi_addr, sin6ptr, sizeof(struct sockaddr_in6));

#ifdef	SIOCGIFDSTADDR
			if (flags & IFF_POINTOPOINT) {
				my_ioctl(sockfd, SIOCGIFDSTADDR, &ifrcopy);
				sin6ptr = (struct sockaddr_in6 *) &ifrcopy.ifr_dstaddr;
				ifi->ifi_dstaddr = my_calloc(1, sizeof(struct sockaddr_in6));
				memcpy(ifi->ifi_dstaddr, sin6ptr, sizeof(struct sockaddr_in6));
			}
#endif
			break;

		default:
			break;
		}
	}
	free(buf);
	return(ifihead);	/* pointer to first structure in linked list */
}
Exemplo n.º 11
0
int
main(int argc, char **argv)
{
    int     sockfd = 0;
    int     n = 0;
    char    recvline[MAXLINE + 1];
    struct  sockaddr_in     servaddr;
    struct  in_addr         **pptr = NULL;             //
    struct  in_addr         *inetaddrp[2];      //
    struct  in_addr         inetaddr;           //
    struct  hostent         *hp = NULL;
    struct  servent         *sp = NULL;

    if ( argc != 3 )
    {
         err_quit("usage: daytimetcpcli <hostname> <service>");
    }

    if ( (hp = gethostbyname(argv[1])) == NULL )
    {
        if (inet_aton(argv[1], &inetaddr) == 0)
        {
             err_quit("hostname error for %s: %s\n",
                      argv[1], hstrerror(h_errno));
        }
        else
        {
            inetaddrp[0] = &inetaddr;
            inetaddrp[1] = NULL;
            pptr = inetaddrp;           //注意是有p的.
        }
    }
    else
    {
         pptr = (struct in_addr **) hp->h_addr_list;
    }

    //获得了相应服务的端口号什么的
    if ( (sp = getservbyname(argv[2], "tcp")) == NULL )
    {
        err_quit("getservbyname error for %s\n", argv[2]);
    }

    for ( ; *pptr != NULL; pptr++ )
    {
         sockfd = my_socket(AF_INET, SOCK_STREAM, 0);

         bzero(&servaddr, sizeof(servaddr));
         servaddr.sin_family    = AF_INET;
         servaddr.sin_port      = sp->s_port;       //帅
         memcpy(&servaddr.sin_addr, *pptr, sizeof(struct in_addr));
         printf("trying %s\n",
                 my_sock_ntop((SA *) &servaddr, sizeof(servaddr)));

         if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) == 0)
         {
              break;        //success
         }
         err_ret("connect error");
         close(sockfd);
    }

    if (*pptr == NULL)                  //这里不是很懂
    {
         err_quit("unable to connect");
    }

    while ((n= my_read(sockfd, recvline, MAXLINE)) > 0)
    {
        recvline[n] = 0;
        my_fputs(recvline, stdout);
    }

    exit (0);
}
Exemplo n.º 12
0
int main(int argc, const char *argv[])
{
    int listenfd, connfd;
    struct sockaddr_in servaddr, cliaddr;
    socklen_t cliaddr_len;
    char buf[MAXLINE];
    char str[INET_ADDRSTRLEN];
    int n, i;
    pid_t pid;

    listenfd = my_socket(AF_INET, SOCK_STREAM, 0);

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(SERV_PORT);

    my_bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

    my_listen(listenfd, 20);

    printf("Accepting connections...\n");

    while (1) 
    {
        cliaddr_len = sizeof(cliaddr);
        connfd = my_accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);

        pid = fork();
        if (pid == -1) 
        {
            perror("call to fork");
            exit(1);
        }
        else if (pid == 0) 
        {
            my_close(listenfd);
            while (1) 
            {
                n = my_read(connfd, buf, MAXLINE);
                if (n == 0)
                {
                    printf("The other side has been closed.\n");
                    break;
                }
                printf("Received from %s at PORT %d\n", inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)), ntohs(cliaddr.sin_port));

                for (i = 0; i < n; i++) 
                {
                    buf[i] = toupper(buf[i]);
                }
                my_write(connfd, buf, n);
            }
            my_close(connfd);
            exit(0);
        }
        else 
        {
            my_close(connfd);
        }
    }

    return 0;
}
Exemplo n.º 13
0
/*
 * Send a listen UDP socket over a UNIX domain socket.
 *
 * Send a listen TCP socket over a UNIX domain socket.
 *
 * Do each twice, with closing of the listen socket vs. socketpair in
 * different orders.
 */
static void
listen_drop(void)
{
	struct sockaddr_un sun;
	struct sockaddr_in sin;
	int inflight, openfiles;
	int s, sv[2];

	bzero(&sun, sizeof(sun));
	sun.sun_family = AF_LOCAL;
	sun.sun_len = sizeof(sun);

	/*
	 * Close listen socket first.
	 */
	test = "listen_drop_unp1";
	printf("%s\n", test);
	snprintf(sun.sun_path, sizeof(sun.sun_path), "%s/%s", dpath, test);
	save_sysctls(&inflight, &openfiles);
	s = my_socket(PF_LOCAL, SOCK_STREAM, 0);
	my_bind(s, (struct sockaddr *)&sun, sizeof(sun));
	my_listen(s, -1);
	my_socketpair(sv);
	sendfd(sv[0], s);
	close3(s, sv[0], sv[1]);
	test_sysctls(inflight, openfiles);

	/*
	 * Close socketpair first.
	 */
	test = "listen_drop_unp2";
	printf("%s\n", test);
	snprintf(sun.sun_path, sizeof(sun.sun_path), "%s/%s", dpath, test);
	save_sysctls(&inflight, &openfiles);
	s = my_socket(PF_LOCAL, SOCK_STREAM, 0);
	my_bind(s, (struct sockaddr *)&sun, sizeof(sun));
	my_listen(s, -1);
	my_socketpair(sv);
	sendfd(sv[0], s);
	close3(sv[0], sv[1], s);
	test_sysctls(inflight, openfiles);

	sin.sin_family = AF_INET;
	sin.sin_len = sizeof(sin);
	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
	sin.sin_port = htons(0);

	/*
	 * Close listen socket first.
	 */
	test = "listen_drop_inet1";
	printf("%s\n", test);
	bzero(&sun, sizeof(sun));
	save_sysctls(&inflight, &openfiles);
	s = my_socket(PF_INET, SOCK_STREAM, 0);
	my_bind(s, (struct sockaddr *)&sin, sizeof(sin));
	my_listen(s, -1);
	my_socketpair(sv);
	sendfd(sv[0], s);
	close3(s, sv[0], sv[1]);
	test_sysctls(inflight, openfiles);

	/*
	 * Close socketpair first.
	 */
	test = "listen_drop_inet2";
	printf("%s\n", test);
	bzero(&sun, sizeof(sun));
	save_sysctls(&inflight, &openfiles);
	s = my_socket(PF_INET, SOCK_STREAM, 0);
	my_bind(s, (struct sockaddr *)&sin, sizeof(sin));
	my_listen(s, -1);
	my_socketpair(sv);
	sendfd(sv[0], s);
	close3(sv[0], sv[1], s);
	test_sysctls(inflight, openfiles);
}
Exemplo n.º 14
0
int main(int argc, const char *argv[])
{
    int listenfd, connfd;
    struct sockaddr_in servaddr, cliaddr;
    socklen_t cliaddr_len;
    char buf[MAXLINE];
    char str[INET_ADDRSTRLEN];
    int n;
    pid_t pid;
    int filefd;

    listenfd = my_socket(AF_INET, SOCK_STREAM, 0);

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(SERV_PORT);

    my_bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

    my_listen(listenfd, 20);

    printf("Accepting connections...\n");

    while (1) 
    {
        cliaddr_len = sizeof(cliaddr);
        connfd = my_accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);

        pid = fork();
        if (pid == -1) 
        {
            perror("call to fork");
            exit(1);
        }
        else if (pid == 0) 
        {
            my_close(listenfd);
            n = my_read(connfd, buf, MAXLINE);
            filefd = open(buf, O_RDWR | O_CREAT | O_TRUNC, 0666);
            my_write(filefd, &buf[strlen(buf)+1], strlen(&buf[strlen(buf)+1]));
            while ((n = my_read(connfd, buf, MAXLINE))) 
            {
                printf("Received from %s at PORT %d\n", inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)), ntohs(cliaddr.sin_port));

                if (filefd < 0) 
                {
                    perror("create file error");
                    exit(1);
                }

                //for (i = 0; i < n; i++) 
                //{
                    //buf[i] = toupper(buf[i]);
                //}
                my_write(filefd, buf, n);
            }
            my_close(filefd);
            exit(0);
        }
        else 
        {
            my_close(connfd);
        }
    }

    return 0;
}
Exemplo n.º 15
0
void echotester (int sock)
{
	setcntl(sock, F_SETFL, O_NONBLOCK, "O_NONBLOCK");
	
	long long sent = 0, recvd = 0, recvdnow = 0;
	int ptrsend = 0;
	int ptrrecv = 0;
	struct pollfd pollfd = { .fd = sock, .events = POLLIN | POLLOUT, };
	struct timeval tb, ti, te;
	
	gettimeofday(&tb, NULL);
	ti = tb;
	
	while (1)
	{
		int ret = poll(&pollfd, 1, 1000 /*ms*/);
		
		if (ret == -1)
		{
			perror("poll");
			exit(1);
		}

		if (pollfd.revents & POLLIN)
		{
			ssize_t ret = read(sock, bufin, BUFLEN);
			if (ret == -1)
			{
				perror("read");
				exit(1);
			}
			size_t pr = 0;
			while (ret)
			{
				ssize_t size = ret;
				if (size > BUFLEN - ptrrecv)
					size = BUFLEN - ptrrecv;
				if (memcmp(bufin + pr, bufout + ptrrecv, size) != 0)
				{
					fprintf(stderr, "\ndata differ (sent=%Li revcd=%Li ptrsend=%i ptrrecv=%i ret=%i size=%i)\n", sent, recvd, ptrsend, ptrrecv, (int)ret, (int)size);
					
					int i = 0;
					for (i = 0; i < size; i++)
						if (bufin[i + pr] != bufout[i + ptrrecv])
						{
							printf("offset-diff @%Li @0x%Lx\n", i + recvd, i + recvd);
							break;
						}
					int j = i > 16? i - 16: 0;
					int k = i + 16 < size? i + 16: size - 1;
					while (j++ < k)
						printf("@%Lx:R%02x/S%02x ", j + recvd, bufin[j + pr], bufout[j + ptrrecv]);
					printf("\n");
					
					exit(1);
				}
				recvd += size;
				recvdnow += size;
				ptrrecv = (ptrrecv + size) & (BUFLEN - 1);
				ret -= size;
				pr += size;
			}
		}
		
		if (pollfd.revents & POLLOUT)
		{
			ssize_t size = BUFLEN - ptrsend;
			ssize_t ret = write(sock, bufout + ptrsend, size);
			if (ret == -1)
			{
				perror("write");
				exit(1);
			}
			sent += ret;
			ptrsend = (ptrsend + ret) & (BUFLEN - 1);
		}
		
		gettimeofday(&te, NULL);
		if (te.tv_sec - ti.tv_sec > 1)
		{
			printbw(te.tv_sec - tb.tv_sec, te.tv_usec - tb.tv_usec, recvd, "avg:");
			printbw(te.tv_sec - ti.tv_sec, te.tv_usec - ti.tv_usec, recvdnow, "now:");
			printsz(recvd, "size:");
			printf("-----\r"); fflush(stdout);
			ti = te;
			recvdnow = 0;
		}
	}

	my_close(sock);
}

void echoserver (int sock)
{
	setcntl(sock, F_SETFL, O_NONBLOCK, "O_NONBLOCK");
	
	int ptrsend = 0;
	int ptrrecv = 0;
	size_t inbuf = 0;
	struct pollfd pollfd = { .fd = sock, .events = POLLIN | POLLOUT, };
	
	while (1)
	{
		pollfd.events =  0;
		if (inbuf < BUFLEN) pollfd.events |= POLLIN;
		if (inbuf) pollfd.events |= POLLOUT;
		int ret = poll(&pollfd, 1, 1000 /*ms*/);
		
		if (ret == -1)
		{
			perror("poll");
			exit(1);
		}

		if (pollfd.revents & POLLIN)
		{
			ssize_t maxrecv = BUFLEN - inbuf;
			if (maxrecv > BUFLEN - ptrrecv)
				maxrecv = BUFLEN - ptrrecv;
			ssize_t ret = read(sock, bufin + ptrrecv, maxrecv);
			if (ret == -1)
			{
				perror("read");
				exit(1);
			}
			inbuf += ret;
			ptrrecv = (ptrrecv + ret) & (BUFLEN - 1);
		}
		
		if (pollfd.revents & POLLOUT)
		{
			ssize_t maxsend = inbuf;
			if (maxsend > BUFLEN - ptrsend)
				maxsend = BUFLEN - ptrsend;
			ssize_t ret = write(sock, bufin + ptrsend, maxsend);
			if (ret == -1)
			{
				perror("write");
				exit(1);
			}
			inbuf -= ret;
			ptrsend = (ptrsend + ret) & (BUFLEN - 1);
		}
	}

	my_close(sock);
}

int main (int argc, char* argv[])
{
	int op;
	const char* host = "localhost";
	int port = 10102;
	int server = 0;
	int i;
	//int nodelay = 0;
	
	while ((op = getopt(argc, argv, "hp:d:fs")) != EOF) switch(op)
	{
		case 'h':
			help();
			return 0;

		case 'p':
			port = atoi(optarg);			
			break;
			
		case 'd':
			host = optarg;
			break;
		
//		case 'f':
//			nodelay = 1;
//			break;

		case 's':
			server = 1;
			break;
		
		default:
			printf("option '%c' not recognized\n", op);
			help();
			return 1;
	}
	
	for (i = 0; i < BUFLEN; i++)
	{
	#if 1
		bufout[i] = random() >> 23;
	#else
		char c = i & 0x0f;
		c += c > 9? 'a' - 10: '0';
		bufout[i] = c;
	#endif
	}

	int sock = my_socket();
	if (server)
	{
		printf("waiting on port %i\n", port);
		my_bind_listen(sock, port);
		int clisock = my_accept(sock);
		echoserver(clisock);
		close(sock);
	}
	else
	{
		printf("remote host:	%s\n"
		       "port:		%i\n",
		       host, port);
	
		my_connect(host, port, sock);
		echotester(sock);
	}
	
	return 0;
}