Skip to content

The questions ​

A task does not run on its own: while it does, STN asks the app eighteen questions and the app answers them. Is this user logged in? What bytes does this task send? What did the answer mean? What is the device's network? — and the rest. Every platform funnels all eighteen through one thing:

your app iswhat answers them
Rustimpl App for MyApp, given to stn.set_callback(MyApp)
iOS / watchOS, Swift or Objective-Cone closure given to MarsStn.setApp { … }, or the block [MarsStn setApp:] takes
Android, Kotlin or JavaStnLogic.ICallBack, given to StnLogic.setCallBack(…)
Kotlin Multiplatformone ask, given to StnLogic.setApp { … }
anything with a C FFIone function pointer, given to mars_stn_set_app(ctx, ask)
HarmonyOSthe same function pointer, through a NAPI shim of your own

The names are the ones the C++ project used, so an answer written there is written here — all eighteen of them, in the order STN numbers them:

#the questionwhat STN wantsRustSwiftshared KotlinAndroidC
1makesureAuthedwhether this user is logged inmakesure_authed.makesureAuthedQuestion.Kind.MakesureAuthedmakesureAuthedMarsStnQuestionMakesureAuthed
2trafficDatahow much went out and came intraffic_data.trafficDataQuestion.Kind.TrafficDatatrafficDataMarsStnQuestionTrafficData
3onNewDnsthe addresses of a hoston_new_dns.onNewDnsQuestion.Kind.OnNewDnsonNewDnsMarsStnQuestionOnNewDns
4onPushthe server sent this, and no task asked for iton_push.onPushQuestion.Kind.OnPushonPushMarsStnQuestionOnPush
5req2Bufthe bytes the task sendsreq2buf.req2BufQuestion.Kind.Req2Bufreq2BufMarsStnQuestionReq2Buf
6buf2Respwhat the answer meantbuf2resp.buf2RespQuestion.Kind.Buf2Respbuf2RespMarsStnQuestionBuf2Resp
7onTaskEndwhat to do about the endon_task_end.onTaskEndQuestion.Kind.OnTaskEndonTaskEndMarsStnQuestionOnTaskEnd
8reportConnectStatusthe network, as the app is to see itreport_connect_status.reportConnectStatusQuestion.Kind.ReportConnectStatusreportConnectInfoMarsStnQuestionReportConnectStatus
9onLongLinkNetworkErrorthe main long link failedon_long_link_network_error.longLinkNetworkErrorQuestion.Kind.LongLinkNetworkError—MarsStnQuestionLongLinkNetworkError
10onShortLinkNetworkErrora short link failedon_short_link_network_error.shortLinkNetworkErrorQuestion.Kind.ShortLinkNetworkError—MarsStnQuestionShortLinkNetworkError
11onLongLinkStatusChangewhere the default long link ison_long_link_status_change.longLinkStatusChangeQuestion.Kind.LongLinkStatusChange—MarsStnQuestionLongLinkStatusChange
12getLonglinkIdentifyCheckBufferthe check a new link is used withidentify_check_buffer.identifyCheckBufferQuestion.Kind.IdentifyCheckBuffergetLongLinkIdentifyCheckBufferMarsStnQuestionIdentifyCheckBuffer
13onLonglinkIdentifyResponsewhether the answer is the one the check asked foridentify_response.identifyResponseQuestion.Kind.IdentifyResponseonLongLinkIdentifyRespMarsStnQuestionIdentifyResponse
14requestSyncthe app is asked to syncrequest_sync.requestSyncQuestion.Kind.RequestSyncrequestDoSyncMarsStnQuestionRequestSync
15requestNetCheckShortLinkHoststhe hosts the network check may probenet_check_shortlink_hosts.netCheckShortLinkHostsQuestion.Kind.NetCheckShortLinkHostsrequestNetCheckShortLinkHostsMarsStnQuestionNetCheckShortLinkHosts
16reportTaskProfileeverything a task left behindreport_task_profile.reportTaskProfileQuestion.Kind.ReportTaskProfilereportTaskProfileMarsStnQuestionReportTaskProfile
17reportTaskLimiteda task the two gates refused: which gate, and its readingreport_task_limited.reportTaskLimitedQuestion.Kind.ReportTaskLimited—MarsStnQuestionReportTaskLimited
18reportDnsProfilehow a dns question wentreport_dns_profile.reportDnsProfileQuestion.Kind.ReportDnsProfile—MarsStnQuestionReportDnsProfile

A question the app does not answer is a question with the default answer, and every platform but Android carries one for all eighteen — so an app writes the ones it cares about: default: return .nothing() in Swift, else -> Answer.None in the shared Kotlin, an App with three methods in Rust.

In Rust, two of the eighteen are asked of the app only for a task nobody is awaiting: the body you hand stn.send(task, body) is what req2buf would have been asked for, and the bytes the server answers with are what buf2resp would have been handed — both are kept for the Sent instead. Every other question is asked the same way, on_task_end included, and all eighteen are asked of the app for a task nobody awaits. See the task.

Android's ICallBack is the plain interface the C++ project's Java declared, and it has no defaults: the object is the app's to finish. It is asked thirteen of the eighteen — the five marked — above are ones the Java api has no method for, so STN takes its own answers for them — plus one of its own, isLogoned, which nothing asks.

marsrs-kmp's shared Kotlin is asked all eighteen on Kotlin/Native and thirteen on Android, the same five.

reportTaskLimited is the one question only a refused task is asked for: the two anti-avalanche gates weigh every task that goes out, and a task they refuse never reaches a queue, so nothing else the app hears carries it. What the app is handed is which gate refused it and the reading it weighed the task against — how long ago the same body went out, or how many bytes the funnel would not take — and what it answers is that reading, changed or not. The reading is limit on the question, and Answer.Limit or .limit(…) is how the shared Kotlin and Swift hand it back; in C it is the limit of MarsStnQuestion and a MarsStnAnswerLimit.

That answer is a report and not an override: the C++'s own is void, and a gate's refusal stands whatever an app writes into it — a task the gates refused stays refused and ends with LOCAL_ANTI_AVALANCHE. What the port does with the answer is nothing at all, which is the same thing: anti_avalanche_check asks and drops it, so no answer of an app's lets a refused task out. See the long link for the link a task goes out on.

The account and the device are not one of the eighteen: on Android they are AppLogic.ICallBack, and on every other platform they are nothing STN asks about.

The boot, on Android ​

Android is the one platform where the app also starts the bridges and hands over what STN asks about the device:

kotlin
Mars.init(context, Handler(Looper.getMainLooper()))
Mars.onCreate(true)

AppLogic.setCallBack(object : AppLogic.ICallBack { /* the account and the device */ })
StnLogic.setCallBack(object : StnLogic.ICallBack { /* the thirteen it is asked, and `isLogoned` */ })

// when the screen or the network changes
BaseEvent.onForeground(true)
BaseEvent.onNetworkChange()

AppLogic is the account and the device; BaseEvent is the screen and the network. The screen and the network are two an app reports on every platform — under the name that platform spells them with, which the long link lists. What is Android's alone is the boot: Mars.init and Mars.onCreate.

Where to go next ​

  • The task — what a task is made of, and how one ends.
  • The long link — the connection an app keeps up.
  • Getting started — the dependency and a running task, on every platform that carries STN.

MIT, like the upstream project.