int swFactoryProcess_end(swFactory *factory, swDataHead *event) { swServer *serv = factory->ptr; swEvent ev; bzero(&ev, sizeof(swEvent)); ev.fd = event->fd; /** * length == 0, close the connection */ ev.len = 0; /** * passive or initiative */ ev.type = event->type; swConnection *conn = swServer_get_connection(serv, ev.fd); if (conn == NULL || conn->active == 0) { swWarn("can not close. Connection[%d] not found.", ev.fd); return SW_ERR; } event->from_id = conn->from_id; return swFactoryProcess_finish(factory, (swSendData *)&ev); }
int swServer_reactor_thread_onWrite(swReactor *reactor, swDataHead *ev) { swServer *serv = SwooleG.serv; swConnection *conn = swServer_get_connection(serv, ev->fd); int ret, sendn; if (conn->output.send_file != NULL) { swTask_sendfile *task = conn->output.send_file; sendn = (task->filesize - task->offset > SW_SENDFILE_TRUNK) ? SW_SENDFILE_TRUNK : task->filesize - task->offset; ret = sendfile(ev->fd, task->fd, &task->offset, sendn); //swWarn("ret=%d|task->offset=%ld|sendn=%d|filesize=%ld", ret, task->offset, sendn, task->filesize); if (ret < 0) { swWarn("sendfile failed. Error: %s[%d]", strerror(errno), errno); return SW_ERR; } if (task->offset >= task->filesize) { reactor->set(reactor, ev->fd, SW_EVENT_TCP | SW_EVENT_READ); conn->output.send_file = NULL; close(task->fd); sw_free(task); } } return SW_OK; }
/** * close the connection */ int swReactorThread_onClose(swReactor *reactor, swEvent *event) { swServer *serv = reactor->ptr; swConnection *conn = swServer_get_connection(serv, event->fd); if (conn != NULL && conn->active == 1) { swConnection_close(serv, event->fd, event->type == SW_EVENT_CLOSE ? 0 : 1); } return SW_OK; }
static int swServer_master_onClose(swReactor *reactor, swEvent *event) { swServer *serv = reactor->ptr; swConnection *conn; int queue[SW_CLOSE_QLEN]; int i, n, fd; n = serv->main_pipe.read(&serv->main_pipe, queue, sizeof(queue)); if (n <= 0) { swWarn("[Master]main_pipe read failed. Error: %s[%d]", strerror(errno), errno); return SW_ERR; } for (i = 0; i < n / sizeof(int); i++) { fd = queue[i]; conn = swServer_get_connection(serv, fd); if (serv->onMasterClose != NULL) { serv->onMasterClose(serv, fd, conn->from_id); } /** * Reset maxfd, use for connection_list */ if (fd == swServer_get_maxfd(serv)) { int find_max_fd = fd - 1; /** * Find the new max_fd */ for (; serv->connection_list[find_max_fd].active == 0 && find_max_fd > swServer_get_minfd(serv); find_max_fd--); swServer_set_maxfd(serv, find_max_fd); swTrace("set_maxfd=%d|close_fd=%d", find_max_fd, fd); } } return SW_OK; }
int my_onReceive(swFactory *factory, swEventData *req) { int ret; char resp_data[SW_BUFFER_SIZE]; swServer *serv = factory->ptr; swSendData resp; g_receive_count ++; memcpy(&resp.info, &req->info, sizeof(resp.info)); resp.info.len = req->info.len + 8; req->data[req->info.len] = 0; snprintf(resp_data, resp.info.len, "Server:%s", req->data); resp.data = resp_data; ret = factory->finish(factory, &resp); if (ret < 0) { printf("send to client fail.errno=%d\n", errno); } if (req->info.from_id >= serv->reactor_num) { struct in_addr addr; addr.s_addr = req->info.fd; printf("onReceive[%d]: ip=%s|port=%d Data=%s|Len=%d\n", g_receive_count, inet_ntoa(addr), req->info.from_id, rtrim(req->data, req->info.len), req->info.len); } else { swConnection *conn = swServer_get_connection(serv, req->info.fd); printf("onReceive[%d]: ip=%s|port=%d Data=%s|Len=%d\n", g_receive_count, inet_ntoa(conn->addr.sin_addr), conn->addr.sin_port, rtrim(req->data, req->info.len), req->info.len); } // req->info.type = 99; // factory->event(factory, g_controller_id, req); return SW_OK; }
/** * Worker进程,向writer发送数据 */ int swFactoryProcess_finish(swFactory *factory, swSendData *resp) { //UDP直接在worker进程内发送 int ret, sendn, count, pipe_i; swFactoryProcess *object = factory->object; swServer *serv = factory->ptr; swReactor *reactor; int fd = resp->info.fd; //UDP在worker进程中直接发送到客户端 if(resp->info.type == SW_EVENT_UDP) { ret = swServer_send_udp_packet(serv, resp); goto finish; } //swQueue_data for msg queue struct { long pti; swEventData _send; } sdata; //写队列mtype sdata.pti = (SwooleWG.id % serv->writer_num) + 1; //copy memcpy(sdata._send.data, resp->data, resp->info.len); swConnection *conn = swServer_get_connection(serv, fd); if(conn == NULL) { swWarn("connection[%d] not found.", fd); return SW_ERR; } sdata._send.info.fd = fd; sdata._send.info.type = resp->info.type; sdata._send.info.len = resp->info.len; sdata._send.info.from_id = conn->from_id; sendn = resp->info.len + sizeof(resp->info); //swWarn("send: type=%d|content=%s", resp->info.type, resp->data); swTrace("[Worker]wt_queue[%ld]->in| fd=%d", sdata.pti, fd); for (count = 0; count < SW_WORKER_SENDTO_COUNT; count++) { #if SW_WORKER_IPC_MODE == 2 ret = object->wt_queue.in(&object->wt_queue, (swQueue_data *)&sdata, sendn); #else reactor = &(serv->reactor_threads[conn->from_id].reactor); if (serv->reactor_pipe_num > 1) { pipe_i = fd % serv->reactor_pipe_num + reactor->id; } else { pipe_i = reactor->id; } //swWarn("send to reactor. fd=%d|pipe_i=%d|reactor_id=%d|reactor_pipe_num=%d", fd, pipe_i, conn->from_id, serv->reactor_pipe_num); ret = write(object->workers[pipe_i].pipe_worker, &sdata._send, sendn); #endif //printf("wt_queue->in: fd=%d|from_id=%d|data=%s|ret=%d|errno=%d\n", 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("[Worker#%d]sendto writer pipe or queue failed. Error: %s [%d]", getpid(), strerror(errno), errno); } return ret; }
/** * close connection */ SWINLINE void swConnection_close(swServer *serv, int fd, int notify) { swConnection *conn = swServer_get_connection(serv, fd); swReactor *reactor; swEvent notify_ev; if(conn == NULL) { swWarn("[Master]connection not found. fd=%d|max_fd=%d", fd, swServer_get_maxfd(serv)); return; } conn->active = 0; int reactor_id = conn->from_id; swCloseQueue *queue = &serv->reactor_threads[reactor_id].close_queue; //将关闭的fd放入队列 queue->events[queue->num] = fd; //增加计数 queue->num ++; reactor = &(serv->reactor_threads[reactor_id].reactor); swTrace("Close Event.fd=%d|from=%d", fd, reactor_id); //释放缓存区占用的内存 if (serv->open_eof_check == 1) { if (conn->in_buffer != NULL) { swBuffer_free(conn->in_buffer); conn->in_buffer = NULL; } } else if (serv->open_length_check == 1) { if (conn->object != NULL) { swString_free(conn->object); } } if (conn->out_buffer != NULL) { swBuffer_free(conn->out_buffer); conn->out_buffer = NULL; } if (conn->in_buffer != NULL) { swBuffer_free(conn->in_buffer); conn->in_buffer = NULL; } //通知到worker进程 if (serv->onClose != NULL && notify == 1) { //通知worker进程 notify_ev.from_id = reactor_id; notify_ev.fd = fd; notify_ev.type = SW_EVENT_CLOSE; SwooleG.factory->notify(SwooleG.factory, ¬ify_ev); } //通知主进程 if (queue->num == SW_CLOSE_QLEN) { swReactorThread_close_queue(reactor, queue); } #ifdef SW_SOCKET_SET_LINGER struct linger linger; linger.l_onoff = 0; linger.l_linger = 0; if (setsockopt(fd, SOL_SOCKET, SO_LINGER, &linger, sizeof(struct linger)) == -1) { swWarn("setsockopt(SO_LINGER) failed. Error: %s[%d]", strerror(errno), errno); } #endif //关闭此连接,必须放在最前面,以保证线程安全 reactor->del(reactor, fd); }
/** * worker: send to client */ int swFactoryProcess_finish(swFactory *factory, swSendData *resp) { int ret, sendn, count; swFactoryProcess *object = factory->object; 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_send_udp_packet(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; //copy memcpy(sdata._send.data, resp->data, resp->info.len); swConnection *conn = swServer_get_connection(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; sdata._send.info.len = resp->info.len; sdata._send.info.from_id = conn->from_id; sendn = resp->info.len + sizeof(resp->info); //swWarn("send: type=%d|content=%s", resp->info.type, resp->data); swTrace("[Worker]wt_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 = object->wt_queue.in(&object->wt_queue, (swQueue_data *)&sdata, sendn); } else { int pipe_i; swReactor *reactor = &(serv->reactor_threads[conn->from_id].reactor); if (serv->reactor_pipe_num > 1) { pipe_i = fd % serv->reactor_pipe_num + reactor->id; } else { pipe_i = reactor->id; } //swWarn("send to reactor. fd=%d|pipe_i=%d|reactor_id=%d|reactor_pipe_num=%d", fd, pipe_i, conn->from_id, serv->reactor_pipe_num); ret = write(object->workers[pipe_i].pipe_worker, &sdata._send, sendn); } //printf("wt_queue->in: fd=%d|from_id=%d|data=%s|ret=%d|errno=%d\n", 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("[Worker#%d]sendto writer pipe or queue failed. Error: %s [%d]", getpid(), strerror(errno), errno); } return ret; }
int swReactorThread_response(swEventData *resp) { int ret; swServer *serv = SwooleG.serv; swFactory *factory = SwooleG.factory; swReactor *reactor; swSendData send_data; swDataHead closeFd; //表示关闭 if (resp->info.len == 0) { close_fd: { closeFd.fd = resp->info.fd; closeFd.from_id = resp->info.from_id; closeFd.type = SW_EVENT_CLOSE; reactor = &(serv->reactor_threads[closeFd.from_id].reactor); //printf("closeFd.fd=%d|from_id=%d\n", closeFd.fd, closeFd.from_id); swServer_reactor_thread_onClose(reactor, &closeFd); } return SW_OK; } //发送文件 else if(resp->info.type == SW_EVENT_SENDFILE) { swConnection *conn = swServer_get_connection(serv, resp->info.fd); conn->output.send_file = sw_malloc(sizeof(swTask_sendfile)); if (conn->output.send_file == NULL) { swWarn("malloc for swTask_sendfile failed."); return SW_ERR; } bzero(conn->output.send_file, sizeof(swTask_sendfile)); int file_fd = open(resp->data, O_RDONLY); if (file_fd < 0) { swWarn("open file[%s] failed. Error: %s[%d]", send_data.data, strerror(errno), errno); return SW_ERR; } struct stat file_stat; if (fstat(file_fd, &file_stat) < 0) { swWarn("swoole_async_readfile: fstat failed. Error: %s[%d]", strerror(errno), errno); return SW_ERR; } conn->output.send_file->filesize = file_stat.st_size; conn->output.send_file->fd = file_fd; reactor = &(serv->reactor_threads[closeFd.from_id].reactor); reactor->set(reactor, resp->info.fd, SW_EVENT_TCP | SW_EVENT_WRITE | SW_EVENT_READ); } else { send_data.data = resp->data; send_data.info.len = resp->info.len; send_data.info.from_id = resp->info.from_id; send_data.info.fd = resp->info.fd; ret = factory->onFinish(factory, &send_data); if (ret < 0) { //连接已被关闭 if (errno == ECONNRESET || errno == EBADF) { goto close_fd; } swWarn("factory->onFinish failed.fd=%d|from_id=%d. Error: %s[%d]", resp->info.fd, resp->info.from_id, strerror(errno), errno); } //printf("[writer]pop.fd=%d|from_id=%d|data=%s\n", resp->info.fd, resp->info.from_id, resp->data); } return SW_OK; }
/** * send to client or append to out_buffer */ int swReactorThread_send(swEventData *resp) { int buf_size, copy_n; swServer *serv = SwooleG.serv; swSendData send_data; swEvent closeFd; swBuffer_trunk *trunk; swTask_sendfile *task; swConnection *conn = swServer_get_connection(serv, resp->info.fd); swReactor *reactor = &(serv->reactor_threads[conn->from_id].reactor); //recv length=0, will close connection if (resp->info.len == 0) { #ifdef SW_REACTOR_DIRECT_SEND close_fd: #endif { closeFd.fd = resp->info.fd; closeFd.from_id = resp->info.from_id; closeFd.type = SW_EVENT_CLOSE; //printf("closeFd.fd=%d|from_id=%d\n", closeFd.fd, closeFd.from_id); swReactorThread_onClose(reactor, &closeFd); } return SW_OK; } //sendfile to client else if(resp->info.type == SW_EVENT_SENDFILE) { trunk = swConnection_get_out_buffer(conn, SW_TRUNK_SENDFILE); if (trunk == NULL) { swWarn("get out_buffer trunk failed."); return SW_ERR; } task = sw_malloc(sizeof(swTask_sendfile)); if (task == NULL) { swWarn("malloc for swTask_sendfile failed."); //TODO: 回收这里的内存 return SW_ERR; } bzero(task, sizeof(swTask_sendfile)); int file_fd = open(resp->data, O_RDONLY); if (file_fd < 0) { swWarn("open file[%s] failed. Error: %s[%d]", task->filename, strerror(errno), errno); return SW_ERR; } struct stat file_stat; if (fstat(file_fd, &file_stat) < 0) { swWarn("swoole_async_readfile: fstat failed. Error: %s[%d]", strerror(errno), errno); return SW_ERR; } task->filesize = file_stat.st_size; task->fd = file_fd; trunk->data = (void *)task; reactor->set(reactor, resp->info.fd, SW_EVENT_TCP | SW_EVENT_WRITE | SW_EVENT_READ); } //send data else { send_data.data = resp->data; send_data.info.len = resp->info.len; send_data.info.from_id = resp->info.from_id; send_data.info.fd = resp->info.fd; #ifdef SW_REACTOR_DIRECT_SEND if(!swBuffer_empty(conn->out_buffer)) { trunk = swBuffer_get_trunk(conn->out_buffer); #else { trunk = swConnection_get_out_buffer(conn, SW_TRUNK_DATA); #endif buf_size = conn->out_buffer->trunk_size - trunk->length; #ifdef SW_REACTOR_DIRECT_SEND append_out_buffer: #else //listen EPOLLOUT event reactor->set(reactor, resp->info.fd, SW_EVENT_TCP | SW_EVENT_WRITE | SW_EVENT_READ); #endif do { copy_n = (buf_size >= send_data.info.len) ? send_data.info.len : buf_size; memcpy(trunk->data, send_data.data, copy_n); send_data.data += copy_n; send_data.info.len -= copy_n; trunk->length += copy_n; buf_size += copy_n; //trunk is full, create new trunk if (trunk->length == conn->out_buffer->trunk_size) { //trunk no enough space, creating a new trunk trunk = swBuffer_new_trunk(conn->out_buffer, SW_TRUNK_DATA); if (trunk == NULL) { swWarn("append to out_buffer failed."); return SW_ERR; } buf_size = conn->out_buffer->trunk_size; } } while(send_data.info.len > 0); } #ifdef SW_REACTOR_DIRECT_SEND else { //try send int ret = swWrite(send_data.info.fd, send_data.data, send_data.info.len); if (ret < 0) { //连接已被关闭 if (errno == ECONNRESET || errno == EBADF) { goto close_fd; } swWarn("factory->onFinish failed.fd=%d|from_id=%d. Error: %s[%d]", resp->info.fd, resp->info.from_id, strerror(errno), errno); } //Did not finish, add to writable event callback else if(ret < resp->info.len) { trunk = swConnection_get_out_buffer(conn, SW_TRUNK_DATA); send_data.data += ret; send_data.info.len -= ret; buf_size = conn->out_buffer->trunk_size; goto append_out_buffer; } //printf("[writer]pop.fd=%d|from_id=%d|data=%s\n", resp->info.fd, resp->info.from_id, resp->data); } #endif }
} else { _send.info.len = length; _send.length = 0; } return factory->finish(factory, &_send); } #else else { char buffer[SW_BUFFER_SIZE]; int trunk_num = (length / SW_BUFFER_SIZE) + 1; int send_n = 0, i, ret; swConnection *conn = swServer_get_connection(serv, fd); if (conn == NULL || conn->active == 0) { swWarn("Connection[%d] has been closed.", fd); return SW_ERR; } for (i = 0; i < trunk_num; i++) { //last chunk if (i == (trunk_num - 1)) { send_n = length % SW_BUFFER_SIZE; if (send_n == 0) break; }