예제 #1
0
connector *connector_new(struct sockaddr *sa, int socklen, rpc_cb_func rpc)
{
    connector *cr = (connector *)malloc(sizeof(connector));
    if (NULL == cr) {
        mfatal("connector alloc failed!");
        return NULL;
    }

    cr->sa = (struct sockaddr *)malloc(socklen);
    if (NULL == cr->sa) {
        mfatal("sockaddr alloc failed!");
        free(cr);
        return NULL;
    }

    cr->cb.rpc = rpc;
    cr->state = STATE_NOT_CONNECTED;
    cr->c = NULL;
    memcpy(cr->sa, sa, socklen);
    cr->socklen = socklen;
    snprintf(cr->addrtext, 32, "%s:%d",
            inet_ntoa(((struct sockaddr_in *)(cr->sa))->sin_addr),
            ntohs(((struct sockaddr_in *)(cr->sa))->sin_port));
    cr->timer = NULL;
    dispatch_conn_new(-1, 't', cr);
    return cr;
}
예제 #2
0
void signal_cb(evutil_socket_t fd, short what, void *arg)
{
    mdebug("signal_cb");
    struct event_base *base = (struct event_base *)arg;
    event_base_loopbreak(base);
    dispatch_conn_new(-1, 'k', NULL);
}
예제 #3
0
파일: vr_master.c 프로젝트: vipshop/vire
static void
client_accept(aeEventLoop *el, int fd, void *privdata, int mask) {
    int sd;
    vr_listen *vlisten = privdata;

    while((sd = vr_listen_accept(vlisten)) > 0) {
        dispatch_conn_new(vlisten, sd);
    }
}
예제 #4
0
/*
 * Wait continously for events.  We exit only if no events are left.
 */
void
event_dispatch_loop(int listenfd)
{
    int connfd;
    printf("======waiting for client's request======\n");
    while(1){
        if( (connfd = accept(listenfd, (struct sockaddr*)NULL, NULL)) == -1){
            perror("accept");
            continue;
        }
        
        dispatch_conn_new(connfd, conn_new_cmd, EV_READ | EV_PERSIST,
                          DATA_BUFFER_SIZE, tcp_transport);
        
        //close(connfd);
    }
}
예제 #5
0
파일: threadsay.c 프로젝트: wadee/go_proj
//void drive_machine(conn* c){
//改成bufferevent之后event_handler和drive_machine都不能幸免需要改参数
void drive_machine(conn* c, struct bufferevent * incoming){
    assert(c != NULL);
    // 真正的处理函数,根据不同的conn的状态来进行不同的处理。
    // 虽然我做这个demo只是把消息回显而已,但貌似这么多种状态还是得处理。
    bool stop = false;
    int sfd;

    socklen_t addrlen;
    struct sockaddr_storage addr;
    struct evbuffer *evreturn;
    char *req;

    while(!stop){
        switch(c->state){
            case conn_listening:
                //如果是listenting状态,则需要把连接accept
                addrlen = sizeof(addr);
                sfd = accept(c->sfd, (struct sockaddr *)&addr, &addrlen);
                if (sfd == -1)
                {
                    // accept错误
                    perror("sfd accept failed");
                    accept_new_conns(false); //用来决定主线程是否还需要accept连接,如果已经接近饱和了,就停住,等一个时间间隔再来试。
                    stop = true;
                }
                //分派conn任务
                dispatch_conn_new(sfd, conn_new_cmd, EV_READ | EV_PERSIST,
                                     DATA_BUFFER_SIZE, tcp_transport);
                stop = true;
                break;
            case conn_new_cmd:
                /* fall through */
            case conn_read:
                /*  now try reading from the socket */
                req = evbuffer_readline(incoming->input); 
                if (req == NULL){
                    //conn_set_state(c, conn_closing);
                    //goto set_conn_closing;
                    conn_set_state(c, conn_waiting);
                    break;    
                }
                if(c->req != NULL){
                    free(c->req);
                    c->req = NULL;
                }
                c->req = req;
                conn_set_state(c, conn_mwrite);
		//if (!update_event(c, EV_WRITE | EV_PERSIST)){
		//	printf("conn_read update event failed");
		//	goto set_conn_closing;
		//}
		//stop = true;
		//stop = true;
                break;
                //evreturn = evbuffer_new();
                //evbuffer_add_printf(evreturn, "You said %s\n", req);
               // bufferevent_write_buffer(incoming, evreturn);
                //evbuffer_free(evreturn);
                //free(req);

            set_conn_closing: 
                conn_set_state(c, conn_closing);
                break;
            case conn_mwrite:
                //所有的回复到在这个函数进行输出
                req = c->req;
                evreturn = evbuffer_new();
	//	bufferevent_setwatermark(incoming, EV_WRITE, 0, 0);
               int res1 =  evbuffer_add_printf(evreturn, "You said %s\n", req);
               int res2 =  bufferevent_write_buffer(incoming, evreturn);
//		int res3 = bufferevent_flush(incoming, EV_WRITE, BEV_FLUSH);
		int res4 = evbuffer_get_length(incoming->output);
                evbuffer_free(evreturn);
                free(req);
		evreturn = NULL;
		//int fd = (int)bufferevent_getfd(incoming);
		//char buf[20];
		//
		//sprintf(buf, "You said %s\n", req);
		//write(fd, buf, 11);
                c->req = NULL;
                conn_set_state(c,conn_waiting);
		stop = true;
                break;
            case conn_waiting:
                if (!update_event(c, EV_READ | EV_PERSIST)) {
                    fprintf(stderr, "Couldn't update event\n");
                    conn_set_state(c, conn_closing);
                    break;
                }
                conn_set_state(c, conn_read);
                stop = true;
                break;
            case conn_closing:
                conn_close(c);
                stop = true;
                break;
            }
                /* otherwise we have a real error, on which we close the connection */
        }

}
예제 #6
0
void drive_machine(conn *c)
{
	bool stop = false;
	int sfd, flags = 1;
	socklen_t addrlen;
	struct sockaddr_storage addr;
	struct linger ling =
	{ 1, 0 };
	int res;

	assert(c != NULL);

	while (!stop)
	{

		switch (c->state)
		{
			case conn_listening:
				addrlen = sizeof(addr);
				if ((sfd = accept(c->sfd, (struct sockaddr *) &addr, &addrlen)) == -1)
				{
					if (errno == EAGAIN || errno == EWOULDBLOCK)
					{
						/* these are transient, so don't log anything */
						stop = true;
					}
					else
						if (errno == EMFILE)
						{
							if (settings.verbose > 0)
								fprintf(stderr, "Too many open connections\n");
							accept_new_conns(false);
							stop = true;
						}
						else
						{
							perror("accept()");
							stop = true;
						}
					break;
				}
				if ((flags = fcntl(sfd, F_GETFL, 0)) < 0
						|| fcntl(sfd, F_SETFL, flags | O_NONBLOCK) < 0)
				{
					perror("setting O_NONBLOCK");
					close(sfd);
					break;
				}
				DEBUG_LOGGER(dsmplog, "accept new socket[%d], wait for request", sfd);
				setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void *) &flags,
						sizeof(flags));
				setsockopt(sfd, SOL_SOCKET, SO_LINGER, (void *) &ling, sizeof(ling));
				dispatch_conn_new(sfd, conn_read, EV_READ | EV_PERSIST,
						DATA_BUFFER_SIZE, false);
				break;

			case conn_read:
				//DEBUG_LOGGER(dsmplog, "-------------socket [%d] has incoming data-------------", c->sfd);
				if (try_read_cli(c))
				{ //数据处理完毕,可以读取下一个请求包
					continue;
				}
				if (try_read_tcp(c))
				{
					continue;
				}
				/* we have no command line and no data to read from network */
				if (!update_event(c, EV_READ | EV_PERSIST))
				{
					if (settings.verbose > 0)
						fprintf(stderr, "Couldn't update event\n");
					conn_set_state(c, conn_closing);
					break;
				}
				stop = true;
				break;

			case conn_closing:
				if (c->udp)
					conn_cleanup(c);
				else
					conn_close(c);
				stop = true;
				break;
		}
	}

	return;
}
예제 #7
0
static int server_socket(const int port, const bool is_udp)
{
	int sfd;
	struct linger ling =
	{ 0, 0 };
	struct addrinfo *ai;
	struct addrinfo *next;
	struct addrinfo hints;
	char port_buf[NI_MAXSERV];
	int error;
	int success = 0;

	int flags = 1;

	/*
	 * the memset call clears nonstandard fields in some impementations
	 * that otherwise mess things up.
	 */
	memset(&hints, 0, sizeof(hints));
	hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
	if (is_udp)
	{
		hints.ai_protocol = IPPROTO_UDP;
		hints.ai_socktype = SOCK_DGRAM;
		hints.ai_family = AF_INET; /* This left here because of issues with OSX 10.5 */
	}
	else
	{
		hints.ai_family = AF_UNSPEC;
		hints.ai_protocol = IPPROTO_TCP;
		hints.ai_socktype = SOCK_STREAM;
	}

	snprintf(port_buf, NI_MAXSERV, "%d", port);
	error = getaddrinfo(settings.inter, port_buf, &hints, &ai);
	if (error != 0)
	{
		if (error != EAI_SYSTEM)
			fprintf(stderr, "getaddrinfo(): %s\n", gai_strerror(error));
		else
			perror("getaddrinfo()");

		return 1;
	}

	for (next = ai; next; next = next->ai_next)
	{
		conn *listen_conn_add;
		if ((sfd = new_socket(next)) == -1)
		{
			freeaddrinfo(ai);
			return 1;
		}

		setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void *) &flags, sizeof(flags));
		if (is_udp)
		{
			maximize_sndbuf(sfd);
		}
		else
		{
			setsockopt(sfd, SOL_SOCKET, SO_KEEPALIVE, (void *) &flags, sizeof(flags));
			setsockopt(sfd, SOL_SOCKET, SO_LINGER, (void *) &ling, sizeof(ling));
			setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (void *) &flags, sizeof(flags));
		}

		if (bind(sfd, next->ai_addr, next->ai_addrlen) == -1)
		{
			if (errno != EADDRINUSE)
			{
				perror("bind()");
				close(sfd);
				freeaddrinfo(ai);
				return 1;
			}
			close(sfd);
			continue;
		}
		else
		{
			success++;
			if (!is_udp && listen(sfd, 1024) == -1)
			{
				perror("listen()");
				close(sfd);
				freeaddrinfo(ai);
				return 1;
			}
		}

		if (is_udp)
		{
			int c;

			for (c = 0; c < settings.num_threads; c++)
			{
				/* this is guaranteed to hit all threads because we round-robin */
				dispatch_conn_new(sfd, conn_read, EV_READ | EV_PERSIST,
						UDP_READ_BUFFER_SIZE, 1);
			}
		}
		else
		{
			if (!(listen_conn_add = conn_new(sfd, conn_listening,
					EV_READ | EV_PERSIST, 1, false, main_base)))
			{
				fprintf(stderr, "failed to create listening connection\n");
				exit (EXIT_FAILURE);
			}

			listen_conn_add->next = listen_conn;
			listen_conn = listen_conn_add;
		}
	}

	freeaddrinfo(ai);

	/* Return zero iff we detected no errors in starting up connections */
	return success == 0;
}