Class: Caldecott::Server::Tunnel

Inherits:
Object
  • Object
show all
Defined in:
lib/caldecott/server/http_tunnel.rb

Constant Summary collapse

DEFAULT_MAX_DATA_TO_BUFFER =

1MB

1 * 1024 * 1024

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(log, tunnels, host, port, max_data_to_buffer = DEFAULT_MAX_DATA_TO_BUFFER) ⇒ Tunnel

Returns a new instance of Tunnel.



19
20
21
22
23
24
25
26
# File 'lib/caldecott/server/http_tunnel.rb', line 19

def initialize(log, tunnels, host, port, max_data_to_buffer = DEFAULT_MAX_DATA_TO_BUFFER)
  @log, @tunnels, @host, @port = log, tunnels, host, port
  @tun_id = UUIDTools::UUID.random_create.to_s
  @data = @data_next = ""
  @seq_out = @seq_in = 0
  @max_data_to_buffer = max_data_to_buffer
  @last_active_at = Time.now
end

Instance Attribute Details

#last_active_atObject (readonly)

Returns the value of attribute last_active_at.



16
17
18
# File 'lib/caldecott/server/http_tunnel.rb', line 16

def last_active_at
  @last_active_at
end

#logObject (readonly)

Returns the value of attribute log.



16
17
18
# File 'lib/caldecott/server/http_tunnel.rb', line 16

def log
  @log
end

#tun_idObject (readonly)

Returns the value of attribute tun_id.



16
17
18
# File 'lib/caldecott/server/http_tunnel.rb', line 16

def tun_id
  @tun_id
end

Instance Method Details

#deleteObject



57
58
59
60
61
62
63
64
# File 'lib/caldecott/server/http_tunnel.rb', line 57

def delete
  @log.debug "target disconnected"
  if @dst_conn
    @dst_conn.close_connection_after_writing
  else
    @tunnels.delete(@tun_id)
  end
end

#get(resp, seq) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/caldecott/server/http_tunnel.rb', line 66

def get(resp, seq)
  @last_active_at = Time.now
  resp.halt(400, "invalid sequence #{seq} for server seq #{@seq_out}") unless (seq == @seq_out or seq == @seq_out + 1)
  if seq == @seq_out + 1
    @data, @data_next = @data_next, ""
    @seq_out = seq
  end

  if @data.empty?
    resp.halt(410, "destination socket closed\n") if @dst_conn.nil?
    @log.debug "get: waiting for data"
    @reader = EM.Callback do
      @data, @data_next = @data_next, ""
      resp.ahalt(410, "destination socket closed\n") if @data.empty?
      @log.debug "get: returning data (async)"
      resp.body @data
    end
  else
    @log.debug "get: returning data (immediate)"
    resp.body @data
    @dst_conn.resume
  end
end

#open(resp) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/caldecott/server/http_tunnel.rb', line 28

def open(resp)
  EM::connect(@host, @port, TcpConnection) do |dst_conn|
    @dst_conn = dst_conn

    @dst_conn.onopen do
      @log.debug "dst connected"
      @tunnels[@tun_id] = self
      resp.content_type :json
      resp.status 201
      resp.body safe_hash.to_json
    end

    @dst_conn.onreceive do |data|
      @log.debug "t <- d #{data.length}"
      @data_next << data
      trigger_reader
      @dst_conn.pause if @data_next.length > @max_data_to_buffer
    end

    @dst_conn.onclose do
      @log.debug "target disconnected"
      @dst_conn = nil
      trigger_reader
      @tunnels.delete(@tun_id) if @data_next.empty?
    end
  end
  @tunnel_created_at = Time.now
end

#put(resp, seq) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/caldecott/server/http_tunnel.rb', line 90

def put(resp, seq)
  @last_active_at = Time.now
  resp.halt(400, "invalid sequence #{seq} for server seq #{@seq_in}") unless (seq == @seq_in or seq == @seq_in + 1)
  if seq == @seq_in
    resp.status 201
  else
    @seq_in = seq
    @log.debug "t -> d #{resp.request.body.length}"
    @dst_conn.send_data(resp.request.body.read)
    resp.status 202
  end
end

#safe_hashObject



110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/caldecott/server/http_tunnel.rb', line 110

def safe_hash
  {
    :path => "/tunnels/#{@tun_id}",
    :path_in => "/tunnels/#{@tun_id}/in",
    :path_out => "/tunnels/#{@tun_id}/out",
    :dst_host => @host,
    :dst_port => @port,
    :dst_connected => @dst_conn.nil? == false,
    :seq_out => @seq_out,
    :seq_in => @seq_in
  }
end

#trigger_readerObject



103
104
105
106
107
108
# File 'lib/caldecott/server/http_tunnel.rb', line 103

def trigger_reader
  return unless @reader
  reader = @reader
  @reader = nil
  reader.call
end