RTCDataChannel-worker.js (3978B)
1 console.log(`Creating worker...`); 2 try { 3 const channels = new Map(); 4 5 function getChannel(label) { 6 const dc = channels.get(label); 7 if (!dc) throw new Error(`No datachannel found for label ${label}`); 8 return dc; 9 } 10 11 function reportWorkerError(label, message) { 12 self.postMessage({ type: 'workerError', label, result: message }); 13 } 14 15 function wireEvents(dc) { 16 const eventTypes = ['open', 'bufferedamountlow', 'error', 'closing', 'close', 'message']; 17 for (const type of eventTypes) { 18 dc.addEventListener(type, ({data, origin}) => { 19 if (type == 'message') { 20 // Events aren't transferable in general, have to reconstruct :( 21 self.postMessage({type, label: dc.label, result: {data, origin}}); 22 } else { 23 self.postMessage({type, label: dc.label}); 24 } 25 }); 26 } 27 } 28 29 onmessage = ({data}) => { 30 const { type, label, arg } = data; 31 32 try { 33 switch (type) { 34 case 'init': { 35 const channel = arg; 36 // We do not put errors in an initResponse message; those are for 37 // RTCDataChannel errors only. 38 if (channels.has(channel.label)) { 39 throw new Error('Duplicate RTCDataChannel label'); 40 } 41 channels.set(channel.label, channel); 42 wireEvents(channel); 43 self.postMessage({ 44 type: 'initResponse', 45 label: channel.label, 46 result: { 47 label: channel.label, 48 ordered: channel.ordered, 49 maxPacketLifeTime: channel.maxPacketLifeTime, 50 maxRetransmits: channel.maxRetransmits, 51 protocol: channel.protocol, 52 negotiated: channel.negotiated, 53 id: channel.id, 54 readyState: channel.readyState, 55 bufferedAmount: channel.bufferedAmount, 56 binaryType: channel.binaryType, 57 bufferedAmountLowThreshold: channel.bufferedAmountLowThreshold, 58 }, 59 }); 60 break; 61 } 62 63 case 'send': { 64 // try block is only for RTCDataChannel errors 65 const channel = getChannel(label); 66 try { 67 channel.send(arg); 68 self.postMessage({ type: 'sendResponse', label, result: undefined }); 69 } catch (e) { 70 // Man it would be nice if we could do "const error = {...} = e" 71 const error = { name: e.name, message: e.message }; 72 self.postMessage({ type: 'sendResponse', label, result: { error } }); 73 } 74 break; 75 } 76 77 case 'close': { 78 // RTCDataChannel.close() does not throw; any error here is ours 79 getChannel(label).close(); 80 self.postMessage({ type: 'closeResponse', label, result: undefined }); 81 break; 82 } 83 84 case 'setBufferedAmountLowThreshold': { 85 // This is fire-and-forget called by a setter, any error will be 86 // dealt with by the code in _errorPromise. 87 getChannel(label).bufferedAmountLowThreshold = arg; 88 break; 89 } 90 91 case 'setBinaryType': { 92 // This is fire-and-forget called by a setter 93 getChannel(label).binaryType = arg; 94 break; 95 } 96 97 case 'queryState': { 98 const channel = getChannel(label); 99 self.postMessage({ 100 type: 'queryStateResponse', 101 label, 102 result: { 103 id: channel.id, 104 readyState: channel.readyState, 105 bufferedAmount: channel.bufferedAmount, 106 }, 107 }); 108 break; 109 } 110 111 default: 112 console.log(`Unknown type`); 113 reportWorkerError(label, `Received unknown message type: ${type}`); 114 } 115 } catch (err) { 116 console.log(`Unhandled error`); 117 reportWorkerError(label, `In handling ${type} request, got ${err.message}`); 118 } 119 }; 120 121 } catch (e) { 122 console.log(`Creation failed! ${e.message}`); 123 }