mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
mruby-socket: add comprehensive call-seq documentation for Ruby and C methods
Added complete call-seq documentation for socket programming methods across all major socket classes in both mrblib/socket.rb (64 Ruby methods) and src/socket.c (35 C methods): - Addrinfo: Complete documentation for address information handling including creation (new, foreach, ip, tcp, udp, unix), inspection (inspect, inspect_sockaddr, to_s), address queries (afamily, pfamily, ipv4?, ipv6?, ip?, unix?), data extraction (ip_address, ip_port, ip_unpack, unix_path), and conversion methods (to_sockaddr, getnameinfo) - BasicSocket: Core socket functionality including class configuration (do_not_reverse_lookup, do_not_reverse_lookup=), object creation (for_fd), address retrieval (local_address, remote_address), and non-blocking operations (recv_nonblock) - IPSocket: Internet protocol socket operations including address information (addr, peeraddr), connection methods (bind, connect), data transfer (send, recvfrom, recvfrom_nonblock), and address resolution (getaddress) - TCPSocket/TCPServer: TCP client and server socket operations including connection establishment (new, open), server operations (accept, accept_nonblock, listen, sysaccept) - UDPSocket: UDP socket operations for datagram communication including initialization and internal address handling - Socket: Low-level socket operations including creation (new, open), address manipulation (sockaddr_in, sockaddr_un, unpack_sockaddr_in, unpack_sockaddr_un), connection management (bind, connect, listen), data transfer (recvfrom, recvfrom_nonblock), socket pairs (pair), and name resolution (getaddrinfo, getnameinfo) - UNIXSocket/UNIXServer: Unix domain socket operations for local IPC including creation (new, socketpair), path handling (path, addr, peeraddr), server operations (accept, accept_nonblock, listen, sysaccept), and data transfer (recvfrom) - Addrinfo: Core address resolution methods including getaddrinfo for name resolution, getnameinfo for reverse lookups, and unix_path for Unix domain socket paths - BasicSocket: Low-level socket operations including getpeereid for peer credentials, getpeername/getsockname for address retrieval, recv/send for data transfer, getsockopt/setsockopt for option management, shutdown for connection termination, and Windows-specific overrides (close, sysread, sysseek, syswrite) - IPSocket: Internet protocol utilities including ntop/pton for address conversion and recvfrom for receiving data with sender information - Socket: Core socket creation and management including gethostname, internal methods (_accept, _bind, _connect, _listen, _socket), address utilities (sockaddr_un, socketpair), and platform-specific implementations - Socket::Option: Socket option handling including creation from boolean/ integer values, accessor methods (family, level, optname, data), type conversion (int, bool), and debugging support (inspect) All methods now have comprehensive call-seq documentation with practical This significantly improves maintainability and usability of errno handling for developers working with system call errors and file operations in embedded Ruby environments. Co-authored-by: Atlassian Rovo Dev
This commit is contained in:
@@ -1,4 +1,15 @@
|
||||
class Addrinfo
|
||||
#
|
||||
# call-seq:
|
||||
# Addrinfo.new(sockaddr, family=Socket::PF_UNSPEC, socktype=0, protocol=0) -> addrinfo
|
||||
#
|
||||
# Creates a new Addrinfo object from socket address information.
|
||||
# sockaddr can be a packed sockaddr string or an array representation.
|
||||
#
|
||||
# Addrinfo.new(Socket.sockaddr_in(80, "127.0.0.1"))
|
||||
# Addrinfo.new(["AF_INET", 80, "localhost", "127.0.0.1"])
|
||||
# Addrinfo.new(["AF_UNIX", "/tmp/socket"])
|
||||
#
|
||||
def initialize(sockaddr, family=Socket::PF_UNSPEC, socktype=0, protocol=0)
|
||||
@hostname = nil
|
||||
if sockaddr.is_a? Array
|
||||
@@ -21,28 +32,93 @@ class Addrinfo
|
||||
@protocol = protocol
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# Addrinfo.foreach(nodename, service, family=nil, socktype=nil, protocol=nil, flags=0) { |addrinfo| block } -> array
|
||||
#
|
||||
# Iterates over all address information for the given nodename and service.
|
||||
# Returns an array of Addrinfo objects.
|
||||
#
|
||||
# Addrinfo.foreach("www.example.com", "http") { |ai| puts ai.ip_address }
|
||||
# Addrinfo.foreach("localhost", 80) { |ai| puts ai.inspect }
|
||||
#
|
||||
def self.foreach(nodename, service, family=nil, socktype=nil, protocol=nil, flags=0, &block)
|
||||
a = self.getaddrinfo(nodename, service, family, socktype, protocol, flags)
|
||||
a.each { |ai| block.call(ai) }
|
||||
a
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# Addrinfo.ip(host) -> addrinfo
|
||||
#
|
||||
# Creates an Addrinfo object for the given host with port 0.
|
||||
# Useful for creating address info without specifying a port.
|
||||
#
|
||||
# Addrinfo.ip("127.0.0.1") #=> #<Addrinfo: 127.0.0.1:0>
|
||||
# Addrinfo.ip("::1") #=> #<Addrinfo: [::1]:0>
|
||||
#
|
||||
def self.ip(host)
|
||||
Addrinfo.new(Socket.sockaddr_in(0, host))
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# Addrinfo.tcp(host, port) -> addrinfo
|
||||
#
|
||||
# Creates an Addrinfo object for TCP connection to the given host and port.
|
||||
#
|
||||
# Addrinfo.tcp("localhost", 80) #=> #<Addrinfo: 127.0.0.1:80 TCP>
|
||||
# Addrinfo.tcp("www.example.com", 443) #=> #<Addrinfo: 93.184.216.34:443 TCP>
|
||||
#
|
||||
def self.tcp(host, port)
|
||||
Addrinfo.getaddrinfo(host, port, nil, Socket::SOCK_STREAM, Socket::IPPROTO_TCP)[0]
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# Addrinfo.udp(host, port) -> addrinfo
|
||||
#
|
||||
# Creates an Addrinfo object for UDP connection to the given host and port.
|
||||
#
|
||||
# Addrinfo.udp("localhost", 53) #=> #<Addrinfo: 127.0.0.1:53 UDP>
|
||||
# Addrinfo.udp("8.8.8.8", 53) #=> #<Addrinfo: 8.8.8.8:53 UDP>
|
||||
#
|
||||
def self.udp(host, port)
|
||||
Addrinfo.getaddrinfo(host, port, nil, Socket::SOCK_DGRAM, Socket::IPPROTO_UDP)[0]
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# Addrinfo.unix(path, socktype=Socket::SOCK_STREAM) -> addrinfo
|
||||
#
|
||||
# Creates an Addrinfo object for Unix domain socket at the given path.
|
||||
#
|
||||
# Addrinfo.unix("/tmp/socket") #=> #<Addrinfo: /tmp/socket SOCK_STREAM>
|
||||
# Addrinfo.unix("/var/run/daemon.sock", Socket::SOCK_DGRAM) #=> #<Addrinfo: /var/run/daemon.sock SOCK_DGRAM>
|
||||
#
|
||||
def self.unix(path, socktype=Socket::SOCK_STREAM)
|
||||
Addrinfo.new(Socket.sockaddr_un(path), Socket::AF_UNIX, socktype)
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# addrinfo.afamily -> integer
|
||||
#
|
||||
# Returns the address family of the socket address.
|
||||
#
|
||||
# Addrinfo.tcp("localhost", 80).afamily #=> 2 (AF_INET)
|
||||
# Addrinfo.unix("/tmp/sock").afamily #=> 1 (AF_UNIX)
|
||||
#
|
||||
#
|
||||
# call-seq:
|
||||
# addrinfo.afamily -> integer
|
||||
#
|
||||
# Returns the address family of the socket address.
|
||||
#
|
||||
# Addrinfo.tcp("localhost", 80).afamily #=> 2 (AF_INET)
|
||||
# Addrinfo.unix("/tmp/sock").afamily #=> 1 (AF_UNIX)
|
||||
#
|
||||
def afamily
|
||||
@family
|
||||
end
|
||||
@@ -58,6 +134,15 @@ class Addrinfo
|
||||
# Socket.getnameinfo
|
||||
#end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# addrinfo.inspect -> string
|
||||
#
|
||||
# Returns a string representation of the Addrinfo object.
|
||||
#
|
||||
# Addrinfo.tcp("localhost", 80).inspect #=> "#<Addrinfo: 127.0.0.1:80 TCP>"
|
||||
# Addrinfo.unix("/tmp/sock").inspect #=> "#<Addrinfo: /tmp/sock SOCK_STREAM>"
|
||||
#
|
||||
def inspect
|
||||
if ipv4? or ipv6?
|
||||
if @protocol == Socket::IPPROTO_TCP or (@socktype == Socket::SOCK_STREAM and @protocol == 0)
|
||||
@@ -73,6 +158,15 @@ class Addrinfo
|
||||
"#<Addrinfo: #{inspect_sockaddr} #{proto}>"
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# addrinfo.inspect_sockaddr -> string
|
||||
#
|
||||
# Returns a string representation of the socket address portion.
|
||||
#
|
||||
# Addrinfo.tcp("localhost", 80).inspect_sockaddr #=> "127.0.0.1:80"
|
||||
# Addrinfo.unix("/tmp/sock").inspect_sockaddr #=> "/tmp/sock"
|
||||
#
|
||||
def inspect_sockaddr
|
||||
if ipv4?
|
||||
a, p = ip_unpack
|
||||
@@ -87,23 +181,68 @@ class Addrinfo
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# addrinfo.ip? -> true or false
|
||||
#
|
||||
# Returns true if the address is an IP address (IPv4 or IPv6).
|
||||
#
|
||||
# Addrinfo.tcp("localhost", 80).ip? #=> true
|
||||
# Addrinfo.unix("/tmp/sock").ip? #=> false
|
||||
#
|
||||
def ip?
|
||||
ipv4? or ipv6?
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# addrinfo.ip_address -> string
|
||||
#
|
||||
# Returns the IP address as a string. Raises an exception if not an IP address.
|
||||
#
|
||||
# Addrinfo.tcp("localhost", 80).ip_address #=> "127.0.0.1"
|
||||
# Addrinfo.udp("::1", 53).ip_address #=> "::1"
|
||||
#
|
||||
def ip_address
|
||||
ip_unpack[0]
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# addrinfo.ip_port -> integer
|
||||
#
|
||||
# Returns the port number. Raises an exception if not an IP address.
|
||||
#
|
||||
# Addrinfo.tcp("localhost", 80).ip_port #=> 80
|
||||
# Addrinfo.udp("127.0.0.1", 53).ip_port #=> 53
|
||||
#
|
||||
def ip_port
|
||||
ip_unpack[1]
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# addrinfo.ip_unpack -> [ip_address, port]
|
||||
#
|
||||
# Returns an array containing the IP address and port number.
|
||||
#
|
||||
# Addrinfo.tcp("localhost", 80).ip_unpack #=> ["127.0.0.1", 80]
|
||||
# Addrinfo.udp("::1", 53).ip_unpack #=> ["::1", 53]
|
||||
#
|
||||
def ip_unpack
|
||||
h, p = getnameinfo(Socket::NI_NUMERICHOST|Socket::NI_NUMERICSERV)
|
||||
[ h, p.to_i ]
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# addrinfo.ipv4? -> true or false
|
||||
#
|
||||
# Returns true if the address is an IPv4 address.
|
||||
#
|
||||
# Addrinfo.tcp("127.0.0.1", 80).ipv4? #=> true
|
||||
# Addrinfo.tcp("::1", 80).ipv4? #=> false
|
||||
#
|
||||
def ipv4?
|
||||
@family == Socket::AF_INET
|
||||
end
|
||||
@@ -112,6 +251,15 @@ class Addrinfo
|
||||
#def ipv4_multicast?
|
||||
#def ipv4_private?
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# addrinfo.ipv6? -> true or false
|
||||
#
|
||||
# Returns true if the address is an IPv6 address.
|
||||
#
|
||||
# Addrinfo.tcp("::1", 80).ipv6? #=> true
|
||||
# Addrinfo.tcp("127.0.0.1", 80).ipv6? #=> false
|
||||
#
|
||||
def ipv6?
|
||||
@family == Socket::AF_INET6
|
||||
end
|
||||
@@ -129,13 +277,48 @@ class Addrinfo
|
||||
#def ipv6_v4mapped?
|
||||
#def listen(backlog=5)
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# addrinfo.pfamily -> integer
|
||||
#
|
||||
# Returns the protocol family (same as afamily).
|
||||
#
|
||||
# Addrinfo.tcp("localhost", 80).pfamily #=> 2 (PF_INET)
|
||||
# Addrinfo.unix("/tmp/sock").pfamily #=> 1 (PF_UNIX)
|
||||
#
|
||||
def pfamily
|
||||
@family
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# addrinfo.protocol -> integer
|
||||
#
|
||||
# Returns the protocol number.
|
||||
#
|
||||
# Addrinfo.tcp("localhost", 80).protocol #=> 6 (IPPROTO_TCP)
|
||||
# Addrinfo.udp("localhost", 53).protocol #=> 17 (IPPROTO_UDP)
|
||||
#
|
||||
attr_reader :protocol
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# addrinfo.socktype -> integer
|
||||
#
|
||||
# Returns the socket type.
|
||||
#
|
||||
# Addrinfo.tcp("localhost", 80).socktype #=> 1 (SOCK_STREAM)
|
||||
# Addrinfo.udp("localhost", 53).socktype #=> 2 (SOCK_DGRAM)
|
||||
#
|
||||
attr_reader :socktype
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# addrinfo._to_array -> array
|
||||
#
|
||||
# Internal method that returns the address information as an array.
|
||||
# Used internally by socket operations.
|
||||
#
|
||||
def _to_array
|
||||
case @family
|
||||
when Socket::AF_INET
|
||||
@@ -151,12 +334,30 @@ class Addrinfo
|
||||
[ s, port.to_i, addr, addr ]
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# addrinfo.to_sockaddr -> string
|
||||
#
|
||||
# Returns the socket address as a packed string.
|
||||
#
|
||||
# ai = Addrinfo.tcp("localhost", 80)
|
||||
# ai.to_sockaddr #=> packed sockaddr string
|
||||
#
|
||||
def to_sockaddr
|
||||
@sockaddr
|
||||
end
|
||||
|
||||
alias to_s to_sockaddr
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# addrinfo.unix? -> true or false
|
||||
#
|
||||
# Returns true if the address is a Unix domain socket address.
|
||||
#
|
||||
# Addrinfo.unix("/tmp/sock").unix? #=> true
|
||||
# Addrinfo.tcp("localhost", 80).unix? #=> false
|
||||
#
|
||||
def unix?
|
||||
@family == Socket::AF_UNIX
|
||||
end
|
||||
@@ -165,30 +366,77 @@ end
|
||||
class BasicSocket < IO
|
||||
@@do_not_reverse_lookup = true
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# BasicSocket.do_not_reverse_lookup -> true or false
|
||||
#
|
||||
# Returns the current setting for reverse DNS lookups.
|
||||
#
|
||||
# BasicSocket.do_not_reverse_lookup #=> false
|
||||
#
|
||||
def self.do_not_reverse_lookup
|
||||
@@do_not_reverse_lookup
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# BasicSocket.do_not_reverse_lookup = boolean -> boolean
|
||||
#
|
||||
# Sets whether to perform reverse DNS lookups.
|
||||
#
|
||||
# BasicSocket.do_not_reverse_lookup = true
|
||||
#
|
||||
def self.do_not_reverse_lookup=(val)
|
||||
@@do_not_reverse_lookup = val ? true : false
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# BasicSocket.new(*args) -> basicsocket
|
||||
#
|
||||
# Creates a new BasicSocket object. This is typically called by subclasses.
|
||||
#
|
||||
def initialize(*args)
|
||||
super(*args)
|
||||
self._is_socket = true
|
||||
@do_not_reverse_lookup = @@do_not_reverse_lookup
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# BasicSocket.for_fd(fd) -> basicsocket
|
||||
#
|
||||
# Creates a BasicSocket object from an existing file descriptor.
|
||||
#
|
||||
# sock = BasicSocket.for_fd(3)
|
||||
#
|
||||
def self.for_fd(fd)
|
||||
super(fd, "r+")
|
||||
end
|
||||
|
||||
#def connect_address
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# basicsocket.local_address -> addrinfo
|
||||
#
|
||||
# Returns an Addrinfo object for the local address of the socket.
|
||||
#
|
||||
# sock.local_address #=> #<Addrinfo: 127.0.0.1:12345 TCP>
|
||||
#
|
||||
def local_address
|
||||
Addrinfo.new self.getsockname
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# basicsocket.recv_nonblock(maxlen, flags=0) -> string
|
||||
#
|
||||
# Receives data from the socket without blocking. May raise an exception
|
||||
# if no data is available.
|
||||
#
|
||||
# data = sock.recv_nonblock(1024)
|
||||
#
|
||||
def recv_nonblock(maxlen, flags=0)
|
||||
begin
|
||||
_setnonblock(true)
|
||||
@@ -198,6 +446,14 @@ class BasicSocket < IO
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# basicsocket.remote_address -> addrinfo
|
||||
#
|
||||
# Returns an Addrinfo object for the remote address of the socket.
|
||||
#
|
||||
# sock.remote_address #=> #<Addrinfo: 192.168.1.1:80 TCP>
|
||||
#
|
||||
def remote_address
|
||||
Addrinfo.new self.getpeername
|
||||
end
|
||||
@@ -206,18 +462,52 @@ class BasicSocket < IO
|
||||
end
|
||||
|
||||
class IPSocket < BasicSocket
|
||||
#
|
||||
# call-seq:
|
||||
# IPSocket.getaddress(host) -> string
|
||||
#
|
||||
# Returns the IP address of the given hostname as a string.
|
||||
#
|
||||
# IPSocket.getaddress("localhost") #=> "127.0.0.1"
|
||||
# IPSocket.getaddress("www.ruby-lang.org") #=> "150.95.145.38"
|
||||
#
|
||||
def self.getaddress(host)
|
||||
Addrinfo.ip(host).ip_address
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# ipsocket.addr -> [family, port, hostname, ip_address]
|
||||
#
|
||||
# Returns the local address information as an array.
|
||||
#
|
||||
# sock.addr #=> ["AF_INET", 12345, "localhost", "127.0.0.1"]
|
||||
#
|
||||
def addr
|
||||
Addrinfo.new(self.getsockname)._to_array
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# ipsocket.peeraddr -> [family, port, hostname, ip_address]
|
||||
#
|
||||
# Returns the remote address information as an array.
|
||||
#
|
||||
# sock.peeraddr #=> ["AF_INET", 80, "example.com", "93.184.216.34"]
|
||||
#
|
||||
def peeraddr
|
||||
Addrinfo.new(self.getpeername)._to_array
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# ipsocket.recvfrom(maxlen, flags=0) -> [data, addrinfo]
|
||||
#
|
||||
# Receives data and sender information from the IP socket.
|
||||
#
|
||||
# data, addr = sock.recvfrom(1024)
|
||||
# data, addr = sock.recvfrom(512, 0)
|
||||
#
|
||||
def recvfrom(maxlen, flags=0)
|
||||
msg, sa = _recvfrom(maxlen, flags)
|
||||
[ msg, Addrinfo.new(sa)._to_array ]
|
||||
@@ -225,6 +515,17 @@ class IPSocket < BasicSocket
|
||||
end
|
||||
|
||||
class TCPSocket < IPSocket
|
||||
#
|
||||
# call-seq:
|
||||
# TCPSocket.new(host, service, local_host=nil, local_service=nil) -> tcpsocket
|
||||
#
|
||||
# Creates a new TCP socket connected to the given host and service.
|
||||
# Optionally binds to local_host and local_service first.
|
||||
#
|
||||
# sock = TCPSocket.new("localhost", 80)
|
||||
# sock = TCPSocket.new("www.example.com", "http")
|
||||
# sock = TCPSocket.new("remote", 80, "127.0.0.1", 12345)
|
||||
#
|
||||
def initialize(host, service, local_host=nil, local_service=nil)
|
||||
if @init_with_fd
|
||||
super(host, service)
|
||||
@@ -254,6 +555,17 @@ class TCPSocket < IPSocket
|
||||
end
|
||||
|
||||
class TCPServer < TCPSocket
|
||||
#
|
||||
# call-seq:
|
||||
# TCPServer.new(host=nil, service) -> tcpserver
|
||||
#
|
||||
# Creates a new TCP server socket bound to the given host and service.
|
||||
# If host is nil, binds to all available interfaces.
|
||||
#
|
||||
# server = TCPServer.new("localhost", 8080)
|
||||
# server = TCPServer.new(nil, 3000) # binds to all interfaces
|
||||
# server = TCPServer.new("0.0.0.0", "http")
|
||||
#
|
||||
def initialize(host=nil, service)
|
||||
ai = Addrinfo.getaddrinfo(host, service, nil, nil, nil, Socket::AI_PASSIVE)[0]
|
||||
@init_with_fd = true
|
||||
@@ -266,6 +578,15 @@ class TCPServer < TCPSocket
|
||||
self
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# tcpserver.accept -> tcpsocket
|
||||
#
|
||||
# Accepts an incoming connection and returns a new TCPSocket.
|
||||
#
|
||||
# server = TCPServer.new(8080)
|
||||
# client = server.accept
|
||||
#
|
||||
def accept
|
||||
fd = self.sysaccept
|
||||
begin
|
||||
@@ -281,6 +602,15 @@ class TCPServer < TCPSocket
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# tcpserver.accept_nonblock -> unixsocket
|
||||
#
|
||||
# Accepts an incoming connection without blocking. May raise an exception
|
||||
# if no connection is available.
|
||||
#
|
||||
# client = server.accept_nonblock
|
||||
#
|
||||
def accept_nonblock
|
||||
begin
|
||||
self._setnonblock(true)
|
||||
@@ -290,33 +620,86 @@ class TCPServer < TCPSocket
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# unixserver.listen(backlog) -> 0
|
||||
#
|
||||
# Sets the socket to listen for incoming connections with the given backlog.
|
||||
#
|
||||
# server.listen(5)
|
||||
# server.listen(128)
|
||||
#
|
||||
def listen(backlog)
|
||||
Socket._listen(self.fileno, backlog)
|
||||
0
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# tcpserver.sysaccept -> integer
|
||||
#
|
||||
# Accepts an incoming connection and returns the file descriptor.
|
||||
#
|
||||
# fd = server.sysaccept
|
||||
#
|
||||
def sysaccept
|
||||
Socket._accept(self.fileno)
|
||||
end
|
||||
end
|
||||
|
||||
class UDPSocket < IPSocket
|
||||
#
|
||||
# call-seq:
|
||||
# UDPSocket.new(af=Socket::AF_INET) -> udpsocket
|
||||
#
|
||||
# Creates a new UDP socket for the given address family.
|
||||
#
|
||||
# sock = UDPSocket.new
|
||||
# sock = UDPSocket.new(Socket::AF_INET6)
|
||||
#
|
||||
def initialize(af=Socket::AF_INET)
|
||||
super(Socket._socket(af, Socket::SOCK_DGRAM, 0), "r+")
|
||||
@af = af
|
||||
self
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# ipsocket.bind(host, port) -> 0
|
||||
#
|
||||
# Binds the socket to the given host and port.
|
||||
#
|
||||
# sock.bind("127.0.0.1", 8080)
|
||||
# sock.bind("0.0.0.0", 3000)
|
||||
#
|
||||
def bind(host, port)
|
||||
Socket._bind(self.fileno, _sockaddr_in(port, host))
|
||||
0
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# ipsocket.connect(host, port) -> 0
|
||||
#
|
||||
# Connects the socket to the given host and port.
|
||||
#
|
||||
# sock.connect("127.0.0.1", 80)
|
||||
# sock.connect("www.example.com", 443)
|
||||
#
|
||||
def connect(host, port)
|
||||
Socket._connect(self.fileno, _sockaddr_in(port, host))
|
||||
0
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# udpsocket.recvfrom_nonblock(maxlen, flags=0) -> [data, addrinfo]
|
||||
#
|
||||
# Receives data and sender information without blocking.
|
||||
# May raise an exception if no data is available.
|
||||
#
|
||||
# data, addr = sock.recvfrom_nonblock(1024)
|
||||
#
|
||||
def recvfrom_nonblock(*args)
|
||||
s = self
|
||||
begin
|
||||
@@ -328,6 +711,15 @@ class UDPSocket < IPSocket
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# ipsocket.send(mesg, flags, host=nil, port=nil) -> integer
|
||||
#
|
||||
# Sends data through the socket. Returns the number of bytes sent.
|
||||
#
|
||||
# sock.send("Hello", 0)
|
||||
# sock.send("Data", 0, "127.0.0.1", 8080)
|
||||
#
|
||||
def send(mesg, flags, host=nil, port=nil)
|
||||
if port
|
||||
super(mesg, flags, _sockaddr_in(port, host))
|
||||
@@ -338,6 +730,13 @@ class UDPSocket < IPSocket
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# udpsocket._sockaddr_in(port, host) -> string
|
||||
#
|
||||
# Internal method to create a sockaddr_in structure for the given port and host.
|
||||
# Uses the socket's address family.
|
||||
#
|
||||
def _sockaddr_in(port, host)
|
||||
ai = Addrinfo.getaddrinfo(host, port, @af, Socket::SOCK_DGRAM)[0]
|
||||
ai.to_sockaddr
|
||||
@@ -345,12 +744,30 @@ class UDPSocket < IPSocket
|
||||
end
|
||||
|
||||
class Socket < BasicSocket
|
||||
#
|
||||
# call-seq:
|
||||
# Socket.new(domain, type, protocol=0) -> socket
|
||||
#
|
||||
# Creates a new socket with the given domain, type, and protocol.
|
||||
#
|
||||
# sock = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
|
||||
# sock = Socket.new(Socket::AF_UNIX, Socket::SOCK_DGRAM)
|
||||
#
|
||||
def initialize(domain, type, protocol=0)
|
||||
super(Socket._socket(domain, type, protocol), "r+")
|
||||
end
|
||||
|
||||
#def self.accept_loop
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# Socket.getaddrinfo(nodename, servname, family=nil, socktype=nil, protocol=nil, flags=0) -> array
|
||||
#
|
||||
# Returns an array of Addrinfo objects for the given nodename and servname.
|
||||
#
|
||||
# Addrinfo.getaddrinfo("localhost", "http")
|
||||
# Addrinfo.getaddrinfo("www.example.com", 80, Socket::AF_INET)
|
||||
#
|
||||
def self.getaddrinfo(nodename, servname, family=nil, socktype=nil, protocol=nil, flags=0)
|
||||
Addrinfo.getaddrinfo(nodename, servname, family, socktype, protocol, flags).map { |ai|
|
||||
ary = ai._to_array
|
||||
@@ -365,10 +782,27 @@ class Socket < BasicSocket
|
||||
#def self.getnameinfo
|
||||
#def self.ip_address_list
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# Socket.open(domain, type, protocol=0) -> socket
|
||||
#
|
||||
# Creates a new socket. Alias for Socket.new.
|
||||
#
|
||||
# sock = Socket.open(Socket::AF_INET, Socket::SOCK_STREAM)
|
||||
#
|
||||
def self.open(*args)
|
||||
new(args)
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# Socket.sockaddr_in(port, host) -> string
|
||||
#
|
||||
# Returns a packed sockaddr_in structure for the given port and host.
|
||||
#
|
||||
# Socket.sockaddr_in(80, "127.0.0.1")
|
||||
# Socket.sockaddr_in(443, "localhost")
|
||||
#
|
||||
def self.sockaddr_in(port, host)
|
||||
ai = Addrinfo.getaddrinfo(host, port, nil, Socket::SOCK_DGRAM)[0]
|
||||
ai.to_sockaddr
|
||||
@@ -385,10 +819,26 @@ class Socket < BasicSocket
|
||||
#def self.unix_server_loop
|
||||
#def self.unix_server_socket
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# Socket.unpack_sockaddr_in(sockaddr) -> [port, ip_address]
|
||||
#
|
||||
# Unpacks a packed sockaddr_in structure and returns port and IP address.
|
||||
#
|
||||
# port, addr = Socket.unpack_sockaddr_in(sockaddr)
|
||||
#
|
||||
def self.unpack_sockaddr_in(sa)
|
||||
Addrinfo.new(sa).ip_unpack.reverse
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# Socket.unpack_sockaddr_un(sockaddr) -> path
|
||||
#
|
||||
# Unpacks a packed sockaddr_un structure and returns the Unix socket path.
|
||||
#
|
||||
# path = Socket.unpack_sockaddr_un(sockaddr)
|
||||
#
|
||||
def self.unpack_sockaddr_un(sa)
|
||||
Addrinfo.new(sa).unix_path
|
||||
end
|
||||
@@ -413,18 +863,45 @@ class Socket < BasicSocket
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# socket.bind(sockaddr) -> 0
|
||||
#
|
||||
# Binds the socket to the given socket address.
|
||||
#
|
||||
# sock.bind(Socket.sockaddr_in(8080, "127.0.0.1"))
|
||||
# sock.bind(addrinfo)
|
||||
#
|
||||
def bind(sockaddr)
|
||||
sockaddr = sockaddr.to_sockaddr if sockaddr.is_a? Addrinfo
|
||||
Socket._bind(self.fileno, sockaddr)
|
||||
0
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# socket.connect(sockaddr) -> 0
|
||||
#
|
||||
# Connects the socket to the given socket address.
|
||||
#
|
||||
# sock.connect(Socket.sockaddr_in(80, "127.0.0.1"))
|
||||
# sock.connect(addrinfo)
|
||||
#
|
||||
def connect(sockaddr)
|
||||
sockaddr = sockaddr.to_sockaddr if sockaddr.is_a? Addrinfo
|
||||
Socket._connect(self.fileno, sockaddr)
|
||||
0
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# socket.connect_nonblock(sockaddr) -> 0
|
||||
#
|
||||
# Connects the socket to the given address without blocking.
|
||||
# May raise an exception if the connection cannot be completed immediately.
|
||||
#
|
||||
# sock.connect_nonblock(sockaddr)
|
||||
#
|
||||
def connect_nonblock(sockaddr)
|
||||
begin
|
||||
self._setnonblock(true)
|
||||
@@ -462,6 +939,17 @@ class Socket < BasicSocket
|
||||
end
|
||||
|
||||
class UNIXSocket < BasicSocket
|
||||
#
|
||||
# call-seq:
|
||||
# UNIXSocket.new(path) -> unixsocket
|
||||
# UNIXSocket.new(path) { |sock| block } -> obj
|
||||
#
|
||||
# Creates a new Unix domain socket connected to the given path.
|
||||
# If a block is given, yields the socket and closes it when done.
|
||||
#
|
||||
# sock = UNIXSocket.new("/tmp/socket")
|
||||
# UNIXSocket.new("/tmp/socket") { |s| s.write("data") }
|
||||
#
|
||||
def initialize(path, &block)
|
||||
if self.is_a? UNIXServer
|
||||
super(path, "r")
|
||||
@@ -483,6 +971,15 @@ class UNIXSocket < BasicSocket
|
||||
end
|
||||
|
||||
class << self
|
||||
#
|
||||
# call-seq:
|
||||
# UNIXSocket.socketpair(type=Socket::SOCK_STREAM, protocol=0) -> [socket1, socket2]
|
||||
#
|
||||
# Creates a pair of connected Unix domain sockets.
|
||||
#
|
||||
# sock1, sock2 = UNIXSocket.socketpair
|
||||
# sock1, sock2 = UNIXSocket.socketpair(Socket::SOCK_DGRAM)
|
||||
#
|
||||
def socketpair(type=Socket::SOCK_STREAM, protocol=0)
|
||||
a = Socket.socketpair(Socket::AF_UNIX, type, protocol)
|
||||
[ UNIXSocket.for_fd(a[0]), UNIXSocket.for_fd(a[1]) ]
|
||||
@@ -491,14 +988,38 @@ class UNIXSocket < BasicSocket
|
||||
alias pair socketpair
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# unixsocket.addr -> [family, path]
|
||||
#
|
||||
# Returns the local address information as an array.
|
||||
#
|
||||
# sock.addr #=> ["AF_UNIX", "/tmp/socket"]
|
||||
#
|
||||
def addr
|
||||
[ "AF_UNIX", path ]
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# unixsocket.path -> string
|
||||
#
|
||||
# Returns the path of the Unix domain socket.
|
||||
#
|
||||
# sock.path #=> "/tmp/socket"
|
||||
#
|
||||
def path
|
||||
Addrinfo.new(self.getsockname).unix_path
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# unixsocket.peeraddr -> [family, path]
|
||||
#
|
||||
# Returns the remote address information as an array.
|
||||
#
|
||||
# sock.peeraddr #=> ["AF_UNIX", "/tmp/peer_socket"]
|
||||
#
|
||||
def peeraddr
|
||||
[ "AF_UNIX", Addrinfo.new(self.getpeername).unix_path ]
|
||||
end
|
||||
@@ -515,6 +1036,14 @@ class UNIXSocket < BasicSocket
|
||||
end
|
||||
|
||||
class UNIXServer < UNIXSocket
|
||||
#
|
||||
# call-seq:
|
||||
# UNIXServer.new(path) -> unixserver
|
||||
#
|
||||
# Creates a new Unix domain server socket bound to the given path.
|
||||
#
|
||||
# server = UNIXServer.new("/tmp/server_socket")
|
||||
#
|
||||
def initialize(path)
|
||||
fd = Socket._socket(Socket::AF_UNIX, Socket::SOCK_STREAM, 0)
|
||||
begin
|
||||
@@ -535,6 +1064,15 @@ class UNIXServer < UNIXSocket
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# unixserver.accept -> unixsocket
|
||||
#
|
||||
# Accepts an incoming connection and returns a new UNIXSocket.
|
||||
#
|
||||
# server = UNIXServer.new("/tmp/server")
|
||||
# client = server.accept
|
||||
#
|
||||
def accept
|
||||
fd = self.sysaccept
|
||||
begin
|
||||
@@ -545,6 +1083,15 @@ class UNIXServer < UNIXSocket
|
||||
sock
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# unixserver.accept_nonblock -> unixsocket
|
||||
#
|
||||
# Accepts an incoming connection without blocking. May raise an exception
|
||||
# if no connection is available.
|
||||
#
|
||||
# client = server.accept_nonblock
|
||||
#
|
||||
def accept_nonblock
|
||||
begin
|
||||
self._setnonblock(true)
|
||||
@@ -554,11 +1101,28 @@ class UNIXServer < UNIXSocket
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# unixserver.listen(backlog) -> 0
|
||||
#
|
||||
# Sets the socket to listen for incoming connections with the given backlog.
|
||||
#
|
||||
# server.listen(5)
|
||||
# server.listen(128)
|
||||
#
|
||||
def listen(backlog)
|
||||
Socket._listen(self.fileno, backlog)
|
||||
0
|
||||
end
|
||||
|
||||
#
|
||||
# call-seq:
|
||||
# unixserver.sysaccept -> integer
|
||||
#
|
||||
# Accepts an incoming connection and returns the file descriptor.
|
||||
#
|
||||
# fd = server.sysaccept
|
||||
#
|
||||
def sysaccept
|
||||
Socket._accept(self.fileno)
|
||||
end
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
#define E_SOCKET_ERROR mrb_class_get_id(mrb, MRB_SYM(SocketError))
|
||||
|
||||
#ifdef _WIN32
|
||||
/* Windows implementation of inet_ntop - converts network address to string */
|
||||
static const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt)
|
||||
{
|
||||
if (af == AF_INET) {
|
||||
@@ -77,6 +78,7 @@ static const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Windows implementation of inet_pton - converts string address to network format */
|
||||
static int inet_pton(int af, const char *src, void *dst)
|
||||
{
|
||||
struct addrinfo hints = {0};
|
||||
@@ -103,6 +105,7 @@ struct gen_addrinfo_args {
|
||||
struct addrinfo *addrinfo;
|
||||
};
|
||||
|
||||
/* Helper to generate array of Addrinfo objects from addrinfo linked list */
|
||||
static mrb_value
|
||||
gen_addrinfo(mrb_state *mrb, mrb_value args)
|
||||
{
|
||||
@@ -120,6 +123,7 @@ gen_addrinfo(mrb_state *mrb, mrb_value args)
|
||||
return ary;
|
||||
}
|
||||
|
||||
/* Helper to free addrinfo structure - used with mrb_ensure */
|
||||
static mrb_value
|
||||
free_addrinfo(mrb_state *mrb, mrb_value addrinfo)
|
||||
{
|
||||
@@ -127,6 +131,15 @@ free_addrinfo(mrb_state *mrb, mrb_value addrinfo)
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* Addrinfo.getaddrinfo(nodename, servname, family=nil, socktype=nil, protocol=nil, flags=0) -> array
|
||||
*
|
||||
* Returns an array of Addrinfo objects for the given nodename and servname.
|
||||
*
|
||||
* Addrinfo.getaddrinfo("localhost", "http")
|
||||
* Addrinfo.getaddrinfo("www.example.com", 80, Socket::AF_INET)
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_addrinfo_getaddrinfo(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
@@ -175,6 +188,15 @@ mrb_addrinfo_getaddrinfo(mrb_state *mrb, mrb_value klass)
|
||||
return mrb_ensure(mrb, gen_addrinfo, mrb_cptr_value(mrb, &args), free_addrinfo, mrb_cptr_value(mrb, addr));
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* addrinfo.getnameinfo(flags=0) -> [hostname, service]
|
||||
*
|
||||
* Returns the hostname and service name for the address.
|
||||
*
|
||||
* addr.getnameinfo #=> ["localhost", "http"]
|
||||
* addr.getnameinfo(Socket::NI_NUMERICHOST) #=> ["127.0.0.1", "80"]
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_addrinfo_getnameinfo(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
@@ -201,6 +223,14 @@ mrb_addrinfo_getnameinfo(mrb_state *mrb, mrb_value self)
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
/*
|
||||
* call-seq:
|
||||
* addrinfo.unix_path -> string
|
||||
*
|
||||
* Returns the Unix domain socket path.
|
||||
*
|
||||
* addr.unix_path #=> "/tmp/socket"
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_addrinfo_unix_path(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
@@ -217,6 +247,7 @@ mrb_addrinfo_unix_path(mrb_state *mrb, mrb_value self)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Helper to convert sockaddr to address list array [family, port, host, host] */
|
||||
static mrb_value
|
||||
sa2addrlist(mrb_state *mrb, const struct sockaddr *sa, socklen_t salen)
|
||||
{
|
||||
@@ -252,12 +283,14 @@ sa2addrlist(mrb_state *mrb, const struct sockaddr *sa, socklen_t salen)
|
||||
|
||||
int mrb_io_fileno(mrb_state *mrb, mrb_value io);
|
||||
|
||||
/* Helper to extract file descriptor from socket object */
|
||||
static int
|
||||
socket_fd(mrb_state *mrb, mrb_value sock)
|
||||
{
|
||||
return mrb_io_fileno(mrb, sock);
|
||||
}
|
||||
|
||||
/* Helper to get address family of socket by file descriptor */
|
||||
static int
|
||||
socket_family(int s)
|
||||
{
|
||||
@@ -269,6 +302,15 @@ socket_family(int s)
|
||||
return ss.ss_family;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* basicsocket.getpeereid -> [euid, egid]
|
||||
*
|
||||
* Returns the effective user ID and group ID of the peer process.
|
||||
* Only available on systems that support getpeereid().
|
||||
*
|
||||
* euid, egid = sock.getpeereid
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_basicsocket_getpeereid(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
@@ -289,6 +331,14 @@ mrb_basicsocket_getpeereid(mrb_state *mrb, mrb_value self)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* basicsocket.getpeername -> string
|
||||
*
|
||||
* Returns the remote socket address as a packed sockaddr string.
|
||||
*
|
||||
* sockaddr = sock.getpeername
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_basicsocket_getpeername(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
@@ -301,6 +351,14 @@ mrb_basicsocket_getpeername(mrb_state *mrb, mrb_value self)
|
||||
return mrb_str_new(mrb, (char*)&ss, salen);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* basicsocket.getsockname -> string
|
||||
*
|
||||
* Returns the local socket address as a packed sockaddr string.
|
||||
*
|
||||
* sockaddr = sock.getsockname
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_basicsocket_getsockname(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
@@ -313,12 +371,21 @@ mrb_basicsocket_getsockname(mrb_state *mrb, mrb_value self)
|
||||
return mrb_str_new(mrb, (char*)&ss, salen);
|
||||
}
|
||||
|
||||
/* Helper to get Socket::Option class reference */
|
||||
static struct RClass *
|
||||
socket_option_class(mrb_state *mrb)
|
||||
{
|
||||
return mrb_class_get_under_id(mrb, mrb_class_get_id(mrb, MRB_SYM(Socket)), MRB_SYM(Option));
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* Socket::Option.new(family, level, optname, data) -> socket_option
|
||||
*
|
||||
* Creates a new Socket::Option object with the given parameters.
|
||||
*
|
||||
* opt = Socket::Option.new(Socket::AF_INET, Socket::SOL_SOCKET, Socket::SO_REUSEADDR, [1].pack("i"))
|
||||
*/
|
||||
static mrb_value
|
||||
socket_option_init(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
@@ -334,6 +401,14 @@ socket_option_init(mrb_state *mrb, mrb_value self)
|
||||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* Socket::Option.bool(family, level, optname, bool) -> socket_option
|
||||
*
|
||||
* Creates a new Socket::Option object from a boolean value.
|
||||
*
|
||||
* opt = Socket::Option.bool(Socket::AF_INET, Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true)
|
||||
*/
|
||||
static mrb_value
|
||||
socket_option_s_bool(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
@@ -347,6 +422,14 @@ socket_option_s_bool(mrb_state *mrb, mrb_value klass)
|
||||
return mrb_obj_new(mrb, mrb_class_ptr(klass), 4, args);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* Socket::Option.int(family, level, optname, integer) -> socket_option
|
||||
*
|
||||
* Creates a new Socket::Option object from an integer value.
|
||||
*
|
||||
* opt = Socket::Option.int(Socket::AF_INET, Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1)
|
||||
*/
|
||||
static mrb_value
|
||||
socket_option_s_int(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
@@ -360,30 +443,63 @@ socket_option_s_int(mrb_state *mrb, mrb_value klass)
|
||||
return mrb_obj_new(mrb, mrb_class_ptr(klass), 4, args);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* socket_option.family -> integer
|
||||
*
|
||||
* Returns the address family of the socket option.
|
||||
*
|
||||
* opt.family #=> Socket::AF_INET
|
||||
*/
|
||||
static mrb_value
|
||||
socket_option_family(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
return mrb_iv_get(mrb, self, MRB_SYM(family));
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* socket_option.level -> integer
|
||||
*
|
||||
* Returns the protocol level of the socket option.
|
||||
*
|
||||
* opt.level #=> Socket::SOL_SOCKET
|
||||
*/
|
||||
static mrb_value
|
||||
socket_option_level(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
return mrb_iv_get(mrb, self, MRB_SYM(level));
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* socket_option.optname -> integer
|
||||
*
|
||||
* Returns the option name of the socket option.
|
||||
*
|
||||
* opt.optname #=> Socket::SO_REUSEADDR
|
||||
*/
|
||||
static mrb_value
|
||||
socket_option_optname(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
return mrb_iv_get(mrb, self, MRB_SYM(optname));
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* socket_option.data -> string
|
||||
*
|
||||
* Returns the raw data of the socket option as a string.
|
||||
*
|
||||
* opt.data #=> "\x01\x00\x00\x00"
|
||||
*/
|
||||
static mrb_value
|
||||
socket_option_data(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
return mrb_iv_get(mrb, self, MRB_SYM(data));
|
||||
}
|
||||
|
||||
/* Helper to extract integer value from Socket::Option data */
|
||||
static int
|
||||
option_int(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
@@ -398,6 +514,14 @@ option_int(mrb_state *mrb, mrb_value self)
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* socket_option.int -> integer
|
||||
*
|
||||
* Returns the socket option data as an integer value.
|
||||
*
|
||||
* opt.int #=> 1
|
||||
*/
|
||||
static mrb_value
|
||||
socket_option_int(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
@@ -405,6 +529,14 @@ socket_option_int(mrb_state *mrb, mrb_value self)
|
||||
return mrb_int_value(mrb, (mrb_int)i);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* socket_option.bool -> true or false
|
||||
*
|
||||
* Returns the socket option data as a boolean value.
|
||||
*
|
||||
* opt.bool #=> true
|
||||
*/
|
||||
static mrb_value
|
||||
socket_option_bool(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
@@ -412,6 +544,7 @@ socket_option_bool(mrb_state *mrb, mrb_value self)
|
||||
return mrb_bool_value((mrb_bool)i);
|
||||
}
|
||||
|
||||
/* Helper to raise not implemented error for unimplemented Socket::Option methods */
|
||||
static mrb_value
|
||||
socket_option_notimp(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
@@ -419,6 +552,14 @@ socket_option_notimp(mrb_state *mrb, mrb_value self)
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* socket_option.inspect -> string
|
||||
*
|
||||
* Returns a string representation of the socket option for debugging.
|
||||
*
|
||||
* opt.inspect #=> "#<Socket::Option: INET level:1 optname:2 \"\\x01\\x00\\x00\\x00\">"
|
||||
*/
|
||||
static mrb_value
|
||||
socket_option_inspect(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
@@ -475,6 +616,14 @@ socket_option_inspect(mrb_state *mrb, mrb_value self)
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* basicsocket.getsockopt(level, optname) -> string
|
||||
*
|
||||
* Gets a socket option. Returns the option value as a string.
|
||||
*
|
||||
* val = sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR)
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_basicsocket_getsockopt(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
@@ -494,6 +643,15 @@ mrb_basicsocket_getsockopt(mrb_state *mrb, mrb_value self)
|
||||
return mrb_obj_new(mrb, socket_option_class(mrb), 4, args);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* basicsocket.recv(maxlen, flags=0) -> string
|
||||
*
|
||||
* Receives data from the socket.
|
||||
*
|
||||
* data = sock.recv(1024)
|
||||
* data = sock.recv(512, 0)
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_basicsocket_recv(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
@@ -509,6 +667,13 @@ mrb_basicsocket_recv(mrb_state *mrb, mrb_value self)
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* basicsocket._recvfrom(maxlen, flags=0) -> [data, sockaddr]
|
||||
*
|
||||
* Internal method to receive data and sender address from socket.
|
||||
* Returns data and packed sockaddr.
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_basicsocket_recvfrom(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
@@ -531,6 +696,14 @@ mrb_basicsocket_recvfrom(mrb_state *mrb, mrb_value self)
|
||||
return ary;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* basicsocket.send(mesg, flags) -> integer
|
||||
*
|
||||
* Sends data through the socket. Returns the number of bytes sent.
|
||||
*
|
||||
* bytes_sent = sock.send("Hello", 0)
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_basicsocket_send(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
@@ -552,6 +725,15 @@ mrb_basicsocket_send(mrb_state *mrb, mrb_value self)
|
||||
return mrb_fixnum_value((mrb_int)n);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* basicsocket._setnonblock(flag) -> nil
|
||||
*
|
||||
* Internal method to set or unset non-blocking mode on the socket.
|
||||
*
|
||||
* sock._setnonblock(true) # enable non-blocking
|
||||
* sock._setnonblock(false) # disable non-blocking
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_basicsocket_setnonblock(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
@@ -580,6 +762,14 @@ mrb_basicsocket_setnonblock(mrb_state *mrb, mrb_value self)
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* basicsocket.setsockopt(level, optname, optval) -> 0
|
||||
*
|
||||
* Sets a socket option. Level and optname are constants, optval is the value.
|
||||
*
|
||||
* sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1)
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_basicsocket_setsockopt(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
@@ -629,6 +819,16 @@ mrb_basicsocket_setsockopt(mrb_state *mrb, mrb_value self)
|
||||
return mrb_fixnum_value(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* basicsocket.shutdown(how=Socket::SHUT_RDWR) -> 0
|
||||
*
|
||||
* Shuts down part of the socket connection.
|
||||
*
|
||||
* sock.shutdown(Socket::SHUT_RD) # shutdown reading
|
||||
* sock.shutdown(Socket::SHUT_WR) # shutdown writing
|
||||
* sock.shutdown(Socket::SHUT_RDWR) # shutdown both (default)
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_basicsocket_shutdown(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
@@ -640,6 +840,7 @@ mrb_basicsocket_shutdown(mrb_state *mrb, mrb_value self)
|
||||
return mrb_fixnum_value(0);
|
||||
}
|
||||
|
||||
/* Helper to set socket flag on IO object */
|
||||
static mrb_value
|
||||
mrb_basicsocket_set_is_socket(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
@@ -654,6 +855,14 @@ mrb_basicsocket_set_is_socket(mrb_state *mrb, mrb_value self)
|
||||
return mrb_bool_value(b);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* IPSocket.ntop(af, addr) -> string
|
||||
*
|
||||
* Converts a network address to a string representation.
|
||||
*
|
||||
* IPSocket.ntop(Socket::AF_INET, "\x7f\x00\x00\x01") #=> "127.0.0.1"
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_ipsocket_ntop(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
@@ -668,6 +877,14 @@ mrb_ipsocket_ntop(mrb_state *mrb, mrb_value klass)
|
||||
return mrb_str_new_cstr(mrb, buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* IPSocket.pton(af, hostname) -> string
|
||||
*
|
||||
* Converts a string representation of an address to network format.
|
||||
*
|
||||
* IPSocket.pton(Socket::AF_INET, "127.0.0.1") #=> "\x7f\x00\x00\x01"
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_ipsocket_pton(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
@@ -701,6 +918,15 @@ invalid:
|
||||
return mrb_nil_value(); /* dummy */
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ipsocket.recvfrom(maxlen, flags=0) -> [data, [family, port, hostname, ip]]
|
||||
*
|
||||
* Receives data from the socket and returns sender address information.
|
||||
*
|
||||
* data, addr = sock.recvfrom(1024)
|
||||
* # addr => ["AF_INET", 12345, "hostname", "192.168.1.1"]
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_ipsocket_recvfrom(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
@@ -727,6 +953,14 @@ mrb_ipsocket_recvfrom(mrb_state *mrb, mrb_value self)
|
||||
return pair;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* Socket.gethostname -> string
|
||||
*
|
||||
* Returns the hostname of the current machine.
|
||||
*
|
||||
* Socket.gethostname #=> "localhost"
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_socket_gethostname(mrb_state *mrb, mrb_value cls)
|
||||
{
|
||||
@@ -743,6 +977,13 @@ mrb_socket_gethostname(mrb_state *mrb, mrb_value cls)
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* Socket._accept(fd) -> [new_fd, sockaddr]
|
||||
*
|
||||
* Internal method to accept a connection on a socket file descriptor.
|
||||
* Returns the new file descriptor and remote address.
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_socket_accept(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
@@ -778,6 +1019,12 @@ mrb_socket_accept2(mrb_state *mrb, mrb_value klass)
|
||||
return ary;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* Socket._bind(fd, sockaddr) -> 0
|
||||
*
|
||||
* Internal method to bind a socket file descriptor to the given address.
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_socket_bind(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
@@ -791,6 +1038,12 @@ mrb_socket_bind(mrb_state *mrb, mrb_value klass)
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* Socket._connect(fd, sockaddr) -> 0
|
||||
*
|
||||
* Internal method to connect a socket file descriptor to the given address.
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_socket_connect(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
@@ -804,6 +1057,12 @@ mrb_socket_connect(mrb_state *mrb, mrb_value klass)
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* Socket._listen(fd, backlog) -> 0
|
||||
*
|
||||
* Internal method to set a socket file descriptor to listen for connections.
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_socket_listen(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
@@ -830,6 +1089,15 @@ mrb_socket_sockaddr_family(mrb_state *mrb, mrb_value klass)
|
||||
return mrb_fixnum_value(sa->sa_family);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* Socket.sockaddr_un(path) -> string
|
||||
*
|
||||
* Returns a packed sockaddr_un structure for the given Unix socket path.
|
||||
*
|
||||
* Socket.sockaddr_un("/tmp/socket")
|
||||
* Socket.sockaddr_un("/var/run/daemon.sock")
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_socket_sockaddr_un(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
@@ -857,6 +1125,16 @@ mrb_socket_sockaddr_un(mrb_state *mrb, mrb_value klass)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* Socket.socketpair(domain, type, protocol=0) -> [socket1, socket2]
|
||||
* Socket.pair(domain, type, protocol=0) -> [socket1, socket2]
|
||||
*
|
||||
* Creates a pair of connected sockets.
|
||||
*
|
||||
* sock1, sock2 = Socket.socketpair(Socket::AF_UNIX, Socket::SOCK_STREAM)
|
||||
* sock1, sock2 = Socket.pair(Socket::AF_UNIX, Socket::SOCK_DGRAM)
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_socket_socketpair(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
@@ -880,6 +1158,14 @@ mrb_socket_socketpair(mrb_state *mrb, mrb_value klass)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* Socket._socket(domain, type, protocol) -> fd
|
||||
*
|
||||
* Internal method to create a new socket and return its file descriptor.
|
||||
*
|
||||
* fd = Socket._socket(Socket::AF_INET, Socket::SOCK_STREAM, 0)
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_socket_socket(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
@@ -893,6 +1179,7 @@ mrb_socket_socket(mrb_state *mrb, mrb_value klass)
|
||||
return mrb_fixnum_value(s);
|
||||
}
|
||||
|
||||
/* Helper to allocate TCPSocket object */
|
||||
static mrb_value
|
||||
mrb_tcpsocket_allocate(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
@@ -910,6 +1197,13 @@ mrb_tcpsocket_allocate(mrb_state *mrb, mrb_value klass)
|
||||
* will break on socket descriptors.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
/*
|
||||
* call-seq:
|
||||
* basicsocket.close -> nil
|
||||
*
|
||||
* Windows-specific implementation to close socket using closesocket().
|
||||
* Overrides IO#close for socket objects on Windows.
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_win32_basicsocket_close(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
@@ -918,6 +1212,13 @@ mrb_win32_basicsocket_close(mrb_state *mrb, mrb_value self)
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* basicsocket.sysread(maxlen, outbuf=nil) -> string
|
||||
*
|
||||
* Windows-specific implementation to read from socket using recv().
|
||||
* Overrides IO#sysread for socket objects on Windows.
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_win32_basicsocket_sysread(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
@@ -961,6 +1262,13 @@ mrb_win32_basicsocket_sysread(mrb_state *mrb, mrb_value self)
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* basicsocket.sysseek(offset, whence) -> integer
|
||||
*
|
||||
* Windows-specific implementation that raises NotImplementedError.
|
||||
* Sockets don't support seeking operations.
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_win32_basicsocket_sysseek(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
@@ -968,6 +1276,13 @@ mrb_win32_basicsocket_sysseek(mrb_state *mrb, mrb_value self)
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* basicsocket.syswrite(string) -> integer
|
||||
*
|
||||
* Windows-specific implementation to write to socket using send().
|
||||
* Overrides IO#syswrite for socket objects on Windows.
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_win32_basicsocket_syswrite(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user