Ejemplo n.º 1
0
static void maxconns_handler(const int fd, const short which, void *arg) {
    struct timeval t = {.tv_sec = 0, .tv_usec = 10000};

    if (fd == -42 || allow_new_conns == false) {
        /* reschedule in 10ms if we need to keep polling */
        evtimer_set(&maxconnsevent, maxconns_handler, 0);
        event_base_set(main_base, &maxconnsevent);
        evtimer_add(&maxconnsevent, &t);
    } else {
        evtimer_del(&maxconnsevent);
        accept_new_conns(true);
    }
}

static bool update_event(conn *c, const int new_flags) {
    assert(c != NULL);

    
    if (c->ev_flags == new_flags)
        return true;
    pthread_t tid = pthread_self();
    if (tid == dispatcher_thread.thread_id)
    {
        struct event_base *base = c->event.ev_base;
        if (event_del(&c->event) == -1) return false;    
        event_set(&c->event, c->sfd, new_flags, master_event_handler, (void *)c);
        event_base_set(base, &c->event);
        c->ev_flags = new_flags;
        if (event_add(&c->event, 0) == -1) return false;
        return true;
    }else{
        struct event_base *base = bufferevent_get_base(c->buf_ev);
        bufferevent_free(c->buf_ev);
        c->buf_ev = bufferevent_new(c->sfd, event_handler, buf_write_callback, buf_error_callback, (void * )c);
        bufferevent_base_set(base, c->buf_ev);
        
        c->ev_flags = new_flags;
        if (bufferevent_enable(c->buf_ev, new_flags) == -1) return false;
        return true;
    }    
    //这个也得改成bufferevent的形式
/*

    event_set(&c->event, c->sfd, new_flags, event_handler, (void *)c);
    event_base_set(base, &c->event);
    event_add(&c->event, 0);


    c->buf_ev = bufferevent_new(c->sfd, event_handler, event_handler, NULL, (void * )c);
    bufferevent_base_set(base, c->buf_ev);
    bufferevent_enable(c->buf_ev, new_flags);

    c->ev_flags = new_flags;
    if (event_add(&c->event, 0) == -1) return false;
    return true;
*/
}
Ejemplo n.º 2
0
void conn_close(conn *c)
{
	assert(c != NULL);

	/* delete the event, the socket and the conn */
	event_del(&c->event);

	if (settings.verbose > 1)
		fprintf(stderr, "<%d connection closed.\n", c->sfd);

	close(c->sfd);
	accept_new_conns(true);
	conn_cleanup(c);

	/* if the connection has big buffers, just free it */
	if (c->rsize > READ_BUFFER_HIGHWAT || conn_add_to_freelist(c))
	{
		conn_free(c);
	}

	return;
}
Ejemplo n.º 3
0
//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 */
        }

}
Ejemplo n.º 4
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;
}