Exemple #1
0
int main(int argc, char** argv)
{
    g_signal.RegisterSignals();

    int port = 7777;
    int g_servfd = listen_net(port);
    if (g_servfd < 0)
    {
        printf("listen_net failed %s\n", strerror(errno));
        return -1;
    }
    printf("listen_net start\n");
    
    int clifd1 = my_accept(g_servfd);
    if (clifd1 < 0)
    {
        printf("my_accept failed %s\n", strerror(errno));
        return -1;
    }
    set_fd_nonblock(clifd1);
    printf("my_accept clifd1 %d\n", clifd1);

    int clifd2 = my_accept(g_servfd);
    if (clifd2 < 0)
    {
        printf("my_accept failed %s\n", strerror(errno));
        return -1;
    }
    set_fd_nonblock(clifd2);
    printf("my_accept clifd2 %d\n", clifd2);
    
    int fds[2];
    fds[0] = clifd1;
    fds[1] = clifd2;

    int pid1 = fork();
    if (pid1 == 0) //子进程
    {
        clildfolw(fds, 2);

        return 0;

    }
    
    
    int pid2 = fork();
    if (pid2 == 0) //子进程
    {
        clildfolw(fds, 2);

        return 0;

    }
     
    
    sleep(1000);

    return 0;
}
int make_new_session(int new_sock_fd)
{
    int ret, sv[2], use_socket_pair=1;
    set_useful_sock_opt(new_sock_fd);
    snd_iac(new_sock_fd,DONT, TELOPT_ECHO);
    snd_iac(new_sock_fd,DO, TELOPT_LFLOW);
    snd_iac(new_sock_fd,WILL, TELOPT_ECHO);
    snd_iac(new_sock_fd,WILL, TELOPT_SGA);

    if (use_socket_pair)
    {
        ret=socketpair(AF_UNIX, SOCK_STREAM, 0, sv);
    }
    else
    {
        ret=openpty(&(sv[0]), &(sv[1]), NULL, NULL, NULL);
        tty_cfg(fd_pty_slave);
    }


    if (ret<0)
    {
        return ret;
    }

    fd_conn = new_sock_fd;
    set_fd_nonblock(fd_conn);
    fd_pty_master = sv[0];
    fd_pty_slave  = sv[1];

    shell_thread_should_exit = 0;
    pthread_create(&the_shell_thread, NULL, the_shell_thread_func, NULL);
    return 0;
}
int main(int argc, char *argv[])
{
    int ret;
    parse_args(argc, argv);
    if (the_working_paras.cpu_idx!=(uint8_t)-1)
	{
		ret = bind_cur_thread_to_cpu(the_working_paras.cpu_idx);
		if (0==ret)
			goto BIND_CPU_OK;
		
		errno = ret;
		ERR_DBG_PRINT_QUIT("bind to cpu %d failed", (int)the_working_paras.cpu_idx);
	}

BIND_CPU_OK:
	register_sig_proc(SIGINT, sig_handler);
    the_working_paras.sockfd = udp_socket_init(the_working_paras.src_ip, the_working_paras.src_port);
	if (the_working_paras.sockfd<0)
	{
	    ERR_DBG_PRINT_QUIT("create socket on %s:%d failed ", the_working_paras.src_ip, (int)the_working_paras.src_port);
	}

	set_fd_nonblock(the_working_paras.sockfd);
	rxtx_loop();
	show_stats();
    return 0;
}
static void connect2dst()
{
    int ret;
	if (the_working_paras.src_ip)
        the_working_paras.sockfd = tcp_socket_init(the_working_paras.src_ip, the_working_paras.src_port);
	else
		the_working_paras.sockfd = tcp_socket_init_no_addr();
	
	if (the_working_paras.sockfd<0)
	{
	    ERR_DBG_PRINT_QUIT("create socket on %s:%d failed ", the_working_paras.src_ip, (int)the_working_paras.src_port);
	}

	
    make_sockaddr(&the_working_paras.dst_sock_addr, inet_addr(the_working_paras.dst_ip), htons(the_working_paras.dst_port));
	ret=connect(the_working_paras.sockfd
		,(void *)&the_working_paras.dst_sock_addr
		,sizeof(struct sockaddr_in));
	if (ret<0)
	{
	    ERR_DBG_PRINT_QUIT("connect to %s:%d failed ", the_working_paras.dst_ip, (int)the_working_paras.dst_port);
	}

    set_fd_nonblock(the_working_paras.sockfd);
	DBG_PRINT("connect to %s:%d succeed!", the_working_paras.dst_ip, (int)the_working_paras.dst_port);

}
Exemple #5
0
pbuf *
new_pbuf(
        int pfd,
        size_t bufsize)
{
        long pipe_buf = 512; /* _POSIX_PIPE_BUF */
        pbuf *buf = NULL;
        buf = Alloc(1, pbuf);
        if(buf == NULL)
                return NULL;
#ifdef _PC_PIPE_BUF
        pipe_buf = fpathconf(pfd, _PC_PIPE_BUF);
        if(pipe_buf == -1L)
        {
                serror("fpathconf %d, _PC_PIPE_BUF", pfd);
                goto err;
        }
#endif
        set_fd_nonblock(pfd);
        buf->pfd = pfd;
        if(bufsize < (size_t)pipe_buf)
                bufsize = (size_t)pipe_buf;
        buf->base = Alloc(bufsize, char);
        if(buf->base == NULL)
                goto err;
        buf->ptr = buf->base;
        buf->upperbound = buf->base + bufsize;
        return buf;
err:
        free(buf);
        return NULL;
}
struct acceptor * acceptor_create( const char * host, uint16_t port )
{
    struct acceptor * a = NULL;

    a = (struct acceptor *)malloc( sizeof(struct acceptor) );
    if ( a )
    {
        a->holding = 0;
        a->socketfd = 0;
        a->ev_accept = NULL;
        pthread_mutex_init( &(a->lock), NULL );

        a->socketfd = tcp_listen( host, port );
        if ( a->socketfd < 0 )
        {
            acceptor_destroy( a );
            return NULL;
        }

        set_fd_nonblock( a->socketfd );

        a->ev_accept = event_create();
        if ( a->ev_accept == NULL )
        {
            acceptor_destroy( a );
            return NULL;
        }
    }

    return a;
}
int32_t tcp_listen( const char * host, uint16_t port )
{
    int32_t fd = -1;

    int32_t flags = 1;
    struct linger ling = {1, 0};

    struct sockaddr_in addr;

    fd = socket( AF_INET, SOCK_STREAM, 0 );
    if ( fd < 0 )
    {
        return -1;
    }

    /* TCP Socket Option Settings */
    setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags) );

    flags = 1;
    setsockopt( fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags) );

    flags = 1;
    setsockopt( fd, IPPROTO_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags) );
    setsockopt( fd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling) );

#if defined (__linux__)
	flags = 1;
	setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &flags, sizeof(flags) );
#endif

    set_fd_nonblock( fd );

    memset( &addr, 0, sizeof(addr) );
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    if ( host != NULL )
    {
        addr.sin_addr.s_addr = inet_addr( host );
    }
    else
    {
        addr.sin_addr.s_addr = INADDR_ANY;
    }

    if ( bind( fd, (struct sockaddr *)&addr, sizeof(addr) ) == -1 )
    {
        close( fd );
        return -2;
    }

    if ( listen( fd, 8192 ) == -1 )
    {
        close( fd );
        return -3;
    }

    return fd;
}
Exemple #8
0
/*
 * @param dest_ip : destination IP address  eg. "192.168.1.1"
 * @param dest_port:  destination Port
 * @param  tries: re-connect times,
 * 		<=0: try infinite times.
 * 		>0: try definite times.
 * @ret  -1: Error
 * 	 >0: socket file descriptor.
 */
int socket_client::connect(const char *dest_ip, unsigned short dest_port,
                           int tries)
{
        int ret= -1;
        int fd = socket(AF_INET, SOCK_STREAM, 0);
        if(fd <= 0) {
                return -1;
        }
        set_fd_nonblock(fd);
        set_sockopt(fd,SOCK_OPT_REUSE, SO_REUSE_ON);
        set_sockopt(fd,SOCK_OPT_LINGER, SO_LINGER_ON);
        //set_sockopt(fd, SOCK_OPT_TCPNODELAY, 1);
        struct sockaddr_in addr;
        bzero((char *)&addr, sizeof(addr));
        addr.sin_family = AF_INET;
        inet_aton(dest_ip, &addr.sin_addr);
        addr.sin_port = htons(dest_port);
        int count = 0;
        while(1) {
                if(::connect(fd, (const struct sockaddr *)&addr, sizeof(addr)) == 0)	{
                        ret =0;
                        break;
                } else {
                        if(errno == EINPROGRESS) {
                                ret = async_connect_check(fd, &count, tries);
                                break;
                        } else if(errno == EISCONN) {
				ret = 0;
				break;
			}
                        /* Re-try(connect) in case of other errors occur,
                         * until a limited re-try times has reached.
                         */
                        if((tries >0) && (++count > tries)) {
                                ret = -1;
                                break;
                        }
                }
                sleep(1);
        } /* End of while(1).*/
        if(ret >=0) {
                socket_conection_conf_t cnt;
                bzero(&cnt,sizeof(cnt));
                cnt.fd =fd;
                strncpy(cnt.target_addr, dest_ip, sizeof(cnt.target_addr));
                cnt.target_port = cnt.target_port;
                clients_conf.push_back(cnt);
                ep_add_fd(fd);
                return fd;
        }
        return -1;
}
Exemple #9
0
int accept_tcp_handler(ae_event_loop *ev_loop, int listenfd, void *data, int mask)
{
    int fd;
    struct sockaddr_in addr;
    socklen_t len = sizeof(addr);
    while (1) {
        fd = accept(listenfd, (struct sockaddr*)&addr, &len);
        if (fd == -1) {
            if (errno == EINTR) {
                continue;
            } else {
                perror("accept error\n");
                return -1;
            }
        }
        break;
    }
    if (set_fd_nonblock(fd) == -1) {
        return -1;
    }
    echoclient *c = (echoclient*)malloc(sizeof(echoclient));
    if (ae_create_file_event(ev_loop, fd, AE_READABLE, read_from_client, c) == AE_ERR) {
        printf("create read_from_client event failed\n");
        close(fd);
        free(c);
        return -1;
    }
    c->fd = fd;
    c->port = ntohs(addr.sin_port);
    inet_ntop(AF_INET, (void*)&addr.sin_addr, c->ip, sizeof(c->ip));
    c->send_buf[0] = '\0';
    c->recv_buf[0] = '\0';
    c->send_buf_len = 0;
    c->packet_len = 0;
    c->recv_buf_len = 0;
    c->ev_loop = ev_loop;
    printf("%s:%d-%d:client connected to server\n", c->ip, c->port, c->fd);
    return 0;

}
Exemple #10
0
/* returns 0 or errno on error */
int
pbuf_flush(
    pbuf*               buf,
    int                 block,          /* bool_t */
    unsigned int        timeo,          /* N.B. Not a struct timeval */
    const char* const   id)             /* destination identifier */
{
    size_t              len = (size_t)(buf->ptr - buf->base);
    int                 changed = 0;
    int                 nwrote = 0;
    int                 status = ENOERR;        /* success */
    int                 tmpErrno;
    time_t              start;
    time_t              duration;

    udebug("        pbuf_flush fd %d %6d %s",
        buf->pfd, len, block ? "block" : "" );

    if(len == 0)
        return 0; /* nothing to do */
    /* else */

    (void)time(&start);

    if(block)
        changed = clr_fd_nonblock(buf->pfd);

    if(block && timeo != 0)             /* (timeo == 0) => don't set alarm */
        SET_ALARM(timeo, flush_timeo);

    nwrote = (int) write(buf->pfd, buf->base, len);
    tmpErrno = errno;                   /* CLR_ALRM() can change "errno" */

    if(block && timeo != 0)
        CLR_ALRM();

    if(nwrote == -1) {
        if((tmpErrno == EAGAIN) && (!block)) {
            udebug("         pbuf_flush: EAGAIN on %d bytes", len);

            nwrote = 0;
        }
        else {
            status = tmpErrno;

            serror(NULL == id
                    ? "pbuf_flush(): fd=%d"
                    : "pbuf_flush(): fd=%d, cmd=(%s)",
                buf->pfd, id);
        }
    }
    else if(nwrote == len) {
        /* wrote the whole buffer */
        udebug("         pbuf_flush: wrote  %d bytes", nwrote);

        buf->ptr = buf->base;
        len = 0;
    }
    else if(nwrote > 0) {
        /* partial write, just shift the buffer by the amount written */
        udebug("         pbuf_flush: partial write %d of %d bytes",
            nwrote, len);

        len -= nwrote;

        /* could be an overlapping copy */
        memmove(buf->base, buf->base + nwrote, len);

        buf->ptr = buf->base +len;
    }

    if(changed)
        set_fd_nonblock(buf->pfd);

    duration = time(NULL) - start;

    if(duration > 5)
        uwarn(id == NULL
                ?  "pbuf_flush(): write(%d,,%d) to decoder took %lu s"
                :  "pbuf_flush(): write(%d,,%d) to decoder took %lu s: %s",
            buf->pfd, nwrote, (unsigned long)duration, id);

    return status;

flush_timeo:
    if(changed)
        set_fd_nonblock(buf->pfd);

    uerror(id == NULL
            ?  "pbuf_flush(): write(%d,,%lu) to decoder timed-out (%lu s)"
            :  "pbuf_flush(): write(%d,,%lu) to decoder timed-out (%lu s): %s",
        buf->pfd, (unsigned long)len, (unsigned long)(time(NULL) - start), id);

    return EAGAIN;
}
void accept_new_session( int32_t fd, int16_t ev, void * arg )
{
    struct iothread * thr = (struct iothread *)arg;
    struct acceptor * a = thr->core_acceptor;

    if ( ev & EV_READ )
    {
        //
        // 接收新连接完毕后
        //
        char srchost[20];
        char dsthost[20];
        uint16_t dstport = 0;

        int32_t newfd = tcp_accept( fd, srchost, dsthost, &dstport );
        if ( newfd > 0 )
        {
            uint64_t sid = 0;
            struct session * newsession = NULL;

            set_fd_nonblock( newfd );

            newsession = (struct session *)malloc( sizeof(struct session) );
            if ( newsession == NULL )
            {
                printf("Out of memory, allocate for 'newsession' failed .\n");
                goto ACCEPT_END;
            }

            newsession->evread = event_create();
            if ( newsession->evread == NULL )
            {
                printf("Out of memory, allocate for 'newsession->evread' failed .\n");
                goto ACCEPT_END;
            }

            newsession->iobytes = 0;
            newsession->fd = newfd;

            sid = thr->key;
            sid <<= 32;
            sid += thr->index++;
            newsession->sid = sid;

#if USE_LIBEVENT
            {
                struct timeval tv = {TIMEOUT_MSECS/1000, 0};
                event_set( newsession->evread, newsession->fd, EV_READ, echoserver_process_message, newsession );
                event_base_set( thr->core_sets, newsession->evread );
                event_add( newsession->evread, &tv );
            }
#else
            event_set( newsession->evread, newsession->fd, EV_READ );
            event_set_callback( newsession->evread, echoserver_process_message, newsession );
            evsets_add( thr->core_sets, newsession->evread, TIMEOUT_MSECS );
#endif

#if __DEBUG
            printf( "Thread[%d] accept a new Client[%lld, fd:%d, '%s':%d] .\n",
                thr->key, newsession->sid, newsession->fd, dsthost, dstport );
#endif
        }

        a->holding = 0;
        pthread_mutex_unlock( &(a->lock) );
    }

ACCEPT_END :

    return;
}
void echoserver_process_message( int32_t fd, int16_t ev, void * arg )
{
    struct session * s = (struct session *)arg;

    if ( ev & EV_READ )
    {
        char buf[16384];
        int32_t readn = -1;

        readn = read( fd, buf, 16384 );
        if ( readn <= 0 )
        {
#if __DEBUG
            printf( "Client[%ld, %d] is closed, BYTES:%d, TIME:%lld .\n",
                s->sid, s->fd, s->iobytes, milliseconds() );
#endif
            //evsets_del( event_get_sets(s->evread), s->evread );
            event_destroy( s->evread );
            close( s->fd );
            free( s );

            goto PROCESS_END;
        }
        else
        {
#if __DEBUG
            printf("echoserver_process_message(ev:%d) : TIME:%lld .\n", ev, milliseconds() );
#endif
            readn = write( fd, buf, readn );
            s->iobytes += readn;
        }

#if USE_LIBEVENT
        {
            struct timeval tv = {TIMEOUT_MSECS/1000, 0};
            event_add( s->evread, &tv );
        }
#else
        evsets_add( event_get_sets(s->evread), s->evread, TIMEOUT_MSECS );
#endif
    }
    else
    {
#if __DEBUG
        printf("echoserver_process_message(ev:%d) : TIME:%lld .\n", ev, milliseconds() );
#endif
    }

PROCESS_END :
}

void accept_new_session( int32_t fd, int16_t ev, void * arg )
{
    struct iothread * thr = (struct iothread *)arg;
    struct acceptor * a = thr->core_acceptor;

    if ( ev & EV_READ )
    {
        //
        // 接收新连接完毕后
        //
        char srchost[20];
        char dsthost[20];
        uint16_t dstport = 0;

        int32_t newfd = tcp_accept( fd, srchost, dsthost, &dstport );
        if ( newfd > 0 )
        {
            uint64_t sid = 0;
            struct session * newsession = NULL;

            set_fd_nonblock( newfd );

            newsession = (struct session *)malloc( sizeof(struct session) );
            if ( newsession == NULL )
            {
                printf("Out of memory, allocate for 'newsession' failed .\n");
                goto ACCEPT_END;
            }

            newsession->evread = event_create();
            if ( newsession->evread == NULL )
            {
                printf("Out of memory, allocate for 'newsession->evread' failed .\n");
                goto ACCEPT_END;
            }

            newsession->iobytes = 0;
            newsession->fd = newfd;

            sid = thr->key;
            sid <<= 32;
            sid += thr->index++;
            newsession->sid = sid;

#if USE_LIBEVENT
            {
                struct timeval tv = {TIMEOUT_MSECS/1000, 0};
                event_set( newsession->evread, newsession->fd, EV_READ, echoserver_process_message, newsession );
                event_base_set( thr->core_sets, newsession->evread );
                event_add( newsession->evread, &tv );
            }
#else
            event_set( newsession->evread, newsession->fd, EV_READ );
            event_set_callback( newsession->evread, echoserver_process_message, newsession );
            evsets_add( thr->core_sets, newsession->evread, TIMEOUT_MSECS );
#endif

#if __DEBUG
            printf( "Thread[%d] accept a new Client[%lld, fd:%d, '%s':%d] .\n",
                thr->key, newsession->sid, newsession->fd, dsthost, dstport );
#endif
        }

        a->holding = 0;
        pthread_mutex_unlock( &(a->lock) );
    }

ACCEPT_END :
}

void trylock_accept_mutex( struct iothread * thr )
{
    struct acceptor * a = thr->core_acceptor;

    if ( pthread_mutex_trylock(&(a->lock)) == 0 )
    {
        if ( a->holding == 0 )
        {
#if USE_LIBEVENT
            event_set( a->ev_accept, a->socketfd, EV_READ, accept_new_session, thr );
            event_base_set( thr->core_sets, a->ev_accept );
            event_add( a->ev_accept, 0 );
#else
            event_set( a->ev_accept, a->socketfd, EV_READ );
            event_set_callback( a->ev_accept, accept_new_session, thr );
            evsets_add(thr->core_sets, a->ev_accept, 0 );
#endif
            a->holding = 1;
        }

        //pthread_mutex_unlock( &(a->lock) );
    }
}

void acceptor_destroy( struct acceptor * self )
{
    pthread_mutex_destroy( &(self->lock) );

    if ( self->socketfd > 0 )
    {
        close( self->socketfd );
    }

    if ( self->ev_accept != NULL )
    {
        event_destroy( self->ev_accept );
    }

    free( self );
}

struct acceptor * acceptor_create( const char * host, uint16_t port )
{
    struct acceptor * a = NULL;

    a = (struct acceptor *)malloc( sizeof(struct acceptor) );
    if ( a )
    {
        a->holding = 0;
        a->socketfd = 0;
        a->ev_accept = NULL;
        pthread_mutex_init( &(a->lock), NULL );

        a->socketfd = tcp_listen( host, port );
        if ( a->socketfd < 0 )
        {
            acceptor_destroy( a );
            return NULL;
        }

        set_fd_nonblock( a->socketfd );

        a->ev_accept = event_create();
        if ( a->ev_accept == NULL )
        {
            acceptor_destroy( a );
            return NULL;
        }
    }

    return a;
}

void * iothread_main( void * arg )
{
    struct iothread * thr = (struct iothread *)arg;

    thr->running = 1;
    while ( thr->running )
    {
        //
        // 尝试加锁
        //
        trylock_accept_mutex( thr );

        //
        // 分发IO事件
        //
        evsets_dispatch( thr->core_sets );
    }

    return (void *)0;
}

struct iothread * iothread_create( uint8_t key, struct acceptor * a )
{
    pthread_t tid;
    struct iothread * thr = NULL;

    thr = (struct iothread *)malloc( sizeof(struct iothread) );
    if ( thr )
    {
        thr->key = key;
        thr->index = 0;
        thr->core_acceptor = a;

        thr->core_sets = evsets_create();
        if ( thr->core_sets == NULL )
        {
#if __DEBUG
            printf( "out of memory, allocate for 'thr->core_sets' failed, Thread[%d] .\n", key );
#endif
            return NULL;
        }

        pthread_create( &tid, NULL, iothread_main, thr );
    }

    return thr;
}
Exemple #13
0
StateResult handle_accept(void* arg) {

    int connfd;
    sai_t client_addr;
    socklen_t caddr_sz = sizeof(client_addr);
    char ipaddr[INET_ADDRSTRLEN];
	Handler *h, *new_h;
	ClientHandler *new_ch;
	int incoming=0,i=1;

	h        = (Handler*) arg;
	incoming = kresult->data;

	while (incoming) {

		dout(2, "[%d]: %s processing event %d of %d\n", mypid, __FUNCTION__,
			i, incoming);

		if (is_nolisten) {
			dout(2, "[%d]: **** !!! I'm in NO Listen, but got request! ****\n",
				mypid);
		}

		memset(&client_addr, 0, sizeof(client_addr));
		if ((connfd = accept(listenfd, (sa_t*) &client_addr, &caddr_sz)) < 0)
		{
			if (errno == EINTR || errno == EAGAIN) {
				dout(2, "[%d]: accept got '%s'; spin again.\n", mypid,
					strerror(errno));
				return STATE_OKAY;
			}

			eout("[%d]: accept failed - [%d] %s\n", errno, strerror(errno));
		}

		if (inet_ntop(AF_INET, &client_addr.sin_addr.s_addr, ipaddr,
				INET_ADDRSTRLEN) < 0)
		{
			eout("[%d]: can't decode client ip addr.\n");
			close(connfd);
			return STATE_OKAY;
		}

		dout(2, "[%d]: got connfd %d { %s, %d }; "
			"spin up handler...\n", mypid, connfd, ipaddr, 
			ntohs(client_addr.sin_port));

		set_fd_nonblock(connfd);

		new_ch = create_clienthandler(BUF_SZ, BUF_SZ);
		new_h  = create_handler(connfd, handle_client_intro, new_ch);

		// We first write an intro to the client and then enqueue on read.

		if (kmgr->enqueue_kevent(connfd, EVFILT_WRITE,
			EV_ADD|EV_ENABLE|EV_ONESHOT, new_h) < 0)
		{
        	eout("[%d]: %s failed to enqueue kevent.\n", mypid, handle_accept);
        	return STATE_ERROR;
    	}

		incoming--; i++;
	}

	return STATE_OKAY;
}
Exemple #14
0
int main(int argc, char** argv) {
    int reqd = 0;
    int min_reqd = 2;
    int arg;
    opterr=0;
	int result;
    sai_t addr;
	char server[1024];
	char port[32];
	char prog[1024];
	char debugconf[1024];
	Handler *new_h;
	AcceptHandler *new_ah;

	init_output_api();

	snprintf(prog,1024, "%s", argv[0]);

	dout(2, "kqueuer is running...\n");

	memset(server,0,1024);
	memset(port,0,32);
	memset(prog,0,1024);
	memset(debugconf,0,1024);

    while ((arg = getopt(argc, argv, "d:s:p:")) != -1) {
        switch (arg) {
        case 's':
            if (optarg[0] == '-') {
                fprintf(stderr, "option -s has bad arg (leading '-')\n");
                usage(prog);
            }
            snprintf(server,1024,"%s",optarg);
            reqd++;
            break;
        case 'p':
            if (optarg[0] == '-') {
                fprintf(stderr, "option -p has bad arg (leading '-')\n");
                usage(prog);
            }

            snprintf(port,32,"%s",optarg);
            reqd++;
            break;
        case 'd':
            if (optarg[0] == '-') {
                fprintf(stderr, "option -d has bad arg (leading '-')\n");
                usage(prog);
            }
            snprintf(debugconf, 1024, "%s", optarg);
            break;
        case 'v':
            version(prog);
            break;
        case 'a':
            about(prog);
            break;
        case 'h':
        default:
            usage(prog);
        };
    };

    argc -= optind;
    argv += optind;

    if (min_reqd > reqd) {
        fprintf(stderr, "Missing arguments.  Try -h for more info.\n");
        exit(1);
    }

	if (debugconf[0] != '\0' && atoi(debugconf) != 0) {
		set_debug_level(atoi(debugconf));
	} else {
		set_debug_level(2); // default
	}

    memset(&addr, 0, sizeof(addr));

    if (inet_pton(AF_INET, server, &addr.sin_addr.s_addr) < 0) {
        eout("kqueuer: failed to get network addr for 192.168.0.71.\n");
        return NULL;
    }

    addr.sin_family = AF_INET;
    addr.sin_port   = htons(atoi(port));

    if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        eout("kqueuer: failed to get socket - [%d] %s\n", errno,
            strerror(errno));
        return NULL;
    }

	dout(2, "binding...\n");

    if (bind(listenfd, (sa_t*) &addr, sizeof(addr)) < 0) {
        eout("kqueuer: failed to bind - [%d] %s\n", errno,
            strerror(errno));
        return NULL;
    }

	dout(2, "listening...\n");

    if (listen(listenfd, 16) < 0) {
        eout("kqueuer: failed to listen - [%d] %s\n", errno,
            strerror(errno));
        return NULL;
    }

    int on=1;
    socklen_t onsz = sizeof(on);

    if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, onsz)<0)
    {
        eout("kqueuer: setsockopt failed - [%d] %s\n", errno,
            strerror(errno));
        return NULL;
    }

	set_fd_nonblock(listenfd);

	ppid = getpid();

	// fork

	result = rfork(RFPROC|RFNOWAIT|RFFDG);

	if (result == 0) {
		mypid = getpid();
		dout(2, "I'm the child [PID: %d] (parent: %d)\n", mypid, ppid);
	} else {
		mypid = getpid();
		dout(2, "I'm the parent [PID: %d]\n", mypid);
	}

	//
	// Both parent and child do the same thing...
	//

	is_nolisten = 0;

	kmgr = new KQueueManager();

    // Add the listenfd to the kmgr

    dout(2, "[%d]: enqueue listenfd %d\n", mypid, listenfd);

	new_ah = create_accepthandler();
	new_h  = create_handler(listenfd, handle_accept, new_ah);

    if (kmgr->enqueue_kevent(listenfd, EVFILT_READ,
            EV_ADD | EV_ENABLE, new_h) < 0)
    {
        eout("[%d]: failed to enqueue kevent.\n", mypid);
        return NULL;
    }

    // Update the kqueue
    if (kmgr->update_kqueue() < 0) {
        eout("[%d]: failed to update kqueue.\n", mypid);
        return NULL;
    }

    dout(2, "[%d]: entering main processing loop...\n", mypid);

    // Enter main processing loop

    int      nevents;
    kevent_t *cur_kevent;
	Handler  *cur_h;
	StateResult sr;

    while (1) {

        dout(2, "[%d]: waiting (blocked) on kqueue for events...\n", mypid);

        if ((nevents =
            kmgr->get_kevents(KQueueManager::KQUEUE_BLOCK)) < 0)
        {
            eout("[%d]: get_kevents failed.\n", mypid);
            return NULL;
        }

        dout(2, "[%d]: got %d kevents (is_nolisten: %d).\n", mypid, nevents,
			is_nolisten);

        // All events in this kqueue are accept events, so we can handle
        // each one in the exact same way.

        while ((cur_kevent = kmgr->get_next_kevent()) != NULL) {

			dout(2, "[%d]: process event for ident %d\n", mypid,
				cur_kevent->ident);

			kresult = cur_kevent;

			cur_h = (Handler*) cur_kevent->udata;
			sr = (cur_h->handler)(cur_h);
		}

        dout(2, "[%d]: done processing kevents.  process pevents...\n",
			mypid);

		while ((cur_h = (Handler*) kmgr->get_next_pevent()) != NULL) {
			dout(2, "[%d]: process pevent for h%d\n", mypid, cur_h->id);
			
			sr = (cur_h->handler)(cur_h);
		}

        dout(2, "[%d]: done processing pevents.  wait for more...\n",
			mypid);

    	// Update the kqueue
    	if (kmgr->update_kqueue() < 0) {
        	eout("[%d]: failed to update kqueue.\n", mypid);
        	return NULL;
    	}

		// Update the pending queue
		if (kmgr->update_pevents() < 0) {
			eout("[%d]: failed to update pending queue.\n", mypid);
			return NULL;
		}
    }

	dout(2, "[%d]: all done.  goodbye.\n", mypid);

	return NULL;
}