void KPR_message_setRequestCertificate(xsMachine* the) { KprMessage self = xsGetHostData(xsThis); FskSocketCertificateRecord* certs = NULL; FskSocketCertificateRecord certsRecord = { NULL, 0, NULL, NULL, NULL, 0, }; if (xsIsInstanceOf(xsArg(0), xsObjectPrototype)) { certs = &certsRecord; if (xsHas(xsArg(0), xsID("certificates"))) { certs->certificates = (void*)xsToString(xsGet(xsArg(0), xsID("certificates"))); certs->certificatesSize = FskStrLen(certs->certificates); } if (xsHas(xsArg(0), xsID("policies"))) { certs->policies = xsToString(xsGet(xsArg(0), xsID("policies"))); } if (xsHas(xsArg(0), xsID("key"))) { certs->key = (void*)xsToString(xsGet(xsArg(0), xsID("key"))); certs->keySize = FskStrLen(certs->key); } } else { // compatibility certs = &certsRecord; if (xsTest(xsArg(0))) { certs->certificates = xsGetHostData(xsArg(0)); certs->certificatesSize = xsToInteger(xsGet(xsArg(0), xsID_length)); } if (xsTest(xsArg(1))) certs->policies = xsToString(xsArg(1)); } xsThrowIfFskErr(KprMessageSetRequestCertificate(self, certs)); }
void KprMessageScriptTargetTransform(void* it, KprMessage message, xsMachine* machine) { KprMessageScriptTarget self = it; if (message->error) return; xsBeginHostSandboxCode(machine, NULL); { xsVars(2); { xsTry { void* data; UInt32 size; KprMessageGetResponseBody(message, &data, &size); if (data && size) { xsIndex id = xsID(self->name); if (xsHas(xsGlobal, id)) { xsVar(0) = xsGet(xsGlobal, id); xsVar(1) = xsNewInstanceOf(xsChunkPrototype); xsSetHostData(xsVar(1), data); xsSetHostDestructor(xsVar(1) , NULL); xsSet(xsVar(1), xsID("length"), xsInteger(size)); xsResult = xsCall1(xsVar(0), xsID("parse"), xsVar(1)); self->result = xsMarshall(xsResult); } } } xsCatch { } } } xsEndHostSandboxCode(); }
FskErr FskSSLWrite(void *a, const void *buf, int *bufLen) { FskSSL *fssl = a; FskErr err = kFskErrNone; int len = *bufLen; if (fssl->skt == NULL) return kFskErrOperationFailed; if (buf == NULL || len == 0) return kFskErrNone; xsBeginHost(fssl->vm->the); xsTry { xsVars(1); xsCall1_noResult(fssl->socket, xsID("attachData"), xsHostData(fssl->skt)); xsVar(0) = xsNew1(xsGlobal, xsID("Chunk"), xsInteger(len)); FskMemCopy(xsGetHostData(xsVar(0)), buf, len); xsResult = xsCall2(fssl->ssl, xsID("write"), fssl->socket, xsVar(0)); *bufLen = xsToInteger(xsResult); if (*bufLen == 0) err = kFskErrNoData; xsCall0_noResult(xsVar(0), xsID("free")); } xsCatch { if (xsHas(xsException, xsID("code"))) err = xsToInteger(xsGet(xsException, xsID("code"))); if (err == kFskErrNone) err = kFskErrOperationFailed; } xsEndHost(fssl->vm->the); return err; }
FskErr FskSSLHandshake(void *a, FskNetSocketCreatedCallback callback, void *refCon, Boolean initiate) { FskSSL *fssl = a; FskErr err = kFskErrNone; fssl->socketCallback = callback; fssl->callbackData = refCon; xsBeginHost(fssl->vm->the); xsTry { xsVars(1); /* set session._hostData = ssl, just for callback */ xsVar(0) = xsNewHostObject(NULL); xsSetHostData(xsVar(0), fssl); xsSet(fssl->ssl, xsID("_hostData"), xsVar(0)); xsVar(0) = xsNewHostFunction(xs_handshake_finished_callback, 2); xsSet(fssl->ssl, xsID("_hostCallback"), xsVar(0)); xsCall3_noResult(fssl->ssl, xsID("handshake"), fssl->socket, xsVar(0), initiate ? xsTrue : xsFalse); } xsCatch { if (xsHas(xsException, xsID("code"))) err = xsToInteger(xsGet(xsException, xsID("code"))); if (err == kFskErrNone) err = kFskErrOperationFailed; } xsEndHost(fssl->vm->the); return err; }
FskErr FskSSLRead(void *a, void *buf, int *bufLen) { FskSSL *fssl = a; FskErr err = kFskErrNone; int len = *bufLen, nread; if (fssl->skt == NULL) return kFskErrOperationFailed; xsBeginHost(fssl->vm->the); xsTry { xsCall1_noResult(fssl->socket, xsID("attachData"), xsHostData(fssl->skt)); xsResult = xsCall2(fssl->ssl, xsID("read"), fssl->socket, xsInteger(len)); if (xsTest(xsResult)) { nread = xsToInteger(xsGet(xsResult, xsID("length"))); if (nread > len) nread = len; FskMemCopy(buf, xsGetHostData(xsResult), nread); xsCall0_noResult(xsResult, xsID("free")); *bufLen = nread; err = nread == 0 ? kFskErrNoData: kFskErrNone; } else err = kFskErrConnectionClosed; } xsCatch { if (xsHas(xsException, xsID("code"))) err = xsToInteger(xsGet(xsException, xsID("code"))); if (err == kFskErrNone) err = kFskErrOperationFailed; } xsEndHost(fssl->vm->the); return err; }
FskErr FskSSLNew(void **fsslp, const char *host, int port, Boolean blocking, long flags, int priority) { FskSSL *fssl; FskErr err; if ((err = FskMemPtrNewClear(sizeof(FskSSL), (FskMemPtr*)(void*)&fssl)) != kFskErrNone) return err; if ((err = newSSLVM(&fssl->vm)) != kFskErrNone) { FskMemPtrDispose(fssl); return err; } xsBeginHost(fssl->vm->the); xsTry { const char *prStr; xsVars(2); /* construct the options */ xsVar(0) = xsNewInstanceOf(xsObjectPrototype); if (blocking) xsSet(xsVar(0), xsID("blocking"), xsTrue); if (flags & kConnectFlagsSynchronous) xsSet(xsVar(0), xsID("synchronous"), xsTrue); switch (priority) { default: case kFskNetSocketLowestPriority: prStr = "lowest"; break; case kFskNetSocketLowPriority: prStr = "low"; break; case kFskNetSocketMediumPriority: prStr = "medium"; break; case kFskNetSocketHighPriority: prStr = "high"; break; case kFskNetSocketHighestPriority: prStr = "highest"; break; } (void)xsSet(xsVar(0), xsID("priority"), xsString((xsStringValue)prStr)); (void)xsSet(xsVar(0), xsID("raw"), xsTrue); xsVar(1) = xsNew3(xsGet(xsGlobal, xsID("Stream")), xsID("Socket"), xsString((xsStringValue)host), xsInteger(port), xsVar(0)); fssl->socket = xsVar(1); xsRemember(fssl->socket); xsVar(1) = xsNew0(xsGet(xsGlobal, xsID("FskSSL")), xsID("Session")); fssl->ssl = xsVar(1); xsRemember(fssl->ssl); } xsCatch { if (xsHas(xsException, xsID("code"))) err = xsToInteger(xsGet(xsException, xsID("code"))); if (err == kFskErrNone) err = kFskErrOperationFailed; } xsEndHost(fssl->vm->the); if (err == kFskErrNone) { if (fsslp != NULL) *fsslp = fssl; } else { disposeSSLVM(fssl->vm); FskMemPtrDispose(fssl); } return err; }
void xs_system_set_timezone(xsMachine *the) { struct timezone tz; xsVars(1); xsGet(xsVar(0), xsArg(0), xsID("timedifference")); tz.tz_minuteswest = xsToInteger(xsVar(0)); xsGet(xsVar(0), xsArg(0), xsID("dst")); tz.tz_dsttime = xsToInteger(xsVar(0)); mc_settimeofday(NULL, &tz); if (xsHas(xsArg(0), xsID("timezone"))) { xsGet(xsVar(0), xsArg(0), xsID("timezone")); mc_env_set_default("TIME_ZONE", xsToString(xsVar(0))); } }
FskErr FskSSLLoadCerts(void *a, FskSocketCertificateRecord *cert) { FskSSL *fssl = a; FskErr err = kFskErrNone; xsBeginHost(fssl->vm->the); xsTry { xsVars(2); xsVar(0) = xsUndefined; xsVar(1) = xsUndefined; if (cert != NULL) { if (cert->certificates != NULL && cert->certificatesSize > 0) { xsVar(0) = xsNew1(xsGlobal, xsID("Chunk"), xsInteger(cert->certificatesSize)); FskMemCopy(xsGetHostData(xsVar(0)), cert->certificates, cert->certificatesSize); } if (cert->policies != NULL) { if (cert->certificates == NULL) xsVar(0) = xsNew0(xsGlobal, xsID("Chunk")); // create a null chunk just for setting the polices xsSet(xsVar(0), xsID("policies"), xsString(cert->policies)); } if (cert->hostname != NULL) { xsSet(fssl->socket, xsID("hostname"), xsString(cert->hostname)); // too easy but should work... } if (cert->key != NULL && cert->keySize > 0) { xsVar(1) = xsNew1(xsGlobal, xsID("Chunk"), xsInteger(cert->keySize)); FskMemCopy(xsGetHostData(xsVar(1)), cert->key, cert->keySize); } } xsCall2_noResult(fssl->ssl, xsID("loadCerts"), xsVar(0), xsVar(1)); } xsCatch { if (xsHas(xsException, xsID("code"))) err = xsToInteger(xsGet(xsException, xsID("code"))); if (err == kFskErrNone) err = kFskErrOperationFailed; } xsEndHost(fssl->vm->the); return err; }
FskErr FskSSLAttach(void **fsslp, FskSocket skt) { FskSSL *fssl; FskErr err; if ((err = FskMemPtrNewClear(sizeof(FskSSL), (FskMemPtr*)(void*)&fssl)) != kFskErrNone) return err; if ((err = newSSLVM(&fssl->vm)) != kFskErrNone) { FskMemPtrDispose(fssl); return err; } xsBeginHost(fssl->vm->the); xsTry { xsVars(2); xsVar(0) = xsNew1(xsGet(xsGlobal, xsID("Stream")), xsID("Socket"), xsHostData(skt)); xsVar(1) = xsNewInstanceOf(xsObjectPrototype); (void)xsSet(xsVar(1), xsID("raw"), xsTrue); xsCall1_noResult(xsVar(0), xsID("setProperties"), xsVar(1)); fssl->socket = xsVar(0); xsRemember(fssl->socket); xsVar(0) = xsNew0(xsGet(xsGlobal, xsID("FskSSL")), xsID("Session")); fssl->ssl = xsVar(0); xsRemember(fssl->ssl); } xsCatch { if (xsHas(xsException, xsID("code"))) err = xsToInteger(xsGet(xsException, xsID("code"))); if (err == kFskErrNone) err = kFskErrOperationFailed; } xsEndHost(fssl->vm->the); if (err == kFskErrNone) { if (fsslp != NULL) *fsslp = fssl; } else { disposeSSLVM(fssl->vm); FskMemPtrDispose(fssl); } return err; }
FskErr FskSSLClose(void *a) { FskSSL *fssl = a; FskErr err = kFskErrNone; if (fssl->skt == NULL) return kFskErrOperationFailed; xsBeginHost(fssl->vm->the); xsTry { xsResult = xsCall1(fssl->ssl, xsID("close"), fssl->socket); } xsCatch { if (xsHas(xsException, xsID("code"))) err = xsToInteger(xsGet(xsException, xsID("code"))); if (err == kFskErrNone) err = kFskErrOperationFailed; } xsEndHost(fssl->vm->the); return err; }
FskErr FskSSLFlush(void *a) { FskSSL *fssl = a; FskErr err = kFskErrNone; if (fssl->skt == NULL) return kFskErrOperationFailed; xsBeginHost(fssl->vm->the); xsTry { xsVars(1); xsCall1_noResult(fssl->socket, xsID("attachData"), xsHostData(fssl->skt)); xsResult = xsCall1(fssl->ssl, xsID("flush"), fssl->socket); err = xsToBoolean(xsResult) ? kFskErrNone: kFskErrNoData; } xsCatch { if (xsHas(xsException, xsID("code"))) err = xsToInteger(xsGet(xsException, xsID("code"))); if (err == kFskErrNone) err = kFskErrOperationFailed; } xsEndHost(fssl->vm->the); return err; }
void console_log(xsMachine* the) { xsIntegerValue c = xsToInteger(xsArgc), i; xsBooleanValue space = 0; xsVars(4); console_log_depth++; for (i = 0; i < c; i++) { if (space) fprintf(stdout, " "); else space = 1; switch (xsTypeOf(xsArg(i))) { case xsUndefinedType: case xsNullType: case xsBooleanType: case xsIntegerType: case xsNumberType: fprintf(stdout, "%s", xsToString(xsArg(i))); break; case xsSymbolType: xsResult = xsCall1(xsGlobal, xsID("String"), xsArg(i)); fprintf(stdout, "%s", xsToString(xsResult)); break; case xsStringType: case xsStringXType: if ((console_log_depth == 1) && (i == 0)) fprintf(stdout, "%s", xsToString(xsArg(i))); else fprintf(stdout, "'%s'", xsToString(xsArg(i))); break; case xsReferenceType: if (console_log_depth < 3) { xsBooleanValue comma = 0; if (xsHas(xsArg(i), xsID("length"))) { xsIntegerValue length = xsToInteger(xsGet(xsArg(i), xsID("length"))), index; fprintf(stdout, "["); for (index = 0; index < length; index++) { if (comma) fprintf(stdout, ","); else comma = 1; fprintf(stdout, " "); if (xsHas(xsArg(i), (xsIndex)index)) { xsVar(1) = xsGet(xsArg(i), (xsIndex)index); fxPush(xsVar(1)); fxPushCount(the, 1); fxPush(xsThis); fxPush(xsFunction); fxCall(the); } } fprintf(stdout, " ]"); } else { fprintf(stdout, "{"); xsVar(0) = xsEnumerate(xsArg(i)); for (;;) { xsVar(1) = xsCall0(xsVar(0), xsID("next")); if (xsTest(xsGet(xsVar(1), xsID("done")))) break; xsVar(2) = xsGet(xsVar(1), xsID("value")); xsVar(3) = xsGetAt(xsArg(i), xsVar(2)); if (comma) fprintf(stdout, ","); else comma = 1; fprintf(stdout, " %s: ", xsToString(xsVar(2))); fxPush(xsVar(3)); fxPushCount(the, 1); fxPush(xsThis); fxPush(xsFunction); fxCall(the); } fprintf(stdout, " }"); } } else fprintf(stdout, "%s", xsToString(xsArg(i))); break; } } console_log_depth--; if (!console_log_depth) fprintf(stdout, "\n"); }
void xs_infoset_scan(xsMachine* the) { int c = xsToInteger(xsArgc); Scanner scanner; Scanner* self; xsVars(COUNT); xsTry { self = &scanner; c_memset(self, 0, sizeof(Scanner)); if (c < 1) xsSyntaxError("no buffer"); self->expat = XML_ParserCreate(NULL); xsThrowIfNULL(self->expat); XML_SetUserData(self->expat, self); XML_SetElementHandler(self->expat, scanStartTag, scanStopTag); XML_SetCdataSectionHandler(self->expat, scanStartCdata, scanStopCdata); XML_SetCharacterDataHandler(self->expat, scanCharacter); XML_SetCommentHandler(self->expat, scanComment); XML_SetProcessingInstructionHandler(self->expat, scanProcessingInstruction); XML_SetUnknownEncodingHandler(self->expat, scanUnknownEncoding, NULL); XML_SetSkippedEntityHandler(self->expat, scanEntity); self->result = 1; self->textBuffer = c_malloc(8192); xsThrowIfNULL(self->textBuffer); self->textSize = 8192; self->the = the; xsVar(ATTRIBUTE_PROTOTYPE) = xsGet(xsThis, xsID_attribute); xsVar(CDATA_PROTOTYPE) = xsGet(xsThis, xsID_cdata); xsVar(COMMENT_PROTOTYPE) = xsGet(xsThis, xsID_comment); xsVar(DOCUMENT_PROTOTYPE) = xsGet(xsThis, xsID_document); xsVar(ELEMENT_PROTOTYPE) = xsGet(xsThis, xsID_element); xsVar(NO_NAMESPACE) = xsString(""); xsVar(NO_PREFIX) = xsString(""); xsVar(PATH) = (c > 1) ? xsArg(1) : xsUndefined; xsVar(PI_PROTOTYPE) = xsGet(xsThis, xsID_pi); xsVar(XML_NAMESPACE) = xsGet(xsThis, xsID_xmlnsNamespace); xsVar(XML_PREFIX) = xsGet(xsThis, xsID_xmlnsPrefix); xsResult = xsNewInstanceOf(xsVar(DOCUMENT_PROTOTYPE)); xsSet(xsResult, xsID_encoding, xsString("UTF-8")); xsSet(xsResult, xsID_version, xsString("1.0")); xsVar(CHILDREN) = xsNewInstanceOf(xsArrayPrototype); xsArrayCacheBegin(xsVar(CHILDREN)); xsSet(xsResult, xsID_children, xsVar(CHILDREN)); xsSet(xsResult, xsID_parent, xsNull); xsSet(xsResult, xsID_xmlnsAttributes, xsNull); if (xsIsInstanceOf(xsArg(0), xsChunkPrototype)) { xsStringValue buffer = xsGetHostData(xsArg(0)); xsIntegerValue size = xsToInteger(xsGet(xsArg(0), xsID_length)); self->result = XML_Parse(self->expat, (const char *)buffer, size, 1); } else if (xsTypeOf(xsArg(0)) == xsStringType) { xsStringValue string = xsToString(xsArg(0)); xsIntegerValue stringOffset = 0; xsIntegerValue stringSize = c_strlen(string); while (self->result && (stringOffset < stringSize)) { xsIntegerValue size = stringSize - stringOffset; xsStringValue buffer = (char *)XML_GetBuffer(self->expat, 1024); xsThrowIfNULL(buffer); if (size > 1024) size = 1024; c_memcpy(buffer, string + stringOffset, size); self->result = XML_ParseBuffer(self->expat, size, (size < 1024) ? 1 : 0); stringOffset += size; string = xsToString(xsArg(0)); // @@ gc } } else { xsStreamGetter* streamGetter = xsGetHostData(xsArg(0)); while (self->result) { xsIntegerValue i; xsStringValue p, buffer = (char *)XML_GetBuffer(self->expat, 1024); xsThrowIfNULL(buffer); for (i = 0, p = buffer; i < 1024; i++, p++) { int c = (*(streamGetter->getter))(streamGetter->stream); if (c == C_EOF) break; *p = (char)c; } self->result = XML_ParseBuffer(self->expat, i, (i < 1024) ? 1 : 0); if (i < 1024) break; } } xsDelete(xsResult, xsID_xmlnsAttributes); xsDelete(xsResult, xsID_parent); xsArrayCacheEnd(xsVar(CHILDREN)); if (!self->result) { xsVar(LINE) = xsInteger(XML_GetCurrentLineNumber(self->expat)); xsVar(VALUE) = xsString((char*)XML_ErrorString(XML_GetErrorCode(self->expat))); if (xsHas(xsThis, xsID_reportError)) xsCall3_noResult(xsThis, xsID_reportError, xsVar(PATH), xsVar(LINE), xsVar(VALUE)); xsThrow(xsNewInstanceOf(xsSyntaxErrorPrototype)); } c_free(self->textBuffer); self->textBuffer = NULL; XML_ParserFree(self->expat); self->expat = NULL; } xsCatch { if (self->textBuffer) c_free(self->textBuffer); if (self->expat) XML_ParserFree(self->expat); } }
void KPR_mqttclient_publish(xsMachine* the) { KPR_MQTTClientRecord *self = xsGetHostData(xsThis); FskErr err = kFskErrNone; xsIntegerValue c = xsToInteger(xsArgc); char *topic = NULL; void *payload = NULL; UInt32 payloadLength = 0; UInt8 qos = 0; Boolean retain = false, hasPayload = false, hasQos = false, hasRetain = false; UInt16 token; /* Case 1. topic, string_or_chunk, qos, retain Case 2 topic, { payload: string_or_chunk}, qos, retain Case 3 topic, { payload: string_or_chunk, qos: 0, retain: true } */ if (c < 1) goto invalidParams; topic = xsToString(xsArg(0)); if (c >= 2) { if (isChunk(xsArg(1))) { payload = xsGetHostData(xsArg(1)); payloadLength = xsToInteger(xsGet(xsArg(1), xsID_length)); } else if (isObject(xsArg(1))) { xsVars(1); xsEnterSandbox(); { hasPayload = xsHas(xsArg(1), xsID("data")); if (hasPayload) xsVar(0) = the->scratch; hasQos = xsHas(xsArg(1), xsID("qos")); if (hasQos) qos = xsToInteger(the->scratch); hasRetain = xsHas(xsArg(1), xsID("retain")); if (hasRetain) retain = xsToInteger(the->scratch); } xsLeaveSandbox(); if (hasPayload) { if (isChunk(xsVar(0))) { payload = xsGetHostData(xsVar(0)); payloadLength = xsToInteger(xsGet(xsVar(0), xsID_length)); } else { payload = xsToString(xsVar(0)); payloadLength = FskStrLen(payload); } } } else { payload = xsToString(xsArg(1)); payloadLength = FskStrLen(payload); } } if (c >= 3 && !hasQos) { qos = xsToInteger(xsArg(2)); } if (c >= 4 && !hasRetain) { retain = xsToBoolean(xsArg(3)); } if (!KprMQTTIsValidTopic(topic, false)) goto badParam; if (qos > 2) goto badParam; bailIfError(KprMQTTClientPublish(self->client, topic, payload, payloadLength, qos, retain, &token)); xsResult = xsInteger(token); goto bail; invalidParams: err = kFskErrInvalidParameter; goto bail; badParam: err = kFskErrBadData; goto bail; bail: xsThrowIfFskErr(err); }
void KPR_mqttclient_connect(xsMachine* the) { KPR_MQTTClientRecord *self = xsGetHostData(xsThis); xsIntegerValue c = xsToInteger(xsArgc); char *host; UInt16 port; KprMQTTClientConnectOptions options; if (c >= 1) { host = xsToString(xsArg(0)); } else { host = "localhost"; } if (c >= 2) { port = xsToInteger(xsArg(1)); } else { port = 1883; } options.isSecure = (port == 1884); options.keepAlive = 60; options.password = NULL; options.username = NULL; options.willIsRetained = false; options.willQualityOfService = 0; options.willTopic = NULL; options.willPayload = NULL; options.willPayloadLength = 0; if (c >= 3) { xsVars(1); xsEnterSandbox(); { if (xsHas(xsArg(2), xsID("secure"))) options.isSecure = xsToBoolean(the->scratch); if (xsHas(xsArg(2), xsID("keepAlive"))) options.keepAlive = xsToInteger(the->scratch); if (xsHas(xsArg(2), xsID("username"))) options.username = xsToString(the->scratch); if (xsHas(xsArg(2), xsID("password"))) options.password = xsToString(the->scratch); if (xsHas(xsArg(2), xsID("will"))) { xsVar(0) = the->scratch; if (xsHas(xsVar(0), xsID("topic"))) options.willTopic = xsToString(the->scratch); if (xsHas(xsVar(0), xsID("qos"))) options.willQualityOfService = xsToInteger(the->scratch); if (xsHas(xsVar(0), xsID("retain"))) options.willIsRetained = xsToBoolean(the->scratch); if (xsHas(xsVar(0), xsID("data"))) { xsVar(0) = the->scratch; if (isChunk(xsVar(0))) { options.willPayload = xsGetHostData(xsVar(0)); options.willPayloadLength = xsToInteger(xsGet(xsVar(0), xsID_length)); } else { options.willPayload = xsToString(xsVar(0)); options.willPayloadLength = FskStrLen(options.willPayload); } } } } xsLeaveSandbox(); } if (options.willQualityOfService > 2 || (options.willTopic && !KprMQTTIsValidTopic(options.willTopic, false))) { xsThrowIfFskErr(kFskErrBadData); } xsThrowIfFskErr(KprMQTTClientConnect(self->client, host, port, &options)); }