// Complete receiving management command void NiFreeAdminAccept(NAT *n) { // Validate arguments if (n == NULL) { return; } n->Halt = true; Disconnect(n->AdminListenSock); Set(n->HaltEvent); while (true) { if (WaitThread(n->AdminAcceptThread, 1000) == false) { Disconnect(n->AdminListenSock); } else { break; } } ReleaseThread(n->AdminAcceptThread); ReleaseSock(n->AdminListenSock); }
// Release void NullPaFree(SESSION *s) { // Validate arguments NULL_LAN *n; BLOCK *b; if (s == NULL || (n = s->PacketAdapter->Param) == NULL) { return; } n->Halt = true; Set(n->Event); WaitThread(n->PacketGeneratorThread, INFINITE); ReleaseThread(n->PacketGeneratorThread); LockQueue(n->PacketQueue); { while (b = GetNext(n->PacketQueue)) { FreeBlock(b); } } UnlockQueue(n->PacketQueue); ReleaseQueue(n->PacketQueue); ReleaseCancel(n->Cancel); ReleaseEvent(n->Event); s->PacketAdapter->Param = NULL; Free(n); }
// Stop the download thread void ViDownloadThreadStop(VI_INSTALL_DLG *d) { // Validate arguments if (d == NULL) { return; } if (d->DownloadStarted == false) { return; } d->DownloadStarted = false; d->Halt = true; while (true) { if (WaitThread(d->DownloadThread, 50)) { break; } DoEvents(NULL); } ReleaseThread(d->DownloadThread); }
// Stop the Layer-3 switch void L3SwStop(L3SW *s) { THREAD *t = NULL; // Validate arguments if (s == NULL) { return; } Lock(s->lock); { if (s->Active == false) { Unlock(s->lock); return; } s->Halt = true; t = s->Thread; s->Active = false; } Unlock(s->lock); WaitThread(t, INFINITE); ReleaseThread(t); }
// Release of the Tick64 void FreeTick64() { UINT i; if (tk64 == NULL) { // Uninitialized return; } // Termination process tk64->Halt = true; Set(halt_tick_event); WaitThread(tk64->Thread, INFINITE); ReleaseThread(tk64->Thread); // Releasing process for (i = 0;i < LIST_NUM(tk64->AdjustTime);i++) { ADJUST_TIME *t = LIST_DATA(tk64->AdjustTime, i); Free(t); } ReleaseList(tk64->AdjustTime); DeleteLock(tk64->TickLock); Free(tk64); tk64 = NULL; ReleaseEvent(halt_tick_event); halt_tick_event = NULL; }
int GMSynthDLL::Stop() { SeqState wasRunning = seq.GetState(); //if (wasRunning != seqOff) seq.Halt(); WaitThread(); seqMode = seqOff; return wasRunning != seqOff; }
// Release the SSTP server void FreeSstpServer(SSTP_SERVER *s) { // Validate arguments if (s == NULL) { return; } TubeDisconnect(s->TubeRecv); TubeDisconnect(s->TubeSend); WaitThread(s->PPPThread, INFINITE); ReleaseThread(s->PPPThread); while (true) { BLOCK *b = GetNext(s->RecvQueue); if (b == NULL) { break; } FreeBlock(b); } while (true) { BLOCK *b = GetNext(s->SendQueue); if (b == NULL) { break; } FreeBlock(b); } ReleaseQueue(s->RecvQueue); ReleaseQueue(s->SendQueue); ReleaseSockEvent(s->SockEvent); FreeInterruptManager(s->Interrupt); ReleaseCedar(s->Cedar); ReleaseTube(s->TubeSend); ReleaseTube(s->TubeRecv); Free(s); }
// Deadlock Detection void CheckDeadLock(LOCK *lock, UINT timeout, char *name) { DEADCHECK c; THREAD *t; char msg[MAX_PATH]; if (lock == NULL) { return; } if (name == NULL) { name = "Unknown"; } Format(msg, sizeof(msg), "error: CheckDeadLock() Failed: %s\n", name); Zero(&c, sizeof(c)); c.Lock = lock; c.Timeout = timeout; c.Unlocked = false; t = NewThread(CheckDeadLockThread, &c); WaitThreadInit(t); if (WaitThread(t, timeout) == false) { if (c.Unlocked == false) { // Deadlock occured AbortExitEx(msg); } else { WaitThread(t, INFINITE); } } ReleaseThread(t); }
void CXtzThreadPool::DestroyThreadPool( ) { for ( unsigned int i = 0; i < m_threads.size(); ++i ) { CXtzThread* thread = m_threads[i].get(); if ( thread != nullptr ) { thread->SetEnd( true ); } } WaitThread( ); }
void Robot::wait(void) { WaitThread(THREAD_MAIN); WaitThread(THREAD_SENSE); WaitThread(THREAD_CONTROL); WaitThread(THREAD_SLAM); WaitThread(THREAD_CAMERA); WaitThread(THREAD_USER); }
// Release and stop the IPsec server void FreeIPsecServer(IPSEC_SERVER *s) { UINT i; IPSEC_SERVICES sl; // Validate arguments if (s == NULL) { return; } s->NoMoreChangeSettings = true; // Stopp the L2TP server StopL2TPServer(s->L2TP, false); // Stop the IKE server StopIKEServer(s->Ike); // Stop all the services explicitly Zero(&sl, sizeof(sl)); IPsecServerSetServices(s, &sl); // Releasing process FreeUdpListener(s->UdpListener); ReleaseCedar(s->Cedar); FreeL2TPServer(s->L2TP); FreeIKEServer(s->Ike); for (i = 0;i < LIST_NUM(s->EtherIPIdList);i++) { ETHERIP_ID *k = LIST_DATA(s->EtherIPIdList, i); Free(k); } ReleaseList(s->EtherIPIdList); // Stop the OS monitoring thread s->Halt = true; Set(s->OsServiceCheckThreadEvent); WaitThread(s->OsServiceCheckThread, INFINITE); ReleaseThread(s->OsServiceCheckThread); ReleaseEvent(s->OsServiceCheckThreadEvent); DeleteLock(s->LockSettings); Free(s); }
// Release the UDP acceleration function void FreeUdpAccel(UDP_ACCEL *a) { // Validate arguments if (a == NULL) { return; } while (true) { BLOCK *b = GetNext(a->RecvBlockQueue); if (b == NULL) { break; } FreeBlock(b); } ReleaseQueue(a->RecvBlockQueue); ReleaseSock(a->UdpSock); if (a->IsInCedarPortList) { LockList(a->Cedar->UdpPortList); { DelInt(a->Cedar->UdpPortList, a->MyPort); } UnlockList(a->Cedar->UdpPortList); } // Release of NAT-T related a->NatT_Halt = true; Set(a->NatT_HaltEvent); if (a->NatT_GetIpThread != NULL) { WaitThread(a->NatT_GetIpThread, INFINITE); ReleaseThread(a->NatT_GetIpThread); } ReleaseEvent(a->NatT_HaltEvent); DeleteLock(a->NatT_Lock); ReleaseCedar(a->Cedar); Free(a); }
int main(int argc, char* argv[]) { tPvErr errCode; // initialize the PvAPI if((errCode = PvInitialize()) != ePvErrSuccess) printf("PvInitialize err: %u\n", errCode); else { //IMPORTANT: Initialize camera structure. See tPvFrame in PvApi.h for more info. memset(&GCamera,0,sizeof(tCamera)); // set the CTRL-C handler SetConsoleCtrlHandler(&CtrlCHandler, TRUE); printf("Waiting for camera discovery...\n"); // register camera plugged in callback if((errCode = PvLinkCallbackRegister(CameraEventCB,ePvLinkAdd,NULL)) != ePvErrSuccess) printf("PvLinkCallbackRegister err: %u\n", errCode); // register camera unplugged callback if((errCode = PvLinkCallbackRegister(CameraEventCB,ePvLinkRemove,NULL)) != ePvErrSuccess) printf("PvLinkCallbackRegister err: %u\n", errCode); // wait until ctrl+c break printf("Ctrl+C to break.\n"); WaitForEver(); CameraStop(); CameraUnsetup(); // If thread spawned (see HandleCameraPlugged), wait to finish if(GCamera.ThHandle) WaitThread(); if((errCode = PvLinkCallbackUnRegister(CameraEventCB,ePvLinkAdd)) != ePvErrSuccess) printf("PvLinkCallbackUnRegister err: %u\n", errCode); if((errCode = PvLinkCallbackUnRegister(CameraEventCB,ePvLinkRemove)) != ePvErrSuccess) printf("PvLinkCallbackUnRegister err: %u\n", errCode); // uninitialize the API PvUnInitialize(); } return 0; }
// Listener stop void ElStopListener(EL *e) { UINT i; THREAD **threads; SOCK **socks; UINT num_threads, num_socks; // Validate arguments if (e == NULL) { return; } StopAllListener(e->Cedar); LockList(e->AdminThreadList); { threads = ToArray(e->AdminThreadList); num_threads = LIST_NUM(e->AdminThreadList); DeleteAll(e->AdminThreadList); socks = ToArray(e->AdminSockList); num_socks = LIST_NUM(e->AdminSockList); DeleteAll(e->AdminSockList); } UnlockList(e->AdminThreadList); for (i = 0;i < num_socks;i++) { Disconnect(socks[i]); ReleaseSock(socks[i]); } for (i = 0;i < num_threads;i++) { WaitThread(threads[i], INFINITE); ReleaseThread(threads[i]); } Free(threads); Free(socks); ReleaseList(e->AdminSockList); ReleaseList(e->AdminThreadList); ReleaseListener(e->Listener); }
int main (int argc, char **argv) { int i; uint32_t id[10], ret; for (i = 0; i < 10; i++) { id[i] = CreateThread(thread_main, NULL); printf("created thread %d\n", id[i]); Delay(25); } for (i = 0; i < 10; i++) { printf("waiting for thread %d\n", id[i]); WaitThread(id[i], (void **) &ret); printf("thread %d return %d\n", id[i], ret); } return 0; }
// Stop the iptables tracking void NsStopIpTablesTracking(NATIVE_STACK *a) { if (a->IpTablesThread == NULL) { return; } a->IpTablesHalt = true; Set(a->IpTablesHaltEvent); WaitThread(a->IpTablesThread, INFINITE); ReleaseThread(a->IpTablesThread); ReleaseEvent(a->IpTablesHaltEvent); a->IpTablesThread = NULL; a->IpTablesHaltEvent = NULL; a->IpTablesInitOk = false; a->IpTablesHalt = false; }
// Release the stack void FreeNativeStack(NATIVE_STACK *a) { // Validate arguments if (a == NULL) { return; } if (a->Ipc != NULL && IsZero(&a->CurrentDhcpOptionList, sizeof(a->CurrentDhcpOptionList)) == false) { IP dhcp_server; UINTToIP(&dhcp_server, a->CurrentDhcpOptionList.ServerAddress); IPCDhcpFreeIP(a->Ipc, &dhcp_server); SleepThread(200); } a->Halt = true; Cancel(a->Cancel); Disconnect(a->Sock1); Disconnect(a->Sock2); WaitThread(a->MainThread, INFINITE); ReleaseThread(a->MainThread); CloseEth(a->Eth); FreeIPC(a->Ipc); NsStopIpTablesTracking(a); ReleaseCancel(a->Cancel); ReleaseSock(a->Sock1); ReleaseSock(a->Sock2); ReleaseCedar(a->Cedar); Free(a); }
// Free VPN Azure client void FreeAzureClient(AZURE_CLIENT *ac) { SOCK *disconnect_sock = NULL; // Validate arguments if (ac == NULL) { return; } ac->Halt = true; Lock(ac->Lock); { if (ac->CurrentSock != NULL) { disconnect_sock = ac->CurrentSock; AddRef(disconnect_sock->ref); } } Unlock(ac->Lock); if (disconnect_sock != NULL) { Disconnect(disconnect_sock); ReleaseSock(disconnect_sock); } Set(ac->Event); // Stop main thread WaitThread(ac->MainThread, INFINITE); ReleaseThread(ac->MainThread); ReleaseEvent(ac->Event); DeleteLock(ac->Lock); Free(ac); }
// Release of DDNS client void FreeDDNSClient(DDNS_CLIENT *c) { // Validate arguments if (c == NULL) { return; } // Stop the thread c->Halt = true; Set(c->Event); WaitThread(c->Thread, INFINITE); ReleaseThread(c->Thread); ReleaseEvent(c->Event); ReleaseCedar(c->Cedar); DeleteLock(c->Lock); Free(c); }
// Delete the capture device bool ElDeleteCaptureDevice(EL *e, char *name) { bool ret = false; EL_DEVICE *d, t; // Validate arguments if (e == NULL || name == NULL) { return false; } LockList(e->DeviceList); { Zero(&t, sizeof(t)); StrCpy(t.DeviceName, sizeof(t.DeviceName), name); d = Search(e->DeviceList, &t); if (d != NULL) { // Stop capture d->Halt = true; Cancel(d->Cancel1); // Wait for thread stop WaitThread(d->Thread, INFINITE); ReleaseThread(d->Thread); // Release the memory Delete(e->DeviceList, d); Free(d); ret = true; } } UnlockList(e->DeviceList); return ret; }
ResultCode AddressArbiter::ArbitrateAddress(SharedPtr<Thread> thread, ArbitrationType type, VAddr address, s32 value, u64 nanoseconds) { auto timeout_callback = [this](ThreadWakeupReason reason, SharedPtr<Thread> thread, SharedPtr<WaitObject> object) { ASSERT(reason == ThreadWakeupReason::Timeout); // Remove the newly-awakened thread from the Arbiter's waiting list. waiting_threads.erase(std::remove(waiting_threads.begin(), waiting_threads.end(), thread), waiting_threads.end()); }; switch (type) { // Signal thread(s) waiting for arbitrate address... case ArbitrationType::Signal: // Negative value means resume all threads if (value < 0) { ResumeAllThreads(address); } else { // Resume first N threads for (int i = 0; i < value; i++) ResumeHighestPriorityThread(address); } break; // Wait current thread (acquire the arbiter)... case ArbitrationType::WaitIfLessThan: if ((s32)Memory::Read32(address) < value) { WaitThread(std::move(thread), address); } break; case ArbitrationType::WaitIfLessThanWithTimeout: if ((s32)Memory::Read32(address) < value) { thread->wakeup_callback = timeout_callback; thread->WakeAfterDelay(nanoseconds); WaitThread(std::move(thread), address); } break; case ArbitrationType::DecrementAndWaitIfLessThan: { s32 memory_value = Memory::Read32(address); if (memory_value < value) { // Only change the memory value if the thread should wait Memory::Write32(address, (s32)memory_value - 1); WaitThread(std::move(thread), address); } break; } case ArbitrationType::DecrementAndWaitIfLessThanWithTimeout: { s32 memory_value = Memory::Read32(address); if (memory_value < value) { // Only change the memory value if the thread should wait Memory::Write32(address, (s32)memory_value - 1); thread->wakeup_callback = timeout_callback; thread->WakeAfterDelay(nanoseconds); WaitThread(std::move(thread), address); } break; } default: LOG_ERROR(Kernel, "unknown type={}", static_cast<u32>(type)); return ERR_INVALID_ENUM_VALUE_FND; } // The calls that use a timeout seem to always return a Timeout error even if they did not put // the thread to sleep if (type == ArbitrationType::WaitIfLessThanWithTimeout || type == ArbitrationType::DecrementAndWaitIfLessThanWithTimeout) { return RESULT_TIMEOUT; } return RESULT_SUCCESS; }
// Close Ethernet adapter void CloseEth(ETH *e) { // Validate arguments if (e == NULL) { return; } if (e->Tap != NULL) { #ifndef NO_VLAN FreeTap(e->Tap); #endif // NO_VLAN } #ifdef BRIDGE_PCAP { struct CAPTUREBLOCK *block; pcap_breakloop(e->Pcap); WaitThread(e->CaptureThread, INFINITE); ReleaseThread(e->CaptureThread); pcap_close(e->Pcap); while (block = GetNext(e->Queue)){ Free(block->Buf); FreeCaptureBlock(block); } ReleaseQueue(e->Queue); } #endif // BRIDGE_PCAP #ifdef BRIDGE_BPF #ifdef BRIDGE_BPF_THREAD { struct CAPTUREBLOCK *block; int fd = e->Socket; e->Socket = INVALID_SOCKET; WaitThread(e->CaptureThread, INFINITE); ReleaseThread(e->CaptureThread); e->Socket = fd; // restore to close after while (block = GetNext(e->Queue)){ Free(block->Buf); FreeCaptureBlock(block); } ReleaseQueue(e->Queue); } #else // BRIDGE_BPF_THREAD Free(e->Buffer); #endif // BRIDGE_BPF_THREAD #endif // BRIDGE_BPF ReleaseCancel(e->Cancel); Free(e->Name); Free(e->Title); // Restore MTU value EthSetMtu(e, 0); if (e->Socket != INVALID_SOCKET) { #if defined(BRIDGE_BPF) || defined(BRIDGE_PCAP) || defined(UNIX_SOLARIS) close(e->Socket); #else // BRIDGE_PCAP closesocket(e->Socket); #endif // BRIDGE_PCAP #if defined(BRIDGE_BPF) || defined(UNIX_SOLARIS) if (e->SocketBsdIf != INVALID_SOCKET) { close(e->SocketBsdIf); } #endif // BRIDGE_BPF || UNIX_SOLARIS } Free(e); }
// Shutdown the Listener void StopListener(LISTENER *r) { UINT port; SOCK *s = NULL; // Validate arguments if (r == NULL) { return; } Lock(r->lock); if (r->Halt) { Unlock(r->lock); return; } // Stop flag set r->Halt = true; if (r->Sock != NULL) { s = r->Sock; AddRef(s->ref); } Unlock(r->lock); port = r->Port; if (r->ShadowIPv6 == false && r->Protocol == LISTENER_TCP) { SLog(r->Cedar, "LS_LISTENER_STOP_1", port); } // Close the socket if (s != NULL) { Disconnect(s); ReleaseSock(s); s = NULL; } // Set the event Set(r->Event); // Wait for stopping the thread WaitThread(r->Thread, INFINITE); // Stop the shadow listener if (r->ShadowIPv6 == false) { if (r->ShadowListener != NULL) { StopListener(r->ShadowListener); ReleaseListener(r->ShadowListener); r->ShadowListener = NULL; } } if (r->ShadowIPv6 == false && r->Protocol == LISTENER_TCP) { SLog(r->Cedar, "LS_LISTENER_STOP_2", port); } }
// Polling process void UdpAccelPoll(UDP_ACCEL *a) { UCHAR *tmp = a->TmpBuf; IP nat_t_ip; UINT num_ignore_errors = 0; // Validate arguments if (a == NULL) { return; } Lock(a->NatT_Lock); { Copy(&nat_t_ip, &a->NatT_IP, sizeof(IP)); } Unlock(a->NatT_Lock); if (IsZeroIp(&nat_t_ip) == false) { // Release the thread which gets the IP address of the NAT-T server because it is no longer needed if (a->NatT_GetIpThread != NULL) { WaitThread(a->NatT_GetIpThread, INFINITE); ReleaseThread(a->NatT_GetIpThread); a->NatT_GetIpThread = NULL; } } // Receive a new UDP packet while (true) { IP src_ip; UINT src_port; UINT ret; ret = RecvFrom(a->UdpSock, &src_ip, &src_port, tmp, UDP_ACCELERATION_TMP_BUF_SIZE); if (ret != 0 && ret != SOCK_LATER) { if (a->UseUdpIpQuery && a->UdpIpQueryPacketSize >= 8 && CmpIpAddr(&a->UdpIpQueryHost, &src_ip) == 0 && src_port == a->UdpIpQueryPort) { // Receive a response of the query for IP and port number IP my_ip = {0}; UINT myport = 0; BUF *b = MemToBuf(a->UdpIpQueryPacketData, a->UdpIpQueryPacketSize); FreeBuf(b); } else if (IsZeroIp(&nat_t_ip) == false && CmpIpAddr(&nat_t_ip, &src_ip) == 0 && src_port == UDP_NAT_T_PORT) { // Receive a response from the NAT-T server IP my_ip; UINT myport; if (RUDPParseIPAndPortStr(tmp, ret, &my_ip, &myport)) { if (myport >= 1 && myport <= 65535) { if (a->MyPortByNatTServer != myport) { a->MyPortByNatTServer = myport; a->MyPortByNatTServerChanged = true; a->CommToNatT_NumFail = 0; Debug("NAT-T: MyPort = %u\n", myport); } } } /* BUF *b = NewBuf(); PACK *p; WriteBuf(b, tmp, ret); SeekBufToBegin(b); p = BufToPack(b); if (p != NULL) { if (PackCmpStr(p, "opcode", "query_for_nat_traversal")) { if (PackGetBool(p, "ok")) { if (PackGetInt64(p, "tran_id") == a->NatT_TranId) { UINT myport = PackGetInt(p, "your_port"); if (myport >= 1 && myport <= 65535) { if (a->MyPortByNatTServer != myport) { a->MyPortByNatTServer = myport; a->MyPortByNatTServerChanged = true; Debug("NAT-T: MyPort = %u\n", myport); } } } } } FreePack(p); } FreeBuf(b);*/ } else { BLOCK *b = UdpAccelProcessRecvPacket(a, tmp, ret, &src_ip, src_port); //Debug("UDP Recv: %u %u %u\n", ret, (b == NULL ? 0 : b->Size), (b == NULL ? 0 : b->Compressed)); /*if (b != NULL) { char tmp[MAX_SIZE * 10]; BinToStr(tmp, sizeof(tmp), b->Buf, b->Size); Debug("Recv Pkt: %s\n", tmp); }*/ if (b != NULL) { // Receive a packet InsertQueue(a->RecvBlockQueue, b); } } } else { if (ret == 0) { if (a->UdpSock->IgnoreRecvErr == false) { // Serious UDP reception error occurs a->FatalError = true; break; } if ((num_ignore_errors++) >= MAX_NUM_IGNORE_ERRORS) { a->FatalError = true; break; } } else { // SOCK_LATER break; } } } // Send a Keep-Alive packet if (a->NextSendKeepAlive == 0 || (a->NextSendKeepAlive <= a->Now) || a->YourPortByNatTServerChanged) { a->YourPortByNatTServerChanged = false; if (UdpAccelIsSendReady(a, false)) { UINT rand_interval; if (a->FastDetect == false) { rand_interval = rand() % (UDP_ACCELERATION_KEEPALIVE_INTERVAL_MAX - UDP_ACCELERATION_KEEPALIVE_INTERVAL_MIN) + UDP_ACCELERATION_KEEPALIVE_INTERVAL_MIN; } else { rand_interval = rand() % (UDP_ACCELERATION_KEEPALIVE_INTERVAL_MAX_FAST - UDP_ACCELERATION_KEEPALIVE_INTERVAL_MIN_FAST) + UDP_ACCELERATION_KEEPALIVE_INTERVAL_MIN_FAST; } a->NextSendKeepAlive = a->Now + (UINT64)rand_interval; //Debug("UDP KeepAlive\n"); UdpAccelSend(a, NULL, 0, false, 1000, false); } } // Send a NAT-T request packet (Only if the connection by UDP has not be established yet) if (a->NoNatT == false) { // In the usual case if (IsZeroIp(&nat_t_ip) == false) { if (UdpAccelIsSendReady(a, true) == false) { if (a->NextPerformNatTTick == 0 || (a->NextPerformNatTTick <= a->Now)) { UINT rand_interval; UCHAR c = 'B'; a->CommToNatT_NumFail++; rand_interval = UDP_NAT_T_INTERVAL_INITIAL * MIN(a->CommToNatT_NumFail, UDP_NAT_T_INTERVAL_FAIL_MAX); //PACK *p = NewPack(); //BUF *b; if (a->MyPortByNatTServer != 0) { rand_interval = GenRandInterval(UDP_NAT_T_INTERVAL_MIN, UDP_NAT_T_INTERVAL_MAX); } a->NextPerformNatTTick = a->Now + (UINT64)rand_interval; // Generate the request packet /*PackAddStr(p, "description", UDP_NAT_T_SIGNATURE); PackAddStr(p, "opcode", "query_for_nat_traversal"); PackAddInt64(p, "tran_id", a->NatT_TranId); b = PackToBuf(p); FreePack(p);*/ // Send the request packet SendTo(a->UdpSock, &nat_t_ip, UDP_NAT_T_PORT, &c, 1); //FreeBuf(b); } } else { a->NextPerformNatTTick = 0; a->CommToNatT_NumFail = 0; } } } else { // NAT_T is disabled, but there is a reference host (such as VGC) if (a->UseUdpIpQuery || a->UseSuperRelayQuery) { } } }
// Management port Listen thread void NiListenThread(THREAD *thread, void *param) { NAT *n = (NAT *)param; SOCK *a; UINT i; bool b = false; // Validate arguments if (thread == NULL || param == NULL) { return; } // Initialize the management list n->AdminList = NewList(NULL); while (true) { a = Listen(DEFAULT_NAT_ADMIN_PORT); if (b == false) { b = true; NoticeThreadInit(thread); } if (a != NULL) { break; } Wait(n->HaltEvent, NAT_ADMIN_PORT_LISTEN_INTERVAL); if (n->Halt) { return; } } n->AdminListenSock = a; AddRef(a->ref); // Waiting while (true) { SOCK *s = Accept(a); THREAD *t; NAT_ADMIN *admin; if (s == NULL) { break; } if (n->Halt) { ReleaseSock(s); break; } admin = ZeroMalloc(sizeof(NAT_ADMIN)); admin->Nat = n; admin->Sock = s; t = NewThread(NiAdminThread, admin); WaitThreadInit(t); ReleaseThread(t); } // Disconnect all management connections LockList(n->AdminList); { for (i = 0;i < LIST_NUM(n->AdminList);i++) { NAT_ADMIN *a = LIST_DATA(n->AdminList, i); Disconnect(a->Sock); WaitThread(a->Thread, INFINITE); ReleaseThread(a->Thread); ReleaseSock(a->Sock); Free(a); } } UnlockList(n->AdminList); ReleaseList(n->AdminList); ReleaseSock(a); }