void xs_gpio_repeat(xsMachine* the) { FskGPIO gpio = xsGetHostData(xsThis); if (gpio) { if (in != gpio->direction) xsThrowDiagnosticIfFskErr(kFskErrUnimplemented, "Digital pin %d cannot repeat on output pin", (int)gpio->pinNum); if (gpio->poller) FskListRemove(&gGPIOPollers, gpio); gpio->poller = (xsTest(xsArg(0))) ? xsGetHostData(xsArg(0)) : NULL; if (gpio->poller) { FskListAppend(&gGPIOPollers, gpio); gpio->pollerValue = -1; // won't match if (NULL == gGPIOPoller) { FskTimeCallbackNew(&gGPIOPoller); FskTimeCallbackScheduleNextRun(gGPIOPoller, gpioPoller, NULL); } } else if ((NULL == gGPIOPollers) && (NULL != gGPIOPoller)) { FskTimeCallbackDispose(gGPIOPoller); gGPIOPoller = NULL; } } }
void DNSSD_API KprZeroconfPlatformGetAddrInfoCallBack(DNSServiceRef serviceRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *hostname, const struct sockaddr *address, uint32_t ttl, void *context) { KprZeroconfBrowser self = context; KprZeroconfPlatformBrowser browser = self->platform; KprZeroconfPlatformService service = KprZeroconfPlatformServiceFind(browser->services, serviceRef); char* serviceType = self->serviceType; if (!self->serviceType) { serviceType = service->owner->name; } if (!service || (errorCode != kDNSServiceErr_NoError)) { FskInstrumentedItemPrintfDebug(browser, "KprZeroconfPlatformResolveCallBack returned %d\n", errorCode); } else { KprZeroconfServiceInfo serviceInfo = NULL; #if TARGET_OS_WIN32 char ip[256]; if (address && address->sa_family == AF_INET) { const unsigned char *b = (const unsigned char *) &((struct sockaddr_in *)address)->sin_addr; snprintf(ip, sizeof(ip), "%d.%d.%d.%d", b[0], b[1], b[2], b[3]); } #else char ip[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &(((struct sockaddr_in *)address)->sin_addr), ip, INET_ADDRSTRLEN); #endif FskInstrumentedItemPrintfDebug(browser, "GETADDRINFO: %s %s is at %s -> %s:%d", self->serviceType, service->name, hostname, ip, service->port); KprZeroconfServiceInfoNew(&serviceInfo, serviceType, service->name, hostname, ip, service->port, service->txt); KprZeroconfBrowserServiceUp(self, serviceInfo); FskListRemove(&browser->services, service); KprZeroconfPlatformServiceDispose(service); } }
static void KprMQTTQueueResendMessage(KprMQTTQueue self, KprMQTTMessage message) { FskListRemove(&self->outbox, message); self->callback(self, &message, self->refcon); KprMQTTMessageDispose(message); }
FskErr KprSSDPClientStop(KprSSDPClient self) { FskErr err = kFskErrNone; FskListRemove(&gKprSSDPClients, self); FskThreadPostCallback(KprHTTPGetThread(), (FskThreadCallback)KprSSDPForget, self, NULL, NULL, NULL); //bail: return err; }
KprMQTTMessage KprMQTTQueueInboxGet(KprMQTTQueue self, UInt16 messageId) { KprMQTTMessage message = KprMQTTQueueInboxFind(self, messageId); if (!message) return NULL; FskListRemove(&self->inbox, message); return message; }
FskErr KprZeroconfBrowserStop(KprZeroconfBrowser self) { FskErr err = kFskErrNone; if (FskListRemove(&gZeroconfBrowsers, self)) { bailIfError(KprZeroconfPlatformBrowserStop(self)); } bail: return err; }
KprMQTTMessage KprMQTTQueueOutboxGet(KprMQTTQueue self, UInt16 messageId) { KprMQTTMessage message = KprMQTTQueueOutboxFind(self, messageId); if (!message) return NULL; FskListRemove(&self->outbox, message); KprMQTTQueueReschedule(self); return message; }
void KplTimeCallbackCancel(KplTimeCallback callback) { Boolean reschedule; KplThread thread; if (NULL == callback) return; thread = callback->owner; if ((NULL == thread) || ((NULL == thread->timerCallbacks) && (NULL == thread->suspendedTimerCallbacks))) return; reschedule = (callback == thread->timerCallbacks); if (!FskListRemove((FskList *)&thread->timerCallbacks, callback)) FskListRemove((FskList *)&thread->suspendedTimerCallbacks, callback); if (reschedule) rescheduleTimer(thread); }
void KprDebugClose(KprDebug self) { KprDebugMachine machine = NULL; FskListRemove(&gKprDebugList, self); while ((machine = self->machine)) KprDebugMachineDispose(machine); if (self->server) { KprSocketServerDispose(self->server); self->server = NULL; } }
FskErr FskFSVolumeNotifierDispose(FskFSVolumeNotifier volNtf) { FskAndroidFilesPrintfDebug("VolumeNotifierDispose\n"); FskMutexAcquire(gVolNotifiersMutex); FskListRemove((FskList *)&gVolNotifiers, &volNtf->next); FskMemPtrDispose(volNtf); FskMutexRelease(gVolNotifiersMutex); return kFskErrNone; }
void KprHTTPClientStop(KprService service) { KprHTTPClient self = gKprHTTPClient; KprHTTPConnection connection; KprHTTPTarget target; /* CONNECTIONS */ while ((connection = self->connections)) { FskListRemove(&self->connections, connection); KprHTTPConnectionDispose(connection); } while ((target = self->targets)) { FskListRemove(&self->targets, target); // @@ cancel message? } /* KEYCHAIN */ if (self->keychain) { KprHTTPKeychainWrite(self->keychain); KprHTTPKeychainDispose(self->keychain); self->keychain = NULL; } /* COOKIES */ if (self->cookies) { KprHTTPCookiesCleanup(self->cookies, true); KprHTTPCookiesWrite(self->cookies); KprHTTPCookiesDispose(self->cookies); self->cookies = NULL; } /* HTTP CACHE */ if (self->cache) { KprHTTPCacheWrite(self->cache); KprHTTPCacheDispose(self->cache); self->cache = NULL; } FskInstrumentedItemDispose(self); FskMemPtrDisposeAt(&gKprHTTPClient); }
void xs_gpio(void *gpio) { if (gpio) { FskListRemove(&gGPIOPollers, gpio); if ((NULL == gGPIOPollers) && (NULL != gGPIOPoller)) { FskTimeCallbackDispose(gGPIOPoller); gGPIOPoller = NULL; } FskGPIOPlatformDispose(gpio); FskMemPtrDispose(gpio); } }
static void KprWebSocketServerRequestDispose(KprWebSocketServerRequest request) { if (request) { FskListRemove((FskList*)&request->server->activeRequests, request); FskThreadRemoveDataHandler(&request->dataHandler); FskNetSocketClose(request->skt); FskHeaderStructDispose(request->requestHeaders); FskHeaderStructDispose(request->responseHeaders); FskStrParsedUrlDispose(request->parts); FskMemPtrDispose(request->out.buffer); FskMemPtrDispose(request); } }
static FskErr KprSocketListenerDispose(KprSocketListener self) { if (self) { FskThreadRemoveDataHandler(&self->dataHandler); FskNetSocketClose(self->socket); if (self->owner) { FskListRemove(&self->owner->listeners, self); } KprMemPtrDispose(self); } return kFskErrNone; }
FskErr FskMuxerTrackDispose(FskMuxerTrack track) { if (NULL == track) goto bail; if (track->dispatch && track->dispatch->doDispose) (track->dispatch->doDispose)(track, track->state); FskListRemove((FskList*)(void*)&track->muxer->tracks, track); FskMemPtrDispose(track); bail: return kFskErrNone; }
void FskHTTPServerRequestDispose(FskHTTPServerRequest request) { FskInstrumentedTypePrintfDebug(&gFskHTTPServerTypeInstrumentation, "FskHTTPServerRequestDispose %p - useCount: %d\n", request, request ? request->useCount : 0); if (request) { FskTimeCallbackDispose(request->timer); FskListRemove((FskList*)&request->http->activeRequests, request); FskThreadRemoveDataHandler(&request->dataHandler); FskTimeCallbackDispose(request->cycleCallback); request->cycleCallback = NULL; FskTimeCallbackDispose(request->keepAliveKillCallback); request->keepAliveKillCallback = NULL; request->keepAliveTimeout = 0; request->http->stats.connectionsCompleted++; sFskHTTPServerRequestDownUse(request); } }
void on_drag_data_received(GtkWidget* widget, GdkDragContext* context, gint x, gint y, GtkSelectionData *data, guint info, guint time, gpointer user_data) { FskGtkWindow gtkWin = user_data; gboolean dnd_success = FALSE; FskDragDropFile dropFileList = NULL; FskDragDropFile droppedFile = NULL; char* path = NULL; if (gdk_drag_context_get_suggested_action(context) == GDK_ACTION_COPY) { char* string = (char*)gtk_selection_data_get_data(data); char* end; FskFileInfo itemInfo; for (end = FskStrStr(string, "\r\n"); end; end = FskStrStr(string, "\r\n")) { BAIL_IF_ERR(FskMemPtrNewClear(sizeof(FskDragDropFileRecord), (FskMemPtr*)&droppedFile)); FskListAppend((FskList *)&dropFileList, droppedFile); *end = 0; BAIL_IF_ERR(KprURLToPath(string, &path)); BAIL_IF_ERR(FskFileGetFileInfo(path, &itemInfo)); if (itemInfo.filetype == kFskDirectoryItemIsDirectory) { int length = FskStrLen(path); BAIL_IF_ERR(FskMemPtrNew(length + 2, &droppedFile->fullPathName)); FskMemCopy(droppedFile->fullPathName, path, length); droppedFile->fullPathName[length] = '/'; droppedFile->fullPathName[length + 1] = 0; FskMemPtrDispose(path); } else { droppedFile->fullPathName = path; } path = NULL; string = end + 2; *end = '\r'; } (*gDropTargetProc)(kFskDragDropTargetEnterWindow, x, y, dropFileList, gtkWin->owner); (*gDropTargetProc)(kFskDragDropTargetDropInWindow, x, y, dropFileList, gtkWin->owner); dnd_success = TRUE; } bail: gtk_drag_finish(context, dnd_success, TRUE, time); FskMemPtrDispose(path); while (NULL != dropFileList) { droppedFile = dropFileList; FskListRemove((FskList *)&dropFileList, droppedFile); FskMemPtrDispose(droppedFile->fullPathName); FskMemPtrDispose(droppedFile); } }
void KprXKPRServiceCancel(KprService self UNUSED, KprMessage message) { message->usage--; // event queue if (gShell && FskListRemove(&gShell->messages, message)) { message->usage--; // message queue if (message->response.callback) (*message->response.callback)(message, message->response.target); if (message->response.dispose) (*message->response.dispose)(message->response.target); message->response.callback = NULL; message->response.dispose = NULL; message->response.target = NULL; message->usage--; // response } if (!message->usage) KprMessageDispose(message); }
static void KprMQTTQueueReschedule(KprMQTTQueue self) { KprMQTTMessage message; if (self->pause) return; message = KprMQTTQueueNextMessageToResend(self); if (message) { if (self->outbox != message) { FskListRemove(&self->outbox, message); FskListPrepend(&self->outbox, message); } FskTimeCallbackSet(self->resendCallback, &message->nextTime, KprMQTTQueueTimeToResendMessage, self); } else { FskTimeCallbackRemove(self->resendCallback); } }
FskErr FskHTTPServerListenerDispose(FskHTTPServerListener listener) { FskInstrumentedTypePrintfDebug(&gFskHTTPServerTypeInstrumentation, "httpServerListenerDispose - listener: %p\n", listener); if (listener) { if (listener->http && listener->http->listeners) FskListRemove((FskList*)&listener->http->listeners, listener); if (listener->handshaking) { FskInstrumentedTypePrintfDebug(&gFskHTTPServerTypeInstrumentation, "httpServerListenerDispose - listener: %p - wait for handshaking\n", listener); listener->http = NULL; } else { FskThreadRemoveDataHandler(&listener->dataHandler); FskNetSocketClose(listener->skt); FskMemPtrDispose(listener->ifcName); FskMemPtrDispose(listener); } } return kFskErrNone; }
void KprZeroconfServiceForget(KprService self, char* authority, char* id) { FskErr err = kFskErrNone; char* type = NULL; KprZeroconfBrowser browser = NULL; bailIfError(KprZeroconfServiceNewType(id, &type)); browser = KprZeroconfBrowserFind(gKprZeroconfBrowsers, type); if (browser) { FskListRemove(&gKprZeroconfBrowsers, browser); bailIfError(KprZeroconfBrowserStop(browser)); KprZeroconfBrowserDispose(browser); } bail: FskMemPtrDispose(type); FskMemPtrDispose(authority); FskMemPtrDispose(id); return; }
FskErr KprSocketDispose(KprSocket self) { FskErr err = kFskErrNone; if (self) { memset(&self->callbacks, 0, sizeof(KprSocketCallbaks)); if (self->preventDispose > 0) { self->disposeRequested = true; } else { FskListRemove(&gSockets, self); KprSocketCleanup(self); FskMemPtrDispose(self); } } return err; }
void KprMessageComplete(KprMessage self) { char* url; FskThread thread = KprShellGetThread(gShell); if (!thread) return; // @@ happens on exit if (thread != FskThreadGetCurrent()) { FskThreadPostCallback(thread, (FskThreadCallback)KprMessageComplete, self, NULL, NULL, NULL); return; } FskInstrumentedItemSendMessageDebug(self, kprInstrumentedMessageComplete, self); if (FskListRemove(&gShell->messages, self)) { self->usage--; // message queue self->waiting = false; url = KprMessageGetResponseHeader(self, "location"); if (url && (!FskStrCompareWithLength(self->url, "xkpr", 4)) && ((!self->sniffing) || (!FskStrCompareWithLength(url, "xkpr", 4)))) { FskMemPtrDispose(self->url); self->url = FskStrDoCopy(url); //bailIfNULL(self->url); KprURLSplit(self->url, &self->parts); FskAssociativeArrayDispose(self->response.headers); self->response.headers = NULL; FskMemPtrDispose(self->response.body); self->response.body = NULL; self->response.size = 0; if (self->request.target) self->usage--; // @@ request if (kFskErrNone == KprMessageInvoke(self, self->request.callback, self->request.dispose, self->request.target)) return; } if (self->request.target) { if (self->request.callback) (*self->request.callback)(self, self->request.target); if (self->request.dispose) (*self->request.dispose)(self->request.target); self->request.callback = NULL; self->request.dispose = NULL; self->request.target = NULL; self->usage--; // request } if (!self->usage) KprMessageDispose(self); } }
void KprDebugMachineDispose(KprDebugMachine self) { if (self) { KprDebug debug = self->debug; xsBeginHostSandboxCode(debug->the, debug->code); xsVars(1); KprDebugMachineCallbackText(self, "onMachineUnregistered", mxNoCommand, NULL); xsEndHostSandboxCode(); FskListRemove(&self->debug->machine, self); KprSocketWriterDispose(self->writer); self->writer = NULL; FskThreadRemoveDataHandler(&self->reader); FskNetSocketClose(self->socket); self->socket = NULL; FskMemPtrDisposeAt(&self->title); FskInstrumentedItemDispose(self); FskMemPtrDispose(self); } }
FskErr KprCoAPClientEndRequest(KprCoAPClient self, KprCoAPClientRequest request, const char *reason) { FskErr err = kFskErrNone; if (self->callbacks.requestEndCallback) { bailIfError(self->callbacks.requestEndCallback(request->message, reason, self->refcon)); } FskListRemove(&self->requests, request); if (request->message->token) { FskListAppend(&self->recycleTokens, KprRetain(request->message->token)); } bailIfError(KprCoAPClientRequestDispose(request)); bail: return err; }
void KprMessageDispose(KprMessage self) { if (self) { FskListRemove(&gShell->messages, self); if (self->stream && self->stream->dispatch->dispose) (*self->stream->dispatch->dispose)(self->stream); if (self->response.dispose) (*self->response.dispose)(self->response.target); FskMemPtrDispose(self->response.body); FskAssociativeArrayDispose(self->response.headers); if (self->request.dispose) (*self->request.dispose)(self->request.target); FskMemPtrDispose(self->request.body); if (self->request.certs != NULL) FskNetUtilDisposeCertificate(self->request.certs); FskAssociativeArrayDispose(self->request.headers); FskMemPtrDispose(self->url); FskMemPtrDispose(self->method); FskInstrumentedItemDispose(self); FskMemPtrDispose(self); } }
void KprZeroconfServiceShare(KprService self, char* authority, Boolean shareIt, Boolean useEnvironment) { FskErr err = kFskErrNone; char* type = NULL; KprZeroconfAdvertisement advertisement = NULL; KprHTTPServer server = KprHTTPServerGet(authority); bailIfError(KprZeroconfServiceNewType(authority, &type)); advertisement = KprZeroconfAdvertisementFind(gKprZeroconfAdvertisements, type, 0); if (shareIt && useEnvironment) shareIt = KprEnvironmentGetUInt32("useZeroconf", 0); if (shareIt && server) { if (!advertisement) { UInt32 port = server ? KprHTTPServerGetPort(server) : 0; Boolean secure = server ? KprHTTPServerIsSecure(server) : false; char* uuid = FskUUIDGetForKey(authority); FskAssociativeArray txt = NULL; if (secure) { txt = FskAssociativeArrayNew(); FskAssociativeArrayElementSetString(txt, "secure", "true"); } bailIfError(KprZeroconfAdvertisementNew(&advertisement, type, uuid, port, txt)); bailIfError(KprZeroconfPlatformAdvertisementStart(advertisement)); FskListAppend(&gKprZeroconfAdvertisements, advertisement); } } else { if (advertisement) { FskListRemove(&gKprZeroconfAdvertisements, advertisement); bailIfError(KprZeroconfPlatformAdvertisementStop(advertisement)); KprZeroconfAdvertisementDispose(advertisement); } } bail: if (err) KprZeroconfAdvertisementDispose(advertisement); FskMemPtrDispose(type); FskMemPtrDispose(authority); return; }
void KprHTTPClientIterate() { KprHTTPClient self = gKprHTTPClient; KprHTTPConnection connection, candidate, available; KprHTTPTarget target, next, other; KprMessage message; for (connection = FskListGetNext(self->connections, NULL); connection; connection = FskListGetNext(self->connections, connection)) { target = connection->target; if (target) { message = connection->target->message; if (!KprMessageContinue(message)) { KprHTTPConnectionClose(connection); KprHTTPClientResumeTarget(target); } } } target = FskListGetNext(self->targets, NULL); while (target) { next = FskListGetNext(self->targets, target); message = target->message; if (!KprMessageContinue(message)) { FskListRemove(&self->targets, target); KprHTTPClientResumeTarget(target); } target = next; } target = FskListGetNext(self->targets, NULL); while (target) { next = FskListGetNext(self->targets, target); message = target->message; candidate = NULL; available = NULL; for (connection = FskListGetNext(self->connections, NULL); connection; connection = FskListGetNext(self->connections, connection)) { if (KprHTTPConnectionCandidate(connection, message)) { candidate = connection; break; } else if (KprHTTPConnectionAvailable(connection)) { if (!available || (FskTimeCompare(&connection->time, &available->time) > 0)) // make the older connection the candidate for re-use available = connection; } } if (candidate) { if (KprHTTPConnectionAvailable(candidate)) { FskInstrumentedItemSendMessageDebug(candidate, kprInstrumentedHTTPConnectionCandidate, candidate->client); } else { candidate = NULL; } } else if (available) { // before closing the available connection, try to find a message that can use it for (other = FskListGetNext(self->targets, target); other; other = FskListGetNext(self->targets, other)) { if (abs(other->message->priority) < abs(message->priority)) { other = NULL; break; // do not let a lower priority request get in ahead of a higher priority one } if (KprHTTPConnectionCandidate(available, other->message)) { break; } } if (other) { FskInstrumentedItemSendMessageDebug(available, kprInstrumentedHTTPConnectionCandidate, available->client); next = target; target = other; } else KprHTTPConnectionClose(available); candidate = available; } else break; if (candidate) { FskListRemove(&self->targets, target); if (KprHTTPConnectionProcess(candidate, target)) { // put back the message in the queue KprHTTPClientAddTarget(target); } } target = next; } }
void KprHTTPClientRemoveTarget(KprHTTPTarget target) { KprHTTPClient self = gKprHTTPClient; FskListRemove(&self->targets, target); KprHTTPClientIterate(); }
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); } } }