📄 server.c
字号:
ConnWriteFromFile(sessionP->conn, fileP, start, end, z, 4096, 0); } } } }}static abyss_boolServerFileHandler(TSession * const r, char * const z, time_t const fileModTime, MIMEType * const mimeTypeP) { const char * mediatype; TFile file; uint64_t filesize; uint64_t start; uint64_t end; TDate date; char * p; TDate filedate; mediatype = MIMETypeGuessFromFile2(mimeTypeP, z); if (!FileOpen(&file,z,O_BINARY | O_RDONLY)) { ResponseStatusErrno(r); return TRUE; } fileDate(r, fileModTime, &filedate); p = RequestHeaderValue(r, "if-modified-since"); if (p) { if (DateDecode(p,&date)) { if (DateCompare(&filedate, &date) <= 0) { ResponseStatus(r, 304); ResponseWrite(r); return TRUE; } else r->ranges.size = 0; } } filesize = FileSize(&file); switch (r->ranges.size) { case 0: ResponseStatus(r, 200); break; case 1: { abyss_bool decoded; decoded = RangeDecode((char *)(r->ranges.item[0]), filesize, &start, &end); if (!decoded) { ListFree(&(r->ranges)); ResponseStatus(r, 200); break; } sprintf(z, "bytes %llu-%llu/%llu", start, end, filesize); ResponseAddField(r, "Content-range", z); ResponseContentLength(r, end - start + 1); ResponseStatus(r, 206); } break; default: ResponseContentType(r, "multipart/ranges; boundary=" BOUNDARY); ResponseStatus(r, 206); break; } if (r->ranges.size == 0) { ResponseContentLength(r, filesize); ResponseContentType(r, mediatype); } if (DateToString(&filedate, z)) ResponseAddField(r, "Last-Modified", z); ResponseWrite(r); if (r->request_info.method != m_head) sendBody(r, &file, filesize, mediatype, start, end, z); FileClose(&file); return TRUE;}static abyss_boolServerDefaultHandlerFunc(TSession * const sessionP) { struct _TServer * const srvP = ConnServer(sessionP->conn)->srvP; char *p; char z[4096]; TFileStat fs; unsigned int i; abyss_bool endingslash=FALSE; if (!RequestValidURIPath(sessionP)) { ResponseStatus(sessionP, 400); return TRUE; } /* Must check for * (asterisk uri) in the future */ if (sessionP->request_info.method == m_options) { ResponseAddField(sessionP, "Allow", "GET, HEAD"); ResponseContentLength(sessionP, 0); ResponseStatus(sessionP, 200); return TRUE; } if ((sessionP->request_info.method != m_get) && (sessionP->request_info.method != m_head)) { ResponseAddField(sessionP, "Allow", "GET, HEAD"); ResponseStatus(sessionP, 405); return TRUE; } strcpy(z, srvP->filespath); strcat(z, sessionP->request_info.uri); p = z + strlen(z) - 1; if (*p == '/') { endingslash = TRUE; *p = '\0'; }#ifdef WIN32 p = z; while (*p) { if ((*p) == '/') *p= '\\'; ++p; }#endif /* WIN32 */ if (!FileStat(z, &fs)) { ResponseStatusErrno(sessionP); return TRUE; } if (fs.st_mode & S_IFDIR) { /* Redirect to the same directory but with the ending slash ** to avoid problems with some browsers (IE for examples) when ** they generate relative urls */ if (!endingslash) { strcpy(z, sessionP->request_info.uri); p = z+strlen(z); *p = '/'; *(p+1) = '\0'; ResponseAddField(sessionP, "Location", z); ResponseStatus(sessionP, 302); ResponseWrite(sessionP); return TRUE; } *p = DIRECTORY_SEPARATOR[0]; ++p; i = srvP->defaultfilenames.size; while (i-- > 0) { *p = '\0'; strcat(z, (srvP->defaultfilenames.item[i])); if (FileStat(z, &fs)) { if (!(fs.st_mode & S_IFDIR)) return ServerFileHandler(sessionP, z, fs.st_mtime, srvP->mimeTypeP); } } *(p-1) = '\0'; if (!FileStat(z, &fs)) { ResponseStatusErrno(sessionP); return TRUE; } return ServerDirectoryHandler(sessionP, z, fs.st_mtime, srvP->mimeTypeP); } else return ServerFileHandler(sessionP, z, fs.st_mtime, srvP->mimeTypeP);}static voidinitUnixStuff(struct _TServer * const srvP) {#ifndef WIN32 srvP->pidfile = srvP->uid = srvP->gid = -1;#endif}static abyss_boollogOpen(struct _TServer * const srvP) { abyss_bool success; success = FileOpenCreate(&srvP->logfile, srvP->logfilename, O_WRONLY | O_APPEND); if (success) { abyss_bool success; success = MutexCreate(&srvP->logmutex); if (success) srvP->logfileisopen = TRUE; else TraceMsg("Can't create mutex for log file"); if (!success) FileClose(&srvP->logfile); } else TraceMsg("Can't open log file '%s'", srvP->logfilename); return success;}static voidlogClose(struct _TServer * const srvP) { if (srvP->logfileisopen) { FileClose(&srvP->logfile); MutexFree(&srvP->logmutex); srvP->logfileisopen = FALSE; }}static voidinitSocketStuff(struct _TServer * const srvP, abyss_bool const noAccept, TSocket * const userSocketP, uint16_t const port, const char ** const errorP) { if (userSocketP) { *errorP = NULL; srvP->serverAcceptsConnections = TRUE; srvP->socketBound = TRUE; srvP->listenSocketP = userSocketP; } else if (noAccept) { *errorP = NULL; srvP->serverAcceptsConnections = FALSE; srvP->socketBound = FALSE; } else { *errorP = NULL; srvP->serverAcceptsConnections = TRUE; srvP->socketBound = FALSE; srvP->port = port; } srvP->weCreatedListenSocket = FALSE;}static voidcreateServer(struct _TServer ** const srvPP, abyss_bool const noAccept, TSocket * const userSocketP, uint16_t const portNumber, const char ** const errorP) { struct _TServer * srvP; MALLOCVAR(srvP); if (srvP == NULL) { xmlrpc_asprintf(errorP, "Unable to allocate space for server descriptor"); } else { srvP->terminationRequested = false; initSocketStuff(srvP, noAccept, userSocketP, portNumber, errorP); if (!*errorP) { srvP->defaulthandler = ServerDefaultHandlerFunc; srvP->name = strdup("unnamed"); srvP->filespath = strdup(DEFAULT_DOCS); srvP->logfilename = NULL; srvP->keepalivetimeout = 15; srvP->keepalivemaxconn = 30; srvP->timeout = 15; srvP->advertise = TRUE; srvP->mimeTypeP = NULL; srvP->useSigchld = FALSE; initUnixStuff(srvP); ListInitAutoFree(&srvP->handlers); ListInitAutoFree(&srvP->defaultfilenames); srvP->logfileisopen = FALSE; *errorP = NULL; } if (*errorP) free(srvP); } *srvPP = srvP;}static voidsetNamePathLog(TServer * const serverP, const char * const name, const char * const filesPath, const char * const logFileName) {/*---------------------------------------------------------------------------- This odd function exists to help with backward compatibility. Today, we have the expandable model where you create a server with default parameters, then use ServerSet... functions to choose non-default parameters. But before, you specified these three parameters right in the arguments of various create functions.-----------------------------------------------------------------------------*/ if (name) ServerSetName(serverP, name); if (filesPath) ServerSetFilesPath(serverP, filesPath); if (logFileName) ServerSetLogFileName(serverP, logFileName);}abyss_boolServerCreate(TServer * const serverP, const char * const name, uint16_t const portNumber, const char * const filesPath, const char * const logFileName) { abyss_bool const noAcceptFalse = FALSE; abyss_bool success; const char * error; createServer(&serverP->srvP, noAcceptFalse, NULL, portNumber, &error); if (error) { TraceMsg(error); xmlrpc_strfree(error); success = FALSE; } else { success = TRUE; setNamePathLog(serverP, name, filesPath, logFileName); } return success;}static voidcreateSocketFromOsSocket(TOsSocket const osSocket, TSocket ** const socketPP) {#ifdef WIN32 SocketWinCreateWinsock(osSocket, socketPP);#else SocketUnixCreateFd(osSocket, socketPP);#endif}abyss_boolServerCreateSocket(TServer * const serverP, const char * const name, TOsSocket const socketFd, const char * const filesPath, const char * const logFileName) { abyss_bool success; TSocket * socketP; createSocketFromOsSocket(socketFd, &socketP); if (socketP) { abyss_bool const noAcceptFalse = FALSE; const char * error; createServer(&serverP->srvP, noAcceptFalse, socketP, 0, &error); if (error) { TraceMsg(error); success = FALSE; xmlrpc_strfree(error); } else { success = TRUE; setNamePathLog(serverP, name, filesPath, logFileName); } } else success = FALSE; return success;}abyss_boolServerCreateNoAccept(TServer * const serverP, const char * const name, const char * const filesPath, const char * const logFileName) { abyss_bool const noAcceptTrue = TRUE; abyss_bool success; const char * error; createServer(&serverP->srvP, noAcceptTrue, NULL, 0, &error); if (error) { TraceMsg(error); success = FALSE; xmlrpc_strfree(error); } else { success = TRUE; setNamePathLog(serverP, name, filesPath, logFileName); } return success;}voidServerCreateSocket2(TServer * const serverP, TSocket * const socketP, const char ** const errorP) { abyss_bool const noAcceptFalse = FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -