Class: Rex::Proto::Http::WebSocket::Interface::Channel
- Inherits:
-
Object
- Object
- Rex::Proto::Http::WebSocket::Interface::Channel
- Includes:
- Rex::Post::Channel::StreamAbstraction
- Defined in:
- lib/rex/proto/http/web_socket.rb
Overview
A channel object that allows reading and writing either text or binary data directly to the remote peer.
Direct Known Subclasses
Msf::Exploit::Remote::HTTP::Kubernetes::Client::ExecChannel, AmazonSsm::Interface::SsmChannel
Defined Under Namespace
Modules: SocketInterface
Instance Attribute Summary collapse
-
#params ⇒ Object
readonly
The socket parameters describing the underlying connection.
Instance Method Summary collapse
- #close ⇒ Object
-
#close_write ⇒ Object
Close the channel for write operations.
- #closed? ⇒ Boolean
-
#initialize(websocket, read_type: nil, write_type: :binary) ⇒ Channel
constructor
A new instance of Channel.
-
#on_data_read(data, _data_type) ⇒ String?
This provides a hook point that is called when data is read from the WebSocket peer.
-
#on_data_write(data) ⇒ String?
This provides a hook point that is called when data is written to the WebSocket peer.
-
#write(buf, length = nil) ⇒ Object
Write buf to the channel, optionally truncating it to length bytes.
Methods included from Rex::Post::Channel::StreamAbstraction
Constructor Details
#initialize(websocket, read_type: nil, write_type: :binary) ⇒ Channel
Returns a new instance of Channel.
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/rex/proto/http/web_socket.rb', line 46 def initialize(websocket, read_type: nil, write_type: :binary) initialize_abstraction # a read type of nil will handle both binary and text frames that are received raise ArgumentError, 'read_type must be nil, :binary or :text' unless [nil, :binary, :text].include?(read_type) raise ArgumentError, 'write_type must be :binary or :text' unless %i[binary text].include?(write_type) @websocket = websocket @read_type = read_type @write_type = write_type @mutex = Mutex.new # beware of: https://github.com/rapid7/rex-socket/issues/32 _, localhost, localport = websocket.getlocalname _, peerhost, peerport = Rex::Socket.from_sockaddr(websocket.getpeername) @params = Rex::Socket::Parameters.from_hash({ 'LocalHost' => localhost, 'LocalPort' => localport, 'PeerHost' => peerhost, 'PeerPort' => peerport, 'SSL' => websocket.respond_to?(:sslctx) && !websocket.sslctx.nil? }) @thread = Rex::ThreadFactory.spawn("WebSocketChannel(#{localhost}->#{peerhost})", false) do websocket.wsloop do |data, data_type| next unless @read_type.nil? || data_type == @read_type data = on_data_read(data, data_type) next if data.nil? rsock.syswrite(data) end close end lsock.extend(SocketInterface) lsock.channel = self rsock.extend(SocketInterface) rsock.channel = self end |
Instance Attribute Details
#params ⇒ Object (readonly)
The socket parameters describing the underlying connection.
40 41 42 |
# File 'lib/rex/proto/http/web_socket.rb', line 40 def params @params end |
Instance Method Details
#close ⇒ Object
93 94 95 96 97 98 99 100 101 102 |
# File 'lib/rex/proto/http/web_socket.rb', line 93 def close @mutex.synchronize do return if closed? @websocket.wsclose @websocket = nil end cleanup_abstraction end |
#close_write ⇒ Object
Close the channel for write operations. This sends a CONNECTION_CLOSE request, after which (per RFC 6455 section 5.5.1) this side must not send any more data frames.
108 109 110 111 112 113 114 |
# File 'lib/rex/proto/http/web_socket.rb', line 108 def close_write if closed? raise IOError, 'Channel has been closed.', caller end @websocket.put_wsframe(Frame.new(header: { opcode: Opcode::CONNECTION_CLOSE })) end |
#closed? ⇒ Boolean
89 90 91 |
# File 'lib/rex/proto/http/web_socket.rb', line 89 def closed? @websocket.nil? end |
#on_data_read(data, _data_type) ⇒ String?
This provides a hook point that is called when data is read from the WebSocket peer. Subclasses can intercept and process the data. The default functionality does nothing.
149 150 151 |
# File 'lib/rex/proto/http/web_socket.rb', line 149 def on_data_read(data, _data_type) data end |
#on_data_write(data) ⇒ String?
This provides a hook point that is called when data is written to the WebSocket peer. Subclasses can intercept and process the data. The default functionality does nothing.
159 160 161 |
# File 'lib/rex/proto/http/web_socket.rb', line 159 def on_data_write(data) data end |
#write(buf, length = nil) ⇒ Object
Write buf to the channel, optionally truncating it to length bytes.
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/rex/proto/http/web_socket.rb', line 122 def write(buf, length = nil) if closed? raise IOError, 'Channel has been closed.', caller end if !length.nil? && buf.length >= length buf = buf[0..length] end length = buf.length buf = on_data_write(buf) if @write_type == :binary @websocket.put_wsbinary(buf) elsif @write_type == :text @websocket.put_wstext(buf) end length end |