int EpollSocket::handle_readable_event(int &epollfd, epoll_event &event, EpollSocketWatcher &socket_handler) { EpollContext *epoll_context = (EpollContext *) event.data.ptr; int fd = epoll_context->fd; int buffer_size = SS_READ_BUFFER_SIZE; char read_buffer[buffer_size]; memset(read_buffer, 0, buffer_size); int read_size = recv(fd, read_buffer, buffer_size, 0); int handle_ret = 0; if(read_size > 0) { LOG_DEBUG("read success which read size:%d", read_size); handle_ret = socket_handler.on_readable(*epoll_context, read_buffer, buffer_size, read_size); } if(read_size <= 0 /* connect close or io error*/ || handle_ret < 0) { close_and_release(epollfd, event, socket_handler); return 0; } if (handle_ret == READ_CONTINUE) { event.events = EPOLLIN | EPOLLET; } else { event.events = EPOLLOUT | EPOLLET; } epoll_ctl(epollfd, EPOLL_CTL_MOD, fd, &event); return 0; }
void* write_func(void *data) { std::unique_ptr<TaskData> tdata((TaskData*)data); int epollfd = tdata->epollfd; epoll_event event = (tdata->event); CEpollSocketWatcher &socket_handler = *(tdata->watcher); CEpollContext *epoll_context = (CEpollContext *) event.data.ptr; int fd = epoll_context->fd; LOG_DEBUG("start write data"); int ret = socket_handler.on_writeable(*epoll_context); if (ret == WRITE_CONN_CLOSE) { close_and_release(epollfd, event, socket_handler); return NULL; } if (ret == WRITE_CONN_CONTINUE) { event.events = EPOLLOUT; } else { event.events = EPOLLIN; } epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event); return NULL; }
void* read_func(void *data) { std::unique_ptr<TaskData> tdata((TaskData*)data); int epollfd = tdata->epollfd; epoll_event event = (tdata->event); CEpollSocketWatcher &socket_handler = *(tdata->watcher); CEpollContext *epoll_context = (CEpollContext *) event.data.ptr; int fd = epoll_context->fd; int ret = socket_handler.on_readable(epollfd, event); if (ret == READ_CLOSE) { close_and_release(epollfd, event, socket_handler); return NULL; } if (ret == READ_CONTINUE) { event.events = EPOLLIN; epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event); } else if (ret == READ_OVER) { // READ_OVER event.events = EPOLLOUT; epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event); } else { LOG_ERROR("unkonw ret!"); } return NULL; }
int CEpollSocket::handle_writeable_event(int epollfd, epoll_event &event, CEpollSocketWatcher &socket_handler) { CEpollContext *epoll_context = (CEpollContext *) event.data.ptr; int fd = epoll_context->fd; epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, &event); TaskData *tdata = new TaskData(); tdata->epollfd = epollfd; tdata->event = event; tdata->watcher = &socket_handler; CTask *task = new CTask(write_func, tdata); int ret = m_thread_pool->add_task(task); if (ret != 0) { LOG_WARN("add write task fail:%d, we will close connect.", ret); close_and_release(epollfd, event, socket_handler); } return ret; }
int EpollSocket::handle_writeable_event(int &epollfd, epoll_event &event, EpollSocketWatcher &socket_handler) { EpollContext *epoll_context = (EpollContext *) event.data.ptr; int fd = epoll_context->fd; LOG_DEBUG("start write data"); int ret = socket_handler.on_writeable(*epoll_context); if(ret == WRITE_CONN_CLOSE) { close_and_release(epollfd, event, socket_handler); return 0; } if (ret == WRITE_CONN_CONTINUE) { event.events = EPOLLOUT | EPOLLET; } else { event.events = EPOLLIN | EPOLLET; } epoll_ctl(epollfd, EPOLL_CTL_MOD, fd, &event); return 0; }
int EpollSocket::start_epoll(int port, EpollSocketWatcher &socket_handler, int backlog) { int sockfd = this->listen_on(port, backlog); struct epoll_event ev; int epollfd = epoll_create(10); if (epollfd == -1) { perror("epoll_create"); exit(EXIT_FAILURE); } ev.events = EPOLLIN; ev.data.fd = sockfd; if(epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, &ev) == -1) { perror("epoll_ctl: listen_sock"); exit(EXIT_FAILURE); } epoll_event events[10]; while(1) { int fds_num = epoll_wait(epollfd, events, 10, -1); if(fds_num == -1) { perror("epoll_pwait"); exit(EXIT_FAILURE); } for (int i = 0; i < fds_num; i++) { if(events[i].data.fd == sockfd) { int conn_sock = accept_socket(sockfd); setNonblocking(conn_sock); LOG_DEBUG("get accept socket which listen fd:%d, conn_sock_fd:%d", sockfd, conn_sock); EpollContext *epoll_context = new EpollContext(); epoll_context->fd = conn_sock; socket_handler.on_accept(*epoll_context); epoll_event conn_sock_ev; conn_sock_ev.events = EPOLLIN | EPOLLET; conn_sock_ev.data.ptr = epoll_context; if (epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock, &conn_sock_ev) == -1) { perror("epoll_ctl: conn_sock"); exit(EXIT_FAILURE); } } else if(events[i].events & EPOLLIN ){ // readable EpollContext *epoll_context = (EpollContext *) events[i].data.ptr; int fd = epoll_context->fd; int buffer_size = 1024; char read_buffer[buffer_size]; memset(read_buffer, 0, buffer_size); int read_size = 0; while((read_size = recv(fd, read_buffer, buffer_size, 0)) > 0) { LOG_DEBUG("read success which read size:%d", read_size); int ret = socket_handler.on_readable(*epoll_context, read_buffer, buffer_size, read_size); if(ret != 0) { close_and_release(epollfd, events[i], socket_handler); continue; } memset(read_buffer, 0, buffer_size); // reset buffer for next read } if(read_size == 0 /* connect close*/ || (read_size == -1 && errno != EAGAIN) /* io error*/) { LOG_DEBUG("read_size not normal which size:%d", read_size); close_and_release(epollfd, events[i], socket_handler); continue; } events[i].events = EPOLLOUT | EPOLLET; epoll_ctl(epollfd, EPOLL_CTL_MOD, fd, &events[i]); } else if(events[i].events & EPOLLOUT) { // writeable EpollContext *epoll_context = (EpollContext *) events[i].data.ptr; int fd = epoll_context->fd; LOG_DEBUG("start write data"); int ret = socket_handler.on_writeable(*epoll_context); if(ret != 0) { close_and_release(epollfd, events[i], socket_handler); continue; } events[i].events = EPOLLIN | EPOLLET; epoll_ctl(epollfd, EPOLL_CTL_MOD, fd, &events[i]); } else { LOG_INFO("unkonw events :%d", events[i].events); continue; } } } }