Class: EventMachine::Synchrony::TCPSocket
- Inherits:
-
Connection
- Object
- Connection
- EventMachine::Synchrony::TCPSocket
- Defined in:
- lib/em-synchrony/tcpsocket.rb
Instance Attribute Summary collapse
-
#unbind_reason ⇒ Object
readonly
Returns the value of attribute unbind_reason.
Class Method Summary collapse
- ._old_new ⇒ Object
- .new(*args) ⇒ Object (also: open)
Instance Method Summary collapse
- #close ⇒ Object
- #closed? ⇒ Boolean
-
#connection_completed ⇒ Object
EventMachine interface.
- #post_init ⇒ Object
- #read(num_bytes = nil, dest = nil) ⇒ Object (also: #read_nonblock)
- #receive_data(data) ⇒ Object
- #recv(num_bytes, flags = 0) ⇒ Object
- #send(msg, flags) ⇒ Object
-
#setsockopt(level, name, value) ⇒ Object
TCPSocket interface.
-
#sync(direction) ⇒ Object
direction must be one of :in or :out.
-
#unbind(reason) ⇒ Object
Can’t set a default value for reason (e.g. reason=nil), as in that case EM fails to pass in the reason argument and you’ll always get the default value.
- #write(msg) ⇒ Object
Instance Attribute Details
#unbind_reason ⇒ Object (readonly)
Returns the value of attribute unbind_reason.
111 112 113 |
# File 'lib/em-synchrony/tcpsocket.rb', line 111 def unbind_reason @unbind_reason end |
Class Method Details
._old_new ⇒ Object
5 |
# File 'lib/em-synchrony/tcpsocket.rb', line 5 alias_method :_old_new, :new |
.new(*args) ⇒ Object Also known as: open
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/em-synchrony/tcpsocket.rb', line 6 def new(*args) if args.size == 1 _old_new(*args) else # In TCPSocket, new against an unknown hostname raises SocketError with # a message "getaddrinfo: nodename nor servname provided, or not known". # In EM, connect against an unknown hostname raises EM::ConnectionError # with a message of "unable to resolve server address" begin socket = EventMachine::connect(*args[0..1], self) rescue EventMachine::ConnectionError => e raise SocketError, e. end # In TCPSocket, new against a closed port raises Errno::ECONNREFUSED. # In EM, connect against a closed port result in a call to unbind with # a reason param of Errno::ECONNREFUSED as a class, not an instance. unless socket.sync(:in) # wait for connection raise socket.unbind_reason.new if socket.unbind_reason.is_a? Class raise SocketError end socket end end |
Instance Method Details
#close ⇒ Object
95 96 97 98 99 100 101 102 103 |
# File 'lib/em-synchrony/tcpsocket.rb', line 95 def close # close on a closed socket raises IOError with a message of "closed stream" raise IOError, "closed stream" if @closed @closed = true close_connection true @in_req = @out_req = nil # close on an open socket returns nil nil end |
#closed? ⇒ Boolean
39 40 41 42 43 44 45 46 |
# File 'lib/em-synchrony/tcpsocket.rb', line 39 def closed? # In TCPSocket, # closed? on a remotely closed socket, when we've not yet read EOF, returns false # closed? on a remotely closed socket, when we've read EOF, returns false # closed? on a socket after #close, returns true # Therefore, we set @close to true when #close is called, but not when unbind is. @closed end |
#connection_completed ⇒ Object
EventMachine interface
106 107 108 109 |
# File 'lib/em-synchrony/tcpsocket.rb', line 106 def connection_completed @opening = false @in_req.succeed self end |
#post_init ⇒ Object
32 33 34 35 36 37 |
# File 'lib/em-synchrony/tcpsocket.rb', line 32 def post_init @in_buff, @out_buff = '', '' @in_req = @out_req = @unbind_reason = @read_type = nil @opening = true @closed = @remote_closed = false end |
#read(num_bytes = nil, dest = nil) ⇒ Object Also known as: read_nonblock
85 86 87 |
# File 'lib/em-synchrony/tcpsocket.rb', line 85 def read(num_bytes = nil, dest = nil) handle_read(:read, num_bytes, dest) end |
#receive_data(data) ⇒ Object
128 129 130 131 132 133 |
# File 'lib/em-synchrony/tcpsocket.rb', line 128 def receive_data(data) @in_buff << data if @in_req && (data = read_data) @in_req.succeed data unless data == :block end end |
#recv(num_bytes, flags = 0) ⇒ Object
90 91 92 93 |
# File 'lib/em-synchrony/tcpsocket.rb', line 90 def recv(num_bytes, flags = 0) raise "Unknown flags in recv(): #{flags}" if flags.nonzero? handle_read(:recv, num_bytes) end |
#send(msg, flags) ⇒ Object
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/em-synchrony/tcpsocket.rb', line 59 def send(msg, flags) raise "Unknown flags in send(): #{flags}" if flags.nonzero? # write(X) on a socket after #close, raises IOError with message "closed stream" # send(X,0) on a socket after #close, raises IOError with message "closed stream" raise IOError, "closed stream" if @closed # the first write(X) on a remotely closed socket, <= than some buffer size, generates no error # the first write(X) on a remotely closed socket, > than some buffer size, generates no error # (on my box this buffer appears to be 80KB) # further write(X) on a remotely closed socket, raises Errno::EPIPE # the first send(X,0) on a remotely closed socket, <= than some buffer size, generates no error # the first send(X,0) on a remotely closed socket, > than some buffer size, generates no error # (on my box this buffer appears to be 80KB) # further send(X,0) on a remotely closed socket, raises Errno::EPIPE raise Errno::EPIPE if @remote_closed len = msg.bytesize # write(X) on an open socket, where the remote end closes during the write, raises Errno::EPIPE # send(X,0) on an open socket, where the remote end closes during the write, raises Errno::EPIPE write_data(msg) or sync(:out) or raise(Errno::EPIPE) len end |
#setsockopt(level, name, value) ⇒ Object
TCPSocket interface
57 |
# File 'lib/em-synchrony/tcpsocket.rb', line 57 def setsockopt(level, name, value); end |
#sync(direction) ⇒ Object
direction must be one of :in or :out
49 50 51 52 53 54 |
# File 'lib/em-synchrony/tcpsocket.rb', line 49 def sync(direction) req = self.instance_variable_set "@#{direction.to_s}_req", EventMachine::DefaultDeferrable.new EventMachine::Synchrony.sync req ensure self.instance_variable_set "@#{direction.to_s}_req", nil end |
#unbind(reason) ⇒ Object
Can’t set a default value for reason (e.g. reason=nil), as in that case EM fails to pass in the reason argument and you’ll always get the default value.
116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/em-synchrony/tcpsocket.rb', line 116 def unbind(reason) @unbind_reason = reason @remote_closed = true unless @closed if @opening @in_req.fail nil if @in_req else @in_req.succeed read_data if @in_req end @out_req.fail nil if @out_req @in_req = @out_req = nil end |
#write(msg) ⇒ Object
81 82 83 |
# File 'lib/em-synchrony/tcpsocket.rb', line 81 def write(msg) send(msg,0) end |