void Normalize::normalizeMPPortDescReplyV4() { using deprecated::PortV2; // Verify size of port list. size_t portListSize = buf_.size() - sizeof(MultipartReply); if ((portListSize % sizeof(PortV2)) != 0) { markInputInvalid("MultipartReply.PortDesc has invalid size"); return; } // Normalize the port structures from V2 to normal size. size_t portCount = portListSize / sizeof(PortV2); UInt8 *pkt = buf_.mutableData(); const PortV2 *portV2 = reinterpret_cast<const PortV2 *>(pkt + sizeof(MultipartReply)); PortList ports; for (size_t i = 0; i < portCount; ++i) { PortBuilder newPort{*portV2}; ports.add(newPort); ++portV2; } // Copy new port list into packet. buf_.addUninitialized(ports.size() - portListSize); pkt = buf_.mutableData(); assert(buf_.size() == sizeof(MultipartReply) + ports.size()); std::memcpy(pkt + sizeof(MultipartReply), ports.data(), ports.size()); }
void Normalize::normalizeFeaturesReplyV1() { using deprecated::PortV1; Header *hdr = header(); // Check minimum size requirement. if (hdr->length() < sizeof(FeaturesReply)) { markInputInvalid("FeaturesReply is too short"); return; } // Verify size of port list. size_t portListSize = hdr->length() - sizeof(FeaturesReply); if ((portListSize % sizeof(PortV1)) != 0) { markInputInvalid("FeaturesReply has invalid port list size"); return; } // Normalize the port structures from V1 to normal size. size_t portCount = portListSize / sizeof(PortV1); UInt8 *pkt = buf_.mutableData(); const PortV1 *portV1 = reinterpret_cast<const PortV1 *>(pkt + sizeof(FeaturesReply)); PortList ports; for (size_t i = 0; i < portCount; ++i) { PortBuilder newPort{*portV1}; ports.add(newPort); ++portV1; } if (ports.size() > 65535 - sizeof(FeaturesReply)) { markInputTooBig("FeaturesReply has too many ports"); return; } // Copy new port list into packet. buf_.addUninitialized(ports.size() - portListSize); pkt = buf_.mutableData(); assert(buf_.size() == sizeof(FeaturesReply) + ports.size()); std::memcpy(pkt + sizeof(FeaturesReply), ports.data(), ports.size()); }
/* Thread that scans for new GPSes, removals etc. */ void Gipsy::scanner_thread() { while (!exit_thread) { // Scan for new ports PortList plist = get_ports(true); vector<unsigned int> changed; vector<unsigned int> removed; PR_Lock(lock); /* Remove non-existent ports */ for (unsigned int i=0; i < gpslist.size(); i++) { if (! gpslist[i] || gpslist[i]->watcher_running) continue; /* Find port */ unsigned int j; for (j=0; j < plist.size(); j++) if (plist[j].device == gpslist[i]->portinfo.device) break; if (j < plist.size()) continue; /* Device does not exist anymore, remove it */ NS_RELEASE(gpslist[i]); gpslist[i] = NULL; removed.push_back(i); } /* Find new ports */ for (unsigned int i=0; i < plist.size(); i++) { int pos; if (find_gps(plist[i].device, pos)) { // Start watcher if not already started // may happen when scanner is stopped and started again if (gpslist[pos]->scan_enabled && !gpslist[pos]->watcher_running) gpslist[pos]->start_watcher(); continue; // Port already in list } /* Add new */ GpsItem *newitem = new GpsItem(); NS_ADDREF(newitem); newitem->portinfo = plist[i]; // Scan_enable according prefs newitem->scan_enabled = prefs_scan_enabled(*newitem); newitem->gpstype = prefs_gpstype(*newitem); newitem->auto_download = newitem->gpstype == GPS_MLR ? false : auto_download; /* Find new slot */ for (pos=0; pos < (int)gpslist.size(); pos++) if (!gpslist[pos]) break; if (pos < (int)gpslist.size()) gpslist[pos] = newitem; else gpslist.push_back(newitem); newitem->pos = pos; changed.push_back(pos); if (newitem->scan_enabled) newitem->start_watcher(); } PR_Unlock(lock); // End of critical section // Send updates to observers for (unsigned int i=0; i < removed.size(); i++) { GpsItem *tmp = new GpsItem(); tmp->pos = removed[i]; NS_ADDREF(tmp); notify(tmp, "gps_removed", true); // - NS_RELEASE will be called in notify } for (unsigned int i=0; i < changed.size(); i++) { int32_t idx = changed[i]; notify(gpslist[idx], "gps_changed"); } sleep(1); } // Abort watchers on scanner exit // TODO: Join them? PR_Lock(lock); for (unsigned int i=0; i < gpslist.size(); i++) if (gpslist[i]) gpslist[i]->exit_thread = true; PR_Unlock(lock); }