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 88 89 |
# File 'lib/rex/proto/http/web_socket.rb', line 46 def initialize(websocket, read_type: nil, write_type: :binary) # 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? }) initialize_abstraction lsock.initinfo(Rex::Socket.(peerhost, peerport), Rex::Socket.(localhost, localport)) @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
95 96 97 98 99 100 101 102 103 104 |
# File 'lib/rex/proto/http/web_socket.rb', line 95 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.
110 111 112 113 114 115 116 |
# File 'lib/rex/proto/http/web_socket.rb', line 110 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
91 92 93 |
# File 'lib/rex/proto/http/web_socket.rb', line 91 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.
151 152 153 |
# File 'lib/rex/proto/http/web_socket.rb', line 151 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.
161 162 163 |
# File 'lib/rex/proto/http/web_socket.rb', line 161 def on_data_write(data) data end |
#write(buf, length = nil) ⇒ Object
Write buf to the channel, optionally truncating it to length bytes.
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/rex/proto/http/web_socket.rb', line 124 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 |