コード例 #1
0
ファイル: FskHTTPServer.c プロジェクト: archite/kinomajs
FskErr FskHTTPServerStart(FskHTTPServer http) {
	if (!http)
		return kFskErrInvalidParameter;

	if (http->stopped) {
		FskInstrumentedItemSendMessage(http, kFskHTTPInstrMsgServerStart, http);
		http->stopped = false;
		FskTimeGetNow(&http->stats.serverStarted);
	}
	else {
		FskInstrumentedItemSendMessage(http, kFskHTTPInstrMsgServerStartedAlready, http);
	}
	return kFskErrNone;
}
コード例 #2
0
FskErr FskSemaphoreNew_(FskSemaphore *sem, UInt32 value, FSK_SYNCHRONIZATION_DEBUG_ARGS)
#endif
{
	FskErr err;

	err = FskMemPtrNewClear(sizeof(FskSemaphoreRecord), (FskMemPtr *)sem);
	BAIL_IF_ERR(err);

	err = KplSemaphoreNew((KplSemaphore*)&(*sem)->kplSem, value);
	BAIL_IF_ERR(err);

	FskInstrumentedItemNew(*sem, NULL, &gFskSemaphoreTypeInstrumentation);
#if SUPPORT_INSTRUMENTATION && SUPPORT_SYNCHRONIZATION_DEBUG
	if (FskInstrumentedItemHasListeners(*sem)) {
		FskSynchronizationInstrMsgRecord msg;
		msg.file = file;
		msg.line = line;
		msg.function = function;
		FskInstrumentedItemSendMessage(*sem, kFskSynchronizationInstrMsgSemaphoreNew, &msg);
	}
#endif

bail:
	if ((err != kFskErrNone) && (*sem != NULL)) {
		KplSemaphoreDispose((*sem)->kplSem);
		FskMemPtrDispose(*sem);
		*sem = NULL;
	}

	return err;
}
コード例 #3
0
ファイル: FskHTTPServer.c プロジェクト: archite/kinomajs
FskErr FskHTTPServerStop(FskHTTPServer http, Boolean flush) {

	if (!http)
		return kFskErrInvalidParameter;

	if (http->stopped == false) {
		FskHTTPServerRequest request = http->activeRequests;
		http->stopped = true;
		FskTimeGetNow(&http->stats.serverStopped);
		// -- should we kill off live requests here?	no. can restart.
		// -- should we kill off active sessions here?	yes when waiting on a keep alive.
		while (request) {
			if (request->state == kHTTPReadRequestHeaders) {
				request->state = kHTTPClose;
				FskHTTPServerRequestCycle(request);
				request = http->activeRequests;
			}
			else
				request = request->next;
		}
	}
	else {
		FskInstrumentedItemSendMessage(http, kFskHTTPInstrMsgServerStoppedAlready, http);
	}
	return kFskErrNone;
}
コード例 #4
0
ファイル: FskNetInterface.c プロジェクト: kouis3940/kinomajs
// ---------------------------------------------------------------------
void sNotifyInterfaceNotifiers(FskNetInterfaceRecord *iface, UInt32 status) {
	FskNetInterfaceNotifier callback = NULL, next;
	FskThread thread = FskThreadGetCurrent();

	callback = (FskNetInterfaceNotifier)FskListMutexGetNext(interfaceChangeCBList, NULL);
	while (callback) {
		next = (FskNetInterfaceNotifier)FskListMutexGetNext(interfaceChangeCBList, callback);
#if 0 && SUPPORT_INSTRUMENTATION
		if (FskInstrumentedItemHasListeners(callback)) {
			FskNetInterfaceRecord *iface = (FskNetInterfaceRecord *)FskNetInterfaceFindByName(ifcName);
			FskInterfaceInstrData data;
			data.notf = callback;
			data.ifc = iface;
			data.status = status;
			FskInstrumentedItemSendMessage(callback, kFskNetInstrMsgInterfaceNotify, &data);
		}
#endif /* SUPPORT_INSTRUMENTATION */
		if (callback->thread != thread) {
			FskNetInterfaceRecord *interFace;
			if (kFskErrNone == FskMemPtrNewFromData(sizeof(FskNetInterfaceRecord), iface, &interFace)) {
				interFace->next = NULL;
				interFace->name = FskStrDoCopy(iface->name);

				// POST notify
				FskInstrumentedTypePrintfDebug(&gNetInterfaceNotifierTypeInstrumentation, " - posting callback to thread %s for interface %s", callback->thread->name, iface->name);
				FskThreadPostCallback(callback->thread, doNetIfcCallback, (void*)callback->callback, (void*)interFace, (void*)status, (void*)callback->param);
			}
		}
		else {
			FskInstrumentedTypePrintfDebug(&gNetInterfaceNotifierTypeInstrumentation, "callback->thread %s - call", callback->thread->name);
			(callback->callback)(iface, status, callback->param);
		}
		callback = next;
	}
}
コード例 #5
0
ファイル: FskHTTPServer.c プロジェクト: archite/kinomajs
FskHTTPServerListener FskHTTPServerListenerNew(FskHTTPServer http, int port, char *interfaceName) {
	FskHTTPServerListener	listener;
	FskErr			err;
	FskSocket		skt;
	FskNetInterfaceRecord *ifc = NULL;

	FskInstrumentedTypePrintfDebug(&gFskHTTPServerTypeInstrumentation, "httpServerListenerNew - interfaceName: %s\n", interfaceName);
	err = FskMemPtrNewClear(sizeof(FskHTTPServerListenerRecord), (FskMemPtr*)&listener);
	BAIL_IF_ERR(err);
	listener->http = http;
	listener->port = port;
	listener->ifcName = FskStrDoCopy(interfaceName);
	err = FskNetSocketNewTCP(&skt, true, "HTTP Server");
	if (err) {
		FskInstrumentedItemSendMessage(listener->http, kFskHTTPInstrMsgErrString, "listener socket create failed.");
		FskInstrumentedTypePrintfDebug(&gFskHTTPServerTypeInstrumentation, "httpServerListenerNew -  creating socket failed: %d\n", err);
        BAIL(kFskErrNoMoreSockets);
	}
	FskNetSocketReuseAddress(skt);
	ifc = FskNetInterfaceFindByName(listener->ifcName);
	if ((NULL == ifc) ||
		(kFskErrNone != (err = FskNetSocketBind(skt, ifc->ip, listener->port)))) {
		FskNetSocketClose(skt);
		FskInstrumentedTypePrintfDebug(&gFskHTTPServerTypeInstrumentation, "httpServerListenerNew - bind failed: %d port: %d\n", err, listener->port);
		listener->http->stats.connectionsAborted++;
		if (listener->http->callbacks)
			err = doCallCondition(listener->http->callbacks->serverCondition, listener->http, kFskHTTPConditionNoSocket, listener->http->refCon);
		goto bail;
	}

	listener->skt = skt;	
	FskNetSocketMakeNonblocking(skt);
	FskListAppend((FskList*)&listener->http->listeners, listener);
	FskInstrumentedTypePrintfDebug(&gFskHTTPServerTypeInstrumentation, "httpServerListenerNew -  about to listen\n");

	FskNetSocketListen(skt);
	FskThreadAddDataHandler(&listener->dataHandler, (FskThreadDataSource)skt, (FskThreadDataReadyCallback)httpServerListenerAcceptNewConnection, true, false, listener);

	FskInstrumentedItemSendMessage(listener->http, kFskHTTPInstrMsgNowListening, listener);
bail:
	FskNetInterfaceDescriptionDispose(ifc);
	if (err) {
		FskInstrumentedItemSendMessage(listener->http, kFskHTTPInstrMsgFailedListener, listener);
		FskMemPtrDisposeAt((void**)&listener);
	}
	return listener;
}
コード例 #6
0
FskErr FskSemaphoreAcquire_(FskSemaphore sem, FSK_SYNCHRONIZATION_DEBUG_ARGS)
#endif
{
#if SUPPORT_INSTRUMENTATION
#if SUPPORT_SYNCHRONIZATION_DEBUG
	if (FskInstrumentedItemHasListeners(sem)) {
		FskSynchronizationInstrMsgRecord msg;
		msg.file = file;
		msg.line = line;
		msg.function = function;
		FskInstrumentedItemSendMessage(sem, kFskSynchronizationInstrMsgSemaphoreAcquire, &msg);
	}
#else
	FskInstrumentedItemSendMessage(sem, kFskSynchronizationInstrMsgSemaphoreAcquire, sem);
#endif
#endif
	WaitForSingleObject(sem->hSem, INFINITE);
	return kFskErrNone;
}
コード例 #7
0
FskErr FskSemaphoreRelease_(FskSemaphore sem, FSK_SYNCHRONIZATION_DEBUG_ARGS)
#endif
{
#if SUPPORT_INSTRUMENTATION
#if SUPPORT_SYNCHRONIZATION_DEBUG
	if (FskInstrumentedItemHasListeners(sem)) {
		FskSynchronizationInstrMsgRecord msg;
		msg.file = file;
		msg.line = line;
		msg.function = function;
		FskInstrumentedItemSendMessage(sem, kFskSynchronizationInstrMsgSemaphoreRelease, &msg);
	}
#else
	FskInstrumentedItemSendMessage(sem, kFskSynchronizationInstrMsgSemaphoreRelease, sem);
#endif
#endif
	ReleaseSemaphore(sem->hSem, 1, NULL);
	return kFskErrNone;
}
コード例 #8
0
FskErr FskMutexRelease_(FskMutex mutex, FSK_SYNCHRONIZATION_DEBUG_ARGS)
#endif
{
#if SUPPORT_INSTRUMENTATION
#if SUPPORT_SYNCHRONIZATION_DEBUG
	if (FskInstrumentedItemHasListeners(mutex)) {
		FskSynchronizationInstrMsgRecord msg;
		msg.name = mutex->name;
		msg.file = file;
		msg.line = line;
		msg.function = function;
		FskInstrumentedItemSendMessage(mutex, kFskSynchronizationInstrMsgMutexRelease, &msg);
	}
#else
	FskInstrumentedItemSendMessage(mutex, kFskSynchronizationInstrMsgMutexRelease, mutex);
#endif
#endif
	KplMutexRelease(mutex->kplMutex);
	return kFskErrNone;
}
コード例 #9
0
ファイル: FskHTTPServer.c プロジェクト: archite/kinomajs
static FskErr httpServerListenerStart(FskHTTPServerListener listener, FskSocket skt) {
	FskErr err = kFskErrNone;
	FskHTTPServerRequest request;

	if (listener->http->stopped) {
		FskInstrumentedItemSendMessage(listener->http, kFskHTTPInstrMsgConnectionRefusedStopped, listener);
		listener->http->stats.connectionsRefused++;
		FskNetSocketClose(skt);
		goto bail;
	}
		
	err = FskMemPtrNewClear(sizeof(FskHTTPServerRequestRecord), (FskMemPtr*)&request);
	BAIL_IF_ERR(err);

	sFskHTTPServerRequestUpUse(request);

	request->http = listener->http;
	request->skt = skt;	
	FskNetSocketGetRemoteAddress(skt, (UInt32 *)&request->requesterAddress, &request->requesterPort);
	FskNetSocketMakeNonblocking(request->skt);
	err = FskHeaderStructNew(&request->requestHeaders);
	BAIL_IF_ERR(err);
	err = FskHeaderStructNew(&request->responseHeaders);
	BAIL_IF_ERR(err);
	request->in.bufferSize = request->http->defaultBufferSize;
	request->out.bufferSize = request->http->defaultBufferSize;
	err = FskMemPtrNew(request->in.bufferSize, (FskMemPtr*)&request->in.buf);
	BAIL_IF_ERR(err);
	err = FskMemPtrNew(request->out.bufferSize, (FskMemPtr*)&request->out.buf);
	BAIL_IF_ERR(err);

	FskListAppend((FskList*)&request->http->activeRequests, request);
	FskTimeCallbackNew(&request->cycleCallback);
	FskTimeCallbackNew(&request->keepAliveKillCallback);

	listener->http->stats.connectionsMade++;

	request->state = kHTTPNewSession;

	FskInstrumentedItemNew(request, NULL, &gFskHTTPServerRequestTypeInstrumentation);
	FskInstrumentedItemSetOwner(request, request->http);
	
	FskTimeCallbackScheduleNextRun(request->cycleCallback, httpServerTimeCycle, request);
	doCallCondition(request->http->callbacks->requestCondition, request, kFskHTTPConditionConnectionInitialized, request->refCon);
	FskTimeCallbackNew(&request->timer);
	FskTimeCallbackScheduleFuture(request->timer, 1, 0, KprHTTPServerTimerCallback, request);
bail:
	if (err)
		FskHTTPServerRequestDispose(request);
	return err;
}
コード例 #10
0
ファイル: FskHTTPServer.c プロジェクト: giapdangle/kinomajs
FskErr FskHTTPServerStop(FskHTTPServer http, Boolean flush) {

	if (!http)
		return kFskErrInvalidParameter;

	if (http->stopped == false) {
		http->stopped = true;
		FskTimeGetNow(&http->stats.serverStopped);
		// -- should we kill off live requests here?	no. can restart.
		// -- should we kill off active sessions here?
	}
	else {
		FskInstrumentedItemSendMessage(http, kFskHTTPInstrMsgServerStoppedAlready, http);
	}
	return kFskErrNone;
}
コード例 #11
0
ファイル: FskHTTPServer.c プロジェクト: archite/kinomajs
FskErr FskHTTPServerDispose(FskHTTPServer http) {
	FskInstrumentedTypePrintfDebug(&gFskHTTPServerTypeInstrumentation, "FskHTTPServerDispose %p  - useCount: %d\n", http, http ? http->useCount : 0);
	if (http) {
		// remove existing requests
		while (http->activeRequests) {
			FskHTTPServerRequest request = http->activeRequests;
			FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestRemainsOnClose, request);
			if (kFskErrNone != doCallCondition(http->callbacks->requestCondition, request, kFskHTTPConditionConnectionTerminating, request->refCon))
				FskHTTPServerRequestDispose(request);
		}

		FskNetInterfaceRemoveNotifier(http->interfaceNotifier);
		while (http->listeners)
			FskHTTPServerListenerDispose(http->listeners);

		sFskHTTPServerDownUse(http);
	}
	return kFskErrNone;
}
コード例 #12
0
FskErr FskMutexNew_(FskMutex *mutex, const char *name, FSK_SYNCHRONIZATION_DEBUG_ARGS)
#endif
{
	FskMutex mtx = NULL;
	FskErr err;

	err = FskMemPtrNewClear(sizeof(FskMutexRecord), (FskMemPtr *)&mtx);
	BAIL_IF_ERR(err);

	err = KplMutexNew((KplMutex*)&mtx->kplMutex);
	BAIL_IF_ERR(err);

#if SUPPORT_INSTRUMENTATION
	mtx->name = FskStrDoCopy_Untracked(name);
	FskInstrumentedItemNew(mtx, mtx->name, &gFskMutexTypeInstrumentation);

#if SUPPORT_SYNCHRONIZATION_DEBUG
	if (FskInstrumentedItemHasListeners(mtx)) {
		FskSynchronizationInstrMsgRecord msg;
		msg.name = name;
		msg.file = file;
		msg.line = line;
		msg.function = function;
		FskInstrumentedItemSendMessage(mtx, kFskSynchronizationInstrMsgMutexNew, &msg);
	}
#endif
#endif

bail:
	if ((err != kFskErrNone) && (mtx != NULL)) {
		KplMutexDispose(mtx->kplMutex);

#if SUPPORT_INSTRUMENTATION
		FskMemPtrDispose_Untracked((void*)mtx->name);
#endif
		FskMemPtrDispose(mtx);
		mtx = NULL;
	}

	*mutex = mtx;

	return err;
}
コード例 #13
0
FskErr FskSemaphoreDispose_(FskSemaphore sem, FSK_SYNCHRONIZATION_DEBUG_ARGS)
#endif
{
	if (sem) {
#if SUPPORT_INSTRUMENTATION && SUPPORT_SYNCHRONIZATION_DEBUG
		if (FskInstrumentedItemHasListeners(sem)) {
			FskSynchronizationInstrMsgRecord msg;
			msg.file = file;
			msg.line = line;
			msg.function = function;
			FskInstrumentedItemSendMessage(sem, kFskSynchronizationInstrMsgSemaphoreDispose, &msg);
		}
#endif
		CloseHandle(sem->hSem);
		FskInstrumentedItemDispose(sem);
		FskMemPtrDispose(sem);
	}
	return kFskErrNone;
}
コード例 #14
0
FskErr FskMutexNew_(FskMutex *mutex, const char *name, FSK_SYNCHRONIZATION_DEBUG_ARGS)
#endif
{
	FskErr err;
	pthread_mutexattr_t   attr;
	err = FskMemPtrNewClear(sizeof(FskMutexRecord), (FskMemPtr *)mutex);
	BAIL_IF_ERR(err);

	if ((pthread_mutexattr_init(&attr) != 0) ||
		(pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) != 0) ||
		(pthread_mutex_init(&(*mutex)->mutex, &attr) != 0)) {
		BAIL(kFskErrOperationFailed);
	}

#if SUPPORT_INSTRUMENTATION
	(*mutex)->name = FskStrDoCopy_Untracked(name);
	FskInstrumentedItemNew(*mutex, NULL, &gFskMutexTypeInstrumentation);

#if SUPPORT_SYNCHRONIZATION_DEBUG
	if (FskInstrumentedItemHasListeners(*mutex)) {
		FskSynchronizationInstrMsgRecord msg;
		msg.name = name;
		msg.file = file;
		msg.line = line;
		msg.function = function;
		FskInstrumentedItemSendMessage(*mutex, kFskSynchronizationInstrMsgMutexNew, &msg);
	}
#endif
#endif

bail:
	pthread_mutexattr_destroy(&attr);

	if ((err != kFskErrNone) && (*mutex != NULL)) {
#if SUPPORT_INSTRUMENTATION
		FskMemPtrDispose((FskMemPtr)(*mutex)->name);
#endif
		FskMemPtrDispose(*mutex);
		*mutex = NULL;
	}

	return err;
}
コード例 #15
0
FskErr FskSemaphoreNew_(FskSemaphore *sem, UInt32 value, FSK_SYNCHRONIZATION_DEBUG_ARGS)
#endif
{
	FskErr err;

	err = FskMemPtrNewClear(sizeof(FskSemaphoreRecord), (FskMemPtr *)sem);
	BAIL_IF_ERR(err);

#if TARGET_OS_MAC
	{
		FskSemaphore s = *sem;
		snprintf(s->name, sizeof(s->name)-1, "/tmp/sem%lx", (unsigned long)s);
		if ((s->hSem = sem_open(s->name, O_CREAT|O_EXCL, 666, value)) == NULL) {
			BAIL(kFskErrOperationFailed);
		}
	}
#else
	if (sem_init(&(*sem)->hSem, 0, value) != 0) {
		BAIL(kFskErrOperationFailed);
	}
#endif

	FskInstrumentedItemNew(*sem, NULL, &gFskSemaphoreTypeInstrumentation);
#if SUPPORT_INSTRUMENTATION && SUPPORT_SYNCHRONIZATION_DEBUG
	if (FskInstrumentedItemHasListeners(*sem)) {
		FskSynchronizationInstrMsgRecord msg;
		msg.file = file;
		msg.line = line;
		msg.function = function;
		FskInstrumentedItemSendMessage(*sem, kFskSynchronizationInstrMsgSemaphoreNew, &msg);
	}
#endif

bail:
	if ((err != kFskErrNone) && (*sem != NULL)) {
		FskMemPtrDispose(*sem);
		*sem = NULL;
	}

	return err;
}
コード例 #16
0
FskErr FskMutexNew_(FskMutex *mutex, const char *name, FSK_SYNCHRONIZATION_DEBUG_ARGS)
#endif
{
	FskErr err;

	err = FskMemPtrNewClear(sizeof(FskMutexRecord), (FskMemPtr *)mutex);
	BAIL_IF_ERR(err);

	InitializeCriticalSection(&(*mutex)->cs);

#if SUPPORT_INSTRUMENTATION
	(*mutex)->name = FskStrDoCopy_Untracked(name);
	FskInstrumentedItemNew(*mutex, (*mutex)->name, &gFskMutexTypeInstrumentation);

#if SUPPORT_SYNCHRONIZATION_DEBUG
	if (FskInstrumentedItemHasListeners(*mutex)) {
		FskSynchronizationInstrMsgRecord msg;
		msg.name = name;
		msg.file = file;
		msg.line = line;
		msg.function = function;
		FskInstrumentedItemSendMessage(*mutex, kFskSynchronizationInstrMsgMutexNew, &msg);
	}
#endif
#endif

bail:
	if ((err != kFskErrNone) && (*mutex != NULL)) {
#if SUPPORT_INSTRUMENTATION
		FskMemPtrDispose_Untracked((*mutex)->name);
#endif
		FskMemPtrDispose(*mutex);
		*mutex = NULL;
	}

	return err;
}
コード例 #17
0
FskErr FskMutexDispose_(FskMutex mutex, FSK_SYNCHRONIZATION_DEBUG_ARGS)
#endif
{
	if (mutex) {
#if SUPPORT_INSTRUMENTATION && SUPPORT_SYNCHRONIZATION_DEBUG
		if (FskInstrumentedItemHasListeners(mutex)) {
			FskSynchronizationInstrMsgRecord msg;
			msg.name = mutex->name;
			msg.file = file;
			msg.line = line;
			msg.function = function;
			FskInstrumentedItemSendMessage(mutex, kFskSynchronizationInstrMsgMutexDispose, &msg);
		}
#endif
		KplMutexDispose(mutex->kplMutex);
		FskInstrumentedItemDispose(mutex);
#if SUPPORT_INSTRUMENTATION
		FskMemPtrDispose_Untracked((void*)mutex->name);
#endif
		FskMemPtrDispose(mutex);
	}

	return kFskErrNone;
}
コード例 #18
0
UInt32 FskMutexTrylock_(FskMutex mutex, FSK_SYNCHRONIZATION_DEBUG_ARGS)
#endif
{
#if SUPPORT_INSTRUMENTATION
	int ret;
#if SUPPORT_SYNCHRONIZATION_DEBUG
	FskSynchronizationInstrMsgRecord msg;
	if (FskInstrumentedItemHasListeners(mutex)) {
		msg.name = mutex->name;
		msg.file = file;
		msg.line = line;
		msg.function = function;
		FskInstrumentedItemSendMessage(mutex, kFskSynchronizationInstrMsgMutexTrylock, &msg);
	}
#else
	FskInstrumentedItemSendMessage(mutex, kFskSynchronizationInstrMsgMutexTrylock, mutex);
#endif
	ret = KplMutexTrylock(mutex->kplMutex);
	if (0 == ret) {
#if SUPPORT_SYNCHRONIZATION_DEBUG
		FskInstrumentedItemSendMessage(mutex, kFskSynchronizationInstrMsgMutexTrylockSucceeded, &msg);
#else
		FskInstrumentedItemSendMessage(mutex, kFskSynchronizationInstrMsgMutexTrylockSucceeded, mutex);
#endif
	}
	else {
#if SUPPORT_SYNCHRONIZATION_DEBUG
		FskInstrumentedItemSendMessage(mutex, kFskSynchronizationInstrMsgMutexTrylockFailed, &msg);
#else
		FskInstrumentedItemSendMessage(mutex, kFskSynchronizationInstrMsgMutexTrylockFailed, mutex);
#endif
	}
	return ret;

#else

	return KplMutexTrylock(mutex->kplMutex);
#endif
}
コード例 #19
0
ファイル: FskHTTPServer.c プロジェクト: archite/kinomajs
static void httpServerEngineCycle(void *param) {
	FskErr err = kFskErrNone, retVal = kFskErrNeedMoreTime;
	FskHTTPServerRequest request = (FskHTTPServerRequest)param;
	int amt, ret, chunkSize = 0;
	UInt32 chunkSizeL;
	char *s, *p;
	Boolean readSomeMore, needsDispose = false;

	FskThreadRemoveDataHandler(&request->dataHandler);
	
	switch (request->state) {
		case kHTTPNewSession:
			FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request);
			FskTimeGetNow(&request->stats.requestStarted);
			request->state = kHTTPReadRequestHeaders;
			
		case kHTTPReadRequestHeaders:
			FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request);
			shoveBuffer(request->in);
			amt = request->in.bufferSize - request->in.max;
			if (amt) {
				err = FskNetSocketRecvTCP(request->skt, &request->in.buf[request->in.max], amt, &ret);
				switch (err) {
					case kFskErrNone:
#if SUPPORT_INSTRUMENTATION
						if (FskInstrumentedItemHasListeners(request)) {
							FskHTTPInstrMsgDataRecord msg;
							msg.buffer = &request->in.buf[request->in.max];
							msg.amt = ret;
							FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestRecvData, &msg);
						}
#endif
						request->http->stats.requestsStarted += 1;
						request->in.max += ret;
						request->state = kHTTPProcessRequestHeaders;
						request->stats.bytesReceived += ret;
						request->http->stats.bytesReceived += ret;
						break;
					case kFskErrNoData:
						retVal = kFskErrNoData;
						break;
					case kFskErrConnectionClosed:
						if (request->stats.bytesReceived) {
							request->state = kHTTPSocketError;
						}
						else {
							request->state = kHTTPDone;
						}
						break;
					default:
						FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgErrString, "kHTTPReadRequestHeaders: RecvTCP - error");
						request->state = kHTTPSocketError;
						break;
				}
			}
			else
				request->state = kHTTPProcessRequestHeaders;

			if (request->state != kHTTPProcessRequestHeaders)
				break;

		case kHTTPProcessRequestHeaders:
			FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request);
			amt = request->in.max - request->in.pos;
			if (amt) {
				ret = FskHeadersParseChunk(&request->in.buf[request->in.pos], amt, kFskHeaderTypeRequest, request->requestHeaders);
				if (ret < 0) {
					err = kFskErrBadData;
					request->state = kHTTPSocketError;
					break;
				}
				request->in.pos += ret;
				
				if (request->requestHeaders->headersParsed) {
					httpProcessRequestHeaders(request);
				}
				else if (ret != amt) {
					// odd case - we didn't consume all the data, but
					// the header parsing isn't complete.
					request->state = kHTTPServerError;
				}
			}
			else 
				request->state = kHTTPReadRequestHeaders;

			if (request->state != kHTTPReadRequestBody)
				break;

		case kHTTPReadRequestBody:
			FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request);
			readSomeMore = false;
			amt = request->in.max - request->in.pos;
			if (request->requestBodyContentLength > 0) {
				if (amt) {
					request->state = kHTTPProcessRequestBody;
				}
				else {
					request->in.max = 0;
					request->in.pos = 0;
					readSomeMore = true;
				}
			}
			else if (request->requestBodyChunked) {		// chunked
				if (amt == 0) {
					readSomeMore = true;
				}
				else {
					p = &request->in.buf[request->in.pos];
					while ((amt > 1) && lineEnd(p)) {
						// consume line-ends
						amt -= 2;
						request->in.pos += 2;
						p += 2;
					}
					while ((amt > 1) && !lineEnd(p)) {
						// scan for chunk size
						amt--;
						p++;
					}
					if ((amt > 1) && lineEnd(p)) {
						// convert the chunksize
						s = &request->in.buf[request->in.pos];
						chunkSize = FskStrHexToNum(s, p-s);
						p += 2;		//lineend
						request->requestBodyContentLength = chunkSize;
						request->in.pos += (p-s);
						request->state = kHTTPReadRequestBody;
						if (0 == chunkSize)	{
							// we've read the end indicator (0)
							if ((amt > 1) && lineEnd(p))
								request->in.pos += 2;			// consume last cr/lf							}
							request->requestBodyChunked = false;
						}
					}
					else {
						readSomeMore = true;
					}
				}
			}
			else {
				// we're done reading chunks
				// we're done reading the request
				request->state = kHTTPPrepareResponse;
				doCallCondition(request->http->callbacks->requestCondition, request, kFskHTTPConditionRequestRequestFinished, request->refCon);
			}

			if (readSomeMore) {
				shoveBuffer(request->in);
				err = FskNetSocketRecvTCP(request->skt, &request->in.buf[request->in.max], request->in.bufferSize - request->in.max, &ret);
				switch (err) {
					case kFskErrNone:
#if SUPPORT_INSTRUMENTATION
						if (FskInstrumentedItemHasListeners(request)) {
							FskHTTPInstrMsgDataRecord msg;
							msg.buffer = &request->in.buf[request->in.max];
							msg.amt = ret;
							FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestRecvData, &msg);
						}
#endif
						request->in.max += ret;
						if (request->requestBodyChunked) 		// chunked?
							request->state = kHTTPReadRequestBody;
						else
							request->state = kHTTPProcessRequestBody;

						request->stats.bytesReceived += ret;
						request->http->stats.bytesReceived += ret;
						break;
					case kFskErrNoData:
						retVal = kFskErrNoData;
						break;
					default:
						FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgErrString, "kHTTPReadRequestBody: RecvTCP - error");
						request->http->stats.requestsFailed += 1;
						request->state = kHTTPSocketError;
						break;
				}
			}

			if (request->state != kHTTPProcessRequestBody)
				break;

		case kHTTPProcessRequestBody:
			FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request);
			amt = request->in.max - request->in.pos;
			if (amt > request->requestBodyContentLength) {
				if (false == request->requestBodyChunked)
					request->requestBodyContentLength = amt;
				else
					amt = request->requestBodyContentLength;
			}
			chunkSizeL = (UInt32)chunkSize;
			err = doDataCallback(request->http->callbacks->requestReceiveRequest, request, &request->in.buf[request->in.pos], amt, &chunkSizeL, request->refCon);
			chunkSize = (int)chunkSizeL;
			if (kFskErrNone == err) {
				if (chunkSize) {
					request->in.pos += chunkSize;
					request->requestBodyContentLength -= chunkSize;
					request->stats.requestBodyReceived += chunkSize;
					if (false == request->requestBodyChunked) {
						if (0 == request->requestBodyContentLength)
							request->state = kHTTPPrepareResponse;
						else
							request->state = kHTTPReadRequestBody;
					}
					else
						request->state = kHTTPReadRequestBody;
				}
				else {
					// data callback wants to suspend the session and not
					// consume the chunk, it can do so
					if (request->state != kHTTPSessionSuspend)
						request->state = kHTTPServerError;
				}
			}
			else {
				// the data callback returned an error.
				if (request->state != kHTTPSessionSuspend)
					request->state = kHTTPServerError;
			}

			if (request->state != kHTTPPrepareResponse)
				break;
			doCallCondition(request->http->callbacks->requestCondition, request, kFskHTTPConditionRequestRequestFinished, request->refCon);
			if (request->state != kHTTPPrepareResponse)
				break;

		case kHTTPPrepareResponse:
			FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request);
			request->state = kHTTPProcessResponse;
			err = doCallCondition(request->http->callbacks->requestCondition, request, kFskHTTPConditionRequestGenerateResponseHeaders, request->refCon);
			if (err == kFskErrNeedMoreTime)
				request->state = kHTTPSessionSuspend;
			else if (err)
				request->responseHeaders->responseCode = 500;
				
			if (request->state != kHTTPProcessResponse)
				break;
				
		case kHTTPProcessResponse:
			request->state = kHTTPGetDataChunk;
			httpPrepareResponseHeaders(request);
			if (request->state != kHTTPGetDataChunk)
				break;

		case kHTTPGetDataChunk:
			FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request);
			if (0 == FskStrCompare(kFskStrHEAD, FskHeaderMethod(request->requestHeaders))) {
				request->state = kHTTPSendDataChunk;
				request->nextState = kHTTPSetupNextRequest;
				break;
			}
			p = &request->out.buf[request->out.max];
			if (request->transferEncoding == kFskTransferEncodingChunked) {
				request->out.max += 6;
			}
			chunkSize = 0;
			amt = (request->out.bufferSize - request->out.max) - 2;
			// fetch response data from callback
			chunkSizeL = (UInt32)chunkSize;
			err = doDataCallback(request->http->callbacks->requestGenerateResponseBody, request, &request->out.buf[request->out.max], amt, &chunkSizeL, request->refCon);
			chunkSize = (int)chunkSizeL;
			FskInstrumentedTypePrintfDebug(&gFskHTTPServerTypeInstrumentation, "doDataCallback returns err: %d, chunkSize: %d\n", err, chunkSize);
			if ((kFskErrNone != err) && (kFskErrEndOfFile != err)) {
				FskInstrumentedTypePrintfDebug(&gFskHTTPServerTypeInstrumentation, "about to doCallCondition -requestResponseFinished - FAIL\n");
				doCallCondition(request->http->callbacks->requestCondition, request, kFskHTTPConditionRequestResponseFinished, request->refCon);
				request->http->stats.requestsFailed += 1;
				request->state = kHTTPServerError;
				break;
			}
			request->out.max += chunkSize;
			if ((0 == chunkSize) && (request->state == kHTTPSessionSuspend)) {
                if (kFskTransferEncodingChunked == request->transferEncoding)
                    request->out.max -= 6;
				break;
            }

			request->state = kHTTPSendDataChunk;
			if ((chunkSize == 0) || (kFskErrEndOfFile == err)) {
				request->nextState = kHTTPSetupNextRequest;
			}
			else
				request->nextState = kHTTPGetDataChunk;
			if (request->transferEncoding == kFskTransferEncodingChunked) {
				FskStrNumToHex(chunkSize, p, 4);
				p += 4;
				*p++ = kFskCR;
				*p++ = kFskLF;
				if (chunkSize)
					p += chunkSize;
				*p++ = kFskCR;
				*p++ = kFskLF;
				request->out.max += 2;
			}
			request->stats.bodyBytesSent += chunkSize;

			if (request->state != kHTTPSendDataChunk)
				break;

		case kHTTPSendDataChunk:
			FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request);
			FskInstrumentedTypePrintfDebug(&gFskHTTPServerTypeInstrumentation, " - request->out.max %d - request->out.pos %d\n", request->out.max, request->out.pos);
			amt = request->out.max - request->out.pos;
			if (0 == amt) {
				FskInstrumentedTypePrintfDebug(&gFskHTTPServerTypeInstrumentation, "amt is zero now - transition to next state.\n");
				request->state = request->nextState;
				break;
			}
			err = FskNetSocketSendTCP(request->skt, &request->out.buf[request->out.pos], amt, &ret);
			switch (err) {
				case kFskErrNone:
#if SUPPORT_INSTRUMENTATION
					if (FskInstrumentedItemHasListeners(request)) {
						FskHTTPInstrMsgDataRecord msg;
						msg.buffer = &request->out.buf[request->out.pos];
						msg.amt = ret;
						FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestSendData, &msg);
					}
#endif
					request->out.pos += ret;
					request->stats.bytesSent += ret;
					request->http->stats.bytesSent += ret;
					if (request->transferEncoding == kFskTransferEncodingChunked) {
						request->stats.bytesSent -= 8;
					}
					if (request->out.pos == request->out.max) {
						request->out.pos = 0;
						request->out.max = 0;
						request->state = request->nextState;
					}
					break;
				case kFskErrNoData:
					retVal = kFskErrSocketFull;
					break;
				default:
					FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgErrString, "kHTTPSendDataChunk: SendTCP - error");
					request->state = kHTTPSocketError;
					request->http->stats.requestsFailed += 1;
					break;
			}			

			if (request->state != kHTTPSetupNextRequest)
				break;

		case kHTTPSetupNextRequest:
			FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request);
			FskTimeGetNow(&request->stats.requestStopped);
			request->http->stats.requestsFinished += 1;
			doCallCondition(request->http->callbacks->requestCondition, request, kFskHTTPConditionRequestResponseFinished, request->refCon);
			request->state = kHTTPDone;
			if (request->keepAlive && !request->http->stopped) {
				if ((request->in.max - request->in.pos) > 0) {
					FskHeaderStructDispose(request->requestHeaders);
					FskHeaderStructDispose(request->responseHeaders);
					FskHeaderStructNew(&request->requestHeaders);
					FskHeaderStructNew(&request->responseHeaders);
					request->keepAlive = false;
					request->out.max = 0;
					request->out.pos = 0;
					FskMemSet(&request->stats, 0, sizeof(request->stats));
					FskTimeGetNow(&request->stats.requestStarted);
					request->state = kHTTPProcessRequestHeaders;
				}
			}

			if (request->state != kHTTPDone)
				break;

		case kHTTPDone:
			FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request);
			if (request->keepAlive && !request->http->stopped) {
				FskHeaderStructDispose(request->requestHeaders);
				FskHeaderStructDispose(request->responseHeaders);
				FskHeaderStructNew(&request->requestHeaders);
				FskHeaderStructNew(&request->responseHeaders);
				request->keepAlive = false;
				request->in.max = 0;
				request->in.pos = 0;
				request->out.max = 0;
				request->out.pos = 0;
				FskMemSet(&request->stats, 0, sizeof(request->stats));
				retVal = kFskErrNoData;		// will cause data handler to be installed 
				request->state = kHTTPNewSession;
			}
			else {
				request->state = kHTTPClose;
				retVal = kFskErrNeedMoreTime;
			}
			break;

		case kHTTPFulfillExpectation:
			FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request);
			request->state = kHTTPSendDataChunk;
			request->nextState = kHTTPReadRequestBody;
			request->out.max += snprintf(request->out.buf, request->out.bufferSize, "%s %d %s\r\n\r\n", httpProtocolVersionString(request), 100, FskFindResponse(100));
			break;

		case kHTTPDenyExpectation:
			FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request);
			request->state = kHTTPSendDataChunk;
			request->nextState = kHTTPDone;
			request->out.max += snprintf(request->out.buf, request->out.bufferSize, "%s %d %s\r\n\r\n", httpProtocolVersionString(request), 417, FskFindResponse(417));
			break;

		case kHTTPServerError:
			FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request);
			request->state = kHTTPSocketError;
			// fall through
		case kHTTPSocketError:
			FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request);
			request->http->stats.connectionsAborted++;
			doCallCondition(request->http->callbacks->requestCondition, request, kFskHTTPConditionRequestErrorAbort, request->refCon);
			request->state = kHTTPClose;
			// fall through
		case kHTTPClose:
			FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request);
			request->state = kHTTPRequestComplete;
			needsDispose = true;
			break;

		case kHTTPRequestComplete:
			FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request);
			retVal = kFskErrNone;				// request is finished, don't call back
			break;

		case kHTTPSessionSuspend:
			FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request);
			retVal = kFskErrNone;				// do nothing in suspend state
			break;
		
		default:
			FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request);
			request->state = kHTTPClose;		// unknown state
			break;
			;
	}

	if ((request->state == kHTTPServerError)
		|| (request->state == kHTTPSocketError)
		|| (request->state == kHTTPDone)
		|| (request->state == kHTTPClose))
		retVal = kFskErrNeedMoreTime;

	if (retVal == kFskErrNoData) {
		FskThreadAddDataHandler(&request->dataHandler, (FskThreadDataSource)request->skt, httpServerDataHandler, true, false, request);
	}
	else if (retVal == kFskErrSocketFull) {
		FskThreadAddDataHandler(&request->dataHandler, (FskThreadDataSource)request->skt, httpServerDataHandler, false, true, request);
	}
	else if (retVal == kFskErrNeedMoreTime) {
		FskTimeCallbackScheduleNextRun(request->cycleCallback, httpServerTimeCycle, request);
	}
	else if (retVal == kFskErrNone) {
		// nothing doin
	}
	else {
		FskInstrumentedTypePrintfDebug(&gFskHTTPServerTypeInstrumentation, "httpCycle - weird retVal %d\n", retVal);
	}

	if (needsDispose) {
		FskListRemove((FskList*)&request->http->activeRequests, request);
		FskTimeCallbackDispose(request->keepAliveKillCallback);
		request->keepAliveKillCallback = NULL;
		if (kFskErrNone != doCallCondition(request->http->callbacks->requestCondition, request, kFskHTTPConditionConnectionTerminating, request->refCon))
			FskHTTPServerRequestDispose(request);
	}
	else {
		if ((retVal == kFskErrNeedMoreTime) || ((retVal != kFskErrNone) && request->keepAlive)) {
			FskTimeCallbackScheduleFuture(request->keepAliveKillCallback, FskHTTPServerRequestGetKeepAliveTimeout(request), 0, httpKillKeepAlive, request);
		}
	}

}
コード例 #20
0
ファイル: FskHTTPServer.c プロジェクト: archite/kinomajs
static void httpKillKeepAlive(FskTimeCallBack cb, const FskTime when, void *param) {
	FskHTTPServerRequest request = (FskHTTPServerRequest)param;
	FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestKillIdle, request);
	request->state = kHTTPClose;
	httpServerEngineCycle(param);
}