Skip to content

Commit

Permalink
Add UNIXSocket.pair
Browse files Browse the repository at this point in the history
  • Loading branch information
Evan Phoenix committed Jun 3, 2010
1 parent 6e2ab63 commit eb2a569
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 56 deletions.
124 changes: 83 additions & 41 deletions lib/socket.rb
Expand Up @@ -9,6 +9,20 @@ class SocketError < StandardError

class BasicSocket < IO

class << self
def from_descriptor(fixnum)
sock = allocate()
sock.from_descriptor(fixnum)
return sock
end

alias :for_fd :from_descriptor
end

def from_descriptor(fixnum)
IO.setup self, fixnum, nil, true
return self
end

def self.do_not_reverse_lookup=(setting)
@no_reverse_lookup = setting
Expand Down Expand Up @@ -93,6 +107,38 @@ def recv(bytes_to_read, flags = 0)
return socket_recv(bytes_to_read, flags, 0)
end

def close_read
ensure_open_and_readable

# If we were only in readonly mode, close it all together
if @mode & ACCMODE == RDONLY
return close
end

# MRI doesn't check if shutdown worked, so we don't.
Socket::Foreign.shutdown @descriptor, 0

@mode = @mode & ~RDONLY

nil
end

def close_write
ensure_open_and_writable

# If we were only in writeonly mode, close it all together
if @mode & ACCMODE == WRONLY
return close
end

Socket::Foreign.shutdown @descriptor, 1

# Remove write from the mode bits
@mode = @mode & ~WRONLY

nil
end

#
# Sets socket nonblocking and reads up to given number of bytes.
#
Expand All @@ -108,25 +154,6 @@ def recv_nonblock(bytes_to_read, flags = 0)


#
# @todo Fix. This is horrible. --rue
#
# #
# # Only close the read stream.
# #
# # This affects all processes using this stream!
# #
# def close_read()
# shutdown Socket::SHUT_RD
# end
#
# #
# # Only close the write stream.
# #
# # This affects all processes using this stream!
# #
# def close_write()
# shutdown Socket::SHUT_WR
# end

end

Expand Down Expand Up @@ -170,6 +197,7 @@ class AddrInfo < FFI::Struct

attach_function :accept, [:int, :pointer, :pointer], :int
attach_function :close, [:int], :int
attach_function :shutdown, [:int, :int], :int
attach_function :listen, [:int, :int], :int
attach_function :socket, [:int, :int, :int], :int
attach_function :send, [:int, :pointer, :int, :int], :int
Expand Down Expand Up @@ -609,12 +637,36 @@ def self.unpack_sockaddr_in(sockaddr)
end
end

def self.socketpair(domain, type, protocol)
def self.socketpair(domain, type, protocol, klass=self)
if domain.kind_of? String
if domain.prefix? "AF_" or domain.prefix? "PF_"
begin
domain = Socket::Constants.const_get(domain)
rescue NameError
raise SocketError, "unknown socket domain #{domani}"
end
else
raise SocketError, "unknown socket domain #{domani}"
end
end

if type.kind_of? String
if type.prefix? "SOCK_"
begin
type = Socket::Constants.const_get(type)
rescue NameError
raise SocketError, "unknown socket type #{type}"
end
else
raise SocketError, "unknown socket type #{type}"
end
end

FFI::MemoryPointer.new :int, 2 do |mp|
Socket::Foreign.socketpair(domain, type, protocol, mp)
fd0, fd1 = mp.read_array_of_int(2)

[ from_descriptor(fd0), from_descriptor(fd1) ]
[ klass.from_descriptor(fd0), klass.from_descriptor(fd1) ]
end
end

Expand Down Expand Up @@ -654,21 +706,6 @@ def initialize(family, socket_type, protocol)
IO.setup self, descriptor, nil, true
end

class << self
def from_descriptor(fixnum)
sock = allocate()
sock.from_descriptor(fixnum)
return sock
end

alias :for_fd :from_descriptor
end

def from_descriptor(fixnum)
IO.setup self, fixnum, nil, true
return self
end

def bind(server_sockaddr)
err = Socket::Foreign.bind(descriptor, server_sockaddr)
Errno.handle 'bind(2)' unless err == 0
Expand All @@ -692,7 +729,6 @@ def connect(*args)

return 0
end

end

class UNIXSocket < BasicSocket
Expand All @@ -711,6 +747,11 @@ def initialize(path)
end
private :initialize

def from_descriptor(fixnum)
super
@path = ""
end

def unix_setup(server = false)
status = nil
phase = 'socket(2)'
Expand Down Expand Up @@ -757,12 +798,13 @@ def peeraddr
["AF_UNIX", sock_path]
end

def from_descriptor(descriptor)
IO.setup self, descriptor, nil, true
class << self
def socketpair(type=Socket::SOCK_STREAM, protocol=0)
Socket.socketpair(Socket::PF_UNIX, type, protocol, self)
end

self
alias_method :pair, :socketpair
end
private :from_descriptor

end

Expand Down
2 changes: 0 additions & 2 deletions spec/tags/ruby/library/socket/basicsocket/close_read_tags.txt
@@ -1,5 +1,3 @@
fails:Socket::BasicSocket#close_read closes the reading end of the socket
fails:Socket::BasicSocket#close_read it works on sockets with closed ends
fails:Socket::BasicSocket#close_read does not close the socket
fails:Socket::BasicSocket#close_read fully closes the socket if it was already closed for writing
fails:Socket::BasicSocket#close_read returns nil
@@ -1,5 +1,3 @@
fails:Socket::BasicSocket#close_write closes the writing end of the socket
fails:Socket::BasicSocket#close_write works on sockets with closed write ends
fails:Socket::BasicSocket#close_write does not close the socket
fails:Socket::BasicSocket#close_write fully closes the socket if it was already closed for reading
fails:Socket::BasicSocket#close_write returns nil

This file was deleted.

1 change: 0 additions & 1 deletion spec/tags/ruby/library/socket/udpsocket/bind_tags.txt

This file was deleted.

6 changes: 0 additions & 6 deletions spec/tags/ruby/library/socket/unixsocket/pair_tags.txt

This file was deleted.

This file was deleted.

0 comments on commit eb2a569

Please sign in to comment.