static void KprPromiseTargetComplete(KprMessage message, void* it) { KprPromiseTarget self = it; xsBeginHost(self->the); xsVars(3); xsVar(0) = xsAccess(self->resolve); xsVar(1) = xsAccess(self->reject); if (message->error) { xsVar(2) = xsNewInstanceOf(xsGet(xsGet(xsGlobal, xsID_KPR), xsID_message)); xsSetHostData(xsVar(2), message); FskInstrumentedItemSendMessageDebug(message, kprInstrumentedMessageConstruct, message); message->usage++; // host (void)xsCallFunction1(xsVar(1), xsUndefined, xsVar(2)); } else { if (message->stream) KprMessageScriptTargetGet(message, the, &xsVar(2)); else { xsVar(2) = xsNewInstanceOf(xsGet(xsGet(xsGlobal, xsID_KPR), xsID_message)); xsSetHostData(xsVar(2), message); FskInstrumentedItemSendMessageDebug(message, kprInstrumentedMessageConstruct, message); message->usage++; // host } (void)xsCallFunction1(xsVar(0), xsUndefined, xsVar(2)); } xsEndHost(self->the); }
void KprMessageRedirect(KprMessage self, char* url, char* mime) { FskInstrumentedItemSendMessageDebug(self, kprInstrumentedMessageRedirect, self); KprMessageSetResponseHeader(self, "location", url); if (mime) KprMessageSetResponseHeader(self, "content-type", mime); }
FskErr KprMessageInvoke(KprMessage self, KprMessageCallbackProc callback, KprMessageDisposeProc dispose, void* target) { KprService service = gServices; FskInstrumentedItemSendMessageDebug(self, kprInstrumentedMessageInvoke, self); if (self->waiting) return kFskErrOutOfSequence; while (service) { if ((*service->accept)(service, self)) { self->waiting = true; if (target) { self->request.callback = callback; self->request.dispose = dispose; self->request.target = target; self->usage++; // request } FskListAppend(&gShell->messages, self); self->usage++; // message queue if (!service->thread) service->thread = KprShellGetThread(gShell); if (service == &gXKPRService) self->usage++; // event queue FskThreadPostCallback(service->thread, (FskThreadCallback)service->invoke, service, self, NULL, NULL); return kFskErrNone; } service = service->next; } return kFskErrUnimplemented; }
void KprMessageCancel(KprMessage self) { KprService service = gServices; FskInstrumentedItemSendMessageDebug(self, kprInstrumentedMessageCancel, self); if (self->waiting) { self->waiting = false; if (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 } while (service) { if ((*service->accept)(service, self)) { if (!service->thread) service->thread = KprShellGetThread(gShell); if (service == &gXKPRService) self->usage++; // event queue FskThreadPostCallback(service->thread, (FskThreadCallback)service->cancel, service, self, NULL, NULL); break; } service = service->next; } } }
void KprHTTPClientResumeTarget(KprHTTPTarget target) { KprMessage message = target->message; FskInstrumentedItemSendMessageDebug(target->message, kprInstrumentedMessageHTTPEnd, message) KprHTTPTargetDispose(target); FskThreadPostCallback(KprShellGetThread(gShell), (FskThreadCallback)KprMessageComplete, message, NULL, NULL, NULL); }
void KprMessageSuspend(KprMessage self, KprMessageCallbackProc callback, KprMessageDisposeProc dispose, void* target) { FskInstrumentedItemSendMessageDebug(self, kprInstrumentedMessageSuspend, self); self->response.callback = callback; self->response.dispose = dispose; self->response.target = target; self->usage++; // response }
void KPR_message(void *it) { if (it) { KprMessage self = it; FskInstrumentedItemSendMessageDebug(self, kprInstrumentedMessageDestruct, self); self->usage--; // host if (!self->usage) KprMessageDispose(self); } }
void KprMessageResuming(KprMessage self) { FskInstrumentedItemSendMessageDebug(self, kprInstrumentedMessageResume, self); if (self->response.dispose) (*self->response.dispose)(self->response.target); self->response.callback = NULL; self->response.dispose = NULL; self->response.target = NULL; self->usage--; // response }
FskErr KprMessageNotify(KprMessage self) { FskErr err = kFskErrNone; FskInstrumentedItemSendMessageDebug(self, kprInstrumentedMessageNotify, self); if (!FskStrCompareWithLength(self->parts.scheme, "xkpr", self->parts.schemeLength)) { self->usage++; // event queue FskThreadPostCallback(KprShellGetThread(gShell), (FskThreadCallback)KprMessageNotifyCallback, gShell, self, NULL, NULL); } else err = kFskErrUnimplemented; return err; }
void KprMessageResume(KprMessage self) { FskInstrumentedItemSendMessageDebug(self, kprInstrumentedMessageResume, self); if (self->response.dispose) (*self->response.dispose)(self->response.target); self->response.callback = NULL; self->response.dispose = NULL; self->response.target = NULL; self->usage--; // response KprMessageTransform(self, gShell->the); KprMessageComplete(self); }
void KPR_Message(xsMachine* the) { xsStringValue url = NULL; KprMessage self = NULL; xsTry { xsThrowIfFskErr(KprMessageURL(xsGetContext(the), xsToString(xsArg(0)), &url)); xsThrowIfFskErr(KprMessageNew(&self, url)); xsSetHostData(xsThis, self); FskInstrumentedItemSendMessageDebug(self, kprInstrumentedMessageConstruct, self); self->usage++; // host FskMemPtrDispose(url); } xsCatch { FskMemPtrDispose(url); xsThrow(xsException); } }
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 KprHTTPClientInvoke(KprService service UNUSED, KprMessage message) { FskErr err = kFskErrNone; KprHTTPClient self = gKprHTTPClient; if (KprMessageContinue(message)) { KprHTTPTarget target = NULL; KprHTTPCacheValue cached = NULL; char* value; FskInstrumentedItemSendMessageDebug(message, kprInstrumentedMessageHTTPBegin, message) bailIfError(KprHTTPTargetNew(&target, message)); if (!message->method || !FskStrCompare(message->method, "GET")) KprHTTPCacheFetch(self->cache, message->url, &cached); if (cached) { if (KprHTTPCacheValueIsFresh(cached)) { if (KprHTTPClientReadCache(message, cached) == kFskErrNone) { KprMessageTransform(message, gHTTPService.machine); KprHTTPClientResumeTarget(target); return; } } else { value = FskAssociativeArrayElementGetString(cached->headers, kprHTTPHeaderLastModified); if (value) (void)KprMessageSetRequestHeader(message, kprHTTPHeaderIfModifiedSince, value); value = FskAssociativeArrayElementGetString(cached->headers, kprHTTPHeaderETag); if (value) (void)KprMessageSetRequestHeader(message, kprHTTPHeaderIfNoneMatch, value); target->cached = cached; } } KprHTTPClientCookiesGet(message->url, &value); if (value) { (void)KprMessageSetRequestHeader(message, kprHTTPHeaderCookie, value); FskMemPtrDispose(value); } KprHTTPClientAddTarget(target); return; bail: message->error = err; } FskThreadPostCallback(KprShellGetThread(gShell), (FskThreadCallback)KprMessageComplete, message, NULL, NULL, NULL); }
void KPR_host_quitting(xsMachine* the) { KprContainer container = xsGetHostData(xsThis); KprContent content = container->first; KprScriptBehavior self = (KprScriptBehavior)content->behavior; #if SUPPORT_INSTRUMENTATION void* params[2] = { self, "xsID_onQuitting" }; FskInstrumentedItemSendMessageDebug(content, kprInstrumentedContentCallBehavior, params); #endif if (self) { xsBeginHostSandboxCode(self->the, self->code); { xsVars(2); xsVar(0) = xsAccess(self->slot); if (xsFindResult(xsVar(0), xsID_onQuitting)) { xsVar(1) = kprContentGetter(content); (void)xsCallFunction1(xsResult, xsVar(0), xsVar(1)); } } xsEndHostSandboxCode(); } }
FskErr KprHTTPClientResetTarget(KprHTTPTarget target) { FskErr err = kFskErrNone; KprMessage message = target->message; KprMessageClearRequestHeader(message, kprHTTPHeaderIfModifiedSince); KprMessageClearRequestHeader(message, kprHTTPHeaderIfNoneMatch); if (target->cached) { target->cached = NULL; } else { FskAssociativeArrayDispose(message->response.headers); KprMemPtrDispose(message->response.body); } message->error = 0; message->response.headers = NULL; message->response.body = NULL; message->response.size = 0; target->responseOffset = 0; FskInstrumentedItemSendMessageDebug(message, kprInstrumentedMessageHTTPContinue, message); //bail: return err; }
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; } }