void PopupServentMenu(int servent_id){ POINT pos; MENUITEMINFO info, separator; HMENU hMenu; DWORD dwID; hMenu = CreatePopupMenu(); memset(&separator, 0, sizeof(MENUITEMINFO)); separator.cbSize = sizeof(MENUITEMINFO); separator.fMask = MIIM_ID | MIIM_TYPE; separator.fType = MFT_SEPARATOR; separator.wID = 8000; memset(&info, 0, sizeof(MENUITEMINFO)); info.cbSize = sizeof(MENUITEMINFO); info.fMask = MIIM_ID | MIIM_TYPE; info.fType = MFT_STRING; ServentData *sd = NULL; ChannelData *cd = channelDataTop; while(cd){ // COUT if (cd->type == Servent::T_COUT && cd->servent_id == servent_id) break; sd = cd->findServentData(servent_id); if (sd){ break; } cd = cd->getNextData(); } if (cd == NULL || sd == NULL && cd->type != Servent::T_COUT) // COUT { return; } info.wID = 1001; info.dwTypeData = "切断"; InsertMenuItem(hMenu, -1, true, &info); // InsertMenuItem(hMenu, -1, true, &separator); GetCursorPos(&pos); dwID = TrackPopupMenu(hMenu, TPM_LEFTALIGN|TPM_RETURNCMD, pos.x, pos.y, 0, guiWnd, NULL); DestroyMenu(hMenu); cd = channelDataTop; while(cd){ // COUT if (cd->type == Servent::T_COUT && cd->servent_id == servent_id) break; sd = cd->findServentData(servent_id); if (sd){ break; } cd = cd->getNextData(); } if (cd == NULL || sd == NULL && cd->type != Servent::T_COUT) // COUT { return; } Servent *s = servMgr->findServentByServentID(servent_id); if (s == NULL){ return; } switch(dwID){ case 1001: // 切断 s->thread.active = false; // COUT切断 if (s->type == Servent::T_COUT) s->thread.finish = true; break; } }
THREAD_PROC GUIDataUpdate(ThreadInfo *thread){ int i; // set GUI thread status to running thread->finish = false; while(thread->active){ // チャンネルデータロック ChannelDataLock.on(); // チャンネルデータの更新フラグを全てFALSEにする ChannelData *cd = channelDataTop; while(cd){ // Serventの更新フラグをFALSEにする ServentData *sv = cd->getServentDataTop(); while(sv){ sv->setEnableFlg(FALSE); sv = sv->getNextData(); } cd->setEnableFlg(FALSE); cd = cd->getNextData(); } Channel *c = chanMgr->channel; // 現在存在するチャンネル分ループ while(c){ // 既にチャンネルデータを持っているか cd = channelDataTop; // 発見フラグFALSE bool bFoundFlg = FALSE; while(cd){ if (cd->getChannelId() == c->channel_id){ //既にチャンネルデータがあるので、そのまま更新 cd->setData(c); // 更新フラグTRUE cd->setEnableFlg(TRUE); // 発見フラグTRUE bFoundFlg = TRUE; // ループ離脱 break; } // 見つからなかった場合、次のデータをチェック cd = cd->getNextData(); } // 新しいチャンネルの場合、新規データ作成 if (!bFoundFlg){ // 新規データ作成 cd = ::new ChannelData(); // データ更新 cd->setData(c); // 更新フラグTRUE cd->setEnableFlg(TRUE); // 新規データをリストの先頭に入れる cd->setNextData(channelDataTop); channelDataTop = cd; } // 次のチャンネルを取得 c = c->next; } #if 1 // COUTを検索 { bool foundFlg = false; bool foundFlg2 = false; Servent *s = servMgr->servents; while (s) { if (s->type == Servent::T_COUT && s->status == Servent::S_CONNECTED) { foundFlg = true; // ChannelData末尾まで探索 ChannelData *prev = NULL; cd = channelDataTop; while (cd) { if (cd->type == Servent::T_COUT && cd->servent_id == s->servent_id) { foundFlg2 = true; cd->setEnableFlg(true); break; } prev = cd; cd = cd->getNextData(); } cd = prev; if (foundFlg2) break; // ノード追加 if (channelDataTop) { // channelDataが空でない。cdはここでリスト末尾を指してる(はず) cd->setNextData(::new ChannelData()); cd = cd->getNextData(); memset(cd, 0, sizeof(cd)); cd->setNextData(NULL); } else { // channelDataが空 channelDataTop = ::new ChannelData(); channelDataTop->setNextData(NULL); cd = channelDataTop; } // データ設定 cd->type = s->type; cd->servent_id = s->servent_id; cd->setEnableFlg(true); } s = s->next; } // COUTが切れてたら削除 if (!foundFlg) { cd = channelDataTop; ChannelData *prev = NULL; while (cd) { // COUTの情報を削除 if (cd->type == Servent::T_COUT) { // 先頭 if (!prev) { channelDataTop = cd->getNextData(); } else { prev->setNextData(cd->getNextData()); } //::delete cd; } prev = cd; cd = cd->getNextData(); } } } #endif // チャンネルがなくなっている場合の処理 cd = channelDataTop; ChannelData *prev = NULL; while(cd){ // データを更新しなかったか if (cd->getEnableFlg() == FALSE){ // チャンネルがなくなっているので削除 ChannelData *next; next = cd->getNextData(); if (!prev){ // 先頭のデータを削除 // ここメモリリークしそう by えるー channelDataTop = next; } else { // 途中のデータを削除 prev->setNextData(next); } // 次のデータへ cd = next; } else { // データ更新済:次のデータへ prev = cd; cd = cd->getNextData(); } } Servent *s = servMgr->servents; while(s){ // 初期化 ChanHitList *chl; bool infoFlg = false; bool relay = true; bool firewalled = false; unsigned int numRelays = 0; int vp_ver = 0; char ver_ex_prefix[2] = {' ', ' '}; int ver_ex_number = 0; // 直下ホスト情報チェック unsigned int totalRelays = 0; unsigned int totalListeners = 0; ChanHit hitData; // 受信中か if ((s->type == Servent::T_RELAY) && (s->status == Servent::S_CONNECTED)){ // ホスト情報ロック chanMgr->hitlistlock.on(); // 直下ホストが受信しているチャンネルのホスト情報を取得 chl = chanMgr->findHitListByID(s->chanID); // チャンネルのホスト情報があるか if (chl){ // チャンネルのホスト情報がある場合 ChanHit *hit = chl->hit; // チャンネルのホスト情報を全走査して while(hit){ // IDが同じものであれば if (hit->servent_id == s->servent_id){ // トータルリレーとトータルリスナーを加算 totalRelays += hit->numRelays; totalListeners += hit->numListeners; // 直下であれば if (hit->numHops == 1){ // 情報を一旦保存 infoFlg = true; hitData.relay = hit->relay; hitData.firewalled = hit->firewalled; hitData.numRelays = hit->numRelays; hitData.version_vp = hit->version_vp; hitData.version_ex_prefix[0] = hit->version_ex_prefix[0]; hitData.version_ex_prefix[1] = hit->version_ex_prefix[1]; hitData.version_ex_number = hit->version_ex_number; } } // 次をチェック hit = hit->next; } } // チャンネルデータからServentを検索 bool bFoundFlg = FALSE; cd = channelDataTop; while(cd){ ServentData *sv = cd->findServentData(s->servent_id); // ServentDataがあれば if (sv && cd->getChannelId() == s->channel_id){ // データ設定 sv->setData(s, &hitData, totalListeners, totalRelays, infoFlg); sv->setEnableFlg(TRUE); bFoundFlg = TRUE; break; } cd = cd->getNextData(); } // ServentDataが見つからなかった場合 if (!bFoundFlg){ // チャンネルデータを探す cd = channelDataTop; while(cd){ // チャンネルIDが同じか if (cd->getChannelId() == s->channel_id){ // データ設定 ServentData *sv = ::new ServentData(); sv->setData(s, &hitData, totalListeners, totalRelays, infoFlg); sv->setEnableFlg(TRUE); // チャンネルデータにServentData追加 cd->addServentData(sv); // ホスト名を取得する IdData *id = ::new IdData(cd->getChannelId(), sv->getServentId(), sv->getHost().ip); ThreadInfo *t; t = ::new ThreadInfo(); t->func = GetHostName; t->data = (void*)id; sys->startThread(t); LOG_DEBUG("resolving thread was started(%d)", id->getServentId()); // ループ終了 break; } // 次のデータへ cd = cd->getNextData(); } } // ホスト情報アンロック chanMgr->hitlistlock.off(); } s = s->next; } // 更新していないServentDataを削除 cd = channelDataTop; while(cd){ cd->deleteDisableServents(); cd = cd->getNextData(); } // チャンネルデータアンロック ChannelDataLock.off(); // 描画更新 if (guiWnd){ MakeBack(guiWnd); } // 0.1秒×10で1秒待ち for(i=0; i<2; i++) { if (!thread->active) break; sys->sleep(100); } } // set GUI thread status to terminated thread->finish = true; return 0; }
THREAD_PROC GetHostName(ThreadInfo *thread){ IdData *id = (IdData*)(thread->data); //HOSTENT *he; u_long ip; struct sockaddr_in sa; char host[256]; char *tmp; bool flg = TRUE; bool findFlg; int error; ip = htonl(id->getIpAddr()); memset(&sa, 0, sizeof(sa)); sa.sin_addr.S_un.S_addr = ip; sa.sin_family = AF_INET; for (int i=0; i<10 && flg; i++){ error = getnameinfo(reinterpret_cast<sockaddr*>(&sa), sizeof(sa), host, sizeof(host)/sizeof(host[0]), NULL, 0, NI_NAMEREQD); switch (error) { case 0: // success flg = FALSE; break; case WSAHOST_NOT_FOUND: LOG_ERROR("cannot resolve host for %s", ((tmp = inet_ntoa(sa.sin_addr)) ? tmp : "")); flg = TRUE; break; default: LOG_ERROR("an error occurred while resolving hostname of %s (%ld)", ((tmp = inet_ntoa(sa.sin_addr)) ? tmp : ""), error); } } if (error) return 0; for (flg=TRUE, findFlg=FALSE; flg; ) { ChannelDataLock.on(); ChannelData* cd = channelDataTop; while(cd){ if (cd->getChannelId() == id->getChannelId()) { findFlg = TRUE; if (cd->findServentData(id->getServentId())) { if (cd->setName(id->getServentId(), host)) { LOG_DEBUG("successfully resolved(%d)", id->getServentId()); flg = FALSE; break; } else { LOG_ERROR("cannot update servent data with resolved information"); flg = FALSE; break; } } else { LOG_DEBUG("servent data has been removed"); flg = FALSE; break; } } cd = cd->getNextData(); } // ::delete id; ChannelDataLock.off(); if (!findFlg) { LOG_DEBUG("servent data has been removed(channel)"); flg = FALSE; } sys->sleep(1000); } return 0; }