module Pytty::Daemon::Components::YieldHandler

Public Class Methods

handle(component:, id:, params:) click to toggle source
# File lib/pytty/daemon/components/yield_handler.rb, line 7
def self.handle(component:, id:, params:)
  process_yield = Pytty::Daemon.yields[id]
  return [404, "not found"] unless process_yield

  return case component
  when "port"
    endpoint = Async::IO::Endpoint.tcp('0.0.0.0', params["from"].to_i)
    endpoint.accept do |client|
      process_yield.spawn unless process_yield.running?
      p ["port accept", client.object_id]
      upstream = Async::IO::Endpoint.tcp('0.0.0.0', params["to"].to_i)
      peer = nil
      upstream.connect do |peer|
        Async::Task.current.async do |task|
          while rata = peer.read(1)
            client.write rata
          end
          client.close
        end

        while data = client.read(2)
          p data
          peer.write(data)
        end
      end
    rescue Errno::ECONNREFUSED
      sleep 0.1
      p ["port upstream retry"]
      retry
    # rescue Async::Wrapper::Cancelled
    #   # ???
    rescue Exception => ex
      p ["accex", ex]
    ensure
      peer.close
      client.close
    end

    [200, "ok"]
  when "stdin"
    process_yield.stdin.enqueue params["c"]

    [200, "ok"]
  when "status"
    return [500, "still running"] if process_yield.running?

    [200, process_yield.status]
  when "signal"
    return [500, "not running"] unless process_yield.running?

    process_yield.signal params["signal"]

    [200, "ok"]
  when "spawn"
    return [500, "already running"] if process_yield.running?
    if process_yield.spawn tty: params["tty"], interactive: params["interactive"]
      Pytty::Daemon.dump
    else
      return [500, "could not spawn"]
    end

    [200, "ok"]
  when "rm"
    process_yield.signal("KILL") if process_yield.running?
    process_yield.cleanup

    Pytty::Daemon.yields.delete process_yield.id
    Pytty::Daemon.dump

    [200, id]
  else
    raise "unknown: #{component} with id: #{id}"
  end
end