dgram#Socket TypeScript Examples

The following examples show how to use dgram#Socket. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: utils.ts    From eufy-security-client with MIT License 7 votes vote down vote up
buildLookupWithKeyPayload = (socket: Socket, p2pDid: string, dskKey: string): Buffer => {
    const p2pDidBuffer = p2pDidToBuffer(p2pDid);

    const addressInfo = socket.address();
    const port = addressInfo.port;
    const portAsBuffer = Buffer.allocUnsafe(2);
    portAsBuffer.writeUInt16LE(port, 0);
    //const ip = socket.address().address;
    const ip = getLocalIpAddress(addressInfo.address);
    const temp_buff: number[] = [];
    ip.split(".").reverse().forEach(element => {
        temp_buff.push(Number.parseInt(element));
    });
    const ipAsBuffer = Buffer.from(temp_buff);

    const splitter = Buffer.from([0x00, 0x02]);
    const magic = Buffer.from([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00]);

    const dskKeyAsBuffer = Buffer.from(dskKey);

    const fourEmpty = Buffer.from([0x00, 0x00, 0x00, 0x00]);
    return Buffer.concat([p2pDidBuffer, splitter, portAsBuffer, ipAsBuffer, magic, dskKeyAsBuffer, fourEmpty]);
}
Example #2
Source File: utils.ts    From eufy-security-client with MIT License 7 votes vote down vote up
sendMessage = async (socket: Socket, address: { host: string; port: number }, msgID: Buffer, payload?: Buffer): Promise<number> => {
    if (!payload)
        payload = Buffer.from([]);
    const payloadLen = Buffer.allocUnsafe(2);
    payloadLen.writeUInt16BE(payload.length, 0);
    const message = Buffer.concat([msgID, payloadLen, payload], 4 + payload.length);

    return new Promise((resolve, reject) => {
        socket.send(message, address.port, address.host, (err, bytes) => {
            return err ? reject(err) : resolve(bytes);
        });
    });
}
Example #3
Source File: stun.ts    From hoprnet with GNU General Public License v3.0 6 votes vote down vote up
/**
 * Handles STUN requests
 * @param socket Node.JS socket to use
 * @param data received packet
 * @param rinfo Addr+Port of the incoming connection
 * @param __fakeRInfo [testing] overwrite incoming information to intentionally send misleading STUN response
 */
export function handleStunRequest(socket: Socket, data: Buffer, rinfo: RemoteInfo, __fakeRInfo?: RemoteInfo): void {
  const req = createBlank()

  // Overwrite console.log because 'webrtc-stun' package
  // pollutes console output
  const consoleBackup = console.log
  console.log = log

  try {
    if (req.loadBuffer(data)) {
      // if STUN message is BINDING_REQUEST and valid content
      if (req.isBindingRequest({ fingerprint: true })) {
        verbose(`Received STUN request from ${rinfo.address}:${rinfo.port}`)

        const res = req
          .createBindingResponse(true)
          .setXorMappedAddressAttribute(__fakeRInfo ?? rinfo)
          .setFingerprintAttribute()

        socket.send(res.toBuffer(), rinfo.port, rinfo.address)
      } else if (!req.isBindingResponseSuccess()) {
        error(`Received a STUN message that is not a binding request. Dropping message.`)
      }
    } else {
      error(`Received a message that is not a STUN message. Dropping message.`)
    }
  } catch (err) {
    consoleBackup(err)
  } finally {
    console.log = consoleBackup
  }
}
Example #4
Source File: stun.ts    From hoprnet with GNU General Public License v3.0 6 votes vote down vote up
/**
 * Performs STUN requests and returns their responses, if any
 * @param multiAddrs STUN servers to contact
 * @param socket socket to send requests and receive responses
 * @param timeout STUN timeout
 * @param runningLocally [optional] enable STUN local-mode
 * @returns the responses, if any
 */
export async function performSTUNRequests(
  multiAddrs: Multiaddr[],
  socket: Socket,
  timeout = STUN_TIMEOUT,
  runningLocally = false
): Promise<RequestWithResponse[]> {
  const requests: Request[] = []
  for (const multiaddr of multiAddrs) {
    requests.push({
      multiaddr,
      tId: generateTransactionId()
    })
  }
  // Assign the event handler before sending the requests
  const results = decodeIncomingSTUNResponses(requests, socket, timeout)
  // Everything is set up, so we can dispatch the requests
  sendStunRequests(requests, socket)

  const responses = await results

  return getUsableResults(responses ?? [], runningLocally)
}
Example #5
Source File: stun.ts    From hoprnet with GNU General Public License v3.0 6 votes vote down vote up
/**
 * Send requests to given STUN servers
 * @param usableMultiaddrs multiaddrs to use for STUN requests
 * @param tIds transaction IDs to use, necessary to link requests and responses
 * @param socket the socket to send the STUN requests
 * @returns usable transaction IDs and the corresponding multiaddrs
 */
function sendStunRequests(addrs: Request[], socket: Socket): void {
  for (const addr of addrs) {
    if (![CODE_IP4, CODE_IP6, CODE_DNS4, CODE_DNS6].includes(addr.multiaddr.tuples()[0][0])) {
      error(`Cannot contact STUN server ${addr.multiaddr.toString()} due to invalid address.`)
      continue
    }

    let nodeAddress: ReturnType<Multiaddr['nodeAddress']>
    try {
      nodeAddress = addr.multiaddr.nodeAddress()
    } catch (err) {
      error(err)
      continue
    }

    const res = createBindingRequest(addr.tId).setFingerprintAttribute()

    socket.send(res.toBuffer(), nodeAddress.port, nodeAddress.address, (err?: any) => {
      if (err) {
        error(err.message)
      } else {
        verbose(`STUN request successfully sent to ${nodeAddress.address}:${nodeAddress.port}`)
      }
    })
  }
}
Example #6
Source File: udpSocket.spec.ts    From regax with MIT License 6 votes vote down vote up
function createServer(onConnection?: any, onData?: any): Socket  {
  const server = dgram.createSocket('udp4')

  server.on('close', () => server.stopped = true)
  server.on('listening',  () => {
    // const address = server.address()
    // console.log('UDP Server listening on ' + address.address + ':' + address.port)
  })

  server.on('message', async (message: any, remote: any) => {
    server.lastRemote = remote
    const msg: any = Package.decode(message)
    const { type } = msg
    switch (type) {
      case PackageType.HANDSHAKE:
        send(server, PackageType.HANDSHAKE, { code: 200, sys: { heartbeat: 1000 }}, remote)
        break
      case PackageType.HANDSHAKE_ACK:
        if (onConnection) onConnection()
        await delay(10)
        send(server, PackageType.HEARTBEAT, {}, remote)
        break
      case PackageType.HEARTBEAT:
        await delay(10)
        console.log('send heartbeat from server')
        send(server, PackageType.HEARTBEAT, {}, remote)
        break
      case PackageType.DATA:
        if (onData) onData(msg.body)
        break
    }
    // console.log(remote.address + ':' + remote.port + ' - ' + message)
  })
  server.bind(PORT, HOST)
  return server
}
Example #7
Source File: mavesp.ts    From node-mavlink with GNU Lesser General Public License v3.0 5 votes vote down vote up
private socket: Socket
Example #8
Source File: Client.ts    From JSPrismarine with Mozilla Public License 2.0 5 votes vote down vote up
public getSocket(): Socket {
        return this.socket;
    }
Example #9
Source File: session.ts    From eufy-security-client with MIT License 5 votes vote down vote up
private socket: Socket;
Example #10
Source File: stun.ts    From hoprnet with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Takes a list of STUN servers and tries them one-by-one
 * in random order.
 * @param multiaddrs list of STUN servers
 * @param socket socket to receive replies
 * @param maxAttempts [optional] maximum number of attempts
 * @param runningLocally [optional] enable STUN local-mode
 * @returns STUN responses
 */
export async function iterateThroughStunServers(
  multiaddrs: Multiaddr[],
  socket: Socket,
  maxAttempts = Infinity,
  runningLocally = false
): Promise<RequestWithResponse[]> {
  const usedStunServers = new Set<string>()

  let selectedStunServers: Multiaddr[]
  if (multiaddrs.length > DEFAULT_PARALLEL_STUN_CALLS) {
    selectedStunServers = randomSubset(multiaddrs, DEFAULT_PARALLEL_STUN_CALLS)
  } else {
    selectedStunServers = multiaddrs
  }

  let responses: RequestWithResponse[] = await performSTUNRequests(
    selectedStunServers,
    socket,
    STUN_TIMEOUT,
    runningLocally
  )

  if (multiaddrs.length > DEFAULT_PARALLEL_STUN_CALLS) {
    while (responses.length < 2) {
      for (const selected of selectedStunServers) {
        usedStunServers.add(selected.toString())
      }

      if (usedStunServers.size >= maxAttempts) {
        break
      }

      const toFetch = Math.min(maxAttempts, DEFAULT_PARALLEL_STUN_CALLS + usedStunServers.size) - usedStunServers.size

      selectedStunServers = randomSubset(multiaddrs, toFetch, (ma: Multiaddr) => !usedStunServers.has(ma.toString()))

      responses.push(...(await performSTUNRequests(selectedStunServers, socket, STUN_TIMEOUT, runningLocally)))

      if (selectedStunServers.length < toFetch) {
        break
      }
    }
  }

  return responses
}
Example #11
Source File: stun.ts    From hoprnet with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Tries to determine the external IPv4 address
 * @returns Addr+Port or undefined if the STUN response are ambiguous (e.g. bidirectional NAT)
 *
 * @param multiAddrs Multiaddrs to use as STUN servers
 * @param socket Node.JS socket to use for the STUN request
 * @param __preferLocalAddress [testing] assume that all nodes run in a local network
 */
export async function getExternalIp(
  multiAddrs: Multiaddr[] | undefined,
  socket: Socket,
  __preferLocalAddress = false
): Promise<Interface | undefined> {
  let responses: RequestWithResponse[] = []
  if (__preferLocalAddress) {
    if (multiAddrs == undefined || multiAddrs.length == 0) {
      const socketAddress = socket.address() as Interface | null
      if (socketAddress == null) {
        throw Error(`Socket is not listening`)
      }
      if (socketAddress.family === 'IPv6') {
        throw Error(`IPv6 is not supported`)
      }
      log(
        `Running in local-mode without any given STUN server, assuming that socket address 127.0.0.1:${socketAddress.port} is public address`
      )
      return {
        ...socketAddress,
        address: '127.0.0.1',
        family: 'IPv4'
      }
    }

    responses.push(...(await iterateThroughStunServers(multiAddrs, socket, Infinity, true)))

    if (responses.length == 0) {
      log(`Cannot determine external IP because running in local mode and none of the local STUN servers replied.`)
      return
    }
  } else {
    if (multiAddrs == undefined || multiAddrs.length == 0) {
      responses.push(...(await iterateThroughStunServers(PUBLIC_STUN_SERVERS, socket)))
    } else {
      responses.push(...(await iterateThroughStunServers(multiAddrs, socket)))

      // We need at least two answers to determine whether the node
      // operates behind a bidirectional NAT
      if (responses.length < 2) {
        responses.push(...(await iterateThroughStunServers(PUBLIC_STUN_SERVERS, socket)))
      }
    }
  }

  if (responses.length < 2) {
    // We have tried all ways to check if the node
    // is operating behind a bidirectional NAT but we
    // could not get more than one response from STUN servers
    log(
      `Could not get more than one response from available STUN servers. Assuming that node operates behind a bidirectional NAT`
    )
    return
  }

  const interpreted = intepreteResults(responses)

  if (interpreted.ambiguous) {
    log(`Received STUN results are ambiguous. Assuming that node operates behind a bidirectional NAT`)
    return
  } else {
    return interpreted.publicAddress
  }
}
Example #12
Source File: wiz.ts    From homebridge-wiz-lan with Apache License 2.0 5 votes vote down vote up
public readonly socket: Socket;
Example #13
Source File: udpSocket.spec.ts    From regax with MIT License 5 votes vote down vote up
describe('udpSocket', () => {
  let server: Socket
  let client: RegaxUDPSocket
  beforeEach(() => {
  })
  afterEach(() => {
    if (server) server.close()
    if (client) client.close()
    // @ts-ignore
    server = undefined
    // @ts-ignore
    client = undefined
  })
  it('should hanshake success when connecting', (done: any) => {
    let clientConnection = false
    server = createServer(() => {
      assert(clientConnection)
      done()
    })
    client = createClient(() => clientConnection = true)
  })
  it('should try again if hanshake was failed', (done: any) => {
    client = createClient(() => {
      done()
    })
    delay(100).then(() => {
      server = createServer()
    })
  })
  it('should start heartbeat if connected', (done: any) => {
    let heartbeatTimes = 0
    client = createClient()
    server = createServer()
    client.on(client.event.HEARTBEAT, () => {
      heartbeatTimes++
      if (heartbeatTimes === 3) done()
    })
  })
  it('should kick user success from server', (done: any) => {
    client = createClient()
    server = createServer(() => {
      send(server, PackageType.KICK, { reason: '' })
    })
    client.on(client.event.DISCONNECT, () => {
      done()
    })
  })
  it('should close once if emitting close duplicately', (done: any) => {
    client = createClient()
    client.on(client.event.DISCONNECT, () => {
      done()
    })
    client.close()
    client.close()
  })
  it ('should close before connecting next time', () => {
  })
  it('should send data success from server to client', () => {
  })
})
Example #14
Source File: udpConnector.ts    From regax with MIT License 5 votes vote down vote up
server: Socket
Example #15
Source File: udpStickyServer.ts    From regax with MIT License 5 votes vote down vote up
protected server: Socket
Example #16
Source File: stun.ts    From hoprnet with GNU General Public License v3.0 4 votes vote down vote up
function decodeIncomingSTUNResponses(addrs: Request[], socket: Socket, ms: number = STUN_TIMEOUT): Promise<Request[]> {
  return new Promise<Request[]>((resolve) => {
    let responsesReceived = 0

    let listener: (msg: Buffer) => void
    let finished = false

    let done = () => {
      if (finished) {
        return
      }
      finished = true

      socket.removeListener('message', listener)

      clearTimeout(timeout)

      resolve(addrs)
    }

    const timeout = setTimeout(() => {
      log(
        `STUN timeout. ${addrs.filter((addr) => addr.response).length} of ${
          addrs.length
        } selected STUN servers replied.`
      )
      done()
    }, ms)

    // Receiving a Buffer, not a Uint8Array
    listener = (msg: Buffer) => {
      const res = createBlank()

      // Overwrite console.log because 'webrtc-stun' package
      // pollutes console output
      const consoleBackup = console.log
      console.log = log

      try {
        if (!res.loadBuffer(msg)) {
          error(`Could not decode STUN response`)
          console.log = consoleBackup
          return
        }

        const index: number = addrs.findIndex((addr: Request) =>
          res.isBindingResponseSuccess({ transactionId: addr.tId })
        )

        if (index < 0) {
          error(`Received STUN response with invalid transactionId. Dropping response.`)
          console.log = consoleBackup
          return
        }

        const attr = res.getXorMappedAddressAttribute() ?? res.getMappedAddressAttribute()

        if (!isInterface(attr)) {
          error(`Invalid STUN response. Got ${attr}`)
          return
        }

        console.log = consoleBackup

        if (attr == null) {
          error(`STUN response seems to have neither MappedAddress nor XORMappedAddress set. Dropping message`)
          return
        }

        verbose(`Received STUN response. External address seems to be: ${attr.address}:${attr.port}`)

        if (addrs[index].response != undefined) {
          verbose(`Recieved duplicate response. Dropping message`)
          return
        }

        addrs[index].response = attr
        responsesReceived++

        if (responsesReceived == addrs.length) {
          done()
        }
      } catch (err) {
        consoleBackup(err)
      } finally {
        console.log = consoleBackup
      }
    }

    socket.on('message', listener)
  })
}