/** * Use message queue ipc */ int swFactoryProcess_writer_loop_queue(swThreadParam *param) { swFactory *factory = param->object; swFactoryProcess *object = factory->object; swEventData *resp; swSendData _send; int pti = param->pti; swQueue_data sdata; //必须加1,msg_type必须不能为0 sdata.mtype = pti + 1; swSignal_none(); while (SwooleG.running > 0) { swTrace("[Writer]wt_queue[%ld]->out wait", sdata.mtype); if (object->wt_queue.out(&object->wt_queue, &sdata, sizeof(sdata.mdata)) < 0) { if (errno == EINTR) { continue; } swWarn("[writer]wt_queue->out fail.Error: %s [%d]", strerror(errno), errno); } else { resp = (swEventData *) sdata.mdata; memcpy(&_send.info, &resp->info, sizeof(resp->info)); _send.data = resp->data; swReactorThread_send(&_send); } } pthread_exit((void *) param); return SW_OK; }
int swFactory_finish(swFactory *factory, swSendData *resp) { if (resp->length == 0) { resp->length = resp->info.len; } if (swReactorThread_send(resp) < 0) { swSysError("sendto to connection#%d failed.", resp->info.fd); return SW_ERR; } else { return SW_OK; } }
int swFactoryProcess_send2client(swReactor *reactor, swDataHead *ev) { int n; swEventData resp; //Unix Sock UDP n = read(ev->fd, &resp, sizeof(resp)); swTrace("[WriteThread]recv: writer=%d|pipe=%d", ev->from_id, ev->fd); //swWarn("send: type=%d|content=%s", resp.info.type, resp.data); if (n > 0) { return swReactorThread_send(&resp); } else { swWarn("[WriteThread]sento fail. Error: %s[%d]", strerror(errno), errno); return SW_ERR; } }
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; }
int swFactory_finish(swFactory *factory, swSendData *_send) { return swReactorThread_send(_send); }
int swPort_http_static_handler(swHttpRequest *request, swConnection *conn) { swServer *serv = SwooleG.serv; char *url = request->buffer->str + request->url_offset; char *params = memchr(url, '?', request->url_length); struct { off_t offset; size_t length; char filename[PATH_MAX]; } buffer; char *p = buffer.filename; memcpy(p, serv->document_root, serv->document_root_len); p += serv->document_root_len; uint32_t n = params ? params - url : request->url_length; memcpy(p, url, n); p += n; *p = 0; struct stat file_stat; if (lstat(buffer.filename, &file_stat) < 0) { return SW_FALSE; } if (file_stat.st_size == 0) { return SW_FALSE; } if ((file_stat.st_mode & S_IFMT) != S_IFREG) { return SW_FALSE; } char header_buffer[1024]; swSendData response; response.info.fd = conn->session_id; response.info.type = SW_EVENT_TCP; p = request->buffer->str + request->url_offset + request->url_length + 10; char *pe = request->buffer->str + request->header_length; char *date_if_modified_since = NULL; int length_if_modified_since = 0; int state = 0; for (; p < pe; p++) { switch(state) { case 0: if (strncasecmp(p, SW_STRL("If-Modified-Since")) == 0) { p += sizeof("If-Modified-Since"); state = 1; } break; case 1: if (!isspace(*p)) { date_if_modified_since = p; state = 2; } break; case 2: if (strncasecmp(p, SW_STRL("\r\n")) == 0) { length_if_modified_since = p - date_if_modified_since; goto check_modify_date; } break; default: break; } } char date_[64]; struct tm *tm1; check_modify_date: tm1 = gmtime(&serv->gs->now); strftime(date_, sizeof(date_), "%a, %d %b %Y %H:%M:%S %Z", tm1); char date_last_modified[64]; #ifdef __MACH__ time_t file_mtime = file_stat.st_mtimespec.tv_sec; #elif defined(_WIN32) time_t file_mtime = file_stat.st_mtime; #else time_t file_mtime = file_stat.st_mtim.tv_sec; #endif struct tm *tm2 = gmtime(&file_mtime); strftime(date_last_modified, sizeof(date_last_modified), "%a, %d %b %Y %H:%M:%S %Z", tm2); if (state == 2) { struct tm tm3; char date_tmp[64]; memcpy(date_tmp, date_if_modified_since, length_if_modified_since); date_tmp[length_if_modified_since] = 0; char *date_format = NULL; if (strptime(date_tmp, SW_HTTP_RFC1123_DATE_GMT, &tm3) != NULL) { date_format = SW_HTTP_RFC1123_DATE_GMT; } else if (strptime(date_tmp, SW_HTTP_RFC1123_DATE_UTC, &tm3) != NULL) { date_format = SW_HTTP_RFC1123_DATE_UTC; } else if (strptime(date_tmp, SW_HTTP_RFC850_DATE, &tm3) != NULL) { date_format = SW_HTTP_RFC850_DATE; } else if (strptime(date_tmp, SW_HTTP_ASCTIME_DATE, &tm3) != NULL) { date_format = SW_HTTP_ASCTIME_DATE; } if (date_format && mktime(&tm3) - (int) timezone >= file_mtime) { response.length = response.info.len = snprintf(header_buffer, sizeof(header_buffer), "HTTP/1.1 304 Not Modified\r\n" "%s" "Date: %s\r\n" "Last-Modified: %s\r\n" "Server: %s\r\n\r\n", request->keep_alive ? "Connection: keep-alive\r\n" : "", date_, date_last_modified, SW_HTTP_SERVER_SOFTWARE ); response.data = header_buffer; swReactorThread_send(&response); goto _finish; } } response.length = response.info.len = snprintf(header_buffer, sizeof(header_buffer), "HTTP/1.1 200 OK\r\n" "%s" "Content-Length: %ld\r\n" "Content-Type: %s\r\n" "Date: %s\r\n" "Last-Modified: %s\r\n" "Server: %s\r\n\r\n", request->keep_alive ? "Connection: keep-alive\r\n" : "", (long) file_stat.st_size, swoole_get_mime_type(buffer.filename), date_, date_last_modified, SW_HTTP_SERVER_SOFTWARE); response.data = header_buffer; #ifdef HAVE_TCP_NOPUSH if (conn->tcp_nopush == 0) { if (swSocket_tcp_nopush(conn->fd, 1) == -1) { swWarn("swSocket_tcp_nopush() failed. Error: %s[%d]", strerror(errno), errno); } conn->tcp_nopush = 1; } #endif swReactorThread_send(&response); buffer.offset = 0; buffer.length = file_stat.st_size; response.info.type = SW_EVENT_SENDFILE; response.length = response.info.len = sizeof(swSendFile_request) + buffer.length + 1; response.data = (void*) &buffer; swReactorThread_send(&response); _finish: if (!request->keep_alive) { response.info.type = SW_EVENT_CLOSE; response.length = 0; response.data = NULL; swReactorThread_send(&response); } return SW_TRUE; }