module GxG::Support::Library::SocketIO
Public Instance Methods
recv(bytecount=nil, flags=0)
click to toggle source
# File lib/gxg/gxg_io.rb, line 340 def recv(bytecount=nil, flags=0) # for now, flags ignored. LATER: study Socket.recv message flags in detail unless self.instance_variable_defined?(:@before_receive_data) @before_receive_data = nil end unless self.instance_variable_defined?(:@after_receive_data) @after_receive_data = nil end unless bytecount.is_a?(::Numeric) bytecount = self.buffer_limits(:in,:socket)[:initial] end unless flags.is_a?(::Numeric) flags = 0 end if self.fcntl(::Fcntl::F_GETFL,::Fcntl::O_NONBLOCK) & ::Fcntl::O_NONBLOCK == ::Fcntl::O_NONBLOCK # on Winderz, just to a buffer sized spoon full until done ?? # if self.closed?() raise IOError, "attempting to recv on a closed stream" else if @before_receive_data.respond_to?(:call) @before_receive_data.call() end if self.is_any?(::UNIXServer, ::UNIXSocket, ::Socket) whatfor = :socket else if self.is_any?(::TCPServer, ::SOCKSocket, ::TCPSocket) whatfor = :tcp else if self.is_any?(::UDPServer, ::UDPSource, ::UDPSocket) whatfor = :udp end end end buffer_size = self.buffer_limits(:in,whatfor)[:initial] unless bytecount.is_a?(::Numeric) bytecount = buffer_size end unless flags.is_a?(::Numeric) flags = 0 end # millisecond: 1/1000th of a second (reminder) read_bytes = 0 result = "" result.force_encoding(::Encoding::ASCII_8BIT) chunk = "abc" # until (read_bytes == bytecount || chunk.bytesize() == 0) begin if ((bytecount - read_bytes) < buffer_size) chunk = self.recv_nonblock((bytecount - read_bytes),flags).to_s else chunk = self.recv_nonblock(buffer_size,flags).to_s end read_bytes += chunk.bytesize() if chunk.bytesize() > 0 result << chunk end # rescue ::IO::WaitReadable, ::IO::WaitWritable, GxG::IO::IO::WaitReadable, GxG::IO::IO::WaitWritable pause begin # about 10 ms selected = GxG::IO::IO::select([self],nil,nil,0.010) until selected pause selected = GxG::IO::IO::select([self],nil,nil,0.010) end rescue Exception pause retry end retry end # pause end # if @after_receive_data.respond_to?(:call) @after_receive_data.call([result,nil,0,nil]) end result end else if self.closed?() raise IOError, "attempting to recv on a closed stream" else if @before_receive_data.respond_to?(:call) @before_receive_data.call() end result = self.original_recv(bytecount.to_i,flags).to_s result.force_encoding(::Encoding::ASCII_8BIT) if @after_receive_data.respond_to?(:call) @after_receive_data.call([result,nil,0,nil]) end end end result end
recvmsg(max_mesg_length=nil, flags=0, max_control_length=nil, options={})
click to toggle source
# File lib/gxg/gxg_io.rb, line 281 def recvmsg(max_mesg_length=nil, flags=0, max_control_length=nil, options={}) # for now, flags ignored. LATER: study Socket.recv message flags in detail if self.fcntl(::Fcntl::F_GETFL,::Fcntl::O_NONBLOCK) & ::Fcntl::O_NONBLOCK == ::Fcntl::O_NONBLOCK # on Winderz, just to a buffer sized spoon full until done ?? if self.closed?() raise IOError, "attempting to recvmsg on a closed stream" else if @before_receive_data.respond_to?(:call) @before_receive_data.call() end begin result = self.recvmsg_nonblock(max_mesg_length, flags, max_control_length, options) # rescue ::IO::WaitReadable, ::IO::WaitWritable, GxG::IO::IO::WaitReadable, GxG::IO::IO::WaitWritable pause begin # about 10 ms selected = GxG::IO::IO::select([self],nil,nil,0.010) until selected pause selected = GxG::IO::IO::select([self],nil,nil,0.010) end rescue Exception pause retry end retry end # if result.is_a?(::Array) if result[0].is_a?(::String) result[0].force_encoding(::Encoding::ASCII_8BIT) end end if @after_receive_data.respond_to?(:call) @after_receive_data.call(result) end end else if self.closed?() raise IOError, "attempting to recvmsg on a closed stream" else if @before_receive_data.respond_to?(:call) @before_receive_data.call() end result = self.original_recvmsg(max_mesg_length, flags, max_control_length, options) if result.is_a?(::Array) if result[0].is_a?(::String) result[0].force_encoding(::Encoding::ASCII_8BIT) end end if @after_receive_data.respond_to?(:call) @after_receive_data.call(result) end end end result end
send(data="", flags=0, destination_socket_address=nil, *controls)
click to toggle source
# File lib/gxg/gxg_io.rb, line 181 def send(data="", flags=0, destination_socket_address=nil, *controls) # for now, flags ignored. LATER: study Socket.send message flags in detail unless self.instance_variable_defined?(:@remote_closed) @remote_closed = nil end unless self.instance_variable_defined?(:@write_latency) @write_latency = {:low => nil, :last => nil, :high => nil} end unless self.instance_variable_defined?(:@before_send_data) @before_send_data = nil end unless self.instance_variable_defined?(:@after_send_data) @after_send_data = nil end if self.closed?() raise IOError, "attempting to send on a closed stream" else if @remote_closed raise Errno::EPIPE else data = data.to_s length = 0 if data.bytesize() > 0 length = data.bytesize() # process controls: if controls.size > 0 if controls[0].is_a?(::Socket::AncillaryData) controls = controls[0] else if controls[0].is_a?(::Hash) controls = ::Socket::AncillaryData.new(::Socket::AF_UNIX, (controls[:level] || :SOCKET), (controls[:type] || ::Socket::SCM_RIGHTS), (controls[:data] || self.fileno)) else controls.flatten! controls = ::Socket::AncillaryData.new(::Socket::AF_UNIX, (controls[0] || :SOCKET), (controls[1] || ::Socket::SCM_RIGHTS), (controls[2] || self.fileno)) end end else controls = nil end # if self.is_any?(::UNIXServer, ::UNIXSocket, ::Socket) whatfor = :socket else if self.is_any?(::TCPServer, ::SOCKSocket, ::TCPSocket) whatfor = :tcp else if self.is_any?(::UDPServer, ::UDPSource, ::UDPSocket) whatfor = :udp end end end buffer_size = self.buffer_limits(:out,whatfor)[:initial] if length >= buffer_size passes = self.passes_needed(length, buffer_size) else passes = 1 end # total = (length - 1) starting = 0 ending = ([length,buffer_size].min - 1) # passes.times do # if remote end closes during write, raise error. if controls reading = self.latency_reading(self.write_latency()) do self.sendmsg(data.slice_bytes(starting..ending),flags,destination_socket_address,controls) or @remote_closed=true end else if destination_socket_address reading = self.latency_reading(self.write_latency()) do self.original_send(data.slice_bytes(starting..ending),flags,destination_socket_address) or @remote_closed=true end else reading = self.latency_reading(self.write_latency()) do self.original_send(data.slice_bytes(starting..ending),flags) or @remote_closed=true end end end if @remote_closed break else @write_latency = reading[:reading] end starting = ending + 1 ending = (starting + (buffer_size - 1)) if ending > total ending = ending - (ending - total) end end # if @remote_closed raise Errno::EPIPE end end length end end end
sendmsg(data="", flags=0, destination_socket_address=nil, *controls)
click to toggle source
# File lib/gxg/gxg_io.rb, line 8 def sendmsg(data="", flags=0, destination_socket_address=nil, *controls) unless self.instance_variable_defined?(:@remote_closed) @remote_closed = nil end unless self.instance_variable_defined?(:@write_latency) @write_latency = {:low => nil, :last => nil, :high => nil} end unless self.instance_variable_defined?(:@before_send_data) @before_send_data = nil end unless self.instance_variable_defined?(:@after_send_data) @after_send_data = nil end if self.fcntl(::Fcntl::F_GETFL,::Fcntl::O_NONBLOCK) & ::Fcntl::O_NONBLOCK == ::Fcntl::O_NONBLOCK # on Winderz, just to a buffer sized spoon full until done ?? if self.closed?() raise IOError, "attempting to sendmsg on a closed stream" else if @remote_closed raise Errno::EPIPE else data = data.to_s written_bytes = data.bytesize() # process controls: if controls.size > 0 if controls[0].is_a?(::Socket::AncillaryData) controls = controls[0] else if controls[0].is_a?(::Hash) controls = ::Socket::AncillaryData.new(::Socket::AF_UNIX, (controls[:level] || :SOCKET), (controls[:type] || ::Socket::SCM_RIGHTS), (controls[:data] || self.fileno)) else controls.flatten! controls = ::Socket::AncillaryData.new(::Socket::AF_UNIX, (controls[0] || :SOCKET), (controls[1] || ::Socket::SCM_RIGHTS), (controls[2] || self.fileno)) end end else raise ArgumentError, "you MUST supply ancillary data as a control" end # if self.is_any?(::UNIXServer, ::UNIXSocket, ::Socket) whatfor = :socket else if self.is_any?(::TCPServer, ::SOCKSocket, ::TCPSocket) whatfor = :tcp else if self.is_any?(::UDPServer, ::UDPSource, ::UDPSocket) whatfor = :udp end end end buffer_size = self.buffer_limits(:out,whatfor)[:initial] if written_bytes >= buffer_size passes = self.passes_needed(written_bytes, buffer_size) else passes = 1 end # total = (written_bytes - 1) starting = 0 ending = ([written_bytes,buffer_size].min - 1) # passes.times do # begin # if remote end closes during write, raise error by setting @remote_closed and breaking loop. reading = self.latency_reading(self.write_latency()) do self.sendmsg_nonblock(data.slice_bytes(starting..ending),flags,destination_socket_address,controls) end @write_latency = reading[:reading] # rescue ::IO::WaitWritable, GxG::IO::IO::WaitWritable, ::Errno::EINTR, ::Errno::EWOULDBLOCK, ::Errno::EAGAIN pause begin selected = ::IO::select(nil,[self],nil,0.010) until selected pause selected = ::IO::select(nil,[self],nil,0.010) end rescue Exception pause retry end retry rescue ::Errno::EPIPE @remote_closed=true break end # starting = ending + 1 ending = (starting + (buffer_size - 1)) if ending > total ending = ending - (ending - total) end end if @remote_closed raise Errno::EPIPE end written_bytes end end else if self.closed?() raise IOError, "attempting to sendmsg on a closed stream" else if @remote_closed raise Errno::EPIPE else data = self.transcode_to_external(data) written_bytes = data.bytesize() # process controls: if controls.size > 0 if controls[0].is_a?(::Socket::AncillaryData) controls = controls[0] else if controls[0].is_a?(::Hash) controls = ::Socket::AncillaryData.new(::Socket::AF_UNIX, (controls[:level] || :SOCKET), (controls[:type] || ::Socket::SCM_RIGHTS), (controls[:data] || self.fileno)) else controls.flatten! controls = ::Socket::AncillaryData.new(::Socket::AF_UNIX, (controls[0] || :SOCKET), (controls[1] || ::Socket::SCM_RIGHTS), (controls[2] || self.fileno)) end end else raise ArgumentError, "you MUST supply ancillary data as a control" end # if self.is_any?(::UNIXServer, ::UNIXSocket, ::Socket) whatfor = :socket else if self.is_any?(::TCPServer, ::SOCKSocket, ::TCPSocket) whatfor = :tcp else if self.is_any?(::UDPServer, ::UDPSource, ::UDPSocket) whatfor = :udp end end end buffer_size = self.buffer_limits(:out,whatfor)[:initial] if written_bytes >= buffer_size passes = self.passes_needed(written_bytes, buffer_size) else passes = 1 end # total = (written_bytes - 1) starting = 0 ending = ([written_bytes,buffer_size].min - 1) # passes.times do # if remote end closes during write, raise error. reading = self.latency_reading(self.write_latency()) do self.original_sendmsg(data.slice_bytes(starting..ending),flags,destination_socket_address,controls) or @remote_closed=true end if @remote_closed break else @write_latency = reading[:reading] end starting = ending + 1 ending = (starting + (buffer_size - 1)) if ending > total ending = ending - (ending - total) end end if @remote_closed raise Errno::EPIPE end # end written_bytes end end end