@rwesa/payu-ble
Version:
A flexible, smart Bluetooth Low Energy challenge system for secure device connections
1 lines • 9.76 kB
Source Map (JSON)
{"version":3,"sources":["../platform_network_helper.ts"],"names":["promisify","exec"],"mappings":"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","file":"platform_network_helper.cjs","sourcesContent":["/**\n * Network MAC Address Detection Helper\n * Requires: npm install arp-a ping\n */\n\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\n\nconst execAsync = promisify(exec);\n\ninterface NetworkScanOptions {\n timeout?: number;\n retries?: number;\n scanSubnet?: boolean;\n subnet?: string;\n}\n\nexport class NetworkMACHelper {\n private cachedMACs: Set<string> = new Set();\n private lastScanTime: number = 0;\n private cacheTimeout: number = 30000; // 30 seconds\n private options: NetworkScanOptions;\n\n constructor(options: NetworkScanOptions = {}) {\n this.options = {\n timeout: 5000,\n retries: 2,\n scanSubnet: false,\n subnet: '192.168.1.0/24',\n ...options\n };\n }\n\n private normalizeMAC(mac: string): string {\n // Normalize MAC address format (remove separators, lowercase)\n return mac.replace(/[:-]/g, '').toLowerCase();\n }\n\n private async getARPTable(): Promise<Set<string>> {\n try {\n let command: string;\n \n // Platform-specific ARP commands\n if (process.platform === 'win32') {\n command = 'arp -a';\n } else if (process.platform === 'darwin') {\n command = 'arp -a';\n } else {\n // Linux and others\n command = 'arp -a';\n }\n\n const { stdout } = await execAsync(command, { timeout: this.options.timeout });\n const macs = new Set<string>();\n\n // Parse ARP table output\n const lines = stdout.split('\\n');\n for (const line of lines) {\n // Match MAC addresses in various formats\n const macMatch = line.match(/([0-9a-fA-F]{2}[:-]){5}[0-9a-fA-F]{2}/);\n if (macMatch) {\n macs.add(this.normalizeMAC(macMatch[0]));\n }\n }\n\n return macs;\n } catch (error) {\n console.error('Error getting ARP table:', error);\n return new Set();\n }\n }\n\n private async pingSubnet(): Promise<void> {\n if (!this.options.scanSubnet || !this.options.subnet) {\n return;\n }\n\n try {\n // Extract network portion (simplified for common cases)\n const baseIP = this.options.subnet.split('/')[0].split('.').slice(0, 3).join('.');\n \n // Ping common IP addresses to populate ARP table\n const pingPromises: Promise<void>[] = [];\n \n for (let i = 1; i <= 254; i++) {\n const ip = `${baseIP}.${i}`;\n const pingPromise = this.pingHost(ip).catch(() => {\n // Ignore ping failures - we just want to populate ARP table\n });\n pingPromises.push(pingPromise);\n }\n\n // Wait for a reasonable number of pings to complete\n await Promise.allSettled(pingPromises.slice(0, 50));\n \n } catch (error) {\n console.error('Error pinging subnet:', error);\n }\n }\n\n private async pingHost(ip: string): Promise<void> {\n const pingCommand = process.platform === 'win32' \n ? `ping -n 1 -w 1000 ${ip}`\n : `ping -c 1 -W 1 ${ip}`;\n \n await execAsync(pingCommand, { timeout: 2000 });\n }\n\n public async scanForMAC(targetMAC: string): Promise<boolean> {\n const normalizedTarget = this.normalizeMAC(targetMAC);\n \n // Check cache first\n const now = Date.now();\n if (now - this.lastScanTime < this.cacheTimeout && this.cachedMACs.has(normalizedTarget)) {\n return true;\n }\n\n try {\n // Optionally ping subnet to populate ARP table\n if (this.options.scanSubnet) {\n await this.pingSubnet();\n }\n\n // Get current ARP table\n const discoveredMACs = await this.getARPTable();\n \n // Update cache\n this.cachedMACs = discoveredMACs;\n this.lastScanTime = now;\n\n return discoveredMACs.has(normalizedTarget);\n \n } catch (error) {\n console.error('Error scanning for MAC:', error);\n return false;\n }\n }\n\n public async getAllDiscoveredMACs(): Promise<string[]> {\n await this.getARPTable();\n return Array.from(this.cachedMACs);\n }\n\n public clearCache(): void {\n this.cachedMACs.clear();\n this.lastScanTime = 0;\n }\n}\n\n// Factory function for creating MAC-based availability triggers\nexport function createMACNetworkTrigger(\n targetMAC: string, \n options?: NetworkScanOptions\n): () => boolean {\n const networkHelper = new NetworkMACHelper(options);\n let isAvailable = false;\n \n // Periodically scan for the MAC address\n const scanInterval = setInterval(async () => {\n try {\n isAvailable = await networkHelper.scanForMAC(targetMAC);\n } catch (error) {\n console.error('MAC scan error:', error);\n isAvailable = false;\n }\n }, 10000); // Scan every 10 seconds\n\n // Cleanup on process exit\n const cleanup = () => {\n clearInterval(scanInterval);\n };\n \n process.on('SIGINT', cleanup);\n process.on('SIGTERM', cleanup);\n\n return () => isAvailable;\n}\n\n// Simpler interface matching the original helper\nexport function macOnNetwork(mac: string): () => boolean {\n return createMACNetworkTrigger(mac, { scanSubnet: true });\n}\n\n// Additional utility functions\nexport async function discoverLocalDevices(options?: NetworkScanOptions): Promise<string[]> {\n const helper = new NetworkMACHelper(options);\n return helper.getAllDiscoveredMACs();\n}\n\nexport async function isDeviceOnNetwork(mac: string, options?: NetworkScanOptions): Promise<boolean> {\n const helper = new NetworkMACHelper(options);\n return helper.scanForMAC(mac);\n}"]}