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

📄 conn.c

📁 一个很好用的解析
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Copyright information is at the end of the file. */#include <time.h>#include <string.h>#include <stdlib.h>#include <stdio.h>#include <ctype.h>#include <assert.h>#include "mallocvar.h"#include "xmlrpc-c/util_int.h"#include "xmlrpc-c/string_int.h"#include "xmlrpc-c/sleep_int.h"#include "xmlrpc-c/abyss.h"#include "socket.h"#include "server.h"#include "thread.h"#include "conn.h"/*********************************************************************** Conn*********************************************************************/static TThreadProc connJob;static voidconnJob(void * const userHandle) {/*----------------------------------------------------------------------------   This is the root function for a thread that processes a connection   (performs HTTP transactions).-----------------------------------------------------------------------------*/    TConn * const connectionP = userHandle;    (connectionP->job)(connectionP);    connectionP->finished = TRUE;        /* Note that if we are running in a forked process, setting           connectionP->finished has no effect, because it's just our own           copy of *connectionP.  In this case, Parent must update his own           copy based on a SIGCHLD signal that the OS will generate right           after we exit.        */    ThreadExit(0);}static voidconnDone(TConn * const connectionP) {    /* In the forked case, this is designed to run in the parent       process after the child has terminated.    */    connectionP->finished = TRUE;    if (connectionP->done)        connectionP->done(connectionP);}static TThreadDoneFn threadDone;static voidthreadDone(void * const userHandle) {    TConn * const connectionP = userHandle;        connDone(connectionP);}static voidmakeThread(TConn *             const connectionP,           enum abyss_foreback const foregroundBackground,           abyss_bool          const useSigchld,           const char **       const errorP) {               switch (foregroundBackground) {    case ABYSS_FOREGROUND:        connectionP->hasOwnThread = FALSE;        *errorP = NULL;        break;    case ABYSS_BACKGROUND: {        const char * error;        connectionP->hasOwnThread = TRUE;        ThreadCreate(&connectionP->threadP, connectionP,                     &connJob, &threadDone, useSigchld,                     &error);        if (error) {            xmlrpc_asprintf(errorP, "Unable to create thread to "                            "process connection.  %s", error);            xmlrpc_strfree(error);        } else            *errorP = NULL;    } break;    } /* switch */}    voidConnCreate(TConn **            const connectionPP,           TServer *           const serverP,           TSocket *           const connectedSocketP,           TThreadProc *       const job,           TThreadDoneFn *     const done,           enum abyss_foreback const foregroundBackground,           abyss_bool          const useSigchld,           const char **       const errorP) {/*----------------------------------------------------------------------------   Create an HTTP connection.   A connection carries one or more HTTP transactions (request/response).   'connectedSocketP' transports the requests and responses.   The connection handles those HTTP requests.   The connection handles the requests primarily by running the   function 'job' once.  Some connections can do that autonomously, as   soon as the connection is created.  Others don't until Caller   subsequently calls ConnProcess.  Some connections complete the   processing before ConnProcess return, while others may run the   connection asynchronously to the creator, in the background, via a   TThread thread.  'foregroundBackground' determines which.   'job' calls methods of the connection to get requests and send   responses.   Some time after the HTTP transactions are all done, 'done' gets   called in some context.-----------------------------------------------------------------------------*/    TConn * connectionP;    MALLOCVAR(connectionP);    if (connectionP == NULL)        xmlrpc_asprintf(errorP, "Unable to allocate memory for a connection "                        "descriptor.");    else {        abyss_bool success;        uint16_t peerPortNumber;        connectionP->server     = serverP;        connectionP->socketP    = connectedSocketP;        connectionP->buffersize = 0;        connectionP->bufferpos  = 0;        connectionP->finished   = FALSE;        connectionP->job        = job;        connectionP->done       = done;        connectionP->inbytes    = 0;        connectionP->outbytes   = 0;        connectionP->trace      = getenv("ABYSS_TRACE_CONN");        SocketGetPeerName(connectedSocketP,                          &connectionP->peerip, &peerPortNumber, &success);        if (success)            makeThread(connectionP, foregroundBackground, useSigchld, errorP);        else            xmlrpc_asprintf(errorP, "Failed to get peer name from socket.");    }    *connectionPP = connectionP;}abyss_boolConnProcess(TConn * const connectionP) {/*----------------------------------------------------------------------------   Drive the main processing of a connection -- run the connection's   "job" function, which should read HTTP requests from the connection   and send HTTP responses.   If we succeed, we guarantee the connection's "done" function will get   called some time after all processing is complete.  It might be before   we return or some time after.  If we fail, we guarantee the "done"   function will not be called.-----------------------------------------------------------------------------*/    abyss_bool retval;    if (connectionP->hasOwnThread) {        /* There's a background thread to handle this connection.  Set           it running.        */        retval = ThreadRun(connectionP->threadP);    } else {        /* No background thread.  We just handle it here while Caller waits. */        (connectionP->job)(connectionP);        connDone(connectionP);        retval = TRUE;    }    return retval;}voidConnWaitAndRelease(TConn * const connectionP) {    if (connectionP->hasOwnThread)        ThreadWaitAndRelease(connectionP->threadP);        free(connectionP);}abyss_boolConnKill(TConn * connectionP) {    connectionP->finished = TRUE;    return ThreadKill(connectionP->threadP);}voidConnReadInit(TConn * const connectionP) {    if (connectionP->buffersize>connectionP->bufferpos) {        connectionP->buffersize -= connectionP->bufferpos;        memmove(connectionP->buffer,                connectionP->buffer+connectionP->bufferpos,                connectionP->buffersize);        connectionP->bufferpos = 0;    } else        connectionP->buffersize=connectionP->bufferpos = 0;    connectionP->inbytes=connectionP->outbytes = 0;}static voidtraceBuffer(const char * const label,            const char * const buffer,            unsigned int const size) {    unsigned int nonPrintableCount;    unsigned int i;        nonPrintableCount = 0;  /* Initial value */        for (i = 0; i < size; ++i) {        if (!isprint(buffer[i]) && buffer[i] != '\n' && buffer[i] != '\r')            ++nonPrintableCount;    }    if (nonPrintableCount > 0)        fprintf(stderr, "%s contains %u nonprintable characters.\n",                 label, nonPrintableCount);        fprintf(stderr, "%s:\n", label);    fprintf(stderr, "%.*s\n", (int)size, buffer);}static voidtraceSocketRead(TConn *      const connectionP,                unsigned int const size) {    if (connectionP->trace)        traceBuffer("READ FROM SOCKET:",                    connectionP->buffer + connectionP->buffersize, size);}static voidtraceSocketWrite(TConn *      const connectionP,                 const char * const buffer,                 unsigned int const size,                 abyss_bool   const failed) {    if (connectionP->trace) {        const char * const label =            failed ? "FAILED TO WRITE TO SOCKET:" : "WROTE TO SOCKET";        traceBuffer(label, buffer, size);    }}static uint32_tbufferSpace(TConn * const connectionP) {        return BUFFER_SIZE - connectionP->buffersize;}                    abyss_boolConnRead(TConn *  const connectionP,         uint32_t const timeout) {/*----------------------------------------------------------------------------   Read some stuff on connection *connectionP from the socket.   Don't wait more than 'timeout' seconds for data to arrive.  Fail if   nothing arrives within that time.-----------------------------------------------------------------------------*/    time_t const deadline = time(NULL) + timeout;    abyss_bool cantGetData;    abyss_bool gotData;    cantGetData = FALSE;    gotData = FALSE;        while (!gotData && !cantGetData) {        int const timeLeft = deadline - time(NULL);        if (timeLeft <= 0)            cantGetData = TRUE;        else {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -