// Stack main thread void NsMainThread(THREAD *thread, void *param) { NATIVE_STACK *a = (NATIVE_STACK *)param; // Validate arguments if (thread == NULL || param == NULL) { return; } while (true) { SOCKSET set; bool err = false; bool flush_tube; LIST *recv_packets; bool state_changed = false; InitSockSet(&set); AddSockSet(&set, a->Sock1); if (a->Halt) { break; } // Pass to the IPC by receiving from the bridge LABEL_RESTART: state_changed = false; flush_tube = false; while (true) { void *data; UINT size; size = EthGetPacket(a->Eth, &data); if (size == INFINITE) { // Device error err = true; break; } else if (size == 0) { // Can not get any more break; } else { // Pass the IPC socket TubeSendEx(a->Sock1->SendTube, data, size, NULL, true); Free(data); flush_tube = true; state_changed = true; } } if (flush_tube) { TubeFlush(a->Sock1->SendTube); } // Pass to the bridge by receiving from IPC recv_packets = NULL; while (true) { TUBEDATA *d = TubeRecvAsync(a->Sock1->RecvTube); if (d == NULL) { break; } if (recv_packets == NULL) { recv_packets = NewListFast(NULL); } Add(recv_packets, d); state_changed = true; } if (recv_packets != NULL) { UINT i; UINT num = LIST_NUM(recv_packets); void **data_array; UINT *size_array; data_array = Malloc(sizeof(void *) * num); size_array = Malloc(sizeof(UINT) * num); for (i = 0;i < num;i++) { TUBEDATA *d = LIST_DATA(recv_packets, i); data_array[i] = d->Data; size_array[i] = d->DataSize; } EthPutPackets(a->Eth, num, data_array, size_array); for (i = 0;i < num;i++) { TUBEDATA *d = LIST_DATA(recv_packets, i); // Because the data buffer has been already released, not to release twice d->Data = NULL; FreeTubeData(d); } Free(data_array); Free(size_array); ReleaseList(recv_packets); } if (IsTubeConnected(a->Sock1->SendTube) == false || IsTubeConnected(a->Sock1->RecvTube) == false) { err = true; } if (err) { // An error has occured Debug("Native Stack: Error !\n"); a->Halt = true; continue; } if (state_changed) { goto LABEL_RESTART; } Select(&set, 1234, a->Cancel, NULL); } Disconnect(a->Sock1); Disconnect(a->Sock2); }
// Process the timer interrupt void SstpProcessInterrupt(SSTP_SERVER *s) { // Validate arguments if (s == NULL) { return; } s->Now = Tick64(); s->FlushRecvTube = false; // Process the received packet while (true) { BLOCK *b = GetNext(s->RecvQueue); SSTP_PACKET *p; if (b == NULL) { break; } p = SstpParsePacket(b->Buf, b->Size); if (p == NULL) { // Disconnect the SSTP since a bad packet received SstpAbort(s); } else { // Process the received packet SstpProcessPacket(s, p); SstpFreePacket(p); } FreeBlock(b); } if (s->FlushRecvTube) { TubeFlush(s->TubeRecv); } // Transmit a packet that the PPP module is trying to send via the SSTP while (true) { TUBEDATA *d = TubeRecvAsync(s->TubeSend); SSTP_PACKET *p; if (d == NULL) { break; } p = SstpNewDataPacket(d->Data, d->DataSize); SstpSendPacket(s, p); SstpFreePacket(p); FreeTubeData(d); } if (s->Status == SSTP_SERVER_STATUS_ESTABLISHED) { if (s->Disconnecting == false && s->Aborting == false) { // Periodic transmission of Echo Request if (s->NextSendEchoRequestTick == 0 || s->NextSendEchoRequestTick <= s->Now) { UINT64 next_interval = (UINT64)(SSTP_ECHO_SEND_INTERVAL_MIN + Rand32() % (SSTP_ECHO_SEND_INTERVAL_MAX - SSTP_ECHO_SEND_INTERVAL_MIN)); SSTP_PACKET *p; s->NextSendEchoRequestTick = s->Now + next_interval; AddInterrupt(s->Interrupt, s->NextSendEchoRequestTick); p = SstpNewControlPacket(SSTP_MSG_ECHO_REQUEST); SstpSendPacket(s, p); SstpFreePacket(p); } } } if ((s->LastRecvTick + (UINT64)SSTP_TIMEOUT) <= s->Now) { // Disconnect the SSTP because a timeout occurred SstpAbort(s); s->Disconnected = true; } if (IsTubeConnected(s->TubeRecv) == false || IsTubeConnected(s->TubeSend) == false) { // Disconnect the SSTP since the PPP module is disconnected SstpDisconnect(s); } if (s->Disconnecting) { // Normal disconnection process if (s->DisconnectSent == false) { // Send a Disconnect SSTP_PACKET *ret = SstpNewControlPacket(s->DisconnectRecved ? SSTP_MSG_CALL_DISCONNECT_ACK : SSTP_MSG_CALL_DISCONNECT); SstpSendPacket(s, ret); SstpFreePacket(ret); s->DisconnectSent = true; } } if (s->Aborting) { // Abnormal disconnection processing if (s->AbortSent == false) { // Send the Abort SSTP_PACKET *ret = SstpNewControlPacket(SSTP_MSG_CALL_ABORT); SstpSendPacket(s, ret); SstpFreePacket(ret); s->AbortSent = true; } } if (s->DisconnectSent && s->DisconnectRecved) { // Disconnect after exchanging the Disconnect each other s->Disconnected = true; } if (s->AbortSent && s->AbortReceived) { // Disconnect after exchanging the Abort each other s->Disconnected = true; } }