📄 servutil.c
字号:
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- *//* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Netscape security libraries. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. */#include "serv.h"#include "secport.h"#include "collectn.h"#include "resource.h"#include "connect.h"#include "plstr.h"#include "prprf.h"#include "base64.h"#include "textgen.h"#include "protocolf.h"#include "p12res.h"#include "ctrlconn.h"#include "newproto.h"#include "messages.h"#ifdef XP_UNIX#include "private/pprio.h"#include <unistd.h>#define GET_LOCK_FILE_PATH(b) \ sprintf(b, "/tmp/.nsmc-%d-lock", (int)geteuid())#define GET_CONTROL_SOCK_PATH(b) \ sprintf(b, "/tmp/.nsmc-%d", (int)geteuid())PRFileDesc *lockfile = NULL;#endif#define DEBUG_QUEUESextern SSMCollection * connections;/* Dumps a (potentially binary) buffer using SSM_DEBUG. (We could have used the version in ssltrace.c, but that's specifically tailored to SSLTRACE.) */#define DUMPBUF_LINESIZE 8voidSSM_DumpBuffer(char *buf, PRIntn len){ char hexbuf[DUMPBUF_LINESIZE*3+1]; char chrbuf[DUMPBUF_LINESIZE+1]; static const char *hex = "0123456789abcdef"; PRIntn i = 0, l = 0; char ch, *c, *h; hexbuf[DUMPBUF_LINESIZE*3] = '\0'; chrbuf[DUMPBUF_LINESIZE] = '\0'; (void) memset(hexbuf, 0x20, DUMPBUF_LINESIZE*3); (void) memset(chrbuf, 0x20, DUMPBUF_LINESIZE); h = hexbuf; c = chrbuf; while (i < len) { ch = buf[i]; if (l == DUMPBUF_LINESIZE) { SSM_DEBUG("%s%s\n", hexbuf, chrbuf); (void) memset(hexbuf, 0x20, DUMPBUF_LINESIZE*3); (void) memset(chrbuf, 0x20, DUMPBUF_LINESIZE); h = hexbuf; c = chrbuf; l = 0; } /* Convert a character to hex. */ *h++ = hex[(ch >> 4) & 0xf]; *h++ = hex[ch & 0xf]; h++; /* Put the character (if it's printable) into the character buffer. */ if ((ch >= 0x20) && (ch <= 0x7e)) *c++ = ch; else *c++ = '.'; i++; l++; } SSM_DEBUG("%s%s\n", hexbuf, chrbuf);}PRIntn SSM_ReadThisMany(PRFileDesc * sockID, void * buffer, PRIntn thisMany){ int got = 0; PRIntn total = 0; while (total < thisMany) { got = PR_Recv(sockID, (void *)((char *)buffer + total), thisMany-total, 0, PR_INTERVAL_NO_TIMEOUT); if (got <= 0 ) break; total += got; } /* Clear the PR error if we got EOF in the final read, as opposed to -1 bytes. */ if (got == 0) PR_SetError(0, 0); return total;} PRIntn SSM_WriteThisMany(PRFileDesc * sockID, void * buffer, PRIntn thisMany){ PRIntn total = 0; while (total < thisMany) { PRIntn got; got = PR_Send(sockID, (void *)((char *)buffer+total), thisMany-total, 0, PR_INTERVAL_NO_TIMEOUT); if (got < 0) break; total += got; } return total;}SECItem * SSM_ConstructMessage(PRUintn size) { SECItem * ptr = NULL; #if 0 SSM_DEBUG("allocating message of size %ld.\n", (long) size);#endif ptr = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); if (!ptr) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); goto loser; } ptr->len = size; if (size > 0) { ptr->data = (unsigned char *)PORT_ZAlloc(size); if (!ptr->data) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); goto loser; } } return ptr;loser: SSM_FreeMessage(ptr); return NULL;}void SSM_FreeMessage(SECItem * msg){ if (!msg) return; if (msg->data) PORT_Free(msg->data); PORT_Free(msg);}voidssm_DrainAndDestroyQueue(SSMCollection **coll){ SSMCollection *v; PRIntn type, len; char *data; if ((coll == NULL) || (*coll == NULL)) return; v = *coll; /* Drain the collection. Don't block; presumably this is being done at destruction time. */ while(SSM_RecvQMessage(v, SSM_PRIORITY_ANY, &type, &len, &data, PR_FALSE) == PR_SUCCESS) { if (data) PR_Free(data); }#if 0 /* NotifyAll on the lock and yield time. */ /* ### mwelch - Causing problems on Linux, and shouldn't even be here since we don't have the queue locked, so I'm removing it. */ PR_NotifyAll(v->lock);#endif /* Destroy the collection. */ SSM_DestroyCollection(v); /* Zero out the original member. */ *coll = NULL;}voidssm_DrainAndDestroyChildCollection(SSMCollection **coll){ SSMCollection *v; SSMConnection *conn; if ((coll == NULL) || (*coll == NULL)) return; v = *coll; /* Drain the collection. Don't block; presumably this is being done at destruction time. */ while(SSM_Dequeue(v, SSM_PRIORITY_ANY, (void **) &conn, PR_FALSE) == PR_SUCCESS); /* Destroy the collection. */ SSM_DestroyCollection(v); /* Zero out the original member. */ *coll = NULL;}static SSMHashTable *ssmThreads = NULL;void SSM_ConnectionThreadName(char *buf){ PRThread * threadptr = PR_GetCurrentThread(); char *name; buf[0] = '\0'; /* in case we fail */ if (!ssmThreads) return; if (SSM_HashFind(ssmThreads, (SSMHashKey) threadptr, (void **) &name) != SSM_SUCCESS) return; if (name) PL_strcpy(buf, name);}static SSMCollection *logSockets = NULL;static PRMonitor *logSocketLock = NULL;/* Add the filedesc to a list of sockets to receive log output */SSMStatusSSM_AddLogSocket(PRFileDesc *fd){ SSMStatus rv = SSM_SUCCESS; PR_ASSERT(logSockets); PR_ASSERT(logSocketLock); PR_EnterMonitor(logSocketLock); rv = SSM_Enqueue(logSockets, SSM_PRIORITY_NORMAL, fd); PR_ExitMonitor(logSocketLock); if (rv != SSM_SUCCESS) SSM_DEBUG("SSM_AddLogSocket returned error %d.\n", rv); return rv;}#ifdef XP_MAC/* Each thread, when registering itself using one of the two functions below, assigns itself as private data at index (thdIndex). This is necessary because when a thread exits, we want it to delete itself from the list of threads we need to kill at exit time. */extern PRUintn thdIndex;#endif/* Called by a newly created thread, this associates a name with the thread. */voidSSM_RegisterThread(char *threadName, SSMResource *ptr){ SSMStatus rv = SSM_SUCCESS; PRThread *thr = PR_GetCurrentThread(); char *value;#ifdef XP_MAC if (thdIndex > 0) PR_SetThreadPrivate(thdIndex, PR_GetCurrentThread());#endif if (ptr) { PR_ASSERT(SSM_IsAKindOf(ptr, SSM_RESTYPE_RESOURCE)); /* Increment the thread count for this resource. */ SSM_LockResource(ptr); ptr->m_threadCount++; SSM_UnlockResource(ptr); } if (threadName) { if (ptr) value = PR_smprintf("%s %p", threadName, ptr); else value = PL_strdup(threadName); } else value = PR_smprintf("unknown %p/%p", thr, ptr); if ((!ssmThreads) && ((rv = SSM_HashCreate(&ssmThreads)) != SSM_SUCCESS)) return; if (!value) return; SSM_HashInsert(ssmThreads, (SSMHashKey) thr, value);}/* Called by a newly created thread, this associates a name with the thread. */voidSSM_RegisterNewThread(char *threadName, SSMResource *ptr){ SSMStatus rv = SSM_SUCCESS; PRThread *thr = PR_GetCurrentThread(); char *value; if (threadName) { if (ptr) value = PR_smprintf("%s %p", threadName, ptr); else value = PL_strdup(threadName); } else value = PR_smprintf("unknown %p/%p", thr, ptr); if ((!ssmThreads) && ((rv = SSM_HashCreate(&ssmThreads)) != SSM_SUCCESS)) return; if (!value) return; SSM_HashInsert(ssmThreads, (SSMHashKey) thr, value);}void SSM_Debug(SSMResource *conn, char *msg){#ifdef DEBUG char name[256]; SSM_ConnectionThreadName(name); printf("%s: %s", name, msg); fflush(stdout); PR_Free(msg);#endif}void SSM_DebugP(char *fmt, ...){#ifdef DEBUG char *tmp = NULL, *tmp2 = NULL; char *timeStamp = NULL; PRFileDesc *sock = NULL; PRIntn len; PRIntn numWritten; char name[256]; va_list argp; PRIntn count, i; PRUint32 rv = 0; PRExplodedTime exploded; /* protect against another socket add */ PR_EnterMonitor(logSocketLock); if (!logSockets) goto done; count = SSM_Count(logSockets); if (count == 0) goto done; va_start(argp, fmt); tmp = PR_vsmprintf(fmt, argp); va_end(argp); if (!tmp) goto done; PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &exploded); timeStamp = PR_smprintf("%02i:%02i:%02i.%03i", exploded.tm_hour, exploded.tm_min, exploded.tm_sec, exploded.tm_usec/1000); SSM_ConnectionThreadName(name); tmp2 = PR_smprintf("[%s] %s: %s", timeStamp, name, tmp); if (!tmp2) goto done; len = strlen(tmp2); count = SSM_Count(logSockets); /* count backwards in case we get an error */ for(i=(count-1);i>=0;i--) { numWritten = 0; sock = (PRFileDesc *) SSM_At(logSockets, i); if (sock) numWritten = PR_Write(sock, tmp2, len); if (numWritten < len) { SSM_Remove(logSockets, sock); /*PR_Close(sock);*/ /*PR_Shutdown(sock, PR_SHUTDOWN_BOTH);*/ rv = 0; } } done: if (tmp) PR_smprintf_free(tmp);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -