Files
metasploit-gs/api/Rex/Proto/Http/WebSocket/Interface.html
T
jenkins-metasploit c3f5bd3de2 Reboot gh-pages
2026-05-08 17:08:43 +00:00

923 lines
39 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>
Module: Rex::Proto::Http::WebSocket::Interface
&mdash; Documentation by YARD 0.9.37
</title>
<link rel="stylesheet" href="../../../../css/style.css" type="text/css" />
<link rel="stylesheet" href="../../../../css/common.css" type="text/css" />
<script type="text/javascript">
pathId = "Rex::Proto::Http::WebSocket::Interface";
relpath = '../../../../';
</script>
<script type="text/javascript" charset="utf-8" src="../../../../js/jquery.js"></script>
<script type="text/javascript" charset="utf-8" src="../../../../js/app.js"></script>
</head>
<body>
<div class="nav_wrap">
<iframe id="nav" src="../../../../class_list.html?1"></iframe>
<div id="resizer"></div>
</div>
<div id="main" tabindex="-1">
<div id="header">
<div id="menu">
<a href="../../../../_index.html">Index (I)</a> &raquo;
<span class='title'><span class='object_link'><a href="../../../../Rex.html" title="Rex (module)">Rex</a></span></span> &raquo; <span class='title'><span class='object_link'><a href="../../../Proto.html" title="Rex::Proto (module)">Proto</a></span></span> &raquo; <span class='title'><span class='object_link'><a href="../../Http.html" title="Rex::Proto::Http (module)">Http</a></span></span> &raquo; <span class='title'><span class='object_link'><a href="../WebSocket.html" title="Rex::Proto::Http::WebSocket (module)">WebSocket</a></span></span>
&raquo;
<span class="title">Interface</span>
</div>
<div id="search">
<a class="full_list_link" id="class_list_link"
href="../../../../class_list.html">
<svg width="24" height="24">
<rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
<rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
<rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
</svg>
</a>
</div>
<div class="clear"></div>
</div>
<div id="content"><h1>Module: Rex::Proto::Http::WebSocket::Interface
</h1>
<div class="box_info">
<dl>
<dt>Defined in:</dt>
<dd>lib/rex/proto/http/web_socket.rb</dd>
</dl>
</div>
<h2>Overview</h2><div class="docstring">
<div class="discussion">
<p>This defines the interface that the standard socket is extended with to provide WebSocket functionality. It should be used on a socket when the server has already successfully handled a WebSocket upgrade request.</p>
</div>
</div>
<div class="tags">
</div><h2>Defined Under Namespace</h2>
<p class="children">
<strong class="classes">Classes:</strong> <span class='object_link'><a href="Interface/Channel.html" title="Rex::Proto::Http::WebSocket::Interface::Channel (class)">Channel</a></span>
</p>
<h2>
Instance Method Summary
<small><a href="#" class="summary_toggle">collapse</a></small>
</h2>
<ul class="summary">
<li class="public ">
<span class="summary_signature">
<a href="#close-instance_method" title="#close (instance method)">#<strong>close</strong> &#x21d2; Object </a>
</span>
<span class="summary_desc"><div class='inline'></div></span>
</li>
<li class="public ">
<span class="summary_signature">
<a href="#get_wsframe-instance_method" title="#get_wsframe (instance method)">#<strong>get_wsframe</strong>(_opts = {}) &#x21d2; Nil, WebSocket::Frame </a>
</span>
<span class="summary_desc"><div class='inline'>
<p>Read a WebSocket::Frame from the peer.</p>
</div></span>
</li>
<li class="public ">
<span class="summary_signature">
<a href="#put_wsbinary-instance_method" title="#put_wsbinary (instance method)">#<strong>put_wsbinary</strong>(value, opts = {}) &#x21d2; Object </a>
</span>
<span class="summary_desc"><div class='inline'>
<p>Build a WebSocket::Frame representing the binary data and send it to the peer.</p>
</div></span>
</li>
<li class="public ">
<span class="summary_signature">
<a href="#put_wsframe-instance_method" title="#put_wsframe (instance method)">#<strong>put_wsframe</strong>(frame, opts = {}) &#x21d2; Object </a>
</span>
<span class="summary_desc"><div class='inline'>
<p>Send a WebSocket::Frame to the peer.</p>
</div></span>
</li>
<li class="public ">
<span class="summary_signature">
<a href="#put_wstext-instance_method" title="#put_wstext (instance method)">#<strong>put_wstext</strong>(value, opts = {}) &#x21d2; Object </a>
</span>
<span class="summary_desc"><div class='inline'>
<p>Build a WebSocket::Frame representing the text data and send it to the peer.</p>
</div></span>
</li>
<li class="public ">
<span class="summary_signature">
<a href="#to_wschannel-instance_method" title="#to_wschannel (instance method)">#<strong>to_wschannel</strong>(**kwargs) &#x21d2; WebSocket::Interface::Channel </a>
</span>
<span class="summary_desc"><div class='inline'>
<p>Build a channel to allow reading and writing from the WebSocket.</p>
</div></span>
</li>
<li class="public ">
<span class="summary_signature">
<a href="#wsclose-instance_method" title="#wsclose (instance method)">#<strong>wsclose</strong>(opts = {}) &#x21d2; Object </a>
</span>
<span class="summary_desc"><div class='inline'>
<p>Close the WebSocket.</p>
</div></span>
</li>
<li class="public ">
<span class="summary_signature">
<a href="#wsloop-instance_method" title="#wsloop (instance method)">#<strong>wsloop</strong>(opts = {}, &amp;block) &#x21d2; Object </a>
</span>
<span class="summary_desc"><div class='inline'>
<p>Run a loop to handle data from the remote end of the websocket.</p>
</div></span>
</li>
</ul>
<div id="instance_method_details" class="method_details_list">
<h2>Instance Method Details</h2>
<div class="method_details first">
<h3 class="signature first" id="close-instance_method">
#<strong>close</strong> &#x21d2; <tt>Object</tt>
</h3><table class="source_code">
<tr>
<td>
<pre class="lines">
309
310
311
312
313
314
315
316
317</pre>
</td>
<td>
<pre class="code"><span class="info file"># File 'lib/rex/proto/http/web_socket.rb', line 309</span>
<span class='kw'>def</span> <span class='id identifier rubyid_close'>close</span>
<span class='comment'># if #wsloop was ever called, a synchronization lock will have been initialized
</span> <span class='ivar'>@wsstream_lock</span><span class='period'>.</span><span class='id identifier rubyid_lock_write'>lock_write</span> <span class='kw'>unless</span> <span class='ivar'>@wsstream_lock</span><span class='period'>.</span><span class='id identifier rubyid_nil?'>nil?</span>
<span class='kw'>begin</span>
<span class='kw'>super</span>
<span class='kw'>ensure</span>
<span class='ivar'>@wsstream_lock</span><span class='period'>.</span><span class='id identifier rubyid_unlock_write'>unlock_write</span> <span class='kw'>unless</span> <span class='ivar'>@wsstream_lock</span><span class='period'>.</span><span class='id identifier rubyid_nil?'>nil?</span>
<span class='kw'>end</span>
<span class='kw'>end</span></pre>
</td>
</tr>
</table>
</div>
<div class="method_details ">
<h3 class="signature " id="get_wsframe-instance_method">
#<strong>get_wsframe</strong>(_opts = {}) &#x21d2; <tt>Nil</tt>, <tt><span class='object_link'><a href="Frame.html" title="Rex::Proto::Http::WebSocket::Frame (class)">WebSocket::Frame</a></span></tt>
</h3><div class="docstring">
<div class="discussion">
<p>Read a WebSocket::Frame from the peer.</p>
</div>
</div>
<div class="tags">
<p class="tag_title">Returns:</p>
<ul class="return">
<li>
<span class='type'>(<tt>Nil</tt>, <tt><span class='object_link'><a href="Frame.html" title="Rex::Proto::Http::WebSocket::Frame (class)">WebSocket::Frame</a></span></tt>)</span>
&mdash;
<div class='inline'>
<p>the frame that was received from the peer.</p>
</div>
</li>
</ul>
</div><table class="source_code">
<tr>
<td>
<pre class="lines">
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212</pre>
</td>
<td>
<pre class="code"><span class="info file"># File 'lib/rex/proto/http/web_socket.rb', line 194</span>
<span class='kw'>def</span> <span class='id identifier rubyid_get_wsframe'>get_wsframe</span><span class='lparen'>(</span><span class='id identifier rubyid__opts'>_opts</span> <span class='op'>=</span> <span class='lbrace'>{</span><span class='rbrace'>}</span><span class='rparen'>)</span>
<span class='id identifier rubyid_frame'>frame</span> <span class='op'>=</span> <span class='const'><span class='object_link'><a href="Frame.html" title="Rex::Proto::Http::WebSocket::Frame (class)">Frame</a></span></span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span>
<span class='id identifier rubyid_frame'>frame</span><span class='period'>.</span><span class='id identifier rubyid_header'>header</span><span class='period'>.</span><span class='id identifier rubyid_read'>read</span><span class='lparen'>(</span><span class='kw'>self</span><span class='rparen'>)</span>
<span class='id identifier rubyid_payload_data'>payload_data</span> <span class='op'>=</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_end'>&#39;</span></span>
<span class='kw'>while</span> <span class='id identifier rubyid_payload_data'>payload_data</span><span class='period'>.</span><span class='id identifier rubyid_length'>length</span> <span class='op'>&lt;</span> <span class='id identifier rubyid_frame'>frame</span><span class='period'>.</span><span class='id identifier rubyid_payload_len'>payload_len</span>
<span class='id identifier rubyid_chunk'>chunk</span> <span class='op'>=</span> <span class='id identifier rubyid_read'>read</span><span class='lparen'>(</span><span class='id identifier rubyid_frame'>frame</span><span class='period'>.</span><span class='id identifier rubyid_payload_len'>payload_len</span> <span class='op'>-</span> <span class='id identifier rubyid_payload_data'>payload_data</span><span class='period'>.</span><span class='id identifier rubyid_length'>length</span><span class='rparen'>)</span>
<span class='kw'>if</span> <span class='id identifier rubyid_chunk'>chunk</span><span class='period'>.</span><span class='id identifier rubyid_empty?'>empty?</span> <span class='comment'># no partial reads!
</span> <span class='id identifier rubyid_elog'><span class='object_link'><a href="../../../../top-level-namespace.html#elog-instance_method" title="#elog (method)">elog</a></span></span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>WebSocket::Interface#get_wsframe: received an empty websocket payload data chunk</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
<span class='kw'>return</span> <span class='kw'>nil</span>
<span class='kw'>end</span>
<span class='id identifier rubyid_payload_data'>payload_data</span> <span class='op'>&lt;&lt;</span> <span class='id identifier rubyid_chunk'>chunk</span>
<span class='kw'>end</span>
<span class='id identifier rubyid_frame'>frame</span><span class='period'>.</span><span class='id identifier rubyid_payload_data'>payload_data</span><span class='period'>.</span><span class='id identifier rubyid_assign'>assign</span><span class='lparen'>(</span><span class='id identifier rubyid_payload_data'>payload_data</span><span class='rparen'>)</span>
<span class='id identifier rubyid_frame'>frame</span>
<span class='kw'>rescue</span> <span class='op'>::</span><span class='const'>IOError</span>
<span class='id identifier rubyid_wlog'><span class='object_link'><a href="../../../../top-level-namespace.html#wlog-instance_method" title="#wlog (method)">wlog</a></span></span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>WebSocket::Interface#get_wsframe: encountered an IOError while reading a websocket frame</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
<span class='kw'>nil</span>
<span class='kw'>end</span></pre>
</td>
</tr>
</table>
</div>
<div class="method_details ">
<h3 class="signature " id="put_wsbinary-instance_method">
#<strong>put_wsbinary</strong>(value, opts = {}) &#x21d2; <tt>Object</tt>
</h3><div class="docstring">
<div class="discussion">
<p>Build a WebSocket::Frame representing the binary data and send it to the peer.</p>
</div>
</div>
<div class="tags">
<p class="tag_title">Parameters:</p>
<ul class="param">
<li>
<span class='name'>value</span>
<span class='type'>(<tt>String</tt>)</span>
&mdash;
<div class='inline'>
<p>the binary value to use as the frame payload.</p>
</div>
</li>
</ul>
</div><table class="source_code">
<tr>
<td>
<pre class="lines">
178
179
180</pre>
</td>
<td>
<pre class="code"><span class="info file"># File 'lib/rex/proto/http/web_socket.rb', line 178</span>
<span class='kw'>def</span> <span class='id identifier rubyid_put_wsbinary'>put_wsbinary</span><span class='lparen'>(</span><span class='id identifier rubyid_value'>value</span><span class='comma'>,</span> <span class='id identifier rubyid_opts'>opts</span> <span class='op'>=</span> <span class='lbrace'>{</span><span class='rbrace'>}</span><span class='rparen'>)</span>
<span class='id identifier rubyid_put_wsframe'>put_wsframe</span><span class='lparen'>(</span><span class='const'><span class='object_link'><a href="Frame.html" title="Rex::Proto::Http::WebSocket::Frame (class)">Frame</a></span></span><span class='period'>.</span><span class='id identifier rubyid_from_binary'><span class='object_link'><a href="Frame.html#from_binary-class_method" title="Rex::Proto::Http::WebSocket::Frame.from_binary (method)">from_binary</a></span></span><span class='lparen'>(</span><span class='id identifier rubyid_value'>value</span><span class='rparen'>)</span><span class='comma'>,</span> <span class='id identifier rubyid_opts'>opts</span> <span class='op'>=</span> <span class='id identifier rubyid_opts'>opts</span><span class='rparen'>)</span>
<span class='kw'>end</span></pre>
</td>
</tr>
</table>
</div>
<div class="method_details ">
<h3 class="signature " id="put_wsframe-instance_method">
#<strong>put_wsframe</strong>(frame, opts = {}) &#x21d2; <tt>Object</tt>
</h3><div class="docstring">
<div class="discussion">
<p>Send a WebSocket::Frame to the peer.</p>
</div>
</div>
<div class="tags">
<p class="tag_title">Parameters:</p>
<ul class="param">
<li>
<span class='name'>frame</span>
<span class='type'>(<tt><span class='object_link'><a href="Frame.html" title="Rex::Proto::Http::WebSocket::Frame (class)">WebSocket::Frame</a></span></tt>)</span>
&mdash;
<div class='inline'>
<p>the frame to send to the peer.</p>
</div>
</li>
</ul>
</div><table class="source_code">
<tr>
<td>
<pre class="lines">
170
171
172</pre>
</td>
<td>
<pre class="code"><span class="info file"># File 'lib/rex/proto/http/web_socket.rb', line 170</span>
<span class='kw'>def</span> <span class='id identifier rubyid_put_wsframe'>put_wsframe</span><span class='lparen'>(</span><span class='id identifier rubyid_frame'>frame</span><span class='comma'>,</span> <span class='id identifier rubyid_opts'>opts</span> <span class='op'>=</span> <span class='lbrace'>{</span><span class='rbrace'>}</span><span class='rparen'>)</span>
<span class='id identifier rubyid_put'>put</span><span class='lparen'>(</span><span class='id identifier rubyid_frame'>frame</span><span class='period'>.</span><span class='id identifier rubyid_to_binary_s'>to_binary_s</span><span class='comma'>,</span> <span class='id identifier rubyid_opts'>opts</span> <span class='op'>=</span> <span class='id identifier rubyid_opts'>opts</span><span class='rparen'>)</span>
<span class='kw'>end</span></pre>
</td>
</tr>
</table>
</div>
<div class="method_details ">
<h3 class="signature " id="put_wstext-instance_method">
#<strong>put_wstext</strong>(value, opts = {}) &#x21d2; <tt>Object</tt>
</h3><div class="docstring">
<div class="discussion">
<p>Build a WebSocket::Frame representing the text data and send it to the peer.</p>
</div>
</div>
<div class="tags">
<p class="tag_title">Parameters:</p>
<ul class="param">
<li>
<span class='name'>value</span>
<span class='type'>(<tt>String</tt>)</span>
&mdash;
<div class='inline'>
<p>the binary value to use as the frame payload.</p>
</div>
</li>
</ul>
</div><table class="source_code">
<tr>
<td>
<pre class="lines">
186
187
188</pre>
</td>
<td>
<pre class="code"><span class="info file"># File 'lib/rex/proto/http/web_socket.rb', line 186</span>
<span class='kw'>def</span> <span class='id identifier rubyid_put_wstext'>put_wstext</span><span class='lparen'>(</span><span class='id identifier rubyid_value'>value</span><span class='comma'>,</span> <span class='id identifier rubyid_opts'>opts</span> <span class='op'>=</span> <span class='lbrace'>{</span><span class='rbrace'>}</span><span class='rparen'>)</span>
<span class='id identifier rubyid_put_wsframe'>put_wsframe</span><span class='lparen'>(</span><span class='const'><span class='object_link'><a href="Frame.html" title="Rex::Proto::Http::WebSocket::Frame (class)">Frame</a></span></span><span class='period'>.</span><span class='id identifier rubyid_from_text'><span class='object_link'><a href="Frame.html#from_text-class_method" title="Rex::Proto::Http::WebSocket::Frame.from_text (method)">from_text</a></span></span><span class='lparen'>(</span><span class='id identifier rubyid_value'>value</span><span class='rparen'>)</span><span class='comma'>,</span> <span class='id identifier rubyid_opts'>opts</span> <span class='op'>=</span> <span class='id identifier rubyid_opts'>opts</span><span class='rparen'>)</span>
<span class='kw'>end</span></pre>
</td>
</tr>
</table>
</div>
<div class="method_details ">
<h3 class="signature " id="to_wschannel-instance_method">
#<strong>to_wschannel</strong>(**kwargs) &#x21d2; <tt><span class='object_link'><a href="Interface/Channel.html" title="Rex::Proto::Http::WebSocket::Interface::Channel (class)">WebSocket::Interface::Channel</a></span></tt>
</h3><div class="docstring">
<div class="discussion">
<p>Build a channel to allow reading and writing from the WebSocket. This provides high level functionality so the caller neednt worry about individual frames.</p>
</div>
</div>
<div class="tags">
<p class="tag_title">Returns:</p>
<ul class="return">
<li>
<span class='type'>(<tt><span class='object_link'><a href="Interface/Channel.html" title="Rex::Proto::Http::WebSocket::Interface::Channel (class)">WebSocket::Interface::Channel</a></span></tt>)</span>
</li>
</ul>
</div><table class="source_code">
<tr>
<td>
<pre class="lines">
219
220
221</pre>
</td>
<td>
<pre class="code"><span class="info file"># File 'lib/rex/proto/http/web_socket.rb', line 219</span>
<span class='kw'>def</span> <span class='id identifier rubyid_to_wschannel'>to_wschannel</span><span class='lparen'>(</span><span class='op'>**</span><span class='id identifier rubyid_kwargs'>kwargs</span><span class='rparen'>)</span>
<span class='const'><span class='object_link'><a href="Interface/Channel.html" title="Rex::Proto::Http::WebSocket::Interface::Channel (class)">Channel</a></span></span><span class='period'>.</span><span class='id identifier rubyid_new'><span class='object_link'><a href="Interface/Channel.html#initialize-instance_method" title="Rex::Proto::Http::WebSocket::Interface::Channel#initialize (method)">new</a></span></span><span class='lparen'>(</span><span class='kw'>self</span><span class='comma'>,</span> <span class='op'>**</span><span class='id identifier rubyid_kwargs'>kwargs</span><span class='rparen'>)</span>
<span class='kw'>end</span></pre>
</td>
</tr>
</table>
</div>
<div class="method_details ">
<h3 class="signature " id="wsclose-instance_method">
#<strong>wsclose</strong>(opts = {}) &#x21d2; <tt>Object</tt>
</h3><div class="docstring">
<div class="discussion">
<p>Close the WebSocket. If the underlying TCP socket is still active a WebSocket CONNECTION_CLOSE request will be sent and then it will wait for a CONNECTION_CLOSE response. Once completed the underlying TCP socket will be closed.</p>
</div>
</div>
<div class="tags">
</div><table class="source_code">
<tr>
<td>
<pre class="lines">
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243</pre>
</td>
<td>
<pre class="code"><span class="info file"># File 'lib/rex/proto/http/web_socket.rb', line 227</span>
<span class='kw'>def</span> <span class='id identifier rubyid_wsclose'>wsclose</span><span class='lparen'>(</span><span class='id identifier rubyid_opts'>opts</span> <span class='op'>=</span> <span class='lbrace'>{</span><span class='rbrace'>}</span><span class='rparen'>)</span>
<span class='kw'>return</span> <span class='kw'>if</span> <span class='id identifier rubyid_closed?'>closed?</span> <span class='comment'># there&#39;s nothing to do if the underlying TCP socket has already been closed
</span>
<span class='comment'># this implementation doesn&#39;t handle the optional close reasons at all
</span> <span class='id identifier rubyid_frame'>frame</span> <span class='op'>=</span> <span class='const'><span class='object_link'><a href="Frame.html" title="Rex::Proto::Http::WebSocket::Frame (class)">Frame</a></span></span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span><span class='lparen'>(</span><span class='label'>header:</span> <span class='lbrace'>{</span> <span class='label'>opcode:</span> <span class='const'><span class='object_link'><a href="Opcode.html" title="Rex::Proto::Http::WebSocket::Opcode (class)">Opcode</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="Opcode.html#CONNECTION_CLOSE-constant" title="Rex::Proto::Http::WebSocket::Opcode::CONNECTION_CLOSE (constant)">CONNECTION_CLOSE</a></span></span> <span class='rbrace'>}</span><span class='rparen'>)</span>
<span class='comment'># close frames must be masked
</span> <span class='comment'># see: https://datatracker.ietf.org/doc/html/rfc6455#section-5.5.1
</span> <span class='id identifier rubyid_frame'>frame</span><span class='period'>.</span><span class='id identifier rubyid_mask!'>mask!</span>
<span class='id identifier rubyid_put_wsframe'>put_wsframe</span><span class='lparen'>(</span><span class='id identifier rubyid_frame'>frame</span><span class='comma'>,</span> <span class='id identifier rubyid_opts'>opts</span> <span class='op'>=</span> <span class='id identifier rubyid_opts'>opts</span><span class='rparen'>)</span>
<span class='kw'>while</span> <span class='lparen'>(</span><span class='id identifier rubyid_frame'>frame</span> <span class='op'>=</span> <span class='id identifier rubyid_get_wsframe'>get_wsframe</span><span class='lparen'>(</span><span class='id identifier rubyid_opts'>opts</span><span class='rparen'>)</span><span class='rparen'>)</span>
<span class='kw'>break</span> <span class='kw'>if</span> <span class='id identifier rubyid_frame'>frame</span><span class='period'>.</span><span class='id identifier rubyid_nil?'>nil?</span>
<span class='kw'>break</span> <span class='kw'>if</span> <span class='id identifier rubyid_frame'>frame</span><span class='period'>.</span><span class='id identifier rubyid_header'>header</span><span class='period'>.</span><span class='id identifier rubyid_opcode'>opcode</span> <span class='op'>==</span> <span class='const'><span class='object_link'><a href="Opcode.html" title="Rex::Proto::Http::WebSocket::Opcode (class)">Opcode</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="Opcode.html#CONNECTION_CLOSE-constant" title="Rex::Proto::Http::WebSocket::Opcode::CONNECTION_CLOSE (constant)">CONNECTION_CLOSE</a></span></span>
<span class='comment'># all other frames are dropped after our connection close request is sent
</span> <span class='kw'>end</span>
<span class='id identifier rubyid_close'>close</span> <span class='comment'># close the underlying TCP socket
</span><span class='kw'>end</span></pre>
</td>
</tr>
</table>
</div>
<div class="method_details ">
<h3 class="signature " id="wsloop-instance_method">
#<strong>wsloop</strong>(opts = {}, &amp;block) &#x21d2; <tt>Object</tt>
</h3><div class="docstring">
<div class="discussion">
<p>Run a loop to handle data from the remote end of the websocket. The loop will automatically handle fragmentation unmasking payload data and ping requests. When the remote connection is closed, the loop will exit. If specified the block will be passed data chunks and their data types.</p>
</div>
</div>
<div class="tags">
</div><table class="source_code">
<tr>
<td>
<pre class="lines">
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307</pre>
</td>
<td>
<pre class="code"><span class="info file"># File 'lib/rex/proto/http/web_socket.rb', line 250</span>
<span class='kw'>def</span> <span class='id identifier rubyid_wsloop'>wsloop</span><span class='lparen'>(</span><span class='id identifier rubyid_opts'>opts</span> <span class='op'>=</span> <span class='lbrace'>{</span><span class='rbrace'>}</span><span class='comma'>,</span> <span class='op'>&amp;</span><span class='id identifier rubyid_block'>block</span><span class='rparen'>)</span>
<span class='id identifier rubyid_buffer'>buffer</span> <span class='op'>=</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_end'>&#39;</span></span>
<span class='id identifier rubyid_buffer_type'>buffer_type</span> <span class='op'>=</span> <span class='kw'>nil</span>
<span class='comment'># since web sockets have their own tear down exchange, use a synchronization lock to ensure we aren&#39;t closed until
</span> <span class='comment'># either the remote socket is closed or the teardown takes place
</span> <span class='ivar'>@wsstream_lock</span> <span class='op'>=</span> <span class='const'><span class='object_link'><a href="../../../../Rex.html" title="Rex (module)">Rex</a></span></span><span class='op'>::</span><span class='const'>ReadWriteLock</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span>
<span class='ivar'>@wsstream_lock</span><span class='period'>.</span><span class='id identifier rubyid_synchronize_read'>synchronize_read</span> <span class='kw'>do</span>
<span class='kw'>while</span> <span class='lparen'>(</span><span class='id identifier rubyid_frame'>frame</span> <span class='op'>=</span> <span class='id identifier rubyid_get_wsframe'>get_wsframe</span><span class='lparen'>(</span><span class='id identifier rubyid_opts'>opts</span><span class='rparen'>)</span><span class='rparen'>)</span>
<span class='id identifier rubyid_frame'>frame</span><span class='period'>.</span><span class='id identifier rubyid_unmask!'>unmask!</span> <span class='kw'>if</span> <span class='id identifier rubyid_frame'>frame</span><span class='period'>.</span><span class='id identifier rubyid_header'>header</span><span class='period'>.</span><span class='id identifier rubyid_masked'>masked</span> <span class='op'>==</span> <span class='int'>1</span>
<span class='kw'>case</span> <span class='id identifier rubyid_frame'>frame</span><span class='period'>.</span><span class='id identifier rubyid_header'>header</span><span class='period'>.</span><span class='id identifier rubyid_opcode'>opcode</span>
<span class='kw'>when</span> <span class='const'><span class='object_link'><a href="Opcode.html" title="Rex::Proto::Http::WebSocket::Opcode (class)">Opcode</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="Opcode.html#CONNECTION_CLOSE-constant" title="Rex::Proto::Http::WebSocket::Opcode::CONNECTION_CLOSE (constant)">CONNECTION_CLOSE</a></span></span>
<span class='id identifier rubyid_put_wsframe'>put_wsframe</span><span class='lparen'>(</span><span class='const'><span class='object_link'><a href="Frame.html" title="Rex::Proto::Http::WebSocket::Frame (class)">Frame</a></span></span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span><span class='lparen'>(</span><span class='label'>header:</span> <span class='lbrace'>{</span> <span class='label'>opcode:</span> <span class='const'><span class='object_link'><a href="Opcode.html" title="Rex::Proto::Http::WebSocket::Opcode (class)">Opcode</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="Opcode.html#CONNECTION_CLOSE-constant" title="Rex::Proto::Http::WebSocket::Opcode::CONNECTION_CLOSE (constant)">CONNECTION_CLOSE</a></span></span> <span class='rbrace'>}</span><span class='rparen'>)</span><span class='period'>.</span><span class='id identifier rubyid_tap'>tap</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_f'>f</span><span class='op'>|</span> <span class='id identifier rubyid_f'>f</span><span class='period'>.</span><span class='id identifier rubyid_mask!'>mask!</span> <span class='rbrace'>}</span><span class='comma'>,</span> <span class='id identifier rubyid_opts'>opts</span> <span class='op'>=</span> <span class='id identifier rubyid_opts'>opts</span><span class='rparen'>)</span>
<span class='kw'>break</span>
<span class='kw'>when</span> <span class='const'><span class='object_link'><a href="Opcode.html" title="Rex::Proto::Http::WebSocket::Opcode (class)">Opcode</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="Opcode.html#CONTINUATION-constant" title="Rex::Proto::Http::WebSocket::Opcode::CONTINUATION (constant)">CONTINUATION</a></span></span>
<span class='comment'># a continuation frame can only be sent for a data frames
</span> <span class='comment'># see: https://datatracker.ietf.org/doc/html/rfc6455#section-5.4
</span> <span class='id identifier rubyid_raise'>raise</span> <span class='const'><span class='object_link'><a href="WebSocketError.html" title="Rex::Proto::Http::WebSocket::WebSocketError (class)">WebSocketError</a></span></span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>Received an unexpected continuation frame (uninitialized buffer)</span><span class='tstring_end'>&#39;</span></span> <span class='kw'>if</span> <span class='id identifier rubyid_buffer_type'>buffer_type</span><span class='period'>.</span><span class='id identifier rubyid_nil?'>nil?</span>
<span class='id identifier rubyid_buffer'>buffer</span> <span class='op'>&lt;&lt;</span> <span class='id identifier rubyid_frame'>frame</span><span class='period'>.</span><span class='id identifier rubyid_payload_data'>payload_data</span>
<span class='kw'>when</span> <span class='const'><span class='object_link'><a href="Opcode.html" title="Rex::Proto::Http::WebSocket::Opcode (class)">Opcode</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="Opcode.html#BINARY-constant" title="Rex::Proto::Http::WebSocket::Opcode::BINARY (constant)">BINARY</a></span></span>
<span class='id identifier rubyid_raise'>raise</span> <span class='const'><span class='object_link'><a href="WebSocketError.html" title="Rex::Proto::Http::WebSocket::WebSocketError (class)">WebSocketError</a></span></span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>Received an unexpected binary frame (incomplete buffer)</span><span class='tstring_end'>&#39;</span></span> <span class='kw'>unless</span> <span class='id identifier rubyid_buffer_type'>buffer_type</span><span class='period'>.</span><span class='id identifier rubyid_nil?'>nil?</span>
<span class='id identifier rubyid_buffer'>buffer</span> <span class='op'>=</span> <span class='id identifier rubyid_frame'>frame</span><span class='period'>.</span><span class='id identifier rubyid_payload_data'>payload_data</span>
<span class='id identifier rubyid_buffer_type'>buffer_type</span> <span class='op'>=</span> <span class='symbol'>:binary</span>
<span class='kw'>when</span> <span class='const'><span class='object_link'><a href="Opcode.html" title="Rex::Proto::Http::WebSocket::Opcode (class)">Opcode</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="Opcode.html#TEXT-constant" title="Rex::Proto::Http::WebSocket::Opcode::TEXT (constant)">TEXT</a></span></span>
<span class='id identifier rubyid_raise'>raise</span> <span class='const'><span class='object_link'><a href="WebSocketError.html" title="Rex::Proto::Http::WebSocket::WebSocketError (class)">WebSocketError</a></span></span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>Received an unexpected text frame (incomplete buffer)</span><span class='tstring_end'>&#39;</span></span> <span class='kw'>unless</span> <span class='id identifier rubyid_buffer_type'>buffer_type</span><span class='period'>.</span><span class='id identifier rubyid_nil?'>nil?</span>
<span class='id identifier rubyid_buffer'>buffer</span> <span class='op'>=</span> <span class='id identifier rubyid_frame'>frame</span><span class='period'>.</span><span class='id identifier rubyid_payload_data'>payload_data</span>
<span class='id identifier rubyid_buffer_type'>buffer_type</span> <span class='op'>=</span> <span class='symbol'>:text</span>
<span class='kw'>when</span> <span class='const'><span class='object_link'><a href="Opcode.html" title="Rex::Proto::Http::WebSocket::Opcode (class)">Opcode</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="Opcode.html#PING-constant" title="Rex::Proto::Http::WebSocket::Opcode::PING (constant)">PING</a></span></span>
<span class='comment'># see: https://datatracker.ietf.org/doc/html/rfc6455#section-5.5.2
</span> <span class='id identifier rubyid_put_wsframe'>put_wsframe</span><span class='lparen'>(</span><span class='id identifier rubyid_frame'>frame</span><span class='period'>.</span><span class='id identifier rubyid_dup'>dup</span><span class='period'>.</span><span class='id identifier rubyid_tap'>tap</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_f'>f</span><span class='op'>|</span> <span class='id identifier rubyid_f'>f</span><span class='period'>.</span><span class='id identifier rubyid_header'>header</span><span class='period'>.</span><span class='id identifier rubyid_opcode'>opcode</span> <span class='op'>=</span> <span class='const'><span class='object_link'><a href="Opcode.html" title="Rex::Proto::Http::WebSocket::Opcode (class)">Opcode</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="Opcode.html#PONG-constant" title="Rex::Proto::Http::WebSocket::Opcode::PONG (constant)">PONG</a></span></span> <span class='rbrace'>}</span><span class='comma'>,</span> <span class='id identifier rubyid_opts'>opts</span> <span class='op'>=</span> <span class='id identifier rubyid_opts'>opts</span><span class='rparen'>)</span>
<span class='kw'>end</span>
<span class='kw'>next</span> <span class='kw'>unless</span> <span class='id identifier rubyid_frame'>frame</span><span class='period'>.</span><span class='id identifier rubyid_header'>header</span><span class='period'>.</span><span class='id identifier rubyid_fin'>fin</span> <span class='op'>==</span> <span class='int'>1</span>
<span class='kw'>if</span> <span class='id identifier rubyid_block_given?'>block_given?</span>
<span class='comment'># text data is UTF-8 encoded
</span> <span class='comment'># see: https://datatracker.ietf.org/doc/html/rfc6455#section-5.6
</span> <span class='id identifier rubyid_buffer'>buffer</span><span class='period'>.</span><span class='id identifier rubyid_force_encoding'>force_encoding</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>UTF-8</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span> <span class='kw'>if</span> <span class='id identifier rubyid_buffer_type'>buffer_type</span> <span class='op'>==</span> <span class='symbol'>:text</span>
<span class='comment'># release the stream lock before entering the callback, allowing it to close the socket if desired
</span> <span class='ivar'>@wsstream_lock</span><span class='period'>.</span><span class='id identifier rubyid_unlock_read'>unlock_read</span>
<span class='kw'>begin</span>
<span class='id identifier rubyid_block'>block</span><span class='period'>.</span><span class='id identifier rubyid_call'>call</span><span class='lparen'>(</span><span class='id identifier rubyid_buffer'>buffer</span><span class='comma'>,</span> <span class='id identifier rubyid_buffer_type'>buffer_type</span><span class='rparen'>)</span>
<span class='kw'>ensure</span>
<span class='ivar'>@wsstream_lock</span><span class='period'>.</span><span class='id identifier rubyid_lock_read'>lock_read</span>
<span class='kw'>end</span>
<span class='kw'>end</span>
<span class='id identifier rubyid_buffer'>buffer</span> <span class='op'>=</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_end'>&#39;</span></span>
<span class='id identifier rubyid_buffer_type'>buffer_type</span> <span class='op'>=</span> <span class='kw'>nil</span>
<span class='kw'>end</span>
<span class='kw'>end</span>
<span class='id identifier rubyid_close'>close</span>
<span class='kw'>end</span></pre>
</td>
</tr>
</table>
</div>
</div>
</div>
<div id="footer">
Generated on Fri May 8 17:03:10 2026 by
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
0.9.37 (ruby-3.1.5).
</div>
</div>
</body>
</html>