From 49b4d6dd9d4d35adc9f02df4010a1a6b33faba63 Mon Sep 17 00:00:00 2001 From: sje Date: Wed, 1 Nov 2006 14:44:34 +0000 Subject: git-svn-id: https://server.scottellis.com.au/svn/mim_plugs@12 4f64403b-2f21-0410-a795-97e2b3489a10 --- ping_protocol/pingthread.cpp | 309 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 309 insertions(+) create mode 100644 ping_protocol/pingthread.cpp (limited to 'ping_protocol/pingthread.cpp') diff --git a/ping_protocol/pingthread.cpp b/ping_protocol/pingthread.cpp new file mode 100644 index 0000000..c9a5fbd --- /dev/null +++ b/ping_protocol/pingthread.cpp @@ -0,0 +1,309 @@ +#include "stdafx.h" +#include "pingthread.h" + +int upCount, total = 0; + +HANDLE mainThread; +HANDLE hWakeEvent = 0; + +// thread protected variables +CRITICAL_SECTION thread_finished_cs, list_changed_cs, data_list_cs; +bool thread_finished = false, list_changed = false; +PINGLIST data_list; + +HANDLE status_update_thread = 0; + +bool get_thread_finished() { + Lock(&thread_finished_cs, "get_thread_finished"); + bool retval = thread_finished; + Unlock(&thread_finished_cs); + return retval; +} + +void set_thread_finished(bool f) { + Lock(&thread_finished_cs, "set_thread_finished"); + thread_finished = f; + Unlock(&thread_finished_cs); +} + +bool get_list_changed() { + Lock(&list_changed_cs, "get_list_changed"); + bool retval = list_changed; + Unlock(&list_changed_cs); + return retval; +} + +void set_list_changed(bool f) { + Lock(&list_changed_cs, "set_list_changed"); + list_changed = f; + Unlock(&list_changed_cs); +} + +void SetProtoStatus(char *pszLabel, char *pszProto, int if_status, int new_status) { + if(strcmp(pszProto, Translate("")) == 0) { + int num_protocols; + PROTOCOLDESCRIPTOR **pppDesc; + + CallService(MS_PROTO_ENUMPROTOCOLS, (LPARAM)&num_protocols, (WPARAM)&pppDesc); + for(int i = 0; i < num_protocols; i++) { + if(pppDesc[i]->type == PROTOTYPE_PROTOCOL) + SetProtoStatus(pszLabel, pppDesc[i]->szName, if_status, new_status); + } + } else { + std::ostringstream get_status, set_status; + get_status << pszProto << PS_GETSTATUS; + if(ServiceExists(get_status.str().c_str())) { + set_status << pszProto << PS_SETSTATUS; + + if(CallService(get_status.str().c_str(), 0, 0) == if_status) { + if(options.logging) { + std::ostringstream oss2; + oss2 << pszLabel << " - setting status of protocol '" << pszProto << "' (" << new_status << ")"; + CallService(PROTO "/Log", (WPARAM)oss2.str().c_str(), 0); + } + CallService(set_status.str().c_str(), new_status, 0); + } + } + } +} + +DWORD WINAPI sttCheckStatusThreadProc( void *vp) +{ + clock_t start_t = clock(), end_t; + while(!get_thread_finished()) { + + end_t = clock(); + + int wait = (options.ping_period - ((end_t - start_t) / (double)CLOCKS_PER_SEC)) * 1000; + if(wait > 0) + WaitForSingleObjectEx(hWakeEvent, wait, TRUE); + + if(get_thread_finished()) break; + + start_t = clock(); + + bool timeout = false; + bool reply = false; + int count = 0; + + PINGADDRESS pa; + //HANDLE next = 0; + + std::pair history_entry; + + Lock(&data_list_cs, "ping thread loop start"); + set_list_changed(false); + int size = data_list.size(); + Unlock(&data_list_cs); + + int ind; + for(ind = 0; ind < size; ind++) { + Lock(&data_list_cs, "ping thread loop start"); + int c = 0; + for(PINGLIST::iterator i = data_list.begin(); i != data_list.end() && c <= ind; i++, c++) { + if(c == ind) { + // copy just what we need - i.e. not history, not command + pa.get_status = i->get_status; + pa.hContact = i->hContact; + pa.miss_count = i->miss_count; + pa.port = i->port; + strcpy(pa.pszLabel, i->pszLabel); + strcpy(pa.pszName, i->pszName); + strcpy(pa.pszProto, i->pszProto); + pa.set_status = i->set_status; + pa.status = i->status; + break; + } + + } + Unlock(&data_list_cs); + + if(get_thread_finished()) break; + if(get_list_changed()) break; + + if(pa.status != options.off_status) { + if(CallService(MS_DB_CONTACT_IS, (WPARAM)pa.hContact, 0)) { + if(!options.no_test_status) + DBWriteContactSettingWord(pa.hContact, PROTO, "Status", options.tstatus); + + CallService(PROTO "/Ping", 0, (LPARAM)&pa); + } else + break; + + if(get_thread_finished()) break; + if(get_list_changed()) break; + + Lock(&data_list_cs, "ping thread loop start"); + for(PINGLIST::iterator i = data_list.begin(); i != data_list.end(); i++) { + if(i->hContact == pa.hContact) { + i->responding = pa.responding; + i->round_trip_time = pa.round_trip_time; + + history_entry.first = i->round_trip_time; + history_entry.second = time(0); + i->history.push_back(history_entry); + // maintain history (-1 represents no response) + while(i->history.size() >= MAX_HISTORY) { + i->history.erase(i->history.begin()); + //i->history.pop_front(); + } + + if(pa.responding) { + if(pa.miss_count > 0) + pa.miss_count = -1; + else + pa.miss_count--; + pa.status = options.rstatus; + } + else { + if(pa.miss_count < 0) + pa.miss_count = 1; + else + pa.miss_count++; + pa.status = options.nrstatus; + } + i->miss_count = pa.miss_count; + i->status = pa.status; + + break; + } + } + Unlock(&data_list_cs); + + if(pa.responding) { + count++; + + if(pa.miss_count == -1 - options.retries || + (((-pa.miss_count) % (options.retries + 1)) == 0 && !options.block_reps)) + { + reply = true; + if(options.show_popup2 && ServiceExists(MS_POPUP_SHOWMESSAGE)) { + ShowPopup("Ping Reply", pa.pszLabel, 1); + } + if(DBGetContactSettingWord(pa.hContact, PROTO, "Status", ID_STATUS_OFFLINE) != pa.status) + DBWriteContactSettingWord(pa.hContact, PROTO, "Status", pa.status); + } + if(pa.miss_count == -1 - options.retries && options.logging) { + std::ostringstream oss2; + oss2 << pa.pszLabel << " - reply"; + CallService(PROTO "/Log", (WPARAM)oss2.str().c_str(), 0); + } + SetProtoStatus(pa.pszLabel, pa.pszProto, pa.get_status, pa.set_status); + if(options.use_status_msg) { + std::ostringstream msg; + char *mode_desc = (char *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, options.rstatus, 0); + msg << (mode_desc ? mode_desc : Translate("Uknnown")) << " (" << pa.round_trip_time << ")"; + DBWriteContactSettingString(pa.hContact, "CList", "StatusMsg", msg.str().c_str()); + } else { + std::ostringstream handle; + handle << pa.pszLabel << " (" << pa.round_trip_time << ")"; + set_changing_clist_handle(TRUE); + DBWriteContactSettingString(pa.hContact, "CList", "MyHandle", handle.str().c_str()); + set_changing_clist_handle(FALSE); + } + } else { + + if(pa.miss_count == 1 + options.retries || + ((pa.miss_count % (options.retries + 1)) == 0 && !options.block_reps)) + { + timeout = true; + if(options.show_popup && ServiceExists(MS_POPUP_SHOWMESSAGE)) { + ShowPopup("Ping Timeout", pa.pszLabel, 0); + } + if(!timeout) timeout = true; + if(DBGetContactSettingWord(pa.hContact, PROTO, "Status", ID_STATUS_OFFLINE) != pa.status) + DBWriteContactSettingWord(pa.hContact, PROTO, "Status", pa.status); + } + if(pa.miss_count == 1 + options.retries && options.logging) { + std::ostringstream oss2; + oss2 << pa.pszLabel << " - timeout"; + CallService(PROTO "/Log", (WPARAM)oss2.str().c_str(), 0); + } + if(options.use_status_msg) { + std::ostringstream msg; + char *mode_desc = (char *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, options.nrstatus, 0); + msg << (mode_desc ? mode_desc : Translate("Uknnown")) << " [" << pa.miss_count << "]"; + DBWriteContactSettingString(pa.hContact, "CList", "StatusMsg", msg.str().c_str()); + } else { + std::ostringstream handle; + handle << pa.pszLabel << " [" << pa.miss_count << "]"; + set_changing_clist_handle(TRUE); + DBWriteContactSettingString(pa.hContact, "CList", "MyHandle", handle.str().c_str()); + set_changing_clist_handle(FALSE); + } + } + if(!options.no_test_status && DBGetContactSettingWord(pa.hContact, PROTO, "Status", ID_STATUS_OFFLINE) != pa.status) + DBWriteContactSettingWord(pa.hContact, PROTO, "Status", pa.status); + } + } + + if(timeout) SkinPlaySound("PingProtoTimeout"); + if(reply) SkinPlaySound("PingProtoReply"); + + if(!get_list_changed()) { + upCount = count; + total = ind; + + if(DBGetContactSettingByte(0, PROTO, "SetProtoStatus", 0)) { + if(upCount == total) + CallService(PROTO PS_SETSTATUS, options.rstatus, 0); + else if(upCount == 0) + CallService(PROTO PS_SETSTATUS, options.nrstatus, 0); + } + } else { + total = 0; + } + } + + return 0; +} + +void start_ping_thread() { + DWORD tid; + + if(status_update_thread) CloseHandle(status_update_thread); + status_update_thread = CreateThread(0, 0, sttCheckStatusThreadProc, 0, 0, &tid); +} + +void stop_ping_thread() { + set_thread_finished(true); + SetEvent(hWakeEvent); + //ICMP::get_instance()->stop(); + WaitForSingleObject(status_update_thread, 2000); + TerminateThread(status_update_thread, 0); + CloseHandle(status_update_thread); + status_update_thread = 0; +} + +int FillList(WPARAM wParam, LPARAM lParam) { + + if(options.logging) + CallService(PROTO "/Log", (WPARAM)"ping address list reload", 0); + + PINGLIST pl; + CallService(PROTO "/GetPingList", 0, (LPARAM)&pl); + + Lock(&data_list_cs, "fill_list"); + + // copy history + for(PINGLIST::iterator i = data_list.begin(); i != data_list.end(); i++) { + for(PINGLIST::iterator j = pl.begin(); j != pl.end(); j++) { + if(i->hContact == j->hContact) { + if(i->history.size()) + j->history = i->history; + else + j->history.clear(); + } + } + } + + if(pl.size()) + data_list = pl; + + set_list_changed(true); + Unlock(&data_list_cs); + + SetEvent(hWakeEvent); + return 0; +} + -- cgit v1.2.3