static void KprMQTTClientResetKeepAliveTimer(KprMQTTClient self) { FskTimeCallbackRemove(self->pingRequestCallaback); if (self->keepAlive > 0) { FskTimeRecord when; FskTimeGetNow(&when); FskTimeAddSecs(&when, self->keepAlive); FskTimeCallbackSet(self->pingRequestCallaback, &when, KprMQTTClientIdle, self); } }
Boolean KplTimeCallbackGetNextTime(const KplTime now, KplTime whenNext, void *threadIn) { KplThread thread = threadIn ? threadIn : KplThreadGetCurrent(); if (thread->timerCallbacks) { KplTimeCallback cb = (KplTimeCallback)thread->timerCallbacks; if (FskTimeCompare((FskTime)now, (FskTime)&cb->trigger) < 1) { FskTimeClear((FskTime)whenNext); return false; } *whenNext = cb->trigger; } else { *whenNext = *now; FskTimeAddSecs((FskTime)whenNext, 3600 * 12); // a long time from now } return true; }
static void KprMQTTClientIdle(FskTimeCallBack callback UNUSED, const FskTime time, void *it) { KprMQTTClient self = it; FskErr err; KprMQTTMessage message = NULL; FskTimeRecord when; bailIfError(KprMQTTMessageNewWithType(&message, kKprMQTTMessageTypePINGREQ)); bailIfError(KprMQTTClientSendMessage(self, &message)); when = *time; FskDebugStr("< PING %ld", when.seconds); FskTimeAddSecs(&when, self->keepAlive); FskTimeCallbackSet(self->pingResponseCallaback, &when, KprMQTTClientCheckPingResponse, self); bail: if (err) { KprMQTTClientHandleError(self, err, "sending ping"); } KprMQTTMessageDispose(message); }
FskErr KprMQTTQueueOutboxPut(KprMQTTQueue self, KprMQTTMessage *it) { KprMQTTMessage message = *it; int i; double m; if (KprMQTTQueueOutboxFind(self, message->messageId) != NULL) return kFskErrDuplicateElement; FskTimeGetNow(&message->nextTime); m = 1.0; for (i = 0; i < message->retryCount; i++) { m *= 1.1; } FskTimeAddSecs(&message->nextTime, self->resendInterval * m); message->retryCount += 1; FskListAppend(&self->outbox, message); KprMQTTQueueReschedule(self); *it = NULL; return kFskErrNone; }
static void fxDoConnect(txMachine *the) { if (!FskStrLen(debugAddress)) { char *address = FskEnvironmentGet("debugger"); if (address) FskStrCopy(debugAddress, address); #if TARGET_OS_WIN32 || (TARGET_OS_MAC && !TARGET_OS_IPHONE) else FskStrCopy(debugAddress, "localhost"); #endif } if (FskStrLen(debugAddress) && !debugAddressFailed) { FskErr err; char host[64]; char* colon; int port; FskTimeRecord expireTime, now; SInt32 waitMS; colon = FskStrNCopyUntil(host, debugAddress, 63, ':'); if (*colon) port = FskStrToNum(colon); else port = 5002; #if TARGET_OS_MAC waitMS = 0; #else waitMS = -1; #endif // Connect to the host asynchronously err = FskNetConnectToHostPrioritized(host, port, false, fxConnectComplete, the, 0, 0, NULL, "fxConnect"); if (err) goto bail; // Allow two seconds for the connection to resolve and for the socket to become readable and writable FskTimeGetNow(&expireTime); FskTimeAddSecs(&expireTime, 2); while (!the->connection) { FskTimeGetNow(&now); if (FskTimeCompare(&expireTime, &now) > 0) goto bail; FskThreadRunloopCycle(waitMS); } while (!FskNetSocketIsReadable((FskSocket)the->connection) && !FskNetSocketIsWritable((FskSocket)the->connection)) { FskTimeGetNow(&now); if (FskTimeCompare(&expireTime, &now) > 0) goto bail; FskThreadRunloopCycle(waitMS); } // Make the socket blocking FskNetSocketMakeBlocking((FskSocket)the->connection); return; bail: if (the->connection) { FskNetSocketClose((FskSocket)the->connection); the->connection = 0; } debugAddressFailed = true; } }