OverviewFilesCommitsIssuesDocsReleasesPeers

ollama_semantic_function_calling / ollamatools-new / keet / node_modules / bare-tcp / index.js

572 lines · javascript ref:
/* global Bare */
const EventEmitter = require('bare-events')
const { Duplex } = require('bare-stream')
const dns = require('bare-dns')
const binding = require('./binding')
const constants = require('./lib/constants')
const errors = require('./lib/errors')
const ip = require('./lib/ip')

const defaultReadBufferSize = 65536

exports.Socket = class TCPSocket extends Duplex {
  constructor(opts = {}) {
    super({ eagerOpen: true })

    const { readBufferSize = defaultReadBufferSize, allowHalfOpen = true } =
      opts

    this._state = 0

    this._allowHalfOpen = allowHalfOpen

    this._remotePort = -1
    this._remoteHost = null
    this._remoteFamily = 0

    this._pendingOpen = null
    this._pendingWrite = null
    this._pendingFinal = null
    this._pendingDestroy = null

    this._timer = null
    this._timeout = 0

    this._buffer = Buffer.alloc(readBufferSize)

    this._handle = binding.init(
      this._buffer,
      this,
      noop,
      this._onconnect,
      this._onread,
      this._onwrite,
      this._onfinal,
      this._onclose
    )
  }

  get connecting() {
    return (this._state & constants.state.CONNECTING) !== 0
  }

  get pending() {
    return (this._state & constants.state.CONNECTED) === 0
  }

  get timeout() {
    return this._timeout || undefined // For Node.js compatibility
  }

  connect(port, host = 'localhost', opts = {}, onconnect) {
    if (
      this._state & constants.state.CONNECTING ||
      this._state & constants.state.CONNECTED
    ) {
      throw errors.SOCKET_ALREADY_CONNECTED('Socket is already connected')
    }

    this._state |= constants.state.CONNECTING

    if (typeof host === 'function') {
      onconnect = host
      host = 'localhost'
    } else if (typeof opts === 'function') {
      onconnect = opts
      opts = {}
    }

    let family = 0

    if (typeof port === 'object' && port !== null) {
      opts = port || {}
      port = opts.port || 0
      host = opts.host || 'localhost'
      family = opts.family || 0
    }

    if (!host) host = 'localhost'

    const type = ip.isIP(host)

    if (type === 0) {
      const { lookup = dns.lookup, hints } = opts

      lookup(host, { family, hints }, (err, address, family) => {
        if (this._state & constants.state.CLOSING) return

        this.emit('lookup', err, address, family, host)

        this._state &= ~constants.state.CONNECTING

        if (err) {
          if (this._pendingOpen) this._continueOpen(err)
          else this.destroy(err)
          return
        }

        this.connect(port, address, { ...opts, family }, onconnect)
      })

      return this
    }

    family = type

    try {
      binding.connect(this._handle, port, host, family)

      if (opts.keepAlive === true) {
        this.setKeepAlive(opts.keepAlive, opts.keepAliveInitialDelay)
      }

      if (opts.noDelay === true) {
        this.setNoDelay()
      }

      if (opts.timeout) {
        this.setTimeout(opts.timeout)
      }

      this._remotePort = port
      this._remoteHost = host
      this._remoteFamily = family

      if (onconnect) this.once('connect', onconnect)
    } catch (err) {
      queueMicrotask(() => {
        if (this._pendingOpen) this._pendingOpen(err)
        else this.destroy(err)
      })
    }

    return this
  }

  setKeepAlive(enable = false, delay = 0) {
    if (typeof enable === 'number') {
      delay = enable
      enable = false
    }

    delay = Math.floor(delay / 1000)

    if (delay === 0) enable = false

    binding.keepalive(this._handle, enable, delay)

    return this
  }

  setNoDelay(enable = true) {
    binding.nodelay(this._handle, enable)

    return this
  }

  setTimeout(ms, ontimeout) {
    if (ms === 0) {
      clearTimeout(this._timer)
      this._timer = null
    } else {
      if (ontimeout) this.once('timeout', ontimeout)

      this._timer = setTimeout(() => this.emit('timeout'), ms)
      this._timer.unref()
    }

    this._timeout = ms

    return this
  }

  ref() {
    binding.ref(this._handle)
  }

  unref() {
    binding.unref(this._handle)
  }

  _open(cb) {
    if (this._state & constants.state.CONNECTED) return cb(null)
    this._pendingOpen = cb
  }

  _read() {
    if ((this._state & constants.state.READING) === 0) {
      this._state |= constants.state.READING
      binding.resume(this._handle)
    }
  }

  _writev(batch, cb) {
    this._pendingWrite = [cb, batch]
    binding.writev(
      this._handle,
      batch.map(({ chunk }) => chunk)
    )
  }

  _final(cb) {
    this._pendingFinal = cb
    binding.end(this._handle)
  }

  _predestroy() {
    if (this._state & constants.state.CLOSING) return
    this._state |= constants.state.CLOSING
    binding.close(this._handle)
  }

  _destroy(err, cb) {
    if (this._state & constants.state.CLOSING) return cb(err)
    this._state |= constants.state.CLOSING
    this._pendingDestroy = cb
    binding.close(this._handle)
  }

  _continueOpen(err) {
    if (this._pendingOpen === null) return
    const cb = this._pendingOpen
    this._pendingOpen = null
    cb(err)
  }

  _continueWrite(err) {
    if (this._pendingWrite === null) return
    const cb = this._pendingWrite[0]
    this._pendingWrite = null
    cb(err)
  }

  _continueFinal(err) {
    if (this._pendingFinal === null) return
    const cb = this._pendingFinal
    this._pendingFinal = null
    cb(err)
  }

  _continueDestroy() {
    if (this._pendingDestroy === null) return
    const cb = this._pendingDestroy
    this._pendingDestroy = null
    cb(null)
  }

  _onconnect(err) {
    if (err) {
      if (this._pendingOpen) this._continueOpen(err)
      else this.destroy(err)
      return
    }

    this._state |= constants.state.CONNECTED
    this._state &= ~constants.state.CONNECTING
    this._continueOpen()

    this.emit('connect')
  }

  _onread(err, read) {
    if (this._timer) this._timer.refresh()

    if (err) {
      this.destroy(err)
      return
    }

    if (read === 0) {
      this.push(null)
      if (this._allowHalfOpen === false) this.end()
      return
    }

    const copy = Buffer.allocUnsafe(read)
    copy.set(this._buffer.subarray(0, read))

    if (this.push(copy) === false && this.destroying === false) {
      this._state &= ~constants.state.READING
      binding.pause(this._handle)
    }
  }

  _onwrite(err) {
    if (this._timer) this._timer.refresh()

    this._continueWrite(err)
  }

  _onfinal(err) {
    this._continueFinal(err)
  }

  _onclose() {
    clearTimeout(this._timer)

    this._handle = null
    this._continueDestroy()
  }
}

exports.Server = class TCPServer extends EventEmitter {
  constructor(opts = {}, onconnection) {
    if (typeof opts === 'function') {
      onconnection = opts
      opts = {}
    }

    super()

    const { readBufferSize = defaultReadBufferSize, allowHalfOpen = true } =
      opts

    this._state = 0

    this._readBufferSize = readBufferSize
    this._allowHalfOpen = allowHalfOpen

    this._keepAlive = opts.keepAlive
    this._keepAliveDelay = opts.keepAliveInitialDelay
    this._noDelay = opts.noDelay

    this._port = -1
    this._host = null
    this._family = 0
    this._connections = new Set()

    this._error = null
    this._handle = null

    if (onconnection) this.on('connection', onconnection)
  }

  get listening() {
    return (this._state & constants.state.BOUND) !== 0
  }

  address() {
    if ((this._state & constants.state.BOUND) === 0) {
      return null
    }

    return {
      address: this._host,
      family: `IPv${this._family}`,
      port: this._port
    }
  }

  listen(port = 0, host = 'localhost', backlog = 511, opts = {}, onlistening) {
    if (
      this._state & constants.state.BINDING ||
      this._state & constants.state.BOUND
    ) {
      throw errors.SERVER_ALREADY_LISTENING('Server is already listening')
    }

    if (this._state & constants.state.CLOSING) {
      throw errors.SERVER_IS_CLOSED('Server is closed')
    }

    this._state |= constants.state.BINDING

    if (typeof port === 'function') {
      onlistening = port
      port = 0
    } else if (typeof host === 'function') {
      onlistening = host
      host = 'localhost'
    } else if (typeof backlog === 'function') {
      onlistening = backlog
      backlog = 511
    } else if (typeof opts === 'function') {
      onlistening = opts
      opts = {}
    }

    let family = 0

    if (typeof port === 'object' && port !== null) {
      opts = port || {}
      port = opts.port || 0
      host = opts.host || 'localhost'
      family = opts.family || 0
      backlog = opts.backlog || 511
    }

    if (!host) host = 'localhost'
    if (!backlog) backlog = 511

    const type = ip.isIP(host)

    if (type === 0) {
      const { lookup = dns.lookup, hints } = opts

      lookup(host, { family, hints }, (err, address, family) => {
        if (this._state & constants.state.CLOSING) return

        this.emit('lookup', err, address, family, host)

        this._state &= ~constants.state.BINDING

        if (err) return this.emit('error', err)

        this.listen(port, address, backlog, { ...opts, family }, onlistening)
      })

      return this
    }

    family = type

    this._handle = binding.init(
      empty,
      this,
      this._onconnection,
      noop,
      noop,
      noop,
      noop,
      this._onclose
    )

    if (this._state & constants.state.UNREFED) binding.unref(this._handle)

    try {
      this._port = binding.bind(this._handle, port, host, backlog, family)
      this._host = host
      this._family = family
      this._state |= constants.state.BOUND
      this._state &= ~constants.state.BINDING

      if (onlistening) this.once('listening', onlistening)

      queueMicrotask(() => this.emit('listening'))
    } catch (err) {
      this._error = err

      binding.close(this._handle)
    }

    return this
  }

  close(onclose) {
    if (onclose) this.once('close', onclose)
    if (this._state & constants.state.CLOSING) return
    this._state |= constants.state.CLOSING
    this._closeMaybe()
  }

  ref() {
    this._state &= ~constants.state.UNREFED
    if (this._handle !== null) binding.ref(this._handle)
  }

  unref() {
    this._state |= constants.state.UNREFED
    if (this._handle !== null) binding.unref(this._handle)
  }

  _closeMaybe() {
    if (this._state & constants.state.CLOSING && this._connections.size === 0) {
      if (this._handle !== null) binding.close(this._handle)
      else queueMicrotask(() => this.emit('close'))
    }
  }

  _onconnection(err) {
    if (err) {
      this.emit('error', err)
      return
    }

    if (this._state & constants.state.CLOSING) return

    const socket = new exports.Socket({
      readBufferSize: this._readBufferSize,
      allowHalfOpen: this._allowHalfOpen
    })

    try {
      binding.accept(this._handle, socket._handle)

      socket._state |= constants.state.CONNECTED

      this._connections.add(socket)

      if (this._keepAlive === true) {
        socket.setKeepAlive(this._keepAlive, this._keepAliveDelay)
      }

      if (this._noDelay === true) {
        socket.setNoDelay()
      }

      socket.on('close', () => {
        this._connections.delete(socket)
        this._closeMaybe()
      })

      this.emit('connection', socket)
    } catch (err) {
      socket.destroy()

      throw err
    }
  }

  _onclose() {
    const err = this._error

    this._state &= ~constants.state.BINDING
    this._error = null
    this._handle = null

    if (err) this.emit('error', err)
    else this.emit('close')
  }
}

exports.constants = constants
exports.errors = errors

exports.isIP = ip.isIP
exports.isIPv4 = ip.isIPv4
exports.isIPv6 = ip.isIPv6

exports.createConnection = function createConnection(
  port,
  host,
  opts,
  onconnect
) {
  if (typeof host === 'function') {
    onconnect = host
    host = 'localhost'
  } else if (typeof opts === 'function') {
    onconnect = opts
    opts = {}
  }

  if (typeof port === 'object' && port !== null) {
    opts = port || {}
    port = opts.port || 0
    host = opts.host || 'localhost'
  }

  return new exports.Socket(opts).connect(port, host, opts, onconnect)
}

// For Node.js compatibility
exports.connect = exports.createConnection

exports.createServer = function createServer(opts, onconnection) {
  return new exports.Server(opts, onconnection)
}

const empty = Buffer.alloc(0)

function noop() {}