void JobThreadFunc(void) { Lock(); O2IMessages queue(Queue); Queue.clear(); Unlock(); if (queue.size() == 0) return; hashT myid; Profile->GetID(myid); O2IMessagesIt it; for (it = queue.begin(); it != queue.end() && IsActive(); it++) { O2IMessage &im = *it; TRACEA("[BroadcastJob]"); TRACEW(it->msg.c_str()); TRACEA("\n"); O2NodeDB::NodeListT neighbors; if (NodeDB->neighbors(myid, neighbors, false, O2_BROADCAST_PATH_LIMIT+2) == 0) return; O2NodeDB::NodeListT::iterator nit = neighbors.begin(); while (nit != neighbors.end()) { if (nit->id == im.id) { nit = neighbors.erase(nit); continue; } hashListT::iterator hit = std::find(im.paths.begin(), im.paths.end(), nit->id); if (hit != im.paths.end()) { nit = neighbors.erase(nit); continue; } nit++; } if (neighbors.empty()) continue; hashT myid; Profile->GetID(myid); im.paths.push_back(myid); while (im.paths.size() > O2_BROADCAST_PATH_LIMIT) im.paths.pop_front(); for (nit = neighbors.begin(); nit != neighbors.end() && IsActive(); nit++) { nit->lastlink = 0; nit->reset(); // Broadcast発行 O2SocketSession ss; ss.ip = nit->ip; ss.port = nit->port; string xml; BroadcastDB->MakeSendXML(im, xml); string url; MakeURL(ss.ip, ss.port, O2PROTOPATH_BROADCAST, url); HTTPHeader hdr(HTTPHEADERTYPE_REQUEST); hdr.method = "POST"; hdr.SetURL(url.c_str()); AddRequestHeaderFields(hdr, Profile); AddContentFields(hdr, xml.size(), "text/xml", DEFAULT_XML_CHARSET); hdr.Make(ss.sbuff); ss.sbuff += xml; Client->AddRequest(&ss); ss.Wait(); HTTPHeader *header = (HTTPHeader*)ss.data; if (CheckResponse(&ss, header, NodeDB, *nit)) { ; } if (header) delete header; Sleep(1000); } for (nit = neighbors.begin(); nit != neighbors.end() && IsActive(); nit++) { if (nit->lastlink) { // 成功したノードをtouch NodeDB->touch(*nit); } else { // 失敗したノードをremove NodeDB->remove(*nit); KeyDB->DeleteKeyByNodeID(nit->id); } } Sleep(IsActive() ? 1000 : 0); } }
uint O2Agent:: NetIOThread(void) { O2SocketSessionListIt ssit; int lasterror; while (Active) { //setup FD fd_set readfds; fd_set writefds; FD_ZERO(&readfds); FD_ZERO(&writefds); //wait Lock(); uint n = sss.size(); Unlock(); if (n == 0) { ResetEvent(SessionAvailableEvent); } WaitForSingleObject(SessionAvailableEvent, INFINITE); if (!Active) break; //FD Lock(); for (ssit = sss.begin(); ssit != sss.end(); ssit++) { O2SocketSession *ss = *ssit; if (!ss->sendcomplete) FD_SET(ss->sock, &writefds); else FD_SET(ss->sock, &readfds); } Unlock(); //select struct timeval tv; tv.tv_sec = SELECT_TIMEOUT_MS/1000; tv.tv_usec = SELECT_TIMEOUT_MS%1000; select(0, &readfds, &writefds, NULL, &tv); // // 既存セッションとの送受信 // Lock(); ssit = sss.begin(); Unlock(); while (1) { bool loopend = false; Lock(); if (ssit == sss.end()) loopend = true; Unlock(); if (loopend) break; #if DEBUG_THREADLOOP && defined(_DEBUG) TRACEA("[NetIO]\n"); #endif O2SocketSession *ss = *ssit; O2AgentService *service = (O2AgentService*)ss->service; ushort port = htons(ss->sin.sin_port); wstring ipstr; #if defined (_DEBUG) ulong2ipstr(ss->sin.sin_addr.S_un.S_addr, ipstr); #else ip2e(ss->sin.sin_addr.S_un.S_addr, ipstr); #endif //send if (FD_ISSET(ss->sock, &writefds)) { int len; const char *buff = ss->GetSendBuffer(len); if (len > 0) { int n = send(ss->sock, buff, len, 0); #if DEBUG_THREADLOOP && defined(_DEBUG) TRACEA("[A]send\n"); #endif if (n > 0) { ss->UpdateSend(n); NodeDB->IncrementSendByte_me2n(ss->sin.sin_addr.S_un.S_addr, n); service->IncrementSendByte(n); service->OnSend(ss); ss->UpdateTimer(); if (hwndSetIconCallback) { PostMessage(hwndSetIconCallback, msgSetIconCallback, 1, 0); } } else if (n == 0) { ; } else if ((lasterror = WSAGetLastError()) != WSAEWOULDBLOCK) { if (Logger) { Logger->AddLog(O2LT_NET, MODULE, L"送信エラー(%d) (%s %s:%d %dbyte)", lasterror, service->GetName(), ipstr.c_str(), port, ss->sbuff.size()); } ss->SetActive(false); } } } //recv if (FD_ISSET(ss->sock, &readfds)) { char buff[RECVBUFFSIZE]; int n = recv(ss->sock, buff, RECVBUFFSIZE, 0); #if DEBUG_THREADLOOP && defined(_DEBUG) TRACEA("[A]recv\n"); #endif if (n > 0) { ss->AppendRecv(buff, n); NodeDB->IncrementRecvByte_me2n(ss->sin.sin_addr.S_un.S_addr, n); service->IncrementRecvByte(n); service->OnRecv(ss); ss->UpdateTimer(); if (hwndSetIconCallback) { PostMessage(hwndSetIconCallback, msgSetIconCallback, 0, 0); } } else if (n == 0) { if (Logger) { Logger->AddLog(O2LT_NET, MODULE, L"受信0 (%s %s:%d)", service->GetName(), ipstr.c_str(), port); } ss->SetActive(false); } else if ((lasterror = WSAGetLastError()) != WSAEWOULDBLOCK) { if (Logger) { Logger->AddLog(O2LT_NET, MODULE, L"受信エラー(%d) (%s %s:%d %dbyte)", lasterror, service->GetName(), ipstr.c_str(), port, ss->rbuff.size()); } ss->SetActive(false); } } //delete if (!ss->IsActive() || ss->GetPastTime() >= SOCKET_TIMEOUT_S) { void *databk = ss->data; ulong ip = ss->sin.sin_addr.S_un.S_addr; closesocket(ss->sock); service->OnClose(ss); NodeDB->RemoveStatusBit(ip, O2_NODESTATUS_LINKEDTO); NodeDB->AddStatusBit(ip, O2_NODESTATUS_PASTLINKEDTO); service->DecrementCount(); if (!ss->rbuff.empty() && !ss->sbuff.empty()) { NodeDB->UpdateLastModified(ip, 2); service->IncrementTotalSessionCount(); } else if (ss->rbuff.empty()) NodeDB->IncrementErrorCount(ip, 1); if (!ss->rbuff.empty() && (!databk || ss->rbuff[0] != 'H')) { NodeDB->DeleteNode(ip); if (Logger) { Logger->AddLog(O2LT_WARNING, MODULE, L"不正データ受信 (ノード削除: %s:%d)", ipstr.c_str(), htons(ss->sin.sin_port)); } if (O2DEBUG) { char filename[256]; sprintf_s(filename, 256, "dump\\A_%d.txt", rand()); FILE *fp; fopen_s(&fp, filename, "wb"); fwrite(ss->rbuff.c_str(), ss->rbuff.size(), 1, fp); fclose(fp); } } #if DEBUG_SESSION_COUNT && defined(_DEBUG) wchar_t abc[256]; swprintf(abc, L"■■削除■■ count:%d limit:%d %s\n", service->GetSessionCount(), service->GetSessionLimit(), service->GetName()); TRACEW(abc); #endif Lock(); ssit = sss.erase(ssit); Unlock(); delete ss; continue; } Sleep(1); ssit++; } } //end Lock(); for (ssit = sss.begin(); ssit != sss.end(); ssit++) { O2SocketSession *ss = *ssit; closesocket(ss->sock); ss->sock = 0; ((O2AgentService*)((O2AgentService*)ss->service))->OnClose(ss); delete ss; } sss.clear(); Unlock(); return (0); }
uint O2Agent:: LaunchThread(void) { for (uint i = 0; i < Services.size(); i++) { Services[i]->SetActive(true); Services[i]->OnServiceStart(); } Agent_GetGlobalIP->SetActive(true); Agent_GetGlobalIP->OnServiceStart(); if (Logger) Logger->AddLog(O2LT_INFO, MODULE, L"エージェント正常起動"); time_t prevconnecttime = time(NULL); uint index = 0; while (Active) { index %= Services.size(); /* * ウェイト処理 */ if (NodeDB->Count() == 0) { #if DEBUG_THREADLOOP && defined(_DEBUG) TRACEA("■Node 0\n"); #endif Sleep(1000); continue; } uint pasttime_ms = ((uint)time(NULL) - (uint)prevconnecttime) * 1000; if (pasttime_ms < Interval) { uint sleeptime_ms = Interval - pasttime_ms; #if DEBUG_THREADLOOP && defined(_DEBUG) TRACEA("Wait interval\n"); #endif if (Agent_GetGlobalIP->IsActive()) { ; //グローバルIP未確定のときは急ぐ } else { if (sleeptime_ms < 1000) Sleep(sleeptime_ms); else Sleep(1000); continue; } } /* * サービス起動 */ O2AgentService *service = Services[index]; if (Agent_GetGlobalIP->IsActive()) //グローバルIP未決定のとき service = Agent_GetGlobalIP; //強制的にAgent_GetGlobalIP起動 #if DEBUG_SESSION_COUNT && defined(_DEBUG) wchar_t abc[256]; swprintf(abc, L"● count:%d limit:%d %s\n", service->GetSessionCount(), service->GetSessionLimit(), service->GetName()); TRACEW(abc); #endif if (!service->IsActive()) { index++; continue; } if (service->GetSessionCount() >= service->GetSessionLimit()) { Sleep(500); index++; continue; } O2SocketSession *ss = new O2SocketSession(); ss->service = (void*)service; ulong ip; ushort port; wstring ipstr; //接続先ノード決定 //接続 TODO:クラスタリング if (service->HaveNodeDecision()) { service->OnLaunch(ss); if (!ss->IsActive()) { delete ss; index++; continue; } ip = ss->sin.sin_addr.S_un.S_addr; port = htons(ss->sin.sin_port); } else if (!NodeDB->GetNodeByPriority(ip, port)) { if (Logger) { Logger->AddLog(O2LT_WARNING, MODULE, L"有効なノード情報が無いので接続不可(%s)", service->GetName()); } delete ss; index++; continue; } #if !defined(_DEBUG) if (ip == Profile->GetIP() || ip == 0x0100007f) { #if 0 struct in_addr addr; addr.S_un.S_addr = ip; if (Logger) { Logger->AddLog(O2LT_WARNING, MODULE, "自ノード情報破棄 IP: %s Port: %d", inet_ntoa(addr), port); } #endif NodeDB->DeleteNode(ip); delete ss; index++; continue; } #endif #if defined(_DEBUG) ulong2ipstr(ip, ipstr); #else ip2e(ip, ipstr); #endif /* * Socket生成 */ ss->sock = socket(AF_INET, SOCK_STREAM, 0); if (ss->sock == INVALID_SOCKET) { if (Logger) Logger->AddLog(O2LT_ERROR, MODULE, L"ソケット生成に失敗"); delete ss; index++; continue; } ss->sin.sin_family = AF_INET; ss->sin.sin_port = htons(port); ss->sin.sin_addr.S_un.S_addr = ip; /* * Connect */ int timeout = service == Agent_GetGlobalIP ? GIP_CONNECT_TIMEOUT_MS : CONNECT_TIMEOUT_MS; if (connect2(ss->sock, (struct sockaddr*)&ss->sin, sizeof(ss->sin), timeout) != 0) { //NodeDB->DeleteNode(ip); NodeDB->IncrementErrorCount(ip, 1); if (Logger) { Logger->AddLog(O2LT_NET, MODULE, L"connect失敗(%s %s:%d)", service->GetName(), ipstr.c_str(), port); } closesocket(ss->sock); delete ss; index++; continue; } if (hwndSetIconCallback) { PostMessage(hwndSetIconCallback, msgSetIconCallback, 1, 0); } //launch if (!service->HaveNodeDecision()) { service->OnLaunch(ss); if (!ss->IsActive()) { closesocket(ss->sock); delete ss; index++; continue; } } ss->UpdateTimer(); service->IncrementCount(); Lock(); sss.push_back(ss); Unlock(); SetEvent(SessionAvailableEvent); NodeDB->AddStatusBit(ip, O2_NODESTATUS_LINKEDTO); prevconnecttime = time(NULL); index++; #if DEBUG_SESSION_COUNT && defined(_DEBUG) swprintf(abc, L"●● count:%d limit:%d %s\n", service->GetSessionCount(), service->GetSessionLimit(), service->GetName()); TRACEW(abc); #endif if (Logger) { Logger->AddLog(O2LT_NET, MODULE, L"connect成功 (%s %s:%d)", service->GetName(), ipstr.c_str(), port); } } //end Lock(); SetEvent(SessionAvailableEvent); Unlock(); for (uint i = 0; i < Services.size(); i++) { O2AgentService *service = Services[i]; if (service->IsActive()) { service->SetActive(false); service->OnServiceEnd(); } } if (Logger) Logger->AddLog(O2LT_INFO, MODULE, L"エージェント正常終了"); return (0); }
void O2Client:: NetIOThread(void) { O2SocketSessionPListIt ssit; int lasterror; while (Active) { // Signal Off SessionListLock.Lock(); { if (sss.empty()) SessionExistSignal.Off(); } SessionListLock.Unlock(); // Wait SessionExistSignal.Wait(); if (!Active) break; // Setup FD fd_set readfds; fd_set writefds; FD_ZERO(&readfds); FD_ZERO(&writefds); SessionListLock.Lock(); { for (ssit = sss.begin(); ssit != sss.end(); ssit++) { O2SocketSession *ss = *ssit; if (ss->can_send) FD_SET(ss->sock, &writefds); if (ss->can_recv) FD_SET(ss->sock, &readfds); } } SessionListLock.Unlock(); // select struct timeval tv; tv.tv_sec = SELECT_TIMEOUT_MS/1000; tv.tv_usec = SELECT_TIMEOUT_MS%1000; select(0, &readfds, &writefds, NULL, &tv); if (!Active) break; // // 既存セッションとの送受信 // SessionListLock.Lock(); ssit = sss.begin(); SessionListLock.Unlock(); while (Active) { bool end = false; SessionListLock.Lock(); { if (ssit == sss.end()) end = true; } SessionListLock.Unlock(); if (end) break; O2SocketSession *ss = *ssit; // IP文字列 wstring ipstr; if (O2DEBUG) ulong2ipstr(ss->ip, ipstr); else ip2e(ss->ip, ipstr); // Send if (FD_ISSET(ss->sock, &writefds)) { int len; const char *buff = ss->GetNextSend(len); if (len > 0) { int n = send(ss->sock, buff, len, 0); if (n > 0) { ss->UpdateSend(n); ss->UpdateTimer(); SendByte += n; OnSend(ss); if (hwndSetIconCallback) { #if defined(_WIN32) && !defined(__WXWINDOWS__) /** Use ordinary windows api */ PostMessage(hwndSetIconCallback, msgSetIconCallback, 1, 0); #else /** Platform is not windows */ #warning "TODO: implement wxWidgets event method here" #endif } } else if (n == 0) { // do nothing } #ifdef _WIN32 /** Windows */ else if ((lasterror = WSAGetLastError()) != WSAEWOULDBLOCK) #else /** Unix */ else if (errno == EAGAIN) #endif { if (Logger) { Logger->AddLog(O2LT_NETERR, ClientName.c_str(), ss->ip, ss->port, L"送信エラー(%d)", lasterror); } ss->error = true; ss->Deactivate(); } } } // Recv if (FD_ISSET(ss->sock, &readfds)) { char buff[RECVBUFFSIZE]; int n = recv(ss->sock, buff, RECVBUFFSIZE, 0); if (n > 0) { ss->AppendRecv(buff, n); ss->UpdateTimer(); RecvByte += n; OnRecv(ss); if (hwndSetIconCallback) { #if defined(_WIN32) && !defined(__WXWINDOWS__) /** Use ordinary windows api */ PostMessage(hwndSetIconCallback, msgSetIconCallback, 0, 0); #else /** Platform is not windows */ #warning "TODO: implement wxWidgets event method here" #endif } } else if (n == 0) { /*if (Logger) { Logger->AddLog(O2LT_NETERR, ClientName.c_str(), ss->ip, ss->port, L"受信0"); }*/ ss->Deactivate(); } #ifdef _WIN32 /** Windows */ else if ((lasterror = WSAGetLastError()) != WSAEWOULDBLOCK) #else /** Unix */ else if (errno == EAGAIN) #endif { if (Logger) { Logger->AddLog(O2LT_NETERR, ClientName.c_str(), ss->ip, ss->port, L"受信エラー(%d)", lasterror); } ss->error = true; ss->Deactivate(); } }
void JobThreadFunc(void) { Lock(); O2KeyList keylist(RequestQueue); RequestQueue.clear(); Unlock(); if (keylist.size() == 0) return; O2NodeDB::NodeListT Nodes; // キーでループ O2KeyListIt it; for (it = keylist.begin(); it != keylist.end() && IsActive(); it++) { O2Key &key = *it; TRACEA("[GETDAT]"); TRACEW(it->url.c_str()); TRACEA("\n"); O2Node node; node.id = it->nodeid; node.ip = it->ip; node.port = it->port; // リクエスト発行 O2SocketSession ss; ss.ip = key.ip; ss.port = key.port; MakeRequest_Dat(&key.hash, NULL, &ss, Profile, DatIO, ss.sbuff); Client->AddRequest(&ss); ss.Wait(); HTTPHeader *header = (HTTPHeader*)ss.data; if (CheckResponse(&ss, header, NodeDB, node)) { // 本文のdat取り込み const char *rawdata = &ss.rbuff[header->length]; uint64 datsize = ss.rbuff.size() - header->length; ImportDat(DatIO, Profile, NULL, *header, rawdata, datsize, Logger, ss.ip, ss.port, QueryDB, hwndBaloonCallback, msgBaloonCallback); } if (header) delete header; Nodes.push_back(node); Sleep(IsActive() ? QUERY_DAT_INTERVAL_MS : 0); } O2NodeDB::NodeListT::iterator nit; for (nit = Nodes.begin(); nit != Nodes.end() && IsActive(); nit++) { if (nit->lastlink) { // 成功したノードをtouch NodeDB->touch(*nit); } else { // 失敗したノードをremove NodeDB->remove(*nit); KeyDB->DeleteKeyByNodeID(nit->id); } } }
void O2Client:: NetIOThread(void) { O2SocketSessionPListIt ssit; int lasterror; while (Active) { // Signal Off SessionListLock.Lock(); { if (sss.empty()) SessionExistSignal.Off(); } SessionListLock.Unlock(); // Wait SessionExistSignal.Wait(); if (!Active) break; // Setup FD fd_set readfds; fd_set writefds; FD_ZERO(&readfds); FD_ZERO(&writefds); SessionListLock.Lock(); { for (ssit = sss.begin(); ssit != sss.end(); ssit++) { O2SocketSession *ss = *ssit; if (ss->can_send) FD_SET(ss->sock, &writefds); if (ss->can_recv) FD_SET(ss->sock, &readfds); } } SessionListLock.Unlock(); // select struct timeval tv; tv.tv_sec = SELECT_TIMEOUT_MS/1000; tv.tv_usec = SELECT_TIMEOUT_MS%1000; select(0, &readfds, &writefds, NULL, &tv); if (!Active) break; // // 既存セッションとの送受信 // SessionListLock.Lock(); ssit = sss.begin(); SessionListLock.Unlock(); while (Active) { bool end = false; SessionListLock.Lock(); { if (ssit == sss.end()) end = true; } SessionListLock.Unlock(); if (end) break; O2SocketSession *ss = *ssit; // IP文字列 wstring ipstr; if (O2DEBUG) ulong2ipstr(ss->ip, ipstr); else ip2e(ss->ip, ipstr); // Send if (FD_ISSET(ss->sock, &writefds)) { int len; const char *buff = ss->GetNextSend(len); if (len > 0) { int n = send(ss->sock, buff, len, 0); if (n > 0) { ss->UpdateSend(n); ss->UpdateTimer(); SendByte += n; OnSend(ss); if (hwndSetIconCallback) { PostMessage(hwndSetIconCallback, msgSetIconCallback, 1, 0); } } else if (n == 0) { ; } else if ((lasterror = WSAGetLastError()) != WSAEWOULDBLOCK) { if (Logger) { Logger->AddLog(O2LT_NETERR, ClientName.c_str(), ss->ip, ss->port, L"送信エラー(%d)", lasterror); } ss->error = true; ss->Deactivate(); } } } // Recv if (FD_ISSET(ss->sock, &readfds)) { char buff[RECVBUFFSIZE]; int n = recv(ss->sock, buff, RECVBUFFSIZE, 0); if (n > 0) { ss->AppendRecv(buff, n); ss->UpdateTimer(); RecvByte += n; OnRecv(ss); if (hwndSetIconCallback) { PostMessage(hwndSetIconCallback, msgSetIconCallback, 0, 0); } } else if (n == 0) { /*if (Logger) { Logger->AddLog(O2LT_NETERR, ClientName.c_str(), ss->ip, ss->port, L"受信0"); }*/ ss->Deactivate(); } else if ((lasterror = WSAGetLastError()) != WSAEWOULDBLOCK) { if (Logger) { Logger->AddLog(O2LT_NETERR, ClientName.c_str(), ss->ip, ss->port, L"受信エラー(%d)", lasterror); } ss->error = true; ss->Deactivate(); } } // Delete if (ss->CanDelete()) { bool timeout = ss->GetPastTime() >= ss->timeout_s ? true : false; if (!ss->IsActive() || timeout) { if (timeout) { if (Logger) { Logger->AddLog(O2LT_NETERR, ClientName.c_str(), ss->ip, ss->port, L"timeout"); } } closesocket(ss->sock); ss->sock = 0; SessionListLock.Lock(); ssit = sss.erase(ssit); SessionListLock.Unlock(); OnClose(ss); continue; } } Sleep(1); SessionListLock.Lock(); ssit++; SessionListLock.Unlock(); } } // End SessionListLock.Lock(); for (ssit = sss.begin(); ssit != sss.end(); ssit++) { O2SocketSession *ss = *ssit; closesocket(ss->sock); ss->sock = 0; OnClose(ss); } sss.clear(); SessionListLock.Unlock(); }