// IPC connection processing thread void EtherIPIpcConnectThread(THREAD *t, void *p) { ETHERIP_SERVER *s; IPC *ipc = NULL; UINT error_code = 0; char tmp[MAX_SIZE]; ETHERIP_ID id; // Validate arguments if (t == NULL || p == NULL) { return; } s = (ETHERIP_SERVER *)p; GetHostName(tmp, sizeof(tmp), &s->ClientIP); // Get the setting of the virtual HUB to be connected based on the client ID presented if (SearchEtherIPId(s->Ike->IPsec, &id, s->ClientId) == false && SearchEtherIPId(s->Ike->IPsec, &id, "*") == false) { // Failed to get the settings for the virtual HUB Debug("Not Found: EtherIP Settings for Client ID \"%s\".\n", s->ClientId); EtherIPLog(s, "LE_NO_SETTING", s->ClientId); } else { UINT mss = CalcEtherIPTcpMss(s); char client_name[MAX_SIZE]; if (s->L2TPv3 == false) { StrCpy(client_name, sizeof(client_name), ETHERIP_CLIENT_NAME); } else { if (IsEmptyStr(s->VendorName)) { StrCpy(client_name, sizeof(client_name), ETHERIP_L2TPV3_CLIENT_NAME); } else { Format(client_name, sizeof(client_name), ETHERIP_L2TPV3_CLIENT_NAME_EX, s->VendorName); } } // Execution of IPC connection process EtherIPLog(s, "LE_START_IPC", id.HubName, id.UserName, mss); ipc = NewIPC(s->Cedar, client_name, (s->L2TPv3 ? ETHERIP_L2TPV3_POSTFIX : ETHERIP_POSTFIX), id.HubName, id.UserName, id.Password, &error_code, &s->ClientIP, s->ClientPort, &s->ServerIP, s->ServerPort, tmp, s->CryptName, true, mss, NULL); if (ipc != NULL) { Copy(&s->CurrentEtherIPIdSetting, &id, sizeof(ETHERIP_ID)); EtherIPLog(s, "LE_IPC_CONNECT_OK", id.HubName); } else { EtherIPLog(s, "LE_IPC_CONNECT_ERROR", id.HubName, error_code, _E(error_code)); } } Lock(s->Lock); { // Set the results ReleaseThread(s->IpcConnectThread); s->IpcConnectThread = NULL; s->Ipc = ipc; s->LastConnectFailedTick = Tick64(); } Unlock(s->Lock); // Hit the event to cause interrupt SetSockEvent(s->SockEvent); // Release the EtherIP object that is hold by this thread ReleaseEtherIPServer(s); }
/****************************************************************************** 处理名 : 本类的析构处理 函数名 : ~CChannelItem() 参数 : 无 返回值 : 无 ******************************************************************************/ CChannelItem::~CChannelItem(){ ReleaseThread(); ReleaseProcess(); }
// Polling process void UdpAccelPoll(UDP_ACCEL *a) { IP nat_t_ip; UINT num_ignore_errors = 0; UCHAR *tmp; // Validate arguments if (a == NULL) { return; } tmp = a->TmpBuf; 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) { } } }
// 管理ポート Listen スレッド void NiListenThread(THREAD *thread, void *param) { NAT *n = (NAT *)param; SOCK *a; UINT i; bool b = false; // 引数チェック if (thread == NULL || param == NULL) { return; } // 管理リストの初期化 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); // 待ち受け 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); } // すべての管理コネクションを切断 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); }