PR_fprintf(PR_STDOUT, "                  %s free\n", FormatNumber(globals.mFreeCount)); PR_fprintf(PR_STDOUT, "Leaks           : %s\n", FormatNumber((globals.mMallocCount + globals.mCallocCount + globals.mReallocCount) - globals.mFreeCount));
serverMode(void){    int retval = 0;    PRFileDesc *socket = NULL;    /*     ** Create a socket.     */    socket = PR_NewTCPSocket();    if (NULL != socket) {        PRStatus closeRes = PR_SUCCESS;        PRNetAddr bindAddr;        PRStatus bindRes = PR_SUCCESS;        /*         ** Bind it to an interface/port.         ** Any interface.         */        bindAddr.inet.family = PR_AF_INET;        bindAddr.inet.port =            PR_htons((PRUint16) globals.mCommandLineOptions.mHttpdPort);        bindAddr.inet.ip = PR_htonl(PR_INADDR_ANY);        bindRes = PR_Bind(socket, &bindAddr);        if (PR_SUCCESS == bindRes) {            PRStatus listenRes = PR_SUCCESS;            const int backlog = 0x20;            /*             ** Start listening for clients.             ** Give a decent backlog, some of our processing will take             **  a bit.             */            listenRes = PR_Listen(socket, backlog);            if (PR_SUCCESS == listenRes) {                PRFileDesc *connection = NULL;                int failureSum = 0;                char message[80];                /*                 ** Output a little message saying we are receiving.                 */                PR_snprintf(message, sizeof(message),                            "server accepting connections at http://localhost:%u/",                            globals.mCommandLineOptions.mHttpdPort);                REPORT_INFO(message);                PR_fprintf(PR_STDOUT, "Peak memory used: %s bytes\n",                           FormatNumber(globals.mPeakMemoryUsed));                PR_fprintf(PR_STDOUT, "Total calls     : %s",                           FormatNumber(globals.mMallocCount +                                        globals.mCallocCount +                                        globals.mReallocCount));                PR_fprintf(PR_STDOUT, " [%s",                           FormatNumber(globals.mMallocCount));                PR_fprintf(PR_STDOUT, " + %s",                           FormatNumber(globals.mCallocCount));                PR_fprintf(PR_STDOUT, " + %s]\n",                           FormatNumber(globals.mReallocCount));                /*                 **  Keep accepting until we know otherwise.                 **                 **  We do a thread per connection.                 **  Up to the thread to close the connection when done.                 **                 **  This is known by me to be suboptimal, and I would rather                 **      do a thread pool if it ever becomes a resource issue.                 **  Any issues would simply point to a need to get                 **      more machines or a beefier machine to handle the                 **      requests, as well as a need to do thread pooling and                 **      avoid thread creation overhead.                 **  The threads are not tracked, except possibly by NSPR                 **      itself and PR_Cleanup will wait on them all to exit as                 **      user threads so our shared data is valid.                 */                while (0 == retval) {                    connection =                        PR_Accept(socket, NULL, PR_INTERVAL_NO_TIMEOUT);                    if (NULL != connection) {                        PRThread *clientThread = NULL;                        /*                         **  Thread per connection.                         */                        clientThread = PR_CreateThread(PR_USER_THREAD,  /* PR_Cleanup sync */                                                       handleClient, (void *) connection, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, /* IO enabled */                                                       PR_UNJOINABLE_THREAD,                                                       0);                        if (NULL == clientThread) {                            PRStatus closeRes = PR_SUCCESS;                            failureSum += __LINE__;                            REPORT_ERROR(__LINE__, PR_Accept);                            /*                             **  Close the connection as well, no service                             */                            closeRes = PR_Close(connection);                            if (PR_FAILURE == closeRes) {                                REPORT_ERROR(__LINE__, PR_Close);                            }                        }                    }                    else {                        failureSum += __LINE__;                        REPORT_ERROR(__LINE__, PR_Accept);                    }                }                if (0 != failureSum) {                    retval = __LINE__;                }                /*                 ** Output a little message saying it is all over.                 */                REPORT_INFO("server no longer accepting connections....");            }            else {                retval = __LINE__;                REPORT_ERROR(__LINE__, PR_Listen);            }        }        else {            retval = __LINE__;            REPORT_ERROR(__LINE__, PR_Bind);        }        /*         ** Done with socket.         */        closeRes = PR_Close(socket);        if (PR_SUCCESS != closeRes) {            retval = __LINE__;            REPORT_ERROR(__LINE__, PR_Close);        }        socket = NULL;    }    else {        retval = __LINE__;        REPORT_ERROR(__LINE__, PR_NewTCPSocket);    }    return retval;}