SWINLINE static void swRingBuffer_collect(swRingBuffer *object) { int i; swRingBuffer_head *item; swTraceLog(SW_TRACE_MEMORY, "collect_offset=%ld, free_n=%d", object->collect_offset, object->free_n); for(i = 0; i<SW_RINGBUFFER_COLLECT_N; i++) { item = (swRingBuffer_head *) (object->memory + object->collect_offset); swTraceLog(SW_TRACE_MEMORY, "collect_offset=%d, item_length=%d, lock=%d", object->collect_offset, item->length, item->lock); //can collect if (item->lock == 0) { object->collect_offset += (sizeof(swRingBuffer_head) + item->length); if (object->free_n > 0) { object->free_n --; } if (object->collect_offset >= object->size) { object->collect_offset = 0; } } else { break; } } }
int swReactorEpoll_add(swReactor *reactor, int fd, int fdtype) { swReactorEpoll *object = reactor->object; struct epoll_event e; swFd fd_; int ret; bzero(&e, sizeof(struct epoll_event)); fd_.fd = fd; fd_.fdtype = swReactor_fdtype(fdtype); e.events = swReactorEpoll_event_set(fdtype); memcpy(&(e.data.u64), &fd_, sizeof(fd_)); ret = epoll_ctl(object->epfd, EPOLL_CTL_ADD, fd, &e); if (ret < 0) { swWarn("add event failed. Error: %s[%d]", strerror(errno), errno); return SW_ERR; } if (swReactor_add(reactor, fd, fdtype) < 0) { return SW_ERR; } swTraceLog(SW_TRACE_EVENT, "add event[reactor_id=%d|fd=%d]", reactor->id, fd); reactor->event_num++; return SW_OK; }
void swTimeWheel_forward(swTimeWheel *tw, swReactor *reactor) { swHashMap *set = tw->wheel[tw->current]; tw->current = tw->current == tw->size - 1 ? 0 : tw->current + 1; swTraceLog(SW_TRACE_REACTOR, "current=%d.", tw->current); swConnection *conn; uint64_t fd; while (1) { conn = swHashMap_each_int(set, &fd); if (conn == NULL) { break; } conn->close_force = 1; conn->close_notify = 1; conn->close_wait = 1; conn->close_actively = 1; //notify to reactor thread if (conn->removed) { reactor->close(reactor, (int) fd); } else { reactor->set(reactor, fd, SW_FD_TCP | SW_EVENT_WRITE); } } }
int swReactorEpoll_del(swReactor *reactor, int fd) { swReactorEpoll *object = reactor->object; int ret; if (fd <= 0) { return SW_ERR; } ret = epoll_ctl(object->epfd, EPOLL_CTL_DEL, fd, NULL); if (ret < 0) { swWarn("epoll remove fd[=%d] failed. Error: %s[%d]", fd, strerror(errno), errno); return SW_ERR; } if (swReactor_del(reactor, fd) < 0) { return SW_ERR; } reactor->event_num = reactor->event_num <= 0 ? 0 : reactor->event_num - 1; swTraceLog(SW_TRACE_EVENT, "remove event[reactor_id=%d|fd=%d]", reactor->id, fd); return SW_OK; }
int swReactorEpoll_del(swReactor *reactor, int fd) { swReactorEpoll *object = reactor->object; int ret; if (fd <= 0) { return SW_ERR; } ret = epoll_ctl(object->epfd, EPOLL_CTL_DEL, fd, NULL); if (ret < 0) { swWarn("epoll remove fd[=%d] failed. Error: %s[%d]", fd, strerror(errno), errno); return SW_ERR; } //close时会自动从epoll事件中移除 //swoole中未使用dup ret = close(fd); if (ret >= 0) { (reactor->event_num <= 0) ? reactor->event_num = 0 : reactor->event_num--; } swTraceLog(SW_TRACE_EVENT, "remove event[reactor_id=%d|fd=%d]", reactor->id, fd); return SW_OK; }
void swTimeWheel_add(swTimeWheel *tw, swConnection *conn) { uint16_t index = tw->current == 0 ? tw->size - 1 : tw->current - 1; swHashMap *new_set = tw->wheel[index]; swHashMap_add_int(new_set, conn->fd, conn); conn->timewheel_index = index; swTraceLog(SW_TRACE_REACTOR, "current=%d, fd=%d, index=%d.", tw->current, conn->fd, index); }
void swTimeWheel_update(swTimeWheel *tw, swConnection *conn) { uint16_t new_index = swTimeWheel_new_index(tw); swHashMap *new_set = tw->wheel[new_index]; swHashMap_add_int(new_set, conn->fd, conn); swHashMap *old_set = tw->wheel[conn->timewheel_index]; swHashMap_del_int(old_set, conn->fd); swTraceLog(SW_TRACE_REACTOR, "current=%d, fd=%d, old_index=%d, new_index=%d.", tw->current, conn->fd, new_index, conn->timewheel_index); conn->timewheel_index = new_index; }
int swReactor_add(swReactor *reactor, int fd, int fdtype) { assert (fd <= SwooleG.max_sockets); swConnection *socket = swReactor_get(reactor, fd); socket->fdtype = swReactor_fdtype(fdtype); socket->events = swReactor_events(fdtype); socket->removed = 0; swTraceLog(SW_TRACE_REACTOR, "fd=%d, type=%d, events=%d", fd, socket->socket_type, socket->events); return SW_OK; }
/** * append to buffer queue */ int swBuffer_in(swBuffer *buffer, swSendData *send_data) { swBuffer_trunk *trunk = swBuffer_new_trunk(buffer, SW_TRUNK_DATA, send_data->info.len); if (trunk == NULL) { return SW_ERR; } trunk->length = send_data->info.len; memcpy(trunk->data, send_data->data, trunk->length); swTraceLog(SW_TRACE_BUFFER, "trunk_n=%d|data_len=%d|trunk_len=%d|trunk=%p", buffer->trunk_num, send_data->info.len, trunk->length, trunk); return SW_OK; }
static int swReactorKqueue_add(swReactor *reactor, int fd, int fdtype) { swReactorKqueue *this = reactor->object; struct kevent e; swFd fd_; int ret; bzero(&e, sizeof(e)); int fflags = 0; fd_.fd = fd; fd_.fdtype = swReactor_fdtype(fdtype); swReactor_add(reactor, fd, fdtype); if (swReactor_event_read(fdtype)) { #ifdef NOTE_EOF fflags = NOTE_EOF; #endif EV_SET(&e, fd, EVFILT_READ, EV_ADD, fflags, 0, NULL); memcpy(&e.udata, &fd_, sizeof(swFd)); ret = kevent(this->epfd, &e, 1, NULL, 0, NULL); if (ret < 0) { swSysError("add events[fd=%d#%d, type=%d, events=read] failed.", fd, reactor->id, fd_.fdtype); swReactor_del(reactor, fd); return SW_ERR; } } if (swReactor_event_write(fdtype)) { EV_SET(&e, fd, EVFILT_WRITE, EV_ADD, 0, 0, NULL); memcpy(&e.udata, &fd_, sizeof(swFd)); ret = kevent(this->epfd, &e, 1, NULL, 0, NULL); if (ret < 0) { swSysError("add events[fd=%d#%d, type=%d, events=write] failed.", fd, reactor->id, fd_.fdtype); swReactor_del(reactor, fd); return SW_ERR; } } swTraceLog(SW_TRACE_EVENT, "[THREAD #%d]EP=%d|FD=%d, events=%d", SwooleTG.id, this->epfd, fd, fdtype); reactor->event_num++; return SW_OK; }
/** * append to buffer queue */ int swBuffer_append(swBuffer *buffer, void *data, uint32_t size) { swBuffer_trunk *chunk = swBuffer_new_trunk(buffer, SW_CHUNK_DATA, size); if (chunk == NULL) { return SW_ERR; } buffer->length += size; chunk->length = size; memcpy(chunk->store.ptr, data, size); swTraceLog(SW_TRACE_BUFFER, "trunk_n=%d|size=%d|trunk_len=%d|trunk=%p", buffer->trunk_num, size, chunk->length, chunk); return SW_OK; }
void php_swoole_reactor_init() { if (!SWOOLE_G(cli)) { swoole_php_fatal_error(E_ERROR, "async-io must be used in PHP CLI mode."); return; } if (SwooleG.main_reactor == NULL) { swTraceLog(SW_TRACE_PHP, "init reactor"); SwooleG.main_reactor = (swReactor *) sw_malloc(sizeof(swReactor)); if (SwooleG.main_reactor == NULL) { swoole_php_fatal_error(E_ERROR, "malloc failed."); return; } if (swReactor_create(SwooleG.main_reactor, SW_REACTOR_MAXEVENTS) < 0) { swoole_php_fatal_error(E_ERROR, "failed to create reactor."); return; } #ifdef SW_COROUTINE SwooleG.main_reactor->can_exit = php_coroutine_reactor_can_exit; #endif //client, swoole_event_exit will set swoole_running = 0 SwooleWG.in_client = 1; SwooleWG.reactor_wait_onexit = 1; SwooleWG.reactor_ready = 0; //only client side php_swoole_at_shutdown("swoole_event_wait"); } SwooleG.main_reactor->setHandle(SwooleG.main_reactor, SW_FD_USER | SW_EVENT_READ, php_swoole_event_onRead); SwooleG.main_reactor->setHandle(SwooleG.main_reactor, SW_FD_USER | SW_EVENT_WRITE, php_swoole_event_onWrite); SwooleG.main_reactor->setHandle(SwooleG.main_reactor, SW_FD_USER | SW_EVENT_ERROR, php_swoole_event_onError); SwooleG.main_reactor->setHandle(SwooleG.main_reactor, SW_FD_WRITE, swReactor_onWrite); SwooleWG.reactor_init = 1; }
void swAio_handler_stream_get_line(swAio_event *event) { int ret = -1; if (flock(event->fd, LOCK_SH) < 0) { swSysError("flock(%d, LOCK_SH) failed.", event->fd); event->ret = -1; event->error = errno; return; } off_t readpos = event->offset; off_t writepos = (long) event->req; size_t avail = 0; char *eol; char *tmp; char *read_buf = event->buf; int read_n = event->nbytes; while (1) { avail = writepos - readpos; swTraceLog(SW_TRACE_AIO, "readpos=%ld, writepos=%ld", (long)readpos, (long)writepos); if (avail > 0) { tmp = event->buf + readpos; eol = find_eol(tmp, avail); if (eol) { event->buf = tmp; event->ret = (eol - tmp) + 1; readpos += event->ret; goto _return; } else if (readpos == 0) { if (writepos == event->nbytes) { writepos = 0; event->ret = event->nbytes; goto _return; } else { event->flags = SW_AIO_EOF; ((char*) event->buf)[writepos] = '\0'; event->ret = writepos; writepos = 0; goto _return; } } else { memmove(event->buf, event->buf + readpos, avail); writepos = avail; read_buf = event->buf + writepos; read_n = event->nbytes - writepos; readpos = 0; goto _readfile; } } else { _readfile: while (1) { ret = read(event->fd, read_buf, read_n); if (ret < 0 && (errno == EINTR || errno == EAGAIN)) { continue; } break; } if (ret > 0) { writepos += ret; } else if (ret == 0) { event->flags = SW_AIO_EOF; if (writepos > 0) { event->ret = writepos; } else { ((char*) event->buf)[0] = '\0'; event->ret = 0; } readpos = writepos = 0; goto _return; } } } _return: if (flock(event->fd, LOCK_UN) < 0) { swSysError("flock(%d, LOCK_UN) failed.", event->fd); } event->offset = readpos; event->req = (void *) (long) writepos; }
static int swReactorKqueue_set(swReactor *reactor, int fd, int fdtype) { swReactorKqueue *this = reactor->object; struct kevent e; swFd fd_; int ret; bzero(&e, sizeof(e)); int fflags = 0; fd_.fd = fd; fd_.fdtype = swReactor_fdtype(fdtype); if (swReactor_event_read(fdtype)) { #ifdef NOTE_EOF fflags = NOTE_EOF; #endif EV_SET(&e, fd, EVFILT_READ, EV_ADD, fflags, 0, NULL); memcpy(&e.udata, &fd_, sizeof(swFd)); ret = kevent(this->epfd, &e, 1, NULL, 0, NULL); if (ret < 0) { swSysError("kqueue->set(%d, SW_EVENT_READ) failed.", fd); return SW_ERR; } } else { EV_SET(&e, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL); memcpy(&e.udata, &fd_, sizeof(swFd)); ret = kevent(this->epfd, &e, 1, NULL, 0, NULL); if (ret < 0) { swSysError("kqueue->del(%d, SW_EVENT_READ) failed.", fd); return SW_ERR; } } if (swReactor_event_write(fdtype)) { EV_SET(&e, fd, EVFILT_WRITE, EV_ADD, 0, 0, NULL); memcpy(&e.udata, &fd_, sizeof(swFd)); ret = kevent(this->epfd, &e, 1, NULL, 0, NULL); if (ret < 0) { swSysError("kqueue->set(%d, SW_EVENT_WRITE) failed.", fd); return SW_ERR; } } else { EV_SET(&e, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL); memcpy(&e.udata, &fd_, sizeof(swFd)); ret = kevent(this->epfd, &e, 1, NULL, 0, NULL); if (ret < 0) { swSysError("kqueue->del(%d, SW_EVENT_WRITE) failed.", fd); return SW_ERR; } } swTraceLog(SW_TRACE_EVENT, "[THREAD #%d]EP=%d|FD=%d, events=%d", SwooleTG.id, this->epfd, fd, fdtype); //execute parent method swReactor_set(reactor, fd, fdtype); return SW_OK; }
static void* swRingBuffer_alloc(swMemoryPool *pool, uint32_t size) { swRingBuffer *object = pool->object; swRingBuffer_head *item; size_t n; uint8_t try_collect = 0; void *ret_mem = NULL; swTraceLog(SW_TRACE_MEMORY, "[0] alloc_offset=%ld|collect_offset=%ld", object->alloc_offset, object->collect_offset); start_alloc: if (object->alloc_offset < object->collect_offset) { head_alloc: item = object->memory + object->alloc_offset; /** * 剩余内存的长度 */ n = object->collect_offset - object->alloc_offset; /** * 剩余内存可供本次分配,必须是>size */ if ((n - sizeof(swRingBuffer_head)) > size) { goto do_alloc; } /** * 内存不足,已尝试回收过 */ else if (try_collect == 1) { swWarn("alloc_offset=%ld|collect_offset=%ld", object->alloc_offset, object->collect_offset); return NULL; } //try collect memory, then try head_alloc else { try_collect = 1; swRingBuffer_collect(object); goto start_alloc; } } else { //tail_alloc: n = object->size - object->alloc_offset; item = object->memory + object->alloc_offset; swTraceLog(SW_TRACE_MEMORY, "[1] size=%ld, ac_size=%d, n_size=%ld", object->size, size, n); if ((n - sizeof(swRingBuffer_head)) >= size) { goto do_alloc; } else { //unlock item->lock = 0; item->length = n - sizeof(swRingBuffer_head); //goto head object->alloc_offset = 0; swTraceLog(SW_TRACE_MEMORY, "switch to head_alloc. ac_size=%d, n_size=%ld", size, n); goto head_alloc; } } do_alloc: item->lock = 1; item->length = size; ret_mem = (void*) (object->memory + object->alloc_offset + sizeof(swRingBuffer_head)); /** * 内存游标向后移动 */ object->alloc_offset += size + sizeof(swRingBuffer_head); if (object->free_n > 0) { swRingBuffer_collect(object); } return ret_mem; }
static int swReactorKqueue_wait(swReactor *reactor, struct timeval *timeo) { swEvent event; swFd fd_; swReactorKqueue *object = reactor->object; swReactor_handle handle; int i, n, ret; struct timespec t; struct timespec *t_ptr; bzero(&t, sizeof(t)); if (reactor->timeout_msec == 0) { if (timeo == NULL) { reactor->timeout_msec = -1; } else { reactor->timeout_msec = timeo->tv_sec * 1000 + timeo->tv_usec / 1000; } } reactor->start = 1; while (reactor->running > 0) { if (reactor->onBegin != NULL) { reactor->onBegin(reactor); } if (reactor->timeout_msec > 0) { t.tv_sec = reactor->timeout_msec / 1000; t.tv_nsec = (reactor->timeout_msec - t.tv_sec * 1000) * 1000; t_ptr = &t; } else { t_ptr = NULL; } n = kevent(object->epfd, NULL, 0, object->events, object->event_max, t_ptr); if (n < 0) { swTrace("kqueue error.EP=%d | Errno=%d\n", object->epfd, errno); if (swReactor_error(reactor) < 0) { swWarn("Kqueue[#%d] Error: %s[%d]", reactor->id, strerror(errno), errno); return SW_ERR; } else { continue; } } else if (n == 0) { if (reactor->onTimeout != NULL) { reactor->onTimeout(reactor); } continue; } for (i = 0; i < n; i++) { swTraceLog(SW_TRACE_EVENT, "n %d events.", n); if (object->events[i].udata) { memcpy(&fd_, &(object->events[i].udata), sizeof(fd_)); event.fd = fd_.fd; event.from_id = reactor->id; event.type = fd_.fdtype; event.socket = swReactor_get(reactor, event.fd); //read if (object->events[i].filter == EVFILT_READ) { if (event.socket->removed) { continue; } handle = swReactor_getHandle(reactor, SW_EVENT_READ, event.type); ret = handle(reactor, &event); if (ret < 0) { swSysError("kqueue event read socket#%d handler failed.", event.fd); } } //write else if (object->events[i].filter == EVFILT_WRITE) { if (event.socket->removed) { continue; } handle = swReactor_getHandle(reactor, SW_EVENT_WRITE, event.type); ret = handle(reactor, &event); if (ret < 0) { swSysError("kqueue event write socket#%d handler failed.", event.fd); } } else { swWarn("unknown event filter[%d].", object->events[i].filter); } } } if (reactor->onFinish != NULL) { reactor->onFinish(reactor); } if (reactor->once) { break; } } return 0; }
void swTimeWheel_remove(swTimeWheel *tw, swConnection *conn) { swHashMap *set = tw->wheel[conn->timewheel_index]; swHashMap_del_int(set, conn->fd); swTraceLog(SW_TRACE_REACTOR, "current=%d, fd=%d.", tw->current, conn->fd); }
static sw_inline int swProtocol_split_package_by_eof(swProtocol *protocol, swConnection *conn, swString *buffer) { #ifdef SW_LOG_TRACE_OPEN static int count; count++; #endif int eof_pos; if (buffer->length - buffer->offset < protocol->package_eof_len) { eof_pos = -1; } else { eof_pos = swoole_strnpos(buffer->str + buffer->offset, buffer->length - buffer->offset, protocol->package_eof, protocol->package_eof_len); } swTraceLog(SW_TRACE_EOF_PROTOCOL, "#[0] count=%d, length=%ld, size=%ld, offset=%ld.", count, buffer->length, buffer->size, (long)buffer->offset); //waiting for more data if (eof_pos < 0) { buffer->offset = buffer->length - protocol->package_eof_len; return SW_CONTINUE; } uint32_t length = buffer->offset + eof_pos + protocol->package_eof_len; swTraceLog(SW_TRACE_EOF_PROTOCOL, "#[4] count=%d, length=%d", count, length); if (protocol->onPackage(conn, buffer->str, length) < 0) { return SW_CLOSE; } if (conn->removed) { return SW_OK; } //there are remaining data if (length < buffer->length) { uint32_t remaining_length = buffer->length - length; char *remaining_data = buffer->str + length; swTraceLog(SW_TRACE_EOF_PROTOCOL, "#[5] count=%d, remaining_length=%d", count, remaining_length); while (1) { if (remaining_length < protocol->package_eof_len) { goto wait_more_data; } eof_pos = swoole_strnpos(remaining_data, remaining_length, protocol->package_eof, protocol->package_eof_len); if (eof_pos < 0) { wait_more_data: swTraceLog(SW_TRACE_EOF_PROTOCOL, "#[1] count=%d, remaining_length=%d, length=%d", count, remaining_length, length); memmove(buffer->str, remaining_data, remaining_length); buffer->length = remaining_length; buffer->offset = 0; #ifdef SW_USE_OPENSSL if (conn->ssl) { return SW_CONTINUE; } else #endif { return SW_OK; } } else { length = eof_pos + protocol->package_eof_len; if (protocol->onPackage(conn, remaining_data, length) < 0) { return SW_CLOSE; } if (conn->removed) { return SW_OK; } swTraceLog(SW_TRACE_EOF_PROTOCOL, "#[2] count=%d, remaining_length=%d, length=%d", count, remaining_length, length); remaining_data += length; remaining_length -= length; } } } swTraceLog(SW_TRACE_EOF_PROTOCOL, "#[3] length=%ld, size=%ld, offset=%ld", buffer->length, buffer->size, (long)buffer->offset); swString_clear(buffer); #ifdef SW_USE_OPENSSL if (conn->ssl) { return SW_CONTINUE; } #endif return SW_OK; }
/** * For Http Protocol */ static int swPort_onRead_http(swReactor *reactor, swListenPort *port, swEvent *event) { swConnection *conn = event->socket; swServer *serv = reactor->ptr; if (conn->websocket_status >= WEBSOCKET_STATUS_HANDSHAKE) { if (conn->http_upgrade == 0) { swHttpRequest_free(conn); conn->websocket_status = WEBSOCKET_STATUS_ACTIVE; conn->http_upgrade = 1; } return swPort_onRead_check_length(reactor, port, event); } #ifdef SW_USE_HTTP2 if (conn->http2_stream) { _parse_frame: return swPort_onRead_check_length(reactor, port, event); } #endif int n = 0; char *buf; int buf_len; swHttpRequest *request = NULL; swProtocol *protocol = &port->protocol; //new http request if (conn->object == NULL) { request = sw_malloc(sizeof(swHttpRequest)); bzero(request, sizeof(swHttpRequest)); conn->object = request; } else { request = (swHttpRequest *) conn->object; } if (!request->buffer) { request->buffer = swString_new(SW_HTTP_HEADER_MAX_SIZE); //alloc memory failed. if (!request->buffer) { swReactorThread_onClose(reactor, event); return SW_ERR; } } swString *buffer = request->buffer; recv_data: buf = buffer->str + buffer->length; buf_len = buffer->size - buffer->length; n = swConnection_recv(conn, buf, buf_len, 0); if (n < 0) { switch (swConnection_error(errno)) { case SW_ERROR: swSysError("recv from connection#%d failed.", event->fd); return SW_OK; case SW_CLOSE: conn->close_errno = errno; goto close_fd; default: return SW_OK; } } else if (n == 0) { close_fd: swHttpRequest_free(conn); swReactorThread_onClose(reactor, event); return SW_OK; } else { buffer->length += n; if (request->method == 0 && swHttpRequest_get_protocol(request) < 0) { if (request->excepted == 0 && request->buffer->length < SW_HTTP_HEADER_MAX_SIZE) { return SW_OK; } swoole_error_log(SW_LOG_TRACE, SW_ERROR_HTTP_INVALID_PROTOCOL, "get protocol failed."); #ifdef SW_HTTP_BAD_REQUEST_TIP if (swConnection_send(conn, SW_STRL(SW_HTTP_BAD_REQUEST_TIP), 0) < 0) { swSysError("send() failed."); } #endif goto close_fd; } if (request->method > HTTP_PRI) { swWarn("method no support"); goto close_fd; } #ifdef SW_USE_HTTP2 else if (request->method == HTTP_PRI) { conn->http2_stream = 1; swHttp2_send_setting_frame(protocol, conn); if (n == sizeof(SW_HTTP2_PRI_STRING) - 1) { swHttpRequest_free(conn); return SW_OK; } swString *buffer = swServer_get_buffer(serv, event->fd); if (!buffer) { goto close_fd; } swString_append_ptr(buffer, buf + (sizeof(SW_HTTP2_PRI_STRING) - 1), n - (sizeof(SW_HTTP2_PRI_STRING) - 1)); swHttpRequest_free(conn); conn->skip_recv = 1; goto _parse_frame; } #endif //http header is not the end if (request->header_length == 0) { if (swHttpRequest_get_header_length(request) < 0) { if (buffer->size == buffer->length) { swWarn("[2]http header is too long."); goto close_fd; } else { goto recv_data; } } } //http body if (request->content_length == 0) { swTraceLog(SW_TRACE_SERVER, "content-length=%u, keep-alive=%d", request->content_length, request->keep_alive); // content length field not found if (swHttpRequest_get_header_info(request) < 0) { /* the request is really no body */ if (buffer->length == request->header_length) { /** * send static file content directly in the reactor thread */ if (!(serv->enable_static_handler && swPort_http_static_handler(request, conn))) { /** * dynamic request, dispatch to worker */ swReactorThread_dispatch(conn, buffer->str, buffer->length); } swHttpRequest_free(conn); return SW_OK; } else if (buffer->size == buffer->length) { swWarn("[0]http header is too long."); goto close_fd; } /* wait more data */ else { goto recv_data; } } else if (request->content_length > (protocol->package_max_length - request->header_length)) { swWarn("Content-Length is too big, MaxSize=[%d].", protocol->package_max_length - request->header_length); goto close_fd; } } //total length uint32_t request_size = request->header_length + request->content_length; if (request_size > buffer->size && swString_extend(buffer, request_size) < 0) { goto close_fd; } //discard the redundant data if (buffer->length > request_size) { buffer->length = request_size; } if (buffer->length == request_size) { swReactorThread_dispatch(conn, buffer->str, buffer->length); swHttpRequest_free(conn); } else { #ifdef SW_HTTP_100_CONTINUE //Expect: 100-continue if (swHttpRequest_has_expect_header(request)) { swSendData _send; _send.data = "HTTP/1.1 100 Continue\r\n\r\n"; _send.length = strlen(_send.data); int send_times = 0; direct_send: n = swConnection_send(conn, _send.data, _send.length, 0); if (n < _send.length) { _send.data += n; _send.length -= n; send_times++; if (send_times < 10) { goto direct_send; } else { swWarn("send http header failed"); } } } else { swTrace("PostWait: request->content_length=%d, buffer->length=%zd, request->header_length=%d\n", request->content_length, buffer->length, request->header_length); } #endif goto recv_data; } } return SW_OK; }