⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 server.c

📁 一个很好用的解析
💻 C
📖 第 1 页 / 共 4 页
字号:
                    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 + -