bayserver-docker-terminal 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 33d1e39cac0afb5af49bc8cc177e7bb275a63965dc9cf17ac288e5284dacab67
4
+ data.tar.gz: f27f672fb7d691d506accfdc699e121990d0b1e67994039657a96d79cdd306cf
5
+ SHA512:
6
+ metadata.gz: 2994251e531a31afd3d27f368bc321e8857d201d02834b438bcacaf5da0df72d40d5fd9d00b4817da71b865d37ed14d1dbdfdc38ae9806b635ce373d7cc38f19
7
+ data.tar.gz: be8c6e48f562cef7fd34f861a99fa582c2e84f468803bacc6ab49129aaf1856cfe8a77f6f1a469535e7f9289ccc7514e38753e99b4136e1db71699e8359514c8
@@ -0,0 +1,155 @@
1
+ require 'baykit/bayserver/agent/next_socket_action'
2
+ require 'baykit/bayserver/watercraft/yacht'
3
+ require 'baykit/bayserver/util/string_util'
4
+ require 'baykit/bayserver/util/reusable'
5
+
6
+ require 'baykit/bayserver/docker/terminal/hijackers_yacht'
7
+
8
+ require 'baykit/bayserver/docker/http/h1/h1_command_handler'
9
+
10
+ module Baykit
11
+ module BayServer
12
+ module Docker
13
+ module Terminal
14
+ class FullyHijackersYacht < HijackersYacht
15
+ include Baykit::BayServer::Docker::Http::H1::H1CommandHandler # implements
16
+
17
+ include Baykit::BayServer::Util
18
+ include Baykit::BayServer::Protocol
19
+ include Baykit::BayServer::Docker::Http::H1
20
+
21
+ STATE_READ_HEADER = 1
22
+ STATE_READ_CONTENT = 2
23
+ STATE_FINISHED = 3
24
+
25
+ attr :state
26
+ attr :packet_store
27
+ attr :packet_unpacker
28
+ attr :command_unpacker
29
+
30
+ def initialize
31
+ super
32
+ end
33
+
34
+ ######################################################
35
+ # Init method
36
+ ######################################################
37
+ #
38
+ def init(tur, io, tp)
39
+ super
40
+ @packet_store = PacketStore.new(tur.ship, H1PacketFactory.new)
41
+ @command_unpacker = H1CommandUnPacker.new(self, false)
42
+ @packet_unpacker = H1PacketUnPacker.new(@command_unpacker, @packet_store)
43
+ end
44
+
45
+ ######################################################
46
+ # implements Reusable
47
+ ######################################################
48
+
49
+ def reset()
50
+ super
51
+ @state = STATE_FINISHED
52
+ end
53
+
54
+ ######################################################
55
+ # implements Yacht
56
+ ######################################################
57
+
58
+ # Override
59
+ def notify_read(buf, adr)
60
+ @file_wrote_len += buf.length
61
+
62
+ BayLog.debug "#{self} read hijack #{buf.length} bytes: total=#{@file_wrote_len}"
63
+
64
+ return @packet_unpacker.bytes_received(buf)
65
+
66
+ end
67
+
68
+
69
+ ######################################################
70
+ # Implements H1CommandHandler
71
+ ######################################################
72
+
73
+ def handle_header(cmd)
74
+ if @state == STATE_FINISHED
75
+ change_state(STATE_READ_HEADER)
76
+ end
77
+
78
+ if @state != STATE_READ_HEADER
79
+ raise ProtocolException("Header command not expected: state=%d", @state)
80
+ end
81
+
82
+ if BayServer.harbor.trace_header?
83
+ BayLog.info("%s hijack: resStatus: %d", self, cmd.status)
84
+ end
85
+
86
+ cmd.headers.each do |nv|
87
+ @tour.res.headers.add(nv[0], nv[1])
88
+ if BayServer.harbor.trace_header?
89
+ BayLog.info("%s hijack: resHeader: %s=%s", self, nv[0], nv[1]);
90
+ end
91
+ end
92
+
93
+ @tour.res.headers.status = cmd.status != nil ? cmd.status : HttpStatus::OK
94
+ @tour.res.send_headers(@tour_id)
95
+
96
+ res_cont_len = @tour.res.headers.content_length
97
+ BayLog.debug("%s contLen in header: %d", self, res_cont_len)
98
+
99
+ if res_cont_len == 0 || cmd.status == HttpStatus::NOT_MODIFIED
100
+ end_res_content(@tour)
101
+ else
102
+ change_state(STATE_READ_CONTENT)
103
+ sid = @tour.ship.id()
104
+ @tour.res.set_consume_listener do |len, resume|
105
+ if resume
106
+ @tour.ship.resume(sid)
107
+ end
108
+ end
109
+ end
110
+ return NextSocketAction::CONTINUE
111
+ end
112
+
113
+ def handle_content(cmd)
114
+
115
+ if @state != STATE_READ_CONTENT
116
+ raise ProtocolException.new("Content command not expected")
117
+ end
118
+
119
+ available = @tour.res.send_content(@tour_id, cmd.buf, cmd.start, cmd.len)
120
+ if @tour.res.bytes_posted == @tour.res.bytes_limit
121
+ end_res_content(@tour)
122
+ return NextSocketAction::CONTINUE
123
+ elsif !available
124
+ return NextSocketAction::SUSPEND
125
+ else
126
+ NextSocketAction::CONTINUE
127
+ end
128
+ end
129
+
130
+ def handle_end_content(cmd)
131
+ # never called
132
+ raise Sink.new()
133
+ end
134
+
135
+ def finished()
136
+ return @state == STATE_FINISHED
137
+ end
138
+
139
+
140
+ private
141
+
142
+ def end_res_content(tur)
143
+ tur.res.end_content(Tour::TOUR_ID_NOCHECK)
144
+ reset()
145
+ end
146
+
147
+ def change_state(new_state)
148
+ @state = new_state
149
+ end
150
+ end
151
+ end
152
+ end
153
+ end
154
+ end
155
+
@@ -0,0 +1,170 @@
1
+ require 'baykit/bayserver/agent/next_socket_action'
2
+ require 'baykit/bayserver/protocol/packet_store'
3
+ require 'baykit/bayserver/docker/http/h1/h1_packet_unpacker'
4
+ require 'baykit/bayserver/docker/http/h1/h1_command_unpacker'
5
+ require 'baykit/bayserver/util/string_util'
6
+ require 'baykit/bayserver/util/http_status'
7
+
8
+
9
+ module Baykit
10
+ module BayServer
11
+ module Docker
12
+ module Terminal
13
+ #
14
+ # Send data of hijacked response
15
+ #
16
+ class HijackedDataSender
17
+ include Baykit::BayServer::Agent::NonBlockingHandler::ChannelListener # implements
18
+ include Baykit::BayServer::Util
19
+ include Baykit::BayServer::Agent
20
+ include Baykit::BayServer::Protocol
21
+ include Baykit::BayServer::Docker::Http::H1
22
+
23
+ attr :tour
24
+ attr :tour_id
25
+ attr :fully
26
+
27
+ attr :file_wrote_len
28
+ attr :file_buf_list
29
+ attr :cur_file_idx
30
+ attr :read_buf_size
31
+ attr :cur_file_idx
32
+ attr :pipe_io
33
+
34
+ attr :packet_store
35
+ attr :packet_unpacker
36
+ attr :command_unpacker
37
+
38
+ DEFAULT_FREAD_BUF_SIZE = 8192
39
+
40
+ def initialize(tur, fully)
41
+ @tour = tur
42
+ @tour_id = @tour.tour_id
43
+ @fully = fully
44
+ @file_buf_list = []
45
+ @read_buf_size = tour.ship.protocol_handler.max_res_packet_data_size
46
+
47
+ if @fully
48
+ @packet_store = PacketStore.new(tur.ship, H1PacketFactory.new)
49
+ @command_unpacker = H1CommandUnPacker.new(self, false)
50
+ @packet_unpacker = H1PacketUnPacker.new(@command_unpacker, @packet_store)
51
+ end
52
+ reset
53
+ end
54
+
55
+ def reset
56
+ @file_wrote_len = 0
57
+ @cur_file_idx = -1
58
+ end
59
+
60
+ def ship
61
+ @tour.ship
62
+ end
63
+
64
+ def on_readable(chk_fd)
65
+ BayLog.debug "#{self} Hijack Readable"
66
+ check_socket(chk_fd)
67
+
68
+ buf = new_file_buffer
69
+ begin
70
+ @pipe_io.read_nonblock(@read_buf_size, buf)
71
+ rescue EOFError => e
72
+ BayLog.debug "#{self} Hijack EOF"
73
+ @tour.res.end_content(@tour_id)
74
+ return NextSocketAction::CLOSE
75
+ end
76
+
77
+ @file_wrote_len += buf.length
78
+
79
+ BayLog.debug "#{self} read hijack #{buf.length} bytes: total=#{@file_wrote_len}"
80
+
81
+ if @fully
82
+ return @packet_unpacker.bytes_received(buf)
83
+ else
84
+ available = @tour.res.send_content(@tour_id, buf, 0, buf.length)
85
+ if !available
86
+ NextSocketAction::SUSPEND
87
+ else
88
+ NextSocketAction::CONTINUE
89
+ end
90
+ end
91
+
92
+ end
93
+
94
+ def check_timeout(chk_fd, duration)
95
+ BayLog.debug "#{self} Hijack timeout(Ignore)"
96
+ end
97
+
98
+ def on_error(chk_fd, e)
99
+ BayLog.debug "#{self} Hijack Error"
100
+ check_socket(chk_fd)
101
+
102
+ BayLog.error_e e
103
+ end
104
+
105
+ def on_closed(chk_fd)
106
+ BayLog.debug "#{self} Hijack Closed(Ignore)"
107
+ check_socket(chk_fd)
108
+ end
109
+
110
+
111
+ def send_pipe_data(io)
112
+ BayLog.debug("#{self} Send hijacked data #{io.inspect}")
113
+ @pipe_io = io
114
+ @file_wrote_len = 0
115
+ @tour.ship.agent.non_blocking_handler.ask_to_read(@pipe_io)
116
+ end
117
+
118
+ # Implements H1CommandHandler
119
+ # Fully hijacked mode
120
+ def handle_header(cmd)
121
+ cmd.headers.each do |nv|
122
+ @tour.res.headers.add(nv[0], nv[1])
123
+ end
124
+
125
+ @tour.res.headers.status = cmd.status != nil ? cmd.status : HttpStatus::OK
126
+ @tour.send_headers(@tour_id)
127
+
128
+ return NextSocketAction::CONTINUE
129
+ end
130
+
131
+ # Implements H1CommandHandler
132
+ # Fully hijacked mode
133
+ def handle_content(cmd)
134
+ available = @tour.res.send_content(@tour_id, cmd.buf, cmd.start, cmd.len)
135
+ if !available
136
+ NextSocketAction::SUSPEND
137
+ else
138
+ NextSocketAction::CONTINUE
139
+ end
140
+ end
141
+
142
+ def resume
143
+ BayLog.debug("#{self} resume")
144
+ @tour.ship.agent.non_blocking_handler.ask_to_read(@pipe_io)
145
+ end
146
+
147
+ def to_s
148
+ "hijack[#{@pipe_io.inspect}]"
149
+ end
150
+
151
+ private
152
+ def check_socket(chk_fd)
153
+ if chk_fd != @pipe_io
154
+ raise RuntimeError.new("BUG: Invalid hijacked data sender instance (file was returned?): #{chk_fd}")
155
+ end
156
+ end
157
+
158
+ def new_file_buffer
159
+ @cur_file_idx += 1
160
+ if @file_buf_list.length == @cur_file_idx
161
+ @file_buf_list << StringUtil.alloc(@read_buf_size)
162
+ end
163
+ @file_buf_list[@cur_file_idx]
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end
169
+ end
170
+
@@ -0,0 +1,106 @@
1
+ require 'baykit/bayserver/agent/next_socket_action'
2
+ require 'baykit/bayserver/watercraft/yacht'
3
+ require 'baykit/bayserver/util/string_util'
4
+ require 'baykit/bayserver/util/reusable'
5
+
6
+ require 'baykit/bayserver/docker/http/h1/h1_command_handler'
7
+
8
+ module Baykit
9
+ module BayServer
10
+ module Docker
11
+ module Terminal
12
+ class HijackersYacht < Baykit::BayServer::WaterCraft::Yacht
13
+ include Baykit::BayServer::Docker::Http::H1::H1CommandHandler # implements
14
+
15
+ include Baykit::BayServer::Util
16
+ include Baykit::BayServer::Agent
17
+ include Baykit::BayServer::Protocol
18
+ include Baykit::BayServer::Docker::Http::H1
19
+
20
+ attr :tour
21
+ attr :tour_id
22
+
23
+ attr :file_wrote_len
24
+ attr :pipe_io
25
+
26
+ attr :packet_store
27
+ attr :packet_unpacker
28
+ attr :command_unpacker
29
+
30
+ def initialize
31
+ super
32
+ reset()
33
+ end
34
+
35
+ def to_s()
36
+ return "hijack##{@yacht_id}/#{@object_id} tour=#{@tour} id=#{@tour_id}";
37
+ end
38
+
39
+ ######################################################
40
+ # Init method
41
+ ######################################################
42
+
43
+ def init(tur, io, tp)
44
+ init_yacht()
45
+ @tour = tur
46
+ @tour_id = @tour.tour_id
47
+
48
+ tur.res.set_consume_listener do |len, resume|
49
+ if resume
50
+ tp.open_valve();
51
+ end
52
+ end
53
+ @pipe_io = io
54
+ @file_wrote_len = 0
55
+ @tour.ship.agent.non_blocking_handler.ask_to_read(@pipe_io)
56
+ end
57
+
58
+
59
+ ######################################################
60
+ # implements Reusable
61
+ ######################################################
62
+
63
+ def reset()
64
+ @file_wrote_len = 0
65
+ @file_len = 0
66
+ @tour = nil
67
+ @tour_id = 0
68
+ end
69
+
70
+ ######################################################
71
+ # implements Yacht
72
+ ######################################################
73
+
74
+ def notify_read(buf, adr)
75
+ @file_wrote_len += buf.length
76
+
77
+ BayLog.debug "#{self} read hijack #{buf.length} bytes: total=#{@file_wrote_len}"
78
+
79
+ available = @tour.res.send_content(@tour_id, buf, 0, buf.length)
80
+ if !available
81
+ return NextSocketAction::SUSPEND
82
+ else
83
+ return NextSocketAction::CONTINUE
84
+ end
85
+ end
86
+
87
+ def notify_eof()
88
+ BayLog.debug "#{self} Hijack EOF"
89
+ @tour.res.end_content(@tour_id)
90
+ return NextSocketAction::CLOSE
91
+ end
92
+
93
+ def notify_close()
94
+ BayLog.debug("%s Hijack Closed(Ignore)", self)
95
+ end
96
+
97
+ def check_timeout(duration)
98
+ BayLog.debug("%s Hijack timeout(Ignore)", self)
99
+ end
100
+
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
106
+
@@ -0,0 +1,204 @@
1
+ require 'baykit/bayserver/agent/transporter/plain_transporter'
2
+ require 'baykit/bayserver/docker/base/port_base'
3
+ require 'baykit/bayserver/tours/content_consume_listener'
4
+
5
+ require 'baykit/bayserver/docker/terminal/fully_hijackers_yacht'
6
+ require 'baykit/bayserver/docker/terminal/terminal_train'
7
+
8
+ module Baykit
9
+ module BayServer
10
+ module Docker
11
+ module Terminal
12
+ class TerminalDocker < Baykit::BayServer::Docker::Base::ClubBase
13
+ include Baykit::BayServer::Bcf
14
+ include Baykit::BayServer::Util
15
+ include Baykit::BayServer::Agent::Transporter
16
+ include Baykit::BayServer::Tours
17
+
18
+ RACK_TERMINAL_PIPE = "rack.terminal.pipe"
19
+ DEFAULT_POST_CACHE_THRESHOLD = 1024 * 128 # 128 KB
20
+ RACK_ERR = "Cannot find rack package. If you want to use terminal docker, please install rack package like 'gem install rack'."
21
+
22
+ RACK_MULTITHREAD = 'rack.multithread'
23
+ RACK_MULTIPROCESS = 'rack.multiprocess'
24
+ RACK_RUNONCE = 'rack.run_once'
25
+ RACK_HIJACK_IO = 'rack.hijack_io'
26
+ HTTP_VERSION = 'HTTP_VERSION'
27
+
28
+ attr_accessor :app
29
+ attr :config
30
+ attr :environment
31
+ attr :post_cache_threshold
32
+ attr :available
33
+
34
+ def initialize
35
+ @post_cache_threshold = DEFAULT_POST_CACHE_THRESHOLD
36
+ @available = false
37
+ end
38
+
39
+ ######################################################
40
+ # Implements Docker
41
+ ######################################################
42
+
43
+ def init(elm, parent)
44
+ super
45
+
46
+ begin
47
+ require 'rack'
48
+ rescue LoadError => e
49
+ BayLog.error(RACK_ERR)
50
+ return
51
+ end
52
+
53
+ require 'rack/handler/bayserver'
54
+
55
+ if Rack::Handler::BayServer.app != nil
56
+ # rackup mode
57
+ @app = Rack::Handler::BayServer.app
58
+ else
59
+ if !StringUtil.set?(@config)
60
+ raise ConfigException.new(elm.file_name, elm.line_no, "Config not specified")
61
+ elsif not ::File.exist?(@config)
62
+ raise ConfigException.new(elm.file_name, elm.line_no, "Config not found: %s", @config)
63
+ end
64
+ if @environment == nil
65
+ @environment = "deployment"
66
+ end
67
+ options = {
68
+ :server => "terminal",
69
+ :config => @config,
70
+ :environment => @environment,
71
+ :docker => self,
72
+ }
73
+ Rack::Server.start options
74
+ end
75
+
76
+ @available = true
77
+ end
78
+
79
+ ######################################################
80
+ # Implements DockerBase
81
+ ######################################################
82
+
83
+ def init_key_val(kv)
84
+ case kv.key.downcase
85
+ when "config"
86
+ @config = Baykit::BayServer::BayServer.parse_path(kv.value)
87
+ when "environment"
88
+ @environment = kv.value
89
+ when "postcachethreshold"
90
+ @post_cache_threshold = kv.value.to_i
91
+ else
92
+ return super
93
+ end
94
+ return true
95
+ end
96
+
97
+ ######################################################
98
+ # Implements Club
99
+ ######################################################
100
+
101
+ def arrive(tur)
102
+
103
+ if not @available
104
+ tur.res.headers.set_content_type("text/plain")
105
+ tur.res.set_consume_listener(&ContentConsumeListener::DEV_NULL)
106
+ tur.res.send_headers(tur.id)
107
+ tur.res.send_content(tur.id, RACK_ERR, 0, RACK_ERR.length)
108
+ tur.res.end_content(tur.id)
109
+ return
110
+ end
111
+
112
+ if tur.req.uri.include? ".."
113
+ raise HttpException.new HttpStatus::FORBIDDEN, tur.req.uri
114
+ end
115
+
116
+ env = create_env tur
117
+ train = TerminalTrain.new(self, tur, @app, env)
118
+ train.start_tour()
119
+ end
120
+
121
+ def create_env(tur)
122
+ env = {}
123
+
124
+ cont_len = tur.req.headers.content_length()
125
+ if cont_len > 0
126
+ env["CONTENT_LENGTH"] = cont_len.to_s
127
+ end
128
+ cont_type = tur.req.headers.content_type()
129
+ if StringUtil.set? cont_type
130
+ env["CONTENT_TYPE"] = cont_type
131
+ end
132
+
133
+
134
+ env["GATEWAY_INTERFACE"] = "CGI/1.1"
135
+ #env[Rack::PATH_INFO] = tur.req.path_info == nil ? "" : tur.req.path_info
136
+ pos = tur.req.uri.index('?')
137
+ if pos and pos > 0
138
+ env[Rack::PATH_INFO] = tur.req.uri[0 .. pos-1]
139
+ else
140
+ env[Rack::PATH_INFO] = tur.req.uri
141
+ end
142
+ env[Rack::QUERY_STRING] = tur.req.query_string == nil ? "" : tur.req.query_string
143
+ env["REMOTE_ADDR"] = tur.req.remote_address
144
+ env["REMOTE_HOST"] = tur.req.remote_address # for performance reason
145
+ env["REMOTE_USER"] = tur.req.remote_user == nil ? "" : tur.req.remote_user
146
+ env[Rack::REQUEST_METHOD] = tur.req.method
147
+ env["REQUEST_URI"] = tur.req.uri
148
+ #env[Rack::SCRIPT_NAME] = tur.req.script_name == nil ? "" : tur.req.script_name
149
+ env[Rack::SCRIPT_NAME] = ""
150
+ env[Rack::SERVER_NAME] = tur.req.server_name
151
+ env[Rack::SERVER_PORT] = tur.req.server_port.to_s
152
+ env[Rack::SERVER_PROTOCOL] = tur.req.protocol
153
+ env["SERVER_SOFTWARE"] = Baykit::BayServer::BayServer.get_software_name
154
+
155
+ tur.req.headers.names.each do |name|
156
+ tur.req.headers.values(name).each do |val|
157
+ if /^content-type$/i =~ name || /^content-length$/i =~ name
158
+ next
159
+ end
160
+ name = "HTTP_" + name
161
+ name.gsub!(/-/o, "_")
162
+ name.upcase!
163
+ env[name] = val
164
+ end
165
+ end
166
+
167
+ env[Rack::RACK_VERSION] = Rack::VERSION
168
+ env[Rack::RACK_ERRORS] = STDERR
169
+ env[Rack::RACK_INPUT] = nil
170
+ env[RACK_MULTITHREAD] = true
171
+ env[RACK_MULTIPROCESS] = BayServer.harbor.multi_core?
172
+ env[RACK_RUNONCE] = false
173
+ env[Rack::RACK_URL_SCHEME] = tur.is_secure ? "https" : "http"
174
+ env[Rack::RACK_IS_HIJACK] = true
175
+
176
+ env[Rack::RACK_HIJACK] = lambda do
177
+ pip = IO.pipe
178
+ env[RACK_TERMINAL_PIPE] = pip
179
+
180
+ w_pipe = pip[1]
181
+
182
+ env[RACK_HIJACK_IO] = w_pipe
183
+
184
+ yat = FullyHijackersYacht.new()
185
+ bufsize = tur.ship.protocol_handler.max_res_packet_data_size()
186
+ tp = PlainTransporter.new(false, bufsize)
187
+
188
+ yat.init(tur, pip[0], tp)
189
+ tp.init(tur.ship.agent.non_blocking_handler, pip[0], yat)
190
+ tur.ship.resume(tur.ship_id)
191
+
192
+ w_pipe
193
+ end
194
+
195
+ env[RACK_HIJACK_IO] = nil
196
+
197
+ env[HTTP_VERSION] = tur.req.protocol
198
+ env
199
+ end
200
+ end
201
+ end
202
+ end
203
+ end
204
+ end
@@ -0,0 +1,209 @@
1
+ require 'baykit/bayserver/agent/transporter/plain_transporter'
2
+ require 'baykit/bayserver/train/train'
3
+ require 'baykit/bayserver/train/train_runner'
4
+ require 'baykit/bayserver/tours/tour'
5
+ require 'baykit/bayserver/tours/req_content_handler'
6
+
7
+ require 'baykit/bayserver/util/string_util'
8
+ require 'baykit/bayserver/util/http_status'
9
+
10
+ require 'baykit/bayserver/docker/terminal/hijackers_yacht'
11
+
12
+ module Baykit
13
+ module BayServer
14
+ module Docker
15
+ module Terminal
16
+ class TerminalTrain < Baykit::BayServer::Train::Train
17
+ include Baykit::BayServer::Tours::ReqContentHandler # implements
18
+
19
+ include Baykit::BayServer::Agent::Transporter
20
+ include Baykit::BayServer::Util
21
+ include Baykit::BayServer::Train
22
+ include Baykit::BayServer::Tours
23
+
24
+ attr :terminal_docker
25
+ attr :tour
26
+ attr :tour_id
27
+ attr :app
28
+ attr :env
29
+
30
+ attr :req_available
31
+ attr :lock
32
+ attr :tmpfile
33
+ attr :req_cont
34
+
35
+ def initialize(terminal_docker, tur, app, env)
36
+ BayLog.debug "%s New Rack Train", tur
37
+ @terminal_docker = terminal_docker
38
+ @tour = tur
39
+ @tour_id = tur.tour_id
40
+ @app = app
41
+ @env = env
42
+ @available = false
43
+ @tmpfile = nil
44
+ @req_cont = nil
45
+
46
+ @lock = Mutex.new
47
+ end
48
+
49
+ def start_tour()
50
+ @tour.req.set_content_handler(self)
51
+ @tmpfile = nil
52
+
53
+ if @env["CONTENT_LENGTH"]
54
+ req_cont_len = @env["CONTENT_LENGTH"].to_i
55
+ else
56
+ req_cont_len = 0
57
+ end
58
+
59
+ if req_cont_len <= @terminal_docker.post_cache_threshold
60
+ # Cache content in memory
61
+ @req_cont = StringUtil.alloc(0)
62
+ else
63
+ # Content save on disk
64
+ @tmpfile = Tempfile.new("terminal_upload")
65
+ @tmpfile.binmode
66
+ end
67
+
68
+ end
69
+
70
+ def depart
71
+
72
+ begin
73
+ if @tour.req.method.casecmp?("post")
74
+ BayLog.debug("%s Terminal: posted: content-length: %s", @tour, @env["CONTENT_LENGTH"])
75
+ end
76
+
77
+
78
+ if BayServer.harbor.trace_header?
79
+ @env.keys.each do |key|
80
+ value = @env[key]
81
+ BayLog.info("%s Terminal: env:%s=%s", @tour, key, value)
82
+ end
83
+ end
84
+
85
+ status, headers, body = @app.call(@env)
86
+
87
+ # Hijack check
88
+ pip = @env[TerminalDocker::RACK_TERMINAL_PIPE]
89
+
90
+ if pip != nil
91
+ # Fully hijacked (Do nothing)
92
+ BayLog.debug("%s Tour is fully hijacked", @tour)
93
+
94
+ else
95
+ @tour.res.headers.status = status
96
+
97
+ hijack = nil
98
+ headers.each do | key, value |
99
+ if key == Rack::RACK_HIJACK
100
+ hijack = value
101
+ else
102
+ @tour.res.headers.add key, value
103
+ end
104
+ end
105
+
106
+ # Send headers
107
+ @tour.res.send_headers @tour_id
108
+
109
+ if hijack != nil
110
+ # Partially hijacked
111
+ BayLog.debug("%s Tour is partially hijacked", @tour)
112
+
113
+ pip = IO.pipe
114
+ yat = HijackersYacht.new()
115
+ bufsize = @tour.ship.protocol_handler.max_res_packet_data_size()
116
+ tp = PlainTransporter.new(false, bufsize)
117
+
118
+ yat.init(@tour, pip[0], tp)
119
+ tp.init(@tour.ship.agent.non_blocking_handler, pip[0], yat)
120
+ @tour.ship.resume(@tour.ship_id)
121
+
122
+ hijack.call pip[1]
123
+
124
+ else
125
+ # Not hijacked
126
+
127
+ # Setup consume listener
128
+ @tour.res.set_consume_listener() do |len, resume|
129
+ if(resume)
130
+ @available = true
131
+ end
132
+ end
133
+
134
+ # Send contents
135
+ body.each do | str |
136
+ bstr = StringUtil.to_bytes(str)
137
+ BayLog.trace("%s TerminalTask: read body: len=%d", @tour, bstr.length)
138
+ @available = @tour.res.send_content(@tour_id, bstr, 0, bstr.length)
139
+ while !@available
140
+ sleep 0.1
141
+ end
142
+ end
143
+
144
+ @tour.res.end_content(@tour_id)
145
+
146
+ end
147
+ end
148
+ rescue HttpException => e
149
+ raise e
150
+ rescue => e
151
+ BayLog.error_e e
152
+ raise HttpException.new HttpStatus::INTERNAL_SERVER_ERROR, "Terminal error"
153
+ ensure
154
+ if @tmpfile
155
+ @tmpfile.close()
156
+ end
157
+ end
158
+ end
159
+
160
+ def on_read_content(tur, buf, start, len)
161
+ BayLog.trace("%s TerminalTask:onReadContent: len=%d", @tour, len)
162
+
163
+ if @req_cont != nil
164
+ # Cache content in memory
165
+ @req_cont << buf[start, len]
166
+ else
167
+ # Content save on disk
168
+ @tmpfile.write(buf[start, len])
169
+ end
170
+
171
+ tur.req.consumed(Tour::TOUR_ID_NOCHECK, len)
172
+ true
173
+ end
174
+
175
+ def on_end_content(tur)
176
+ BayLog.trace("%s TerminalTask:endContent", @tour)
177
+
178
+ if @req_cont != nil
179
+ # Cache content in memory
180
+ rack_input = StringIO.new(@req_cont)
181
+ else
182
+ # Content save on disk
183
+ @tmpfile.rewind()
184
+ rack_input = @tmpfile
185
+ end
186
+ env[Rack::RACK_INPUT] = rack_input
187
+
188
+ if !TrainRunner.post(self)
189
+ raise HttpException.new(HttpStatus::SERVICE_UNAVAILABLE, "TrainRunner is busy")
190
+ end
191
+ end
192
+
193
+ def on_abort(tur)
194
+ BayLog.trace("%s TerminalTask:abort", @tour)
195
+ if @tmpfile
196
+ @tmpfile.close()
197
+ @tmpfile = nil
198
+ end
199
+ return false
200
+ end
201
+
202
+ def inspect
203
+ "TerminalTask #{@tour}"
204
+ end
205
+ end
206
+ end
207
+ end
208
+ end
209
+ end
@@ -0,0 +1,66 @@
1
+ require 'rack/handler'
2
+ require 'baykit/bayserver/bayserver'
3
+ require 'baykit/bayserver/util/string_util'
4
+
5
+ module Rack
6
+ module Handler
7
+ module BayServer
8
+ include Baykit::BayServer::Util
9
+
10
+ class << self
11
+ attr :app
12
+ end
13
+ @app = nil
14
+
15
+ ENV_BSERV_HOME = Baykit::BayServer::BayServer::ENV_BSERV_HOME
16
+ ENV_BSERV_PLAN = Baykit::BayServer::BayServer::ENV_BSERV_PLAN
17
+
18
+ def self.run(app, **options)
19
+
20
+ @app = app
21
+
22
+ port = options[:Port]
23
+ host = options[:Host]
24
+ config = options[:config]
25
+ environment = options[:environment]
26
+ access_log = options[:AccessLog]
27
+
28
+ # Get bayserver home from environment
29
+ if StringUtil.set? ENV[ENV_BSERV_HOME]
30
+ bserv_home = ENV[ENV_BSERV_HOME]
31
+ else
32
+ raise "Set #{ENV_BSERV_HOME} environment variable"
33
+ end
34
+
35
+ # Get bayserver plan from evironment
36
+ if StringUtil.set? ENV[ENV_BSERV_PLAN]
37
+ bserv_plan = ENV[ENV_BSERV_PLAN]
38
+ else
39
+ bserv_plan = "/tmp/rack.plan"
40
+ plan_str = <<EOF
41
+ [harbor]
42
+ grandAgents 4
43
+
44
+ [port #{port}]
45
+ docker http
46
+
47
+ [city *]
48
+ [town /]
49
+ [club *]
50
+ docker terminal
51
+ EOF
52
+ ::File.write(bserv_plan, plan_str)
53
+ end
54
+
55
+ Baykit::BayServer::BayServer.init bserv_home, bserv_plan
56
+ Baykit::BayServer::BayServer.start
57
+ end
58
+
59
+ end
60
+
61
+
62
+
63
+
64
+ register :bayserver, BayServer
65
+ end
66
+ end
@@ -0,0 +1,17 @@
1
+ require 'rack/handler'
2
+
3
+
4
+ module Rack
5
+ module Handler
6
+ module Terminal
7
+
8
+ def self.run(app, **options)
9
+ dkr = options[:docker]
10
+ dkr.app = app
11
+ end
12
+ end
13
+
14
+ register :terminal, Terminal
15
+ end
16
+ end
17
+
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bayserver-docker-terminal
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Michisuke-P
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-08-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bayserver-core
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 2.2.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 2.2.0
27
+ description: AJP docker of BayServer
28
+ email: michisukep@gmail.com
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - lib/baykit/bayserver/docker/terminal/fully_hijackers_yacht.rb
34
+ - lib/baykit/bayserver/docker/terminal/hijacked_data_sender.rb
35
+ - lib/baykit/bayserver/docker/terminal/hijackers_yacht.rb
36
+ - lib/baykit/bayserver/docker/terminal/terminal_docker.rb
37
+ - lib/baykit/bayserver/docker/terminal/terminal_train.rb
38
+ - lib/rack/handler/bayserver.rb
39
+ - lib/rack/handler/terminal.rb
40
+ homepage: https://baykit.yokohama
41
+ licenses:
42
+ - MIT
43
+ metadata: {}
44
+ post_install_message:
45
+ rdoc_options: []
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ requirements: []
59
+ rubygems_version: 3.1.6
60
+ signing_key:
61
+ specification_version: 4
62
+ summary: AJP docker of BayServer
63
+ test_files: []