Class: RSpec::Buildkite::Analytics::SocketConnection
- Inherits:
-
Object
- Object
- RSpec::Buildkite::Analytics::SocketConnection
- Defined in:
- lib/rspec/buildkite/analytics/socket_connection.rb
Defined Under Namespace
Classes: HandshakeError, SocketError
Instance Method Summary collapse
- #close ⇒ Object
-
#initialize(session, url, headers) ⇒ SocketConnection
constructor
A new instance of SocketConnection.
- #transmit(data, type: :text) ⇒ Object
Constructor Details
#initialize(session, url, headers) ⇒ SocketConnection
Returns a new instance of SocketConnection.
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 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 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/rspec/buildkite/analytics/socket_connection.rb', line 12 def initialize(session, url, headers) uri = URI.parse(url) @session = session protocol = "http" begin socket = TCPSocket.new(uri.host, uri.port || (uri.scheme == "wss" ? 443 : 80)) if uri.scheme == "wss" ctx = OpenSSL::SSL::SSLContext.new protocol = "https" ctx.min_version = :TLS1_2 ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER ctx.cert_store = OpenSSL::X509::Store.new.tap(&:set_default_paths) socket = OpenSSL::SSL::SSLSocket.new(socket, ctx) socket.connect end rescue # We are rescuing all here, as there are a range of Errno errors that could be # raised when we fail to establish a TCP connection raise SocketError end @socket = socket headers = { "Origin" => "#{protocol}://#{uri.host}" }.merge(headers) handshake = WebSocket::Handshake::Client.new(url: url, headers: headers) @socket.write handshake.to_s until handshake.finished? if byte = @socket.getc handshake << byte end end # The errors below are raised when we establish the TCP connection, but get back # an error, i.e. in dev we can still connect to puma-dev while nginx isn't # running, or in prod we can hit a load balancer while app is down unless handshake.valid? case handshake.error when Exception, String raise HandshakeError.new(handshake.error) when nil raise HandshakeError.new("Invalid handshake") else raise HandshakeError.new(handshake.error.inspect) end end @version = handshake.version # Setting up a new thread that listens on the socket, and processes incoming # comms from the server @thread = Thread.new do @session.logger.write("listening in on socket") frame = WebSocket::Frame::Incoming::Client.new while @socket frame << @socket.readpartial(4096) while data = frame.next @session.handle(self, data.data) end end rescue EOFError, Errno::ECONNRESET => e @session.logger.write("#{e}") if @socket @session.logger.write("attempting disconnected flow") @session.disconnected(self) disconnect end rescue IOError # This is fine to ignore @session.logger.write("IOError") rescue IndexError # I don't like that we're doing this but I think it's the best of the options # # This relates to this issue https://github.com/ruby/openssl/issues/452 # A fix for it has been released but the repercussions of overriding # the OpenSSL version in the stdlib seem worse than catching this error here. @session.logger.write("IndexError") if @socket @session.logger.write("attempting disconnected flow") @session.disconnected(self) disconnect end end end |
Instance Method Details
#close ⇒ Object
131 132 133 134 135 |
# File 'lib/rspec/buildkite/analytics/socket_connection.rb', line 131 def close @session.logger.write("socket close") transmit(nil, type: :close) disconnect end |
#transmit(data, type: :text) ⇒ Object
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/rspec/buildkite/analytics/socket_connection.rb', line 104 def transmit(data, type: :text) # this line prevents us from calling disconnect twice return if @socket.nil? raw_data = data.to_json frame = WebSocket::Frame::Outgoing::Client.new(data: raw_data, type: :text, version: @version) @socket.write(frame.to_s) rescue Errno::EPIPE, Errno::ECONNRESET, OpenSSL::SSL::SSLError => e return unless @socket return if type == :close @session.logger.write("got #{e}, attempting disconnected flow") @session.disconnected(self) disconnect rescue IndexError # I don't like that we're doing this but I think it's the best of the options # # This relates to this issue https://github.com/ruby/openssl/issues/452 # A fix for it has been released but the repercussions of overriding # the OpenSSL version in the stdlib seem worse than catching this error here. @session.logger.write("IndexError") if @socket @session.logger.write("attempting disconnected flow") @session.disconnected(self) disconnect end end |