int swServer_udp_send(swServer *serv, swSendData *resp) { socklen_t len; struct sockaddr_in addr_in; int sock = resp->info.from_fd; addr_in.sin_family = AF_INET; addr_in.sin_port = htons((unsigned short) resp->info.from_id); //from_id is port addr_in.sin_addr.s_addr = resp->info.fd; //from_id is port len = sizeof(addr_in); return swSendto(sock, resp->data, resp->info.len, 0, (struct sockaddr*) &addr_in, len); }
int swFactory_finish(swFactory *factory, swSendData *resp) { int ret; swServer *serv = SwooleG.serv; //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; } else { resp->length = resp->info.len; swReactorThread_send(resp); } finish: if (ret < 0) { swWarn("sendto to reactor failed. Error: %s [%d]", strerror(errno), errno); } return ret; }
/** * 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; }
/** * 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; }
/** * 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; }