void EventHandler::HandleEpollEvents(uint32_t events) { if (events & EPOLLIN) { HandleReadEvent(); } else if (events & EPOLLOUT) { HandleWriteEvent(); } else { assert((events & (EPOLLHUP | EPOLLERR)) && "unknown event"); HandleErrorEvent(); } }
/*----------------------------------------------------------------------------*/ void * RunServerThread(void *arg) { int core = *(int *)arg; struct thread_context *ctx; mctx_t mctx; int listener; int ep; struct mtcp_epoll_event *events; int nevents; int i, ret; int do_accept; /* initialization */ ctx = InitializeServerThread(core); if (!ctx) { TRACE_ERROR("Failed to initialize server thread.\n"); return NULL; } mctx = ctx->mctx; ep = ctx->ep; events = (struct mtcp_epoll_event *) calloc(MAX_EVENTS, sizeof(struct mtcp_epoll_event)); if (!events) { TRACE_ERROR("Failed to create event struct!\n"); exit(-1); } listener = CreateListeningSocket(ctx); if (listener < 0) { TRACE_ERROR("Failed to create listening socket.\n"); exit(-1); } while (!done[core]) { nevents = mtcp_epoll_wait(mctx, ep, events, MAX_EVENTS, -1); if (nevents < 0) { if (errno != EINTR) perror("mtcp_epoll_wait"); break; } do_accept = FALSE; for (i = 0; i < nevents; i++) { if (events[i].data.sockid == listener) { /* if the event is for the listener, accept connection */ do_accept = TRUE; } else if (events[i].events & MTCP_EPOLLERR) { int err; socklen_t len = sizeof(err); /* error on the connection */ TRACE_APP("[CPU %d] Error on socket %d\n", core, events[i].data.sockid); if (mtcp_getsockopt(mctx, events[i].data.sockid, SOL_SOCKET, SO_ERROR, (void *)&err, &len) == 0) { if (err != ETIMEDOUT) { fprintf(stderr, "Error on socket %d: %s\n", events[i].data.sockid, strerror(err)); } } else { perror("mtcp_getsockopt"); } CloseConnection(ctx, events[i].data.sockid, &ctx->svars[events[i].data.sockid]); } else if (events[i].events & MTCP_EPOLLIN) { ret = HandleReadEvent(ctx, events[i].data.sockid, &ctx->svars[events[i].data.sockid]); if (ret == 0) { /* connection closed by remote host */ CloseConnection(ctx, events[i].data.sockid, &ctx->svars[events[i].data.sockid]); } else if (ret < 0) { /* if not EAGAIN, it's an error */ if (errno != EAGAIN) { CloseConnection(ctx, events[i].data.sockid, &ctx->svars[events[i].data.sockid]); } } } else if (events[i].events & MTCP_EPOLLOUT) { struct server_vars *sv = &ctx->svars[events[i].data.sockid]; if (sv->rspheader_sent) { SendUntilAvailable(ctx, events[i].data.sockid, sv); } else { TRACE_APP("Socket %d: Response header not sent yet.\n", events[i].data.sockid); } } else { assert(0); } } /* if do_accept flag is set, accept connections */ if (do_accept) { while (1) { ret = AcceptConnection(ctx, listener); if (ret < 0) break; } } } /* destroy mtcp context: this will kill the mtcp thread */ mtcp_destroy_context(mctx); pthread_exit(NULL); return NULL; }
/*----------------------------------------------------------------------------*/ int RunServerThread() { int ret; int server_sockfd; int client_sockfd; struct sockaddr_in my_addr; struct sockaddr_in remote_addr; int sin_size; int do_accept; int opt_val = 1; ret = anssock_init(NULL); if (ret != 0) printf("init sock failed \n"); // end initialized memset(&my_addr, 0, sizeof(my_addr)); my_addr.sin_family = AF_INET; my_addr.sin_addr.s_addr = INADDR_ANY; my_addr.sin_port = htons(8089); if ((server_sockfd = anssock_socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("socket error \n"); return 1; } if(anssock_setsockopt(server_sockfd, SOL_SOCKET, SO_REUSEPORT, &opt_val, sizeof(int)) < 0) { printf("set socket option failed \n"); } if (anssock_bind(server_sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) < 0) { printf("bind error \n"); return 1; } if (anssock_listen(server_sockfd, 2048) < 0) { printf("listen error \n"); return 1; } sin_size = sizeof(struct sockaddr_in); /* wait for incoming accept events */ /* create epoll descriptor */ int epoll_fd; epoll_fd = anssock_epoll_create(MAX_EVENTS); if (epoll_fd == -1) { printf("epoll_create failed \n"); return 1; } struct epoll_event ev; struct epoll_event events[MAX_EVENTS]; ev.events = EPOLLIN | EPOLLET; ev.data.fd = server_sockfd; if (anssock_epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_sockfd, &ev) == -1) { printf("epll_ctl:server_sockfd register failed"); anssock_close(server_sockfd); anssock_close(epoll_fd); return 1; } int nfds; struct sockaddr_in* pV4Addr = (struct sockaddr_in*)&my_addr; int ipAddr = pV4Addr->sin_addr.s_addr; char ipstr[INET_ADDRSTRLEN]; inet_ntop( AF_INET, &ipAddr, ipstr, INET_ADDRSTRLEN ); printf("open socket on ip:%s port: %d\n", ipstr, ntohs(my_addr.sin_port)); while (1) { nfds = anssock_epoll_wait(epoll_fd, events, MAX_EVENTS, -1); if (nfds == -1) { printf("start epoll_wait failed"); anssock_close(server_sockfd); anssock_close(epoll_fd); return 1; } int i; do_accept = 0; for (i = 0; i < nfds; i++) { int sockid = events[i].data.fd; if (sockid == server_sockfd) { //accept case do_accept = 1; } else { if (events[i].events & EPOLLERR) { //epoll error event int err; socklen_t len = sizeof(err); /* error on the connection */ anssock_epoll_ctl(epoll_fd, EPOLL_CTL_DEL, sockid, NULL); anssock_close(sockid); } if (events[i].events == EPOLLIN) { //epollin read and write int ret = HandleReadEvent(epoll_fd, events[i]); anssock_close(sockid); } if (events[i].events == EPOLLOUT) { //epollout write int LEN = strlen(http_200); anssock_send(sockid, http_200, LEN, 0); anssock_epoll_ctl(epoll_fd, EPOLL_CTL_DEL, sockid, NULL); anssock_close(sockid); } if (events[i].events == EPOLLHUP) { //remote close the socket anssock_epoll_ctl(epoll_fd, EPOLL_CTL_DEL, sockid, NULL); anssock_close(sockid); } } } if (do_accept) { while (1) { int c = anssock_accept(server_sockfd, NULL, NULL); if (c >= 0) { if (c >= MAX_FLOW_NUM) { printf("Invalid socket id %d.\n", c); exit(-1); } struct epoll_event ev; //accept connection and wait EPOLLIN EVENT ev.events = EPOLLIN | EPOLLET; ev.data.fd = c; anssock_epoll_ctl(epoll_fd, EPOLL_CTL_ADD, c, &ev); // printf("Socket %d registered.\n", c); } else { //c<0 /* printf("mtcp_accept() error %s\n", strerror(errno));*/ break; } } }//end if } anssock_close(server_sockfd); return 0; }
void Socket::HandleErrorEvent() { HandleReadEvent(); HandleWriteEvent(); }