lib/bunny/cruby/ssl_socket.rb in bunny-1.5.1 vs lib/bunny/cruby/ssl_socket.rb in bunny-1.6.0.pre1

- old
+ new

@@ -10,10 +10,13 @@ # IO::WaitReadable is 1.9+ only READ_RETRY_EXCEPTION_CLASSES = [Errno::EAGAIN, Errno::EWOULDBLOCK] READ_RETRY_EXCEPTION_CLASSES << IO::WaitReadable if IO.const_defined?(:WaitReadable) + # IO::WaitWritable is 1.9+ only + WRITE_RETRY_EXCEPTION_CLASSES = [Errno::EAGAIN, Errno::EWOULDBLOCK] + WRITE_RETRY_EXCEPTION_CLASSES << IO::WaitWritable if IO.const_defined?(:WaitWritable) # Reads given number of bytes with an optional timeout # # @param [Integer] count How many bytes to read # @param [Integer] timeout Timeout @@ -48,9 +51,54 @@ raise Timeout::Error, "IO timeout when reading #{count} bytes" end end value end + + # Writes provided data using IO#write_nonblock, taking care of handling + # of exceptions it raises when writing would fail (e.g. due to socket buffer + # being full). + # + # IMPORTANT: this method will mutate (slice) the argument. Pass in duplicates + # if this is not appropriate in your case. + # + # @param [String] data Data to write + # @param [Integer] timeout Timeout + # + # @api public + def write_nonblock_fully(data, timeout = nil) + return nil if @__bunny_socket_eof_flag__ + + length = data.bytesize + total_count = 0 + count = 0 + loop do + begin + count = self.write_nonblock(data) + rescue OpenSSL::SSL::SSLError => e + if e.message == "write would block" + if IO.select([], [self], nil, timeout) + retry + else + raise Timeout::Error, "IO timeout when writing to socket" + end + end + raise e + rescue *WRITE_RETRY_EXCEPTION_CLASSES + if IO.select([], [self], nil, timeout) + retry + else + raise Timeout::Error, "IO timeout when writing to socket" + end + end + + total_count += count + return total_count if total_count >= length + data = data.byteslice(count..-1) + end + + end + end rescue LoadError => le puts "Could not load OpenSSL" end end