/*! \brief Send out report messages to all requestors. You may append additional data to the report messages. The data length may not be greater than \c PPP_REPORT_DATA_LIMIT. \param type The report type. \param code The report code belonging to the report type. \param data Additional data. \param length Length of the data. \return \c false on error. */ bool KPPPReportManager::Report(ppp_report_type type, int32 code, void *data, int32 length) { TRACE("KPPPReportManager: Report(type=%d code=%ld length=%ld) to %ld receivers\n", type, code, length, fReportRequests.CountItems()); if (length > PPP_REPORT_DATA_LIMIT) return false; if (fReportRequests.CountItems() == 0) return true; if (!data) length = 0; LockerHelper locker(fLock); status_t result; thread_id me = find_thread(NULL); ppp_report_packet report; report.type = type; report.code = code; report.length = length; memcpy(report.data, data, length); ppp_report_request *request; for (int32 index = 0; index < fReportRequests.CountItems(); index++) { request = fReportRequests.ItemAt(index); // do not send to yourself if (request->thread == me) continue; result = send_data_with_timeout(request->thread, PPP_REPORT_CODE, &report, sizeof(report), PPP_REPORT_TIMEOUT); #if DEBUG if (result == B_TIMED_OUT) TRACE("KPPPReportManager::Report(): timed out sending\n"); #endif if (result == B_BAD_THREAD_ID || result == B_NO_MEMORY || request->flags & PPP_REMOVE_AFTER_REPORT) { fReportRequests.RemoveItem(request); --index; continue; } } return true; }
/*! \brief Send the given report message to the given thread. \param thread The report receiver. \param report The report message. \return \c false on error. */ bool KPPPReportManager::SendReport(thread_id thread, const ppp_report_packet *report) { if (!report) return false; if (thread == find_thread(NULL)) { report_sender_info *info = new report_sender_info; info->thread = thread; memcpy(&info->report, report, sizeof(ppp_report_packet)); resume_thread(spawn_kernel_thread(report_sender_thread, "PPP: ReportSender", B_NORMAL_PRIORITY, info)); return true; } send_data_with_timeout(thread, PPP_REPORT_CODE, &report, sizeof(report), PPP_REPORT_TIMEOUT); return true; }
static void SendQueryPacket(pppoe_query *query, DiscoveryPacket& discovery) { char data[PPPoE_QUERY_REPORT_SIZE]; uint32 position = sizeof(uint32); pppoe_tag *acName = discovery.TagWithType(AC_NAME); if (acName) { if (acName->length >= PPPoE_QUERY_REPORT_SIZE) return; memcpy(data + position, acName->data, acName->length); position += acName->length; } data[position++] = 0; pppoe_tag *tag; for (int32 index = 0; index < discovery.CountTags(); index++) { tag = discovery.TagAt(index); if (tag && tag->type == SERVICE_NAME) { if (position + tag->length >= PPPoE_QUERY_REPORT_SIZE) return; memcpy(data + position, tag->data, tag->length); position += tag->length; data[position++] = 0; } } memcpy(data, &position, sizeof(uint32)); // add the total length send_data_with_timeout(query->receiver, PPPoE_QUERY_REPORT, data, PPPoE_QUERY_REPORT_SIZE, 700000); }