int swFactory_dispatch(swFactory *factory, swDispatchData *task) { swServer *serv = SwooleG.serv; factory->last_from_id = task->data.info.from_id; if (swEventData_is_stream(task->data.info.type)) { swConnection *conn = swServer_connection_get(serv, task->data.info.fd); if (conn == NULL || conn->active == 0) { swWarn("dispatch[type=%d] failed, connection#%d is not active.", task->data.info.type, task->data.info.fd); return SW_ERR; } //server active close, discard data. if (conn->closed) { swWarn("dispatch[type=%d] failed, connection#%d is closed by server.", task->data.info.type, task->data.info.fd); return SW_OK; } //converted fd to session_id task->data.info.fd = conn->session_id; task->data.info.from_fd = conn->from_fd; } return swWorker_onTask(factory, &task->data); }
int swFactoryProcess_end(swFactory *factory, swDataHead *event) { swServer *serv = factory->ptr; swSendData _send; bzero(&_send, sizeof(_send)); _send.info.fd = event->fd; /** * length == 0, close the connection */ _send.info.len = 0; /** * passive or initiative */ _send.info.type = event->type; swConnection *conn = swServer_connection_get(serv, _send.info.fd); if (conn == NULL || conn->active == 0) { swWarn("can not close. Connection[%d] not found.", _send.info.fd); return SW_ERR; } if (serv->onClose != NULL) { serv->onClose(serv, event->fd, conn->from_id); } return swFactoryProcess_finish(factory, &_send); }
static int swPort_onRead_check_eof(swReactor *reactor, swListenPort *port, swEvent *event) { swServer *serv = SwooleG.serv; swConnection *conn = swServer_connection_get(serv, event->fd); swProtocol *protocol = &port->protocol; #ifdef SW_USE_OPENSSL if (swPort_check_ssl_state(port, conn) < 0) { return swReactorThread_onClose(reactor, event); } #endif if (conn->object == NULL) { conn->object = swString_new(SW_BUFFER_SIZE); //alloc memory failed. if (!conn->object) { return SW_ERR; } } if (swProtocol_recv_check_eof(protocol, conn, conn->object) < 0) { swReactorThread_onClose(reactor, event); } return SW_OK; }
/** * Close the connection */ int swFactoryProcess_end(swFactory *factory, int fd) { swServer *serv = factory->ptr; swSendData _send; bzero(&_send, sizeof(_send)); _send.info.fd = fd; _send.info.len = 0; _send.info.type = SW_EVENT_CLOSE; swConnection *conn = swServer_connection_get(serv, _send.info.fd); if (conn == NULL || conn->active == 0) { //swWarn("can not close. Connection[%d] not found.", _send.info.fd); return SW_ERR; } else if (conn->active & SW_STATE_CLOSEING) { swWarn("The connection[%d] is closeing.", fd); return SW_ERR; } else if (conn->active & SW_STATE_CLOSED) { return SW_ERR; } else { if (serv->onClose != NULL) { serv->onClose(serv, fd, conn->from_id); } conn->active |= SW_STATE_CLOSED; return swFactoryProcess_finish(factory, &_send); } }
/** * [ReactorThread] dispatch request to worker */ static int swFactoryProcess_dispatch(swFactory *factory, swDispatchData *task) { uint32_t schedule_key; uint32_t send_len = sizeof(task->data.info) + task->data.info.len; uint16_t target_worker_id; swServer *serv = SwooleG.serv; if (task->target_worker_id < 0) { schedule_key = task->data.info.fd; #ifndef SW_USE_RINGBUFFER if (SwooleTG.factory_lock_target) { if (SwooleTG.factory_target_worker < 0) { target_worker_id = swServer_worker_schedule(serv, schedule_key); SwooleTG.factory_target_worker = target_worker_id; } else { target_worker_id = SwooleTG.factory_target_worker; } } else #endif { target_worker_id = swServer_worker_schedule(serv, schedule_key); } } else { target_worker_id = task->target_worker_id; } if (swEventData_is_stream(task->data.info.type)) { swConnection *conn = swServer_connection_get(serv, task->data.info.fd); if (conn == NULL || conn->active == 0) { swWarn("dispatch[type=%d] failed, connection#%d is not active.", task->data.info.type, task->data.info.fd); return SW_ERR; } //server active close, discard data. if (conn->closed) { if (!(task->data.info.type == SW_EVENT_CLOSE && conn->close_force)) { swWarn("dispatch[type=%d] failed, connection#%d[session_id=%d] is closed by server.", task->data.info.type, task->data.info.fd, conn->session_id); return SW_OK; } } //converted fd to session_id task->data.info.fd = conn->session_id; task->data.info.from_fd = conn->from_fd; } return swReactorThread_send2worker((void *) &(task->data), send_len, target_worker_id); }
static int swPort_onRead_raw(swReactor *reactor, swListenPort *port, swEvent *event) { int ret = 0, n; swServer *serv = reactor->ptr; swDispatchData task; swConnection *conn = swServer_connection_get(serv, event->fd); #ifdef SW_USE_OPENSSL if (swPort_check_ssl_state(port, conn) < 0) { goto close_fd; } #endif n = swConnection_recv(conn, task.data.data, SW_BUFFER_SIZE, 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: goto close_fd; default: return SW_OK; } } else if (n == 0) { close_fd: swReactorThread_onClose(reactor, event); return SW_OK; } else { conn->last_time = SwooleGS->now; task.data.info.fd = event->fd; task.data.info.from_id = event->from_id; task.data.info.len = n; task.data.info.type = SW_EVENT_TCP; task.target_worker_id = -1; #ifdef SW_USE_RINGBUFFER if (serv->factory_mode == SW_MODE_PROCESS) { ret = swReactorThread_dispatch(conn, task.data.data, task.data.info.len); } else #else { ret = serv->factory.dispatch(&serv->factory, &task); } #endif return ret; } return SW_OK; }
/** * 写线程模式 */ int swFactoryThread_dispatch(swFactory *factory, swDispatchData *task) { swServer *serv = SwooleG.serv; swFactoryThread *object = factory->object; if (swEventData_is_stream(task->data.info.type)) { swConnection *conn = swServer_connection_get(serv, task->data.info.fd); if (conn == NULL || conn->active == 0) { swWarn("dispatch[type=%d] failed, connection#%d is not active.", task->data.info.type, task->data.info.fd); return SW_ERR; } //server active close, discard data. if (conn->closed) { swWarn("dispatch[type=%d] failed, connection#%d is closed by server.", task->data.info.type, task->data.info.fd); return SW_OK; } //converted fd to session_id task->data.info.fd = conn->session_id; } int mem_size = sizeof(swDataHead) + task->data.info.len + 1; char *data = sw_malloc(mem_size); if (data == NULL) { swWarn("malloc failed"); return SW_ERR; } memcpy(data, &(task->data), mem_size); data[sizeof(swDataHead) + task->data.info.len] = 0; if (swThreadPool_dispatch(&object->workers, (void *) data, 0) < 0) { swWarn("RingQueue is full"); return SW_ERR; } else { return SW_OK; } }
int swFactory_notify(swFactory *factory, swDataHead *info) { swServer *serv = factory->ptr; swConnection *conn = swServer_connection_get(serv, info->fd); if (conn == NULL || conn->active == 0) { swWarn("dispatch[type=%d] failed, connection#%d is not active.", info->type, info->fd); return SW_ERR; } //server active close, discard data. if (conn->closed) { swWarn("dispatch[type=%d] failed, connection#%d is closed by server.", info->type, info->fd); return SW_OK; } //converted fd to session_id info->fd = conn->session_id; info->from_fd = conn->from_fd; return swWorker_onTask(factory, (swEventData *) info); }
static void handshake_success(int fd) { TSRMLS_FETCH_FROM_CTX(sw_thread_ctx ? sw_thread_ctx : NULL); SwooleG.lock.lock(&SwooleG.lock); swConnection *conn = swServer_connection_get(SwooleG.serv, fd); if (conn->websocket_status == WEBSOCKET_STATUS_CONNECTION) { conn->websocket_status = WEBSOCKET_STATUS_HANDSHAKE; } SwooleG.lock.unlock(&SwooleG.lock); swTrace("\n\n\n\nconn ws status:%d\n\n\n", conn->websocket_status); if (php_sw_http_server_callbacks[3] != NULL) { swTrace("\n\n\n\nhandshake success\n\n\n"); zval *zresponse; MAKE_STD_ZVAL(zresponse); object_init_ex(zresponse, swoole_http_wsresponse_class_entry_ptr); //socket fd zend_update_property_long(swoole_http_wsresponse_class_entry_ptr, zresponse, ZEND_STRL("fd"), fd TSRMLS_CC); zval **args[1]; args[0] = &zresponse; zval *retval; if (call_user_function_ex(EG(function_table), NULL, php_sw_http_server_callbacks[3], &retval, 1, args, 0, NULL TSRMLS_CC) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "onMessage handler error"); } swTrace("===== message callback end======"); if (EG(exception)) { zend_exception_error(EG(exception), E_ERROR TSRMLS_CC); } if (retval) { zval_ptr_dtor(&retval); } } }
/** * worker: send to client */ int swFactoryProcess_finish(swFactory *factory, swSendData *resp) { int ret, sendn, count; swServer *serv = factory->ptr; int fd = resp->info.fd; //unix dgram if (resp->info.type == SW_EVENT_UNIX_DGRAM) { socklen_t len; struct sockaddr_un addr_un; int from_sock = resp->info.from_fd; addr_un.sun_family = AF_UNIX; memcpy(addr_un.sun_path, resp->sun_path, resp->sun_path_len); len = sizeof(addr_un); ret = swSendto(from_sock, resp->data, resp->info.len, 0, (struct sockaddr *) &addr_un, len); goto finish; } //UDP pacakge else if (resp->info.type == SW_EVENT_UDP || resp->info.type == SW_EVENT_UDP6) { ret = swServer_udp_send(serv, resp); goto finish; } //swQueue_data for msg queue struct { long pti; swEventData _send; } sdata; //for message queue sdata.pti = (SwooleWG.id % serv->writer_num) + 1; swConnection *conn = swServer_connection_get(serv, fd); if (conn == NULL || conn->active == 0) { swWarn("connection[%d] not found.", fd); return SW_ERR; } sdata._send.info.fd = fd; sdata._send.info.type = resp->info.type; swWorker *worker = swServer_get_worker(serv, SwooleWG.id); /** * Big response, use shared memory */ if (resp->length > 0) { int64_t wait_reactor; /** * Storage is in use right now, wait notify. */ if (worker->store.lock == 1) { worker->notify->read(worker->notify, &wait_reactor, sizeof(wait_reactor)); } swPackage_response response; response.length = resp->length; response.worker_id = SwooleWG.id; //swWarn("BigPackage, length=%d|worker_id=%d", response.length, response.worker_id); sdata._send.info.from_fd = SW_RESPONSE_BIG; sdata._send.info.len = sizeof(response); memcpy(sdata._send.data, &response, sizeof(response)); /** * Lock the worker storage */ worker->store.lock = 1; memcpy(worker->store.ptr, resp->data, resp->length); } else { //copy data memcpy(sdata._send.data, resp->data, resp->info.len); sdata._send.info.len = resp->info.len; sdata._send.info.from_fd = SW_RESPONSE_SMALL; } #if SW_REACTOR_SCHEDULE == 2 sdata._send.info.from_id = fd % serv->reactor_num; #else sdata._send.info.from_id = conn->from_id; #endif sendn = sdata._send.info.len + sizeof(resp->info); //swWarn("send: sendn=%d|type=%d|content=%s", sendn, resp->info.type, resp->data); swTrace("[Worker]input_queue[%ld]->in| fd=%d", sdata.pti, fd); for (count = 0; count < SW_WORKER_SENDTO_COUNT; count++) { if (serv->ipc_mode == SW_IPC_MSGQUEUE) { ret = serv->write_queue.in(&serv->write_queue, (swQueue_data *) &sdata, sendn); } else { int master_pipe = swWorker_get_write_pipe(serv, fd); //swWarn("send to reactor. fd=%d|pipe=%d|reactor_id=%d|reactor_pipe_num=%d", fd, master_pipe, conn->from_id, serv->reactor_pipe_num); ret = write(master_pipe, &sdata._send, sendn); #ifdef SW_WORKER_WAIT_PIPE if (ret < 0 && errno == EAGAIN) { /** * Wait pipe can be written. */ if (swSocket_wait(master_pipe, SW_WORKER_WAIT_TIMEOUT, SW_EVENT_WRITE) == SW_OK) { continue; } else { goto finish; } } #endif } //swTraceLog("wt_queue->in: fd=%d|from_id=%d|data=%s|ret=%d|errno=%d", sdata._send.info.fd, sdata._send.info.from_id, sdata._send.data, ret, errno); if (ret >= 0) { break; } else if (errno == EINTR) { continue; } else if (errno == EAGAIN) { swYield(); } else { break; } } finish: if (ret < 0) { swWarn("sendto to reactor failed. Error: %s [%d]", strerror(errno), errno); } return ret; }
static int http_onReceive(swFactory *factory, swEventData *req) { TSRMLS_FETCH_FROM_CTX(sw_thread_ctx ? sw_thread_ctx : NULL); int fd = req->info.fd; // swTrace("on receive:%s pid:%d\n", zdata, getpid()); swConnection *conn = swServer_connection_get(SwooleG.serv, fd); if(conn->websocket_status == WEBSOCKET_STATUS_HANDSHAKE) //websocket callback { zval *zdata = php_swoole_get_data(req TSRMLS_CC); swTrace("on message callback\n"); char *buf = Z_STRVAL_P(zdata); long fin = buf[0] ? 1 : 0; long opcode = buf[1] ? 1 : 0; buf+=2; zval *zresponse; MAKE_STD_ZVAL(zresponse); object_init_ex(zresponse, swoole_http_wsresponse_class_entry_ptr); //socket fd zend_update_property_long(swoole_http_wsresponse_class_entry_ptr, zresponse, ZEND_STRL("fd"), fd TSRMLS_CC); zend_update_property_long(swoole_http_wsresponse_class_entry_ptr, zresponse, ZEND_STRL("fin"), fin TSRMLS_CC); zend_update_property_long(swoole_http_wsresponse_class_entry_ptr, zresponse, ZEND_STRL("opcode"), opcode TSRMLS_CC); zend_update_property_stringl(swoole_http_wsresponse_class_entry_ptr, zresponse, ZEND_STRL("data"), buf, (Z_STRLEN_P(zdata)-2) TSRMLS_CC); zval **args[1]; args[0] = &zresponse; zval *retval; if (call_user_function_ex(EG(function_table), NULL, php_sw_http_server_callbacks[1], &retval, 1, args, 0, NULL TSRMLS_CC) == FAILURE) { zval_ptr_dtor(&zdata); php_error_docref(NULL TSRMLS_CC, E_WARNING, "onMessage handler error"); } swTrace("===== message callback end======"); if (EG(exception)) { zval_ptr_dtor(&zdata); zend_exception_error(EG(exception), E_ERROR TSRMLS_CC); } if (retval) { zval_ptr_dtor(&retval); } zval_ptr_dtor(&zdata); return SW_OK; } http_client *client = swHashMap_find_int(php_sw_http_clients, fd); if (!client) { client = http_client_new(fd TSRMLS_CC); } php_http_parser *parser = &client->parser; /** * create request and response object */ http_request_new(client TSRMLS_CC); parser->data = client; php_http_parser_init(parser, PHP_HTTP_REQUEST); zval *zdata = php_swoole_get_data(req TSRMLS_CC); //server info zval *_request; MAKE_STD_ZVAL(_request); array_init(_request); zend_update_property(swoole_http_request_class_entry_ptr, client->zrequest, ZEND_STRL("request"), _request TSRMLS_CC); size_t n = php_http_parser_execute(parser, &http_parser_settings, Z_STRVAL_P(zdata), Z_STRLEN_P(zdata)); zval_ptr_dtor(&zdata); if (n < 0) { swWarn("php_http_parser_execute failed."); if(conn->websocket_status == WEBSOCKET_STATUS_CONNECTION) { SwooleG.serv->factory.end(&SwooleG.serv->factory, fd); } } else { if(conn->websocket_status == WEBSOCKET_STATUS_CONNECTION) // need handshake { if(php_sw_http_server_callbacks[2] == NULL) { int ret = websocket_handshake(client); http_request_free(client TSRMLS_CC); if (ret == SW_ERR) { swTrace("websocket handshake error\n"); SwooleG.serv->factory.end(&SwooleG.serv->factory, fd); } else { handshake_success(fd); swTrace("websocket handshake_success\n"); return SW_OK; } return ret; } } zval *retval; zval **args[2]; zval *zrequest = client->zrequest; //server info zval *zserver; MAKE_STD_ZVAL(zserver); array_init(zserver); zend_update_property(swoole_http_request_class_entry_ptr, zrequest, ZEND_STRL("server"), zserver TSRMLS_CC); switch (parser->method) { case PHP_HTTP_GET: add_assoc_string(zserver, "REQUEST_METHOD", "GET", 1);break; case PHP_HTTP_POST: add_assoc_string(zserver, "REQUEST_METHOD", "POST", 1);break; case PHP_HTTP_HEAD: add_assoc_string(zserver, "REQUEST_METHOD", "HEAD", 1);break; case PHP_HTTP_PUT: add_assoc_string(zserver, "REQUEST_METHOD", "PUT", 1);break; case PHP_HTTP_DELETE: add_assoc_string(zserver, "REQUEST_METHOD", "DELETE", 1);break; case PHP_HTTP_PATCH: add_assoc_string(zserver, "REQUEST_METHOD", "PATCH", 1);break; /* pathological */ case PHP_HTTP_CONNECT: add_assoc_string(zserver, "REQUEST_METHOD", "CONNECT", 1);break; case PHP_HTTP_OPTIONS: add_assoc_string(zserver, "REQUEST_METHOD", "OPTIONS", 1);break; case PHP_HTTP_TRACE: add_assoc_string(zserver, "REQUEST_METHOD", "TRACE", 1);break; /* webdav */ case PHP_HTTP_COPY: add_assoc_string(zserver, "REQUEST_METHOD", "COPY", 1);break; case PHP_HTTP_LOCK: add_assoc_string(zserver, "REQUEST_METHOD", "LOCK", 1);break; case PHP_HTTP_MKCOL: add_assoc_string(zserver, "REQUEST_METHOD", "MKCOL", 1);break; case PHP_HTTP_MOVE: add_assoc_string(zserver, "REQUEST_METHOD", "MOVE", 1);break; case PHP_HTTP_PROPFIND: add_assoc_string(zserver, "REQUEST_METHOD", "PROPFIND", 1);break; case PHP_HTTP_PROPPATCH: add_assoc_string(zserver, "REQUEST_METHOD", "PROPPATCH", 1);break; case PHP_HTTP_UNLOCK: add_assoc_string(zserver, "REQUEST_METHOD", "UNLOCK", 1);break; /* subversion */ case PHP_HTTP_REPORT: add_assoc_string(zserver, "REQUEST_METHOD", "REPORT", 1);break; case PHP_HTTP_MKACTIVITY: add_assoc_string(zserver, "REQUEST_METHOD", "MKACTIVITY", 1);break; case PHP_HTTP_CHECKOUT: add_assoc_string(zserver, "REQUEST_METHOD", "CHECKOUT", 1);break; case PHP_HTTP_MERGE: add_assoc_string(zserver, "REQUEST_METHOD", "MERGE", 1);break; /* upnp */ case PHP_HTTP_MSEARCH: add_assoc_string(zserver, "REQUEST_METHOD", "MSEARCH", 1);break; case PHP_HTTP_NOTIFY: add_assoc_string(zserver, "REQUEST_METHOD", "NOTIFY", 1);break; case PHP_HTTP_SUBSCRIBE: add_assoc_string(zserver, "REQUEST_METHOD", "SUBSCRIBE", 1);break; case PHP_HTTP_UNSUBSCRIBE: add_assoc_string(zserver, "REQUEST_METHOD", "UNSUBSCRIBE", 1);break; case PHP_HTTP_NOT_IMPLEMENTED: add_assoc_string(zserver, "REQUEST_METHOD", "GET", 1);break; } // if (parser->method == PHP_HTTP_POST) // { // add_assoc_string(zserver, "REQUEST_METHOD", "POST", 1); // } // else // { // add_assoc_string(zserver, "REQUEST_METHOD", "GET", 1); // } add_assoc_stringl(zserver, "REQUEST_URI", client->request.path, client->request.path_len, 1); add_assoc_stringl(zserver, "PATH_INFO", client->request.path, client->request.path_len, 1); add_assoc_long_ex(zserver, ZEND_STRS("REQUEST_TIME"), SwooleGS->now); swConnection *conn = swServer_connection_get(SwooleG.serv, fd); add_assoc_long(zserver, "SERVER_PORT", SwooleG.serv->connection_list[conn->from_fd].addr.sin_port); add_assoc_long(zserver, "REMOTE_PORT", ntohs(conn->addr.sin_port)); add_assoc_string(zserver, "REMOTE_ADDR", inet_ntoa(conn->addr.sin_addr), 1); if (client->request.version == 101) { add_assoc_string(zserver, "SERVER_PROTOCOL", "HTTP/1.1", 1); } else { add_assoc_string(zserver, "SERVER_PROTOCOL", "HTTP/1.0", 1); } add_assoc_string(zserver, "SERVER_SOFTWARE", SW_HTTP_SERVER_SOFTWARE, 1); add_assoc_string(zserver, "GATEWAY_INTERFACE", SW_HTTP_SERVER_SOFTWARE, 1); // ZEND_SET_SYMBOL(&EG(symbol_table), "_SERVER", zserver); zval *zresponse; MAKE_STD_ZVAL(zresponse); object_init_ex(zresponse, swoole_http_response_class_entry_ptr); //socket fd zend_update_property_long(swoole_http_response_class_entry_ptr, zresponse, ZEND_STRL("fd"), client->fd TSRMLS_CC); client->zresponse = zresponse; args[0] = &zrequest; args[1] = &zresponse; int called = 0; if(conn->websocket_status == WEBSOCKET_STATUS_CONNECTION) { called = 2; } if (call_user_function_ex(EG(function_table), NULL, php_sw_http_server_callbacks[called], &retval, 2, args, 0, NULL TSRMLS_CC) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "onRequest handler error"); } if (EG(exception)) { zend_exception_error(EG(exception), E_ERROR TSRMLS_CC); } if (retval) { zval_ptr_dtor(&retval); } swTrace("======call end======\n"); if(called == 2) { handshake_success(fd); } } return SW_OK; }
static int http_request_on_header_value(php_http_parser *parser, const char *at, size_t length) { TSRMLS_FETCH_FROM_CTX(sw_thread_ctx ? sw_thread_ctx : NULL); http_client *client = parser->data; char *header_name = zend_str_tolower_dup(client->current_header_name, client->current_header_name_len); if (memcmp(header_name, ZEND_STRL("cookie")) == 0) { zval *cookie; MAKE_STD_ZVAL(cookie); array_init(cookie); zend_update_property(swoole_http_request_class_entry_ptr, client->zrequest, ZEND_STRL("cookie"), cookie TSRMLS_CC); struct { char *k; int klen; char *v; int vlen; } kv = { 0 }; char keybuf[SW_HTTP_COOKIE_KEYLEN]; char *_c = (char *) at; int n = 1; kv.k = _c; while (_c < at + length) { if (*_c == '=') { kv.v = _c + 1; kv.klen = n; n = 0; } else if (*_c == ';') { kv.vlen = n; if (kv.klen >= SW_HTTP_COOKIE_KEYLEN) { kv.klen = SW_HTTP_COOKIE_KEYLEN - 1; } memcpy(keybuf, kv.k, kv.klen - 1); keybuf[kv.klen - 1] = 0; add_assoc_stringl_ex(cookie, keybuf, kv.klen, kv.v, kv.vlen, 1); kv.k = _c + 2; n = 0; } else { n++; } _c++; } kv.vlen = n; if (kv.klen >= SW_HTTP_COOKIE_KEYLEN) { kv.klen = SW_HTTP_COOKIE_KEYLEN - 1; } memcpy(keybuf, kv.k, kv.klen - 1); keybuf[kv.klen - 1] = 0; add_assoc_stringl_ex(cookie, keybuf, kv.klen , kv.v, kv.vlen, 1); // ZEND_SET_SYMBOL(&EG(symbol_table), "_COOKIE", cookie); mergeGlobal(cookie, client->zrequest, HTTP_GLOBAL_COOKIE); } else if (memcmp(header_name, ZEND_STRL("upgrade")) == 0 && memcmp(at, ZEND_STRL("websocket")) == 0) { SwooleG.lock.lock(&SwooleG.lock); swConnection *conn = swServer_connection_get(SwooleG.serv, client->fd); if(conn->websocket_status == 0) { conn->websocket_status = WEBSOCKET_STATUS_CONNECTION; } SwooleG.lock.unlock(&SwooleG.lock); zval *header = zend_read_property(swoole_http_request_class_entry_ptr, client->zrequest, ZEND_STRL("header"), 1 TSRMLS_CC); add_assoc_stringl_ex(header, header_name, client->current_header_name_len + 1, (char *) at, length, 1); } else if (parser->method == PHP_HTTP_POST && memcmp(header_name, ZEND_STRL("content-type")) == 0 && memcmp(at, ZEND_STRL("application/x-www-form-urlencoded")) == 0) { client->request.post_form_urlencoded = 1; zval *header = zend_read_property(swoole_http_request_class_entry_ptr, client->zrequest, ZEND_STRL("header"), 1 TSRMLS_CC); add_assoc_stringl_ex(header, header_name, client->current_header_name_len + 1, (char *) at, length, 1); } else { zval *header = zend_read_property(swoole_http_request_class_entry_ptr, client->zrequest, ZEND_STRL("header"), 1 TSRMLS_CC); add_assoc_stringl_ex(header, header_name, client->current_header_name_len + 1, (char *) at, length, 1); } if (client->current_header_name_allocated) { efree(client->current_header_name); client->current_header_name_allocated = 0; } efree(header_name); return 0; }
/** * worker: send to client */ int swFactoryProcess_finish(swFactory *factory, swSendData *resp) { int ret, sendn; swServer *serv = factory->ptr; int fd = resp->info.fd; //unix dgram if (resp->info.type == SW_EVENT_UNIX_DGRAM) { socklen_t len; struct sockaddr_un addr_un; int from_sock = resp->info.from_fd; addr_un.sun_family = AF_UNIX; memcpy(addr_un.sun_path, resp->sun_path, resp->sun_path_len); len = sizeof(addr_un); ret = swSendto(from_sock, resp->data, resp->info.len, 0, (struct sockaddr *) &addr_un, len); goto finish; } //UDP pacakge else if (resp->info.type == SW_EVENT_UDP || resp->info.type == SW_EVENT_UDP6) { return swServer_udp_send(serv, resp); } //for message queue swEventData_overflow sdata; sdata.pti = (SwooleWG.id % serv->writer_num) + 1; swConnection *conn = swServer_connection_get(serv, fd); if (conn == NULL || conn->active == 0) { swWarn("connection[%d] not found.", fd); return SW_ERR; } sdata._send.info.fd = fd; sdata._send.info.type = resp->info.type; swWorker *worker = swServer_get_worker(serv, SwooleWG.id); /** * Big response, use shared memory */ if (resp->length > 0) { swPackage_response response; worker->lock.lock(&worker->lock); response.length = resp->length; response.worker_id = SwooleWG.id; //swWarn("BigPackage, length=%d|worker_id=%d", response.length, response.worker_id); sdata._send.info.from_fd = SW_RESPONSE_BIG; sdata._send.info.len = sizeof(response); memcpy(sdata._send.data, &response, sizeof(response)); memcpy(worker->send_shm, resp->data, resp->length); } else { //copy data memcpy(sdata._send.data, resp->data, resp->info.len); sdata._send.info.len = resp->info.len; sdata._send.info.from_fd = SW_RESPONSE_SMALL; } #if SW_REACTOR_SCHEDULE == 2 sdata._send.info.from_id = fd % serv->reactor_num; #else sdata._send.info.from_id = conn->from_id; #endif sendn = sdata._send.info.len + sizeof(resp->info); //swWarn("send: sendn=%d|type=%d|content=%s", sendn, resp->info.type, resp->data); swTrace("[Worker]input_queue[%ld]->in| fd=%d", sdata.pti, fd); ret = swWorker_send2reactor(&sdata, sendn, fd); finish: if (ret < 0) { swWarn("sendto to reactor failed. Error: %s [%d]", strerror(errno), errno); } return ret; }