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 LockerHelper locker(fLock); 32 33 ppp_report_request *request = new ppp_report_request; 34 request->type = type; 35 request->thread = thread; 36 request->flags = flags; 37 38 fReportRequests.AddItem(request); 39 } 40 41 42 void 43 KPPPReportManager::DisableReports(ppp_report_type type, thread_id thread) 44 { 45 LockerHelper locker(fLock); 46 47 ppp_report_request *request; 48 49 for(int32 i = 0; i < fReportRequests.CountItems(); i++) { 50 request = fReportRequests.ItemAt(i); 51 52 if(request->thread != thread) 53 continue; 54 55 if(request->type == type || request->type == PPP_ALL_REPORTS) 56 fReportRequests.RemoveItem(request); 57 } 58 } 59 60 61 bool 62 KPPPReportManager::DoesReport(ppp_report_type type, thread_id thread) 63 { 64 LockerHelper locker(fLock); 65 66 ppp_report_request *request; 67 68 for(int32 i = 0; i < fReportRequests.CountItems(); i++) { 69 request = fReportRequests.ItemAt(i); 70 71 if(request->thread == thread && request->type == type) 72 return true; 73 } 74 75 return false; 76 } 77 78 79 bool 80 KPPPReportManager::Report(ppp_report_type type, int32 code, void *data, int32 length) 81 { 82 #if DEBUG 83 dprintf("KPPPReportManager: Report(type=%d code=%ld length=%ld) to %ld receivers\n", 84 type, code, length, fReportRequests.CountItems()); 85 #endif 86 87 if(length > PPP_REPORT_DATA_LIMIT) 88 return false; 89 90 if(fReportRequests.CountItems() == 0) 91 return true; 92 93 if(!data) 94 length = 0; 95 96 LockerHelper locker(fLock); 97 98 status_t result; 99 thread_id sender, me = find_thread(NULL); 100 bool acceptable = true; 101 102 ppp_report_packet report; 103 report.type = type; 104 report.code = code; 105 report.length = length; 106 memcpy(report.data, data, length); 107 108 ppp_report_request *request; 109 110 for(int32 index = 0; index < fReportRequests.CountItems(); index++) { 111 request = fReportRequests.ItemAt(index); 112 113 // do not send to yourself 114 if(request->thread == me) 115 continue; 116 117 result = send_data_with_timeout(request->thread, PPP_REPORT_CODE, &report, 118 sizeof(report), PPP_REPORT_TIMEOUT); 119 120 #if DEBUG 121 if(result == B_TIMED_OUT) 122 dprintf("KPPPReportManager::Report(): timed out sending\n"); 123 #endif 124 125 if(result == B_BAD_THREAD_ID || result == B_NO_MEMORY) { 126 fReportRequests.RemoveItem(request); 127 --index; 128 continue; 129 } else if(result == B_OK) { 130 if(request->flags & PPP_WAIT_FOR_REPLY) { 131 thread_info info; 132 133 if(request->flags & PPP_NO_REPLY_TIMEOUT) { 134 sender = -1; 135 result = B_ERROR; 136 // always check if the thread still exists 137 while(sender != request->thread 138 && get_thread_info(request->thread, &info) 139 != B_BAD_THREAD_ID) { 140 result = receive_data_with_timeout(&sender, &code, NULL, 0, 141 PPP_REPORT_TIMEOUT); 142 143 if(request->flags & PPP_ALLOW_ANY_REPLY_THREAD) 144 sender = request->thread; 145 } 146 } else { 147 sender = -1; 148 result = B_OK; 149 while(sender != request->thread && result == B_OK) { 150 result = receive_data_with_timeout(&sender, &code, NULL, 0, 151 PPP_REPORT_TIMEOUT); 152 153 if(request->flags & PPP_ALLOW_ANY_REPLY_THREAD) 154 sender = request->thread; 155 } 156 } 157 158 if(result == B_OK && code != B_OK) 159 acceptable = false; 160 #if DEBUG 161 if(result == B_TIMED_OUT) 162 dprintf("KPPPReportManager::Report(): reply timed out\n"); 163 #endif 164 } 165 } 166 167 if(request->flags & PPP_REMOVE_AFTER_REPORT) { 168 fReportRequests.RemoveItem(request); 169 --index; 170 } 171 } 172 173 #if DEBUG 174 dprintf("KPPPReportManager::Report(): returning: %s\n", acceptable?"true":"false"); 175 #endif 176 177 return acceptable; 178 } 179