static void sock_handle_write(int fd, void *data) { if(!data) return; int error = 0; struct mstate_write *wstate = data; assert(fd == wstate->fd); int size_need = wstate->size - wstate->offset; int size_write = write(fd, wstate->buf + wstate->offset, size_need); debug("sock_handle_write fd %d, offset %d, size %d\n", fd, wstate->offset, wstate->size); if(size_write == -1) { warning("sock_handle_write(%s)\n", strerror(errno)); if(ignore_error(errno)) { sock_set_event(fd, SOCK_EVENT_WR); sock_register_event(fd, NULL, NULL, sock_handle_write, wstate); } else { error = 1; WPF *handle = wstate->callback; void *data = wstate->data; int res = wstate->offset; safe_free(wstate->buf); safe_free(wstate); handle(error, data, res); } return; } wstate->offset += size_write; if(wstate->offset < wstate->size) { sock_set_event(fd, SOCK_EVENT_WR); sock_register_event(fd, NULL, NULL, sock_handle_write, wstate); } else { WPF *handle = wstate->callback; void *data = wstate->data; int res = wstate->offset; safe_free(wstate->buf); safe_free(wstate); handle(0, data, res); } }
void sock_write(int fd, char *buf, int size, WPF *callback, void *data, int use_event) { int size_write; struct mstate_write *wstate = calloc(1, sizeof(*wstate)); if(wstate == NULL) { error("sock_write %s\n", strerror(errno)); abort(); } wstate->callback = callback; wstate->data = data; wstate->fd = fd; wstate->buf = calloc(1, size); /* remind to free */ memcpy(wstate->buf, buf, size); wstate->offset = 0; wstate->size = size; if(use_event) { sock_event_append(EVENT_WRITE, fd, sock_handle_write, wstate); sock_set_event(fd, SOCK_EVENT_WR); if(fd_table[fd].ops.write_handler != NULL) { debug("warning! fd %d write handler is not null\n", fd); return; } sock_register_event(fd, NULL, NULL, sock_event_run, NULL); return; } sock_handle_write(fd, wstate); }
static void sock_handle_sendfile(int fd, void *data) { int error = 0; struct fstate_write *fs = data; assert(fs->out_fd == fd); int size_need = fs->size - fs->size_sent; int size_write = sendfile(fs->out_fd, fs->in_fd, (off_t *)&fs->offset, size_need); int res = 0; if(size_write == -1) { warning("sock_handle_sendfile fd %d %s\n", fd, strerror(errno)); if(ignore_error(errno)) { sock_set_event(fd, SOCK_EVENT_WR); sock_register_event(fd, NULL, NULL, sock_handle_sendfile, fs); } else { s_error("sock_handle_sendfile fd %d %s\n", fd, strerror(errno)); error = 1; WPF *handle = fs->callback; void *data = fs->data; res = fs->size_sent; safe_free(fs); handle(error, data, res); } return; } fs->size_sent += size_write; if(fs->size_sent < fs->size) { sock_set_event(fd, SOCK_EVENT_WR); sock_register_event(fd, NULL, NULL, sock_handle_sendfile, fs); } else { WPF *handle = fs->callback; res = fs->size_sent; void *data = fs->data; safe_free(fs); handle(error, data, res); } }
void sock_close(int fd) { assert(fd_table); if(!fd_table[fd].flags.open) return; debug("sock_close fd %d\n", fd); sock_set_event(fd, SOCK_EVENT_NO); /* do not need to listen again */ fd_close(fd); close(fd); }
static int port__ctl_mod(port_state_t* port_state, SOCKET sock, struct epoll_event* ev) { sock_state_t* sock_state = port_find_socket(port_state, sock); if (sock_state == NULL) return -1; if (sock_set_event(port_state, sock_state, ev) < 0) return -1; port__update_events_if_polling(port_state); return 0; }
static int port__ctl_add(port_state_t* port_state, SOCKET sock, struct epoll_event* ev) { sock_state_t* sock_state = sock_new(port_state, sock); if (sock_state == NULL) return -1; if (sock_set_event(port_state, sock_state, ev) < 0) { sock_delete(port_state, sock_state); return -1; } port__update_events_if_polling(port_state); return 0; }
void sock_event_run(int fd, void *data) { struct fd_t *f = &fd_table[fd]; int fin = 0; struct event *e = f->wqueue; debug("sock_event_run fd %d\n", fd); if(e == NULL) { sock_set_event(fd, SOCK_EVENT_NO); return; } fin = event_exec_one(e); if( -1 == fin) { if(f->ops.write_handler == NULL) { int type = 1; sock_register_event(fd, NULL, NULL, sock_event_run, &type); } } }
void sock_init() { assert(config); if(fd_table) return; if(MAX_FD < 20240) warning("sock_init MAX_FD %d, too small\n", MAX_FD); fd_table = calloc(MAX_FD, sizeof(*fd_table)); int listen_fd = -1; assert(fd_table); sock_epoll_init(); listen_fd = sock_listen_open(); sock_set_event(listen_fd, SOCK_EVENT_RD); sock_register_event(listen_fd, http_request_accept, NULL, NULL, NULL); log_debug(__FILE__, __LINE__, "Listen port %d, fd %d\n", ntohs(config->server.port), listen_fd); }