127 Commits

Author SHA1 Message Date
James Coglan befd449e00 Prefer text frames over binary; if the input is in some non-UTF-8 text encoding, then transcode it 2025-05-25 11:35:17 +01:00
James Coglan 22e070485c Default to text frames if the input buffer is specifically UTF8-encoded 2025-05-24 15:47:45 +01:00
James Coglan 370ac9b944 Emit binary frames as binary strings by default, and make Driver.frame() treat such strings as binary frames 2025-05-24 13:16:00 +01:00
Kuba Suder 61bfc0725f added :binary_data_format option 2025-05-08 02:19:07 +02:00
James Coglan 3a2931751c Fix handling of default ports on Ruby 3.1 2022-09-10 15:37:55 +01:00
Daniel Morrison 0e950c5134 Flag files that modify string literals
When running in an environment that freezes string literals by default, `hybi.rb` raises exceptions as it modifies the `'C2'` string.

Adding the magic comment supports this use case without modifying behavior for anyone else. I added it to one spec too, so that running specs this way (`RUBYOPT="--enable=frozen-string-literal" rspec`) keeps them all passing.
2021-09-13 10:15:25 -04:00
James Coglan 586c27f44e Clarify behaviour of Driver.encode to convert strings to UTF-8 and arrays to ASCII-8BIT 2021-06-12 16:53:51 +01:00
James Coglan 9a4f2f2d1d Do not change the encoding of strings passed to text() 2021-06-09 21:39:40 +01:00
James Coglan 3ae2e3a0f6 Validate UTF-8 encoding of strings where needed, not on every call to Driver.encode 2021-02-26 16:26:08 +00:00
James Coglan 9ec01dc328 Avoid allocating an array of the string bytes in Hybi#emit_frame 2021-02-26 16:14:58 +00:00
James Coglan 472569ad38 Avoid allocating so many arrays during Hybi#frame 2021-02-26 16:14:53 +00:00
James Coglan 219c409844 Use the Ruby Encoding constants instead of their string names 2021-02-26 14:44:50 +00:00
James Coglan e87bfef9bc Accept HTTP responses that have an empty reason-phrase, per RFC 2616 2020-07-09 19:06:13 +01:00
pjaspers 202e1800e0 Allow rack.input.read to return a frozen string
We're seeing this occasionally in our error logs, where the `env`
passed into to the driver will return a frozen string when read.

The stack trace always includes ActionCable in to the mix, so
something like this:

      "/app/vendor/bundle/ruby/2.6.0/gems/websocket-driver-0.7.0/lib/websocket/driver/draft76.rb" line 11 in force_encoding
      "/app/vendor/bundle/ruby/2.6.0/gems/websocket-driver-0.7.0/lib/websocket/driver/draft76.rb" line 11 in initialize
      "/app/vendor/bundle/ruby/2.6.0/gems/websocket-driver-0.7.0/lib/websocket/driver.rb" line 162 in new
      "/app/vendor/bundle/ruby/2.6.0/gems/websocket-driver-0.7.0/lib/websocket/driver.rb" line 162 in rack
      "/app/vendor/bundle/ruby/2.6.0/gems/actioncable-5.2.3/lib/action_cable/connection/client_socket.rb" line 47 in initialize
      "/app/vendor/bundle/ruby/2.6.0/gems/actioncable-5.2.3/lib/action_cable/connection/web_socket.rb" line 10 in new
      "/app/vendor/bundle/ruby/2.6.0/gems/actioncable-5.2.3/lib/action_cable/connection/web_socket.rb" line 10 in initialize
      "/app/vendor/bundle/ruby/2.6.0/gems/actioncable-5.2.3/lib/action_cable/connection/base.rb" line 59 in new
      "/app/vendor/bundle/ruby/2.6.0/gems/actioncable-5.2.3/lib/action_cable/connection/base.rb" line 59 in initialize
      "/app/vendor/bundle/ruby/2.6.0/gems/actioncable-5.2.3/lib/action_cable/server/base.rb" line 30 in new
      "/app/vendor/bundle/ruby/2.6.0/gems/actioncable-5.2.3/lib/action_cable/server/base.rb" line 30 in call

I still don't quite know why someone is sometimes returning a frozen
string (it could also have to with any of the current rack middleware
we're using), but I do know that we can handle it here.

So this adds a spec and some behavior to fix that.
2020-05-14 16:22:20 +01:00
James Coglan b00f58701e Emit ping and pong events from the Server driver 2020-02-14 14:41:43 +01:00
James Coglan e568366f82 Formatting change: {...} should have spaces inside the braces 2019-06-11 16:12:52 +01:00
James Coglan 019ba714cd Remove a redundant statement from the Hybi setup code. 2019-05-29 00:10:46 +01:00
James Coglan 03b46b8db6 Fail a draft-76 connection of a header does not contain any digits. 2019-05-29 00:10:46 +01:00
James Coglan 8a6f9ef737 Fix an uninitialised variable warning. 2019-05-24 14:59:01 +01:00
James Coglan 11476318ea If any header used by Hybi is present, then pick Hybi, and likewise for Draft76. This means the driver is more likely to pick Hybi and report likely combinations of malformed headers as errors to the client. 2017-11-23 23:02:15 +00:00
James Coglan 2ec898c6a1 If any driver encounters a validation error in the request headers, it can throw an error and Driver#start will catch that and send a 400 response to the client. 2017-11-23 23:01:26 +00:00
James Coglan cd38349f9a Make the ping/pong tests check the content of the events. 2017-08-02 21:54:59 +01:00
James Coglan 5daa01be5e Emit ping and pong events after all other effects of those frames have been carried out. 2017-08-02 21:32:17 +01:00
Matthew O'Riordan f22c97f977 Emit :ping and :pong events in the driver 2017-05-16 15:00:10 +01:00
Keith Barrette cfc45f2360 Fall back to ruby 2016-12-07 11:32:43 -05:00
Keith Barrette 6e32ee04f3 Add Ruby mask implementation 2016-12-07 11:32:43 -05:00
James Coglan 9ce857b3d4 Revise uses of encoding APIs.
When originally implemented, we still supported Ruby 1.8, which
necessitated checking for encoding methods and using a regex to validate
UTF-8. These checks are now gone.

We tagged many strings as binary when not strictly necessary, either
because we were just going to iterate their bytes or because we were
going to hand them off to the caller which should just write them
directly to a socket. Strings used as buffers to accumulate streaming
input are still tagged as binary to avoid encoding
collision/conversion.

The places where we do need to tag as UTF-8 (i.e. just before emitting
to the application) remain, but copy the string if necessary. This
allows us to work with frozen strings.

Finally, strings passed in via the Driver#text method should be
*transcoded* to UTF-8 if necessary, not merely tagged. The Ruby
String#encode method produces a new string so this should also be safe
with frozen strings.
2016-05-19 21:08:22 +01:00
James Coglan 115d82bebb Silence all -W2 warnings. 2016-05-18 22:42:16 +01:00
James Coglan 15ba7410c6 Remove some unused variables from Hybi#send_frame. 2016-05-18 22:33:33 +01:00
James Coglan 4ae198b1d3 Throw a more helpful error if a client driver is created with an invalid URL. 2015-10-17 21:37:13 +01:00
James Coglan c63220194c Close the connection if a draft-76 client sends a Sec-WebSocket-Key header where the numeric value is a non-integer multiple of the number of spaces. 2015-10-02 21:32:35 +01:00
Akira Matsuda 5ce5c98339 "warning: instance variable @delegate not initialized" 2015-07-21 16:41:50 +09:00
James Coglan bc7d29cb52 Emit a protocol error when a closing frame has a 1-byte payload. 2015-07-17 22:02:51 +01:00
James Coglan 59940290c9 Emit close code 1000 if the closing frame does not contain one. 2015-07-16 08:19:05 +01:00
James Coglan be2e5ed9ce A few stylistic tweaks. 2015-07-11 14:24:19 +01:00
James Coglan d4245ed3f4 Rather than implementing integer (un)packing ourselves, use the Array#pack and String#unpack methods. 2015-07-10 20:05:19 +01:00
James Coglan 7128d1b030 Standardise the words used to refer to chunks of parser input. 2015-07-10 09:37:03 +01:00
James Coglan 75fe55eaba Adjust how on() calls add_listener(). This is necessary because faye-websocket overrides add_listener with one argument, so users with faye-websocket locked at < 0.10 will see errors. 2015-07-10 09:22:16 +01:00
James Coglan f1fd96e093 Emit an error event *after* setting the ready state to 3. 2015-07-08 20:13:50 +01:00
James Coglan fed81a5a88 Small format changes to StreamReader. 2015-07-07 21:24:13 +01:00
James Coglan 91653036ce Parse the mask flag and length in the order they appear in the protocol. 2015-07-07 20:49:29 +01:00
James Coglan e39fa15c07 Revert variable names in Draft75#parse to what they were in 0.5. 2015-07-07 20:45:55 +01:00
James Coglan 50ca31b4c8 Remove empty Driver#shutdown method. 2015-07-07 20:40:53 +01:00
James Coglan 9523937428 Initialize StreamReader in the base constructor. 2015-07-07 20:38:26 +01:00
James Coglan 91df761990 Hybi#shutdown doesn't really need to take a block, it can just take a flag to say whether to emit an error. 2015-07-07 20:33:22 +01:00
James Coglan dcfd35fde8 Remove some excessive whitespace. 2015-07-07 20:32:47 +01:00
James Coglan 582a3b0541 Merge pull request #29 from ioquatix/buffered-input
Use StreamReader for both hybi and draft75.
2015-07-06 20:49:24 +01:00
James Coglan fe6163c336 Perform state changes in #shutdown before calling frame(), which might fail when calling @socket.write. 2015-07-06 20:50:18 +01:00
James Coglan 9b561b6e12 The 'rescue' clause for errors from outgoing extensions should be in #frame, not #send_frame. 2015-07-06 20:48:44 +01:00
Samuel Williams 425e15da83 Use StreamReader for both hybi and draft75. 2015-07-06 10:29:18 +09:00