tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }