struct connection *connmgr_accept(int fd)
{
	struct sockaddr_in sai;
	int new_fd;
	unsigned int len = sizeof(sai);
	struct connection *c;
	long c_id;

	new_fd = accept(fd, (struct sockaddr *)&sai, &len);
	if (-1 == new_fd) {
		perror("accept");
		return NULL;
	}
	c_id = http_open_connection(new_fd);
	c = cos_map_lookup(&conn_map, c_id);
	if (NULL == c) http_close_connection(c_id);

	return c;
}
int main(void)
{
	int sfd, epfd;
	struct connection main_c;
	struct epoll_event new_evts[MAX_CONNECTIONS];

	if (unittest_http_parse(0)) return -1;

	prep_signals();

	epfd = epoll_create(MAX_CONNECTIONS);
	sfd = connmgr_create_server(8000);
	main_c.evt_id = sfd;
	event_new(epfd, &main_c);

	cos_init(NULL);

	while (1) {
		int nevts, i, accept_event = 0;

		nevts = epoll_wait(epfd, new_evts, MAX_CONNECTIONS, -1);
		if (nevts < 0) {
			perror("waiting for events");
			return -1;
		}
		for (i = 0 ; i < nevts ; i++) {
			struct epoll_event *e = &new_evts[i];
			struct connection *c = (struct connection *)e->data.ptr;

			if (c == &main_c) {
				if (e->events & (EPOLLERR | EPOLLHUP)) {
					printf("errors on the listen fd\n");
					return -1;
				}
				accept_event = 1;
			} else if (e->events & (EPOLLERR | EPOLLHUP)) {
				event_delete(epfd, c);
				close(c->evt_id);
				http_close_connection(c->conn_id);
				/* FIXME: free requests for connection */
			} else {
				int ret;

				ret = connection_event(c);
				if (ret > 0) {
					event_delete(epfd, c);
					close(c->evt_id);
					http_close_connection(c->conn_id);
				} else if (ret < 0) {
					return -1;
				}
			}
		}

		if (accept_event) {
			struct connection *c;
			c = connmgr_accept(main_c.evt_id);
			if (NULL == c) {
				printf("Not a large enough connection namespace.");
			} else {
				event_new(epfd, c);
			}
		}
	}
	return 0;
}
예제 #3
0
int main(int argc, char *argv[]) {
    struct sockaddr_in server_addr;
    struct sockaddr_in remote_addr;
    struct epoll_event ev, events[MAX_EVENTS];

    const int BUFFER_SIZE = 4096;
    char buf[BUFFER_SIZE];

    int SERVER_PORT = 10000;
    int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
    int reuseaddr = 1;

    bzero(&ev, sizeof(ev));
    int epoll_fd = epoll_create(500/*deprecated?*/);
    if (epoll_fd == -1) {
        printf("could not create epoll descriptor\n");
        return -1;
    }
    
    setnonblocking(listen_fd);
    setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr));
    memset(&server_addr, 0, sizeof(server_addr));

    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(SERVER_PORT);

    printf("binding on port %d\n", SERVER_PORT);
    if (bind(listen_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        printf("Could not bind address\n");
        return -2;
    }

    if (listen(listen_fd, 1) < 0) {
        printf("Could not listen on port\n");
        return -3;
    }

    ev.events = EPOLLIN;
    ev.data.fd = listen_fd;

    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_fd, &ev) == -1) {
        printf("Could not add listen fd to epoll descriptor\n");
        return -4;
    }

    while (1) {
        int nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
        if (nfds == -1) {
            printf("Could not wait epoll events\n");
            return -5;
        }

        for (int n = 0; n < nfds; n++) {
            if (events[n].data.fd == listen_fd) {
                socklen_t sock_len = sizeof(remote_addr);
                int client_fd = accept(listen_fd, (struct sockaddr *)&remote_addr, &sock_len);
                if (client_fd == -1) {
                    printf("Could not accept connection request\n");
                }

                //char client_ip[32];
                //inet_ntop(AF_INET, (const void *)&remote_addr.sin_addr, client_ip, sizeof(client_ip));
                //printf("Request from %s[fd:%d]\n", client_ip, client_fd);

                buffered_request_init(client_fd);

                setnonblocking(client_fd);
                setsockopt(client_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr));
                ev.events = EPOLLIN | EPOLLOUT | EPOLLET;
                ev.data.fd = client_fd;
                if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_fd, &ev) == -1) {
                    printf("Could not add new connection request to epoll descriptor\n");
                }
            } else {
                int client_fd = events[n].data.fd;
                buffered_request_t *buffered = buffered_request_for_connection(client_fd);
                static int disable_cork = 0;
                if (events[n].events & EPOLLHUP) {
                  printf("[%d]Hup Disconnected\n", client_fd);
                      setsockopt(client_fd, SOL_TCP, TCP_CORK, &disable_cork, sizeof(disable_cork));
                  http_close_connection(buffered);
                    //                    epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client_fd, &ev);                    
                    continue;
                }
                
                if (events[n].events & EPOLLIN) {
                    int read_count = buffered_request_read_all_available_data(buffered);
                    if(read_count > 0){
                      //printf("[%d]Received request:\n%s\n", client_fd, &(buffered->readbuf[buffered->readpos]));
                        
                        //TODO: handle request only if already a full request
                        http_request_t request;
                        if(http_parse_request(buffered, &request)< 0){
                          printf("failed to parse request\n");
                        }
                    
                        http_handle_request(buffered, &request);
                    }else if(read_count == 0){
                      http_close_connection(buffered);
                      //epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client_fd, &ev);                      
                      continue;
                    }
                }

                if (events[n].events & EPOLLOUT) {
                  if(!buffered_request_has_wroten_all(buffered)){
                    static int enable_cork = 1;
                    setsockopt(client_fd, SOL_TCP, TCP_CORK, &enable_cork, sizeof(enable_cork));
                    //printf("[%d]SEND response:\n%s\n", client_fd, &(buffered->writebuf[buffered->writepos]));
                    buffered_request_write_all_available_data(buffered);
                                         
                    if(buffered_request_has_wroten_all(buffered)){

                      setsockopt(client_fd, SOL_TCP, TCP_CORK, &disable_cork, sizeof(disable_cork));
                      //printf("[%d]Disconnected\n", client_fd);
                      http_close_connection(buffered);
                      //epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client_fd, &ev);
                      continue;
                      }
                    
                  }
                }

                if (events[n].events & EPOLLERR) {
                    printf("[%d] ERR Disconnected\n", client_fd);
                    setsockopt(client_fd, SOL_TCP, TCP_CORK, &disable_cork, sizeof(disable_cork));
                    http_close_connection(buffered);
                    //epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client_fd, &ev);                    
                    continue;
                }

            }
        }
    }
    return 0;
}