/** * Send data to ReactorThread */ int swWorker_send2reactor(swEventData *ev_data, size_t sendn, int fd) { int ret; swServer *serv = SwooleG.serv; /** * reactor_id: The fd in which the reactor. */ int reactor_id = ev_data->info.from_id; int pipe_index = fd % serv->reactor_pipe_num; /** * pipe_worker_id: The pipe in which worker. */ int pipe_worker_id = reactor_id + (pipe_index * serv->reactor_num); swWorker *worker = swServer_get_worker(serv, pipe_worker_id); if (SwooleG.main_reactor) { ret = SwooleG.main_reactor->write(SwooleG.main_reactor, worker->pipe_worker, ev_data, sendn); } else { ret = swSocket_write_blocking(worker->pipe_worker, ev_data, sendn); } return ret; }
static int swFactoryThread_finish(swFactory *factory, swSendData *_send) { swServer *serv = SwooleG.serv; uint32_t session_id = _send->info.fd; if (_send->length == 0) { _send->length = _send->info.len; } swConnection *conn = swServer_connection_verify(serv, session_id); if (!conn) { if (_send->info.type == SW_EVENT_TCP) { swWarn("send %d byte failed, session#%d is closed.", _send->length, session_id); } else { swWarn("send [%d] failed, session#%d is closed.", _send->info.type, session_id); } return SW_ERR; } return swSocket_write_blocking(conn->fd, _send->data, _send->length); }
int swWorker_send2worker(swWorker *dst_worker, uint16_t is_master, void *buf, int n) { int pipefd, ret; pipefd = is_master ? dst_worker->pipe_master : dst_worker->pipe_worker; //message-queue if (dst_worker->pool->use_msgqueue) { struct { long mtype; swEventData buf; } msg; msg.mtype = dst_worker->id + 1; memcpy(&msg.buf, buf, n); ret = dst_worker->pool->queue->in(dst_worker->pool->queue, (swQueue_data *) &msg, n); } //event worker else if (SwooleG.main_reactor) { ret = SwooleG.main_reactor->write(SwooleG.main_reactor, pipefd, buf, n); } //task worker else { ret = swSocket_write_blocking(pipefd, buf, n); } return ret; }
/** * Send data to ReactorThread */ int swWorker_send2reactor(swEventData *ev_data, size_t sendn, int session_id) { int ret; swServer *serv = SwooleG.serv; int _pipe_fd = swWorker_get_send_pipe(serv, session_id, ev_data->info.from_id); if (SwooleG.main_reactor) { ret = SwooleG.main_reactor->write(SwooleG.main_reactor, _pipe_fd, ev_data, sendn); } else { ret = swSocket_write_blocking(_pipe_fd, ev_data, sendn); } return ret; }
int swWorker_send2worker(swWorker *dst_worker, void *buf, int n, int flag) { int pipefd, ret; if (flag & SW_PIPE_MASTER) { pipefd = dst_worker->pipe_master; } else { pipefd = dst_worker->pipe_worker; } //message-queue if (dst_worker->pool->use_msgqueue) { struct { long mtype; swEventData buf; } msg; msg.mtype = dst_worker->id + 1; memcpy(&msg.buf, buf, n); return swMsgQueue_push(dst_worker->pool->queue, (swQueue_data *) &msg, n); } if ((flag & SW_PIPE_NONBLOCK) && SwooleG.main_reactor) { return SwooleG.main_reactor->write(SwooleG.main_reactor, pipefd, buf, n); } else { ret = swSocket_write_blocking(pipefd, buf, n); } return ret; }
static int swProcessPool_worker_loop(swProcessPool *pool, swWorker *worker) { struct { long mtype; swEventData buf; } out; int n = 0, ret; int task_n, worker_task_always = 0; if (pool->max_request < 1) { task_n = 1; worker_task_always = 1; } else { task_n = pool->max_request; n = swoole_system_random(1, pool->max_request / 2); if (n > 0) { task_n += n; } } /** * Use from_fd save the task_worker->id */ out.buf.info.from_fd = worker->id; if (pool->dispatch_mode == SW_DISPATCH_QUEUE) { out.mtype = 0; } else { out.mtype = worker->id + 1; } while (SwooleG.running > 0 && task_n > 0) { /** * fetch task */ if (pool->use_msgqueue) { n = swMsgQueue_pop(pool->queue, (swQueue_data *) &out, sizeof(out.buf)); if (n < 0 && errno != EINTR) { swSysError("[Worker#%d] msgrcv() failed.", worker->id); } } else if (pool->use_socket) { int fd = accept(pool->stream->socket, NULL, NULL); if (fd < 0) { if (errno == EAGAIN || errno == EINTR) { continue; } else { swSysError("accept(%d) failed.", pool->stream->socket); break; } } n = swStream_recv_blocking(fd, (void*) &out.buf, sizeof(out.buf)); if (n == SW_CLOSE) { close(fd); continue; } pool->stream->last_connection = fd; } else { n = read(worker->pipe_worker, &out.buf, sizeof(out.buf)); if (n < 0 && errno != EINTR) { swSysError("[Worker#%d] read(%d) failed.", worker->id, worker->pipe_worker); } } /** * timer */ if (n < 0) { if (errno == EINTR && SwooleG.signal_alarm) { alarm_handler: SwooleG.signal_alarm = 0; swTimer_select(&SwooleG.timer); } continue; } /** * do task */ worker->status = SW_WORKER_BUSY; worker->request_time = time(NULL); ret = pool->onTask(pool, &out.buf); worker->status = SW_WORKER_IDLE; worker->request_time = 0; worker->traced = 0; if (pool->use_socket && pool->stream->last_connection > 0) { int _end = 0; swSocket_write_blocking(pool->stream->last_connection, (void *) &_end, sizeof(_end)); close(pool->stream->last_connection); pool->stream->last_connection = 0; } /** * timer */ if (SwooleG.signal_alarm) { goto alarm_handler; } if (ret >= 0 && !worker_task_always) { task_n--; } } return SW_OK; }
static int swClient_onStreamRead(swReactor *reactor, swEvent *event) { int n; swClient *cli = event->socket->object; char *buf = cli->buffer->str; long buf_size = cli->buffer->size; if (cli->socks5_proxy && cli->socks5_proxy->state != SW_SOCKS5_STATE_READY) { int n = swConnection_recv(event->socket, buf, buf_size, 0); if (n <= 0) { goto __close; } if (swSocks5_connect(cli, buf, buf_size) < 0) { goto __close; } if (cli->socks5_proxy->state != SW_SOCKS5_STATE_READY) { return SW_OK; } #ifdef SW_USE_OPENSSL if (cli->open_ssl) { if (swClient_enable_ssl_encrypt(cli) < 0) { connect_fail: cli->close(cli); if (cli->onError) { cli->onError(cli); } } else { if (swClient_ssl_handshake(cli) < 0) { goto connect_fail; } else { cli->socket->ssl_state = SW_SSL_STATE_WAIT_STREAM; } return SwooleG.main_reactor->set(SwooleG.main_reactor, event->fd, SW_FD_STREAM_CLIENT | SW_EVENT_WRITE); } } else #endif { cli->onConnect(cli); } return SW_OK; } #ifdef SW_USE_OPENSSL if (cli->open_ssl && cli->socket->ssl_state == SW_SSL_STATE_WAIT_STREAM) { if (swClient_ssl_handshake(cli) < 0) { return cli->close(cli); } if (cli->socket->ssl_state != SW_SSL_STATE_READY) { return SW_OK; } //ssl handshake sucess else if (cli->onConnect) { cli->onConnect(cli); } } #endif /** * redirect stream data to other socket */ if (cli->redirect) { int ret = 0; n = swConnection_recv(event->socket, buf, buf_size, 0); if (n < 0) { goto __error; } else if (n == 0) { goto __close; } if (cli->_redirect_to_socket) { ret = SwooleG.main_reactor->write(SwooleG.main_reactor, cli->_redirect_to_socket, buf, n); } else if (cli->_redirect_to_session) { if (SwooleG.serv->send(SwooleG.serv, cli->_redirect_to_session, buf, n) < 0) { if (SwooleG.error >= SW_ERROR_SESSION_CLOSED_BY_SERVER || SwooleG.error >= SW_ERROR_SESSION_INVALID_ID) { goto __close; } } else { return SW_OK; } } else { ret = swSocket_write_blocking(cli->_redirect_to_file, buf, n); } if (ret < 0) { goto __error; } return SW_OK; } if (cli->open_eof_check || cli->open_length_check) { swConnection *conn = cli->socket; swProtocol *protocol = &cli->protocol; if (cli->open_eof_check) { n = swProtocol_recv_check_eof(protocol, conn, cli->buffer); } else { n = swProtocol_recv_check_length(protocol, conn, cli->buffer); } if (n < 0) { return cli->close(cli); } else { return SW_OK; } } #ifdef SW_CLIENT_RECV_AGAIN recv_again: #endif n = swConnection_recv(event->socket, buf, buf_size, 0); if (n < 0) { __error: switch (swConnection_error(errno)) { case SW_ERROR: swSysError("Read from socket[%d] failed.", event->fd); return SW_OK; case SW_CLOSE: goto __close; case SW_WAIT: return SW_OK; default: return SW_OK; } } else if (n == 0) { __close: return cli->close(cli); } else { cli->onReceive(cli, buf, n); #ifdef SW_CLIENT_RECV_AGAIN if (n == buf_size) { goto recv_again; } #endif return SW_OK; } return SW_OK; }
/** * Send the task result to worker */ int swTaskWorker_finish(swServer *serv, char *data, int data_len, int flags) { swEventData buf; if (!current_task) { swWarn("cannot use finish in worker"); return SW_ERR; } if (serv->task_worker_num < 1) { swWarn("cannot use task/finish, because no set serv->task_worker_num."); return SW_ERR; } if (current_task->info.type == SW_EVENT_PIPE_MESSAGE) { swWarn("task/finish is not supported in onPipeMessage callback."); return SW_ERR; } uint16_t source_worker_id = current_task->info.from_id; swWorker *worker = swServer_get_worker(serv, source_worker_id); if (worker == NULL) { swWarn("invalid worker_id[%d].", source_worker_id); return SW_ERR; } int ret; //for swoole_server_task if (swTask_type(current_task) & SW_TASK_NONBLOCK) { buf.info.type = SW_EVENT_FINISH; buf.info.fd = current_task->info.fd; //callback function if (swTask_type(current_task) & SW_TASK_CALLBACK) { flags |= SW_TASK_CALLBACK; } else if (swTask_type(current_task) & SW_TASK_COROUTINE) { flags |= SW_TASK_COROUTINE; } swTask_type(&buf) = flags; //write to file if (data_len >= SW_IPC_MAX_SIZE - sizeof(buf.info)) { if (swTaskWorker_large_pack(&buf, data, data_len) < 0 ) { swWarn("large task pack failed()"); return SW_ERR; } } else { memcpy(buf.data, data, data_len); buf.info.len = data_len; } if (worker->pool->use_socket && worker->pool->stream->last_connection > 0) { int32_t _len = htonl(data_len); ret = swSocket_write_blocking(worker->pool->stream->last_connection, (void *) &_len, sizeof(_len)); if (ret > 0) { ret = swSocket_write_blocking(worker->pool->stream->last_connection, data, data_len); } } else { ret = swWorker_send2worker(worker, &buf, sizeof(buf.info) + buf.info.len, SW_PIPE_MASTER); } } else { uint64_t flag = 1; /** * Use worker shm store the result */ swEventData *result = &(serv->task_result[source_worker_id]); swPipe *task_notify_pipe = &(serv->task_notify[source_worker_id]); //lock worker worker->lock.lock(&worker->lock); if (swTask_type(current_task) & SW_TASK_WAITALL) { sw_atomic_t *finish_count = (sw_atomic_t*) result->data; char *_tmpfile = result->data + 4; int fd = open(_tmpfile, O_APPEND | O_WRONLY); if (fd >= 0) { buf.info.type = SW_EVENT_FINISH; buf.info.fd = current_task->info.fd; swTask_type(&buf) = flags; //result pack if (data_len >= SW_IPC_MAX_SIZE - sizeof(buf.info)) { if (swTaskWorker_large_pack(&buf, data, data_len) < 0) { swWarn("large task pack failed()"); buf.info.len = 0; } } else { buf.info.len = data_len; memcpy(buf.data, data, data_len); } //write to tmpfile if (swoole_sync_writefile(fd, &buf, sizeof(buf.info) + buf.info.len) < 0) { swSysError("write(%s, %ld) failed.", _tmpfile, sizeof(buf.info) + buf.info.len); } sw_atomic_fetch_add(finish_count, 1); close(fd); } } else { result->info.type = SW_EVENT_FINISH; result->info.fd = current_task->info.fd; swTask_type(result) = flags; if (data_len >= SW_IPC_MAX_SIZE - sizeof(buf.info)) { if (swTaskWorker_large_pack(result, data, data_len) < 0) { //unlock worker worker->lock.unlock(&worker->lock); swWarn("large task pack failed()"); return SW_ERR; } } else { memcpy(result->data, data, data_len); result->info.len = data_len; } } //unlock worker worker->lock.unlock(&worker->lock); while (1) { ret = task_notify_pipe->write(task_notify_pipe, &flag, sizeof(flag)); #ifdef HAVE_KQUEUE if (ret < 0 && (errno == EAGAIN || errno == ENOBUFS)) #else if (ret < 0 && errno == EAGAIN) #endif { if (swSocket_wait(task_notify_pipe->getFd(task_notify_pipe, 1), -1, SW_EVENT_WRITE) == 0) { continue; } } break; } } if (ret < 0) { swWarn("TaskWorker: send result to worker failed. Error: %s[%d]", strerror(errno), errno); } return ret; }