1 //----------------------------------------------------------------------- 2 // This software is part of the OpenBeOS distribution and is covered 3 // by the OpenBeOS license. 4 // 5 // Copyright (c) 2003-2004 Waldemar Kornewald, Waldemar.Kornewald@web.de 6 //----------------------------------------------------------------------- 7 8 #include <KPPPReportManager.h> 9 #include <LockerHelper.h> 10 11 #include <KPPPUtils.h> 12 13 14 KPPPReportManager::KPPPReportManager(BLocker& lock) 15 : fLock(lock) 16 { 17 } 18 19 20 KPPPReportManager::~KPPPReportManager() 21 { 22 for(int32 index = 0; index < fReportRequests.CountItems(); index++) 23 delete fReportRequests.ItemAt(index); 24 } 25 26 27 void 28 KPPPReportManager::EnableReports(ppp_report_type type, thread_id thread, 29 int32 flags = PPP_NO_FLAGS) 30 { 31 if(thread < 0 || type == PPP_ALL_REPORTS) 32 return; 33 34 LockerHelper locker(fLock); 35 36 ppp_report_request *request = new ppp_report_request; 37 request->type = type; 38 request->thread = thread; 39 request->flags = flags; 40 41 fReportRequests.AddItem(request); 42 } 43 44 45 void 46 KPPPReportManager::DisableReports(ppp_report_type type, thread_id thread) 47 { 48 if(thread < 0) 49 return; 50 51 LockerHelper locker(fLock); 52 53 ppp_report_request *request; 54 55 for(int32 i = 0; i < fReportRequests.CountItems(); i++) { 56 request = fReportRequests.ItemAt(i); 57 58 if(request->thread != thread) 59 continue; 60 61 if(request->type == type || type == PPP_ALL_REPORTS) 62 fReportRequests.RemoveItem(request); 63 } 64 } 65 66 67 bool 68 KPPPReportManager::DoesReport(ppp_report_type type, thread_id thread) 69 { 70 if(thread < 0) 71 return false; 72 73 LockerHelper locker(fLock); 74 75 ppp_report_request *request; 76 77 for(int32 i = 0; i < fReportRequests.CountItems(); i++) { 78 request = fReportRequests.ItemAt(i); 79 80 if(request->thread == thread && request->type == type) 81 return true; 82 } 83 84 return false; 85 } 86 87 88 bool 89 KPPPReportManager::Report(ppp_report_type type, int32 code, void *data, int32 length) 90 { 91 #if DEBUG 92 dprintf("KPPPReportManager: Report(type=%d code=%ld length=%ld) to %ld receivers\n", 93 type, code, length, fReportRequests.CountItems()); 94 #endif 95 96 if(length > PPP_REPORT_DATA_LIMIT) 97 return false; 98 99 if(fReportRequests.CountItems() == 0) 100 return true; 101 102 if(!data) 103 length = 0; 104 105 LockerHelper locker(fLock); 106 107 status_t result; 108 thread_id sender, me = find_thread(NULL); 109 bool acceptable = true; 110 111 ppp_report_packet report; 112 report.type = type; 113 report.code = code; 114 report.length = length; 115 memcpy(report.data, data, length); 116 117 ppp_report_request *request; 118 119 for(int32 index = 0; index < fReportRequests.CountItems(); index++) { 120 request = fReportRequests.ItemAt(index); 121 122 // do not send to yourself 123 if(request->thread == me) 124 continue; 125 126 result = send_data_with_timeout(request->thread, PPP_REPORT_CODE, &report, 127 sizeof(report), PPP_REPORT_TIMEOUT); 128 129 #if DEBUG 130 if(result == B_TIMED_OUT) 131 dprintf("KPPPReportManager::Report(): timed out sending\n"); 132 #endif 133 134 thread_info info; 135 136 if(result == B_BAD_THREAD_ID || result == B_NO_MEMORY) { 137 fReportRequests.RemoveItem(request); 138 --index; 139 continue; 140 } else if(result == B_OK && request->flags & PPP_WAIT_FOR_REPLY) { 141 if(request->flags & PPP_NO_REPLY_TIMEOUT) { 142 sender = -1; 143 result = B_ERROR; 144 // always check if the thread still exists 145 while(sender != request->thread 146 && get_thread_info(request->thread, &info) == B_OK) { 147 result = receive_data_with_timeout(&sender, &code, NULL, 0, 148 PPP_REPORT_TIMEOUT); 149 150 if(request->flags & PPP_ALLOW_ANY_REPLY_THREAD 151 && result == B_OK) 152 sender = request->thread; 153 } 154 } else { 155 sender = -1; 156 result = B_OK; 157 while(sender != request->thread && result == B_OK 158 && get_thread_info(request->thread, &info) == B_OK) { 159 result = receive_data_with_timeout(&sender, &code, NULL, 0, 160 PPP_REPORT_TIMEOUT); 161 162 if(request->flags & PPP_ALLOW_ANY_REPLY_THREAD) 163 sender = request->thread; 164 } 165 } 166 167 if(sender != request->thread) { 168 #if DEBUG 169 dprintf("KPPPReportManager::Report(): sender != requested\n"); 170 #endif 171 continue; 172 } 173 174 if(result == B_OK && code != B_OK) 175 acceptable = false; 176 #if DEBUG 177 if(result == B_TIMED_OUT) 178 dprintf("KPPPReportManager::Report(): reply timed out\n"); 179 #endif 180 } 181 182 // remove thread if it is not existant or if remove-flag is set 183 if(request->flags & PPP_REMOVE_AFTER_REPORT 184 || get_thread_info(request->thread, &info) != B_OK) { 185 fReportRequests.RemoveItem(request); 186 --index; 187 } 188 } 189 190 #if DEBUG 191 dprintf("KPPPReportManager::Report(): returning: %s\n", acceptable?"true":"false"); 192 #endif 193 194 return acceptable; 195 } 196