#===============================================================================
# ** Module Win32 - Handles numerical based data.
#-------------------------------------------------------------------------------
# Author   Ruby
# Version  1.8.1
#===============================================================================
Â
Â
module Win32
Â
 #--------------------------------------------------------------------------
 # ◠Retrieves data from a pointer.
 #--------------------------------------------------------------------------
 def copymem(len)
  buf = "\0" * len
  Win32API.new("kernel32", "RtlMoveMemory", "ppl", "").call(buf, self, len)
  buf
 end
Â
end
Â
# Extends the numeric class.
class Numeric
 include Win32
end
Â
# Extends the string class.
class String
 include Win32
end
Â
Â
#===============================================================================
# ** Module Winsock - Maps out the functions held in the Winsock DLL.
#-------------------------------------------------------------------------------
# Author   Ruby
# Version  1.8.1
#===============================================================================
Â
module Winsock
Â
 DLL = "ws2_32"
Â
 #--------------------------------------------------------------------------
 # * Accept Connection
 #--------------------------------------------------------------------------
 def self.accept(*args)
  Win32API.new(DLL, "accept", "ppl", "l").call(*args)
 end
Â
 #--------------------------------------------------------------------------
 # * Bind
 #--------------------------------------------------------------------------
 def self.bind(*args)
  Win32API.new(DLL, "bind", "ppl", "l").call(*args)
 end
Â
 #--------------------------------------------------------------------------
 # * Close Socket
 #--------------------------------------------------------------------------
 def self.closesocket(*args)
  Win32API.new(DLL, "closesocket", "p", "l").call(*args)
 end Â
Â
 #--------------------------------------------------------------------------
 # * Connect
 #--------------------------------------------------------------------------
 def self.connect(*args)
  Win32API.new(DLL, "connect", "ppl", "l").call(*args)
 end  Â
Â
 #--------------------------------------------------------------------------
 # * Get host (Using Adress)
 #--------------------------------------------------------------------------
 def self.gethostbyaddr(*args)
  Win32API.new(DLL, "gethostbyaddr", "pll", "l").call(*args)
 end
Â
 #--------------------------------------------------------------------------
 # * Get host (Using Name)
 #--------------------------------------------------------------------------
 def self.gethostbyname(*args)
  Win32API.new(DLL, "gethostbyname", "p", "l").call(*args)
 end
Â
 #--------------------------------------------------------------------------
 # * Get host's Name
 #--------------------------------------------------------------------------
 def self.gethostname(*args)
  Win32API.new(DLL, "gethostname", "pl", "").call(*args)
 end
Â
 #--------------------------------------------------------------------------
 # * Get Server (Using Name)
 #--------------------------------------------------------------------------
 def self.getservbyname(*args)
  Win32API.new(DLL, "getservbyname", "pp", "p").call(*args)
 end
Â
 #--------------------------------------------------------------------------
 # * HT OnL
 #--------------------------------------------------------------------------
 def self.htonl(*args)
  Win32API.new(DLL, "htonl", "l", "l").call(*args)
 end
Â
 #--------------------------------------------------------------------------
 # * HT OnS
 #--------------------------------------------------------------------------
 def self.htons(*args)
  Win32API.new(DLL, "htons", "l", "l").call(*args)
 end
Â
 #--------------------------------------------------------------------------
 # * Inet Adress
 #--------------------------------------------------------------------------
 def self.inet_addr(*args)
  Win32API.new(DLL, "inet_addr", "p", "l").call(*args)
 end
Â
 #--------------------------------------------------------------------------
 # * Inet NtOA
 #--------------------------------------------------------------------------
 def self.inet_ntoa(*args)
  Win32API.new(DLL, "inet_ntoa", "l", "p").call(*args)
 end Â
Â
 #--------------------------------------------------------------------------
 # * Listen
 #--------------------------------------------------------------------------
 def self.listen(*args)
  Win32API.new(DLL, "listen", "pl", "l").call(*args)
 end
Â
 #--------------------------------------------------------------------------
 # * Recieve
 #--------------------------------------------------------------------------
 def self.recv(*args)
  Win32API.new(DLL, "recv", "ppll", "l").call(*args)
 end
Â
 #--------------------------------------------------------------------------
 # * Select
 #--------------------------------------------------------------------------
 def self.select(*args)
  Win32API.new(DLL, "select", "lpppp", "l").call(*args)
 end
Â
 #--------------------------------------------------------------------------
 # * Send
 #--------------------------------------------------------------------------
 def self.send(*args)
  Win32API.new(DLL, "send", "ppll", "l").call(*args)
 end
Â
 #--------------------------------------------------------------------------
 # * Set Socket Options
 #--------------------------------------------------------------------------
 def self.setsockopt(*args)
  Win32API.new(DLL, "setsockopt", "pllpl", "l").call(*args)
 end Â
Â
 #--------------------------------------------------------------------------
 # * Shutdown
 #--------------------------------------------------------------------------
 def self.shutdown(*args)
  Win32API.new(DLL, "shutdown", "pl", "l").call(*args)
 end
Â
 #--------------------------------------------------------------------------
 # * Socket
 #--------------------------------------------------------------------------
 def self.socket(*args)
  Win32API.new(DLL, "socket", "lll", "l").call(*args) Â
 end
Â
 #--------------------------------------------------------------------------
 # * Get Last Error
 #--------------------------------------------------------------------------
 def self.WSAGetLastError(*args)
  Win32API.new(DLL, "WSAGetLastError", "", "l").call(*args)
 end
Â
end
Â
#===============================================================================
# ** Socket - Creates and manages sockets.
#-------------------------------------------------------------------------------
# Author   Ruby
# Version  1.8.1
#===============================================================================
Â
class Socket
Â
 #--------------------------------------------------------------------------
 # ◠Constants
 #--------------------------------------------------------------------------
 AF_UNSPEC         = 0 Â
 AF_UNIX          = 1
 AF_INET          = 2
 AF_IPX           = 6
 AF_APPLETALK        = 16
Â
 PF_UNSPEC         = 0 Â
 PF_UNIX          = 1
 PF_INET          = 2
 PF_IPX           = 6
 PF_APPLETALK        = 16
Â
 SOCK_STREAM        = 1
 SOCK_DGRAM         = 2
 SOCK_RAW          = 3
 SOCK_RDM          = 4
 SOCK_SEQPACKET       = 5
Â
 IPPROTO_IP         = 0
 IPPROTO_ICMP        = 1
 IPPROTO_IGMP        = 2
 IPPROTO_GGP        = 3
 IPPROTO_TCP        = 6
 IPPROTO_PUP        = 12
 IPPROTO_UDP        = 17
 IPPROTO_IDP        = 22
 IPPROTO_ND         = 77
 IPPROTO_RAW        = 255
 IPPROTO_MAX        = 256
Â
 SOL_SOCKET         = 65535
Â
 SO_DEBUG          = 1
 SO_REUSEADDR        = 4
 SO_KEEPALIVE        = 8
 SO_DONTROUTE        = 16
 SO_BROADCAST        = 32
 SO_LINGER         = 128
 SO_OOBINLINE        = 256
 SO_RCVLOWAT        = 4100
 SO_SNDTIMEO        = 4101
 SO_RCVTIMEO        = 4102
 SO_ERROR          = 4103
 SO_TYPE          = 4104
 SO_SNDBUF         = 4097
 SO_RCVBUF         = 4098
 SO_SNDLOWAT        = 4099
Â
 TCP_NODELAY        =  1
Â
 MSG_OOB          = 1
 MSG_PEEK          = 2
 MSG_DONTROUTE       = 4
Â
 IP_OPTIONS         =  1
 IP_DEFAULT_MULTICAST_LOOP =  1
 IP_DEFAULT_MULTICAST_TTL  =  1
 IP_MULTICAST_IF      =  2
 IP_MULTICAST_TTL      =  3
 IP_MULTICAST_LOOP     =  4
 IP_ADD_MEMBERSHIP     =  5
 IP_DROP_MEMBERSHIP     =  6
 IP_TTL           =  7
 IP_TOS           =  8
 IP_MAX_MEMBERSHIPS     =  20
Â
 EAI_ADDRFAMILY       = 1
 EAI_AGAIN         = 2
 EAI_BADFLAGS        = 3
 EAI_FAIL          = 4
 EAI_FAMILY         = 5
 EAI_MEMORY         = 6
 EAI_NODATA         = 7
 EAI_NONAME         = 8
 EAI_SERVICE        = 9
 EAI_SOCKTYPE        = 10
 EAI_SYSTEM         = 11
 EAI_BADHINTS        = 12
 EAI_PROTOCOL        = 13
 EAI_MAX          = 14
Â
 AI_PASSIVE         = 1
 AI_CANONNAME        = 2
 AI_NUMERICHOST       = 4
 AI_MASK          = 7
 AI_ALL           = 256
 AI_V4MAPPED_CFG      = 512
 AI_ADDRCONFIG       = 1024
 AI_DEFAULT         = 1536
 AI_V4MAPPED        = 2048
Â
 #--------------------------------------------------------------------------
 # ◠Returns the associated IP address for the given hostname.
 #-------------------------------------------------------------------------- Â
 def self.getaddress(host)
  gethostbyname(host)[3].unpack("C4").join(".")
 end
Â
 #--------------------------------------------------------------------------
 # ◠Returns the associated IP address for the given hostname.
 #-------------------------------------------------------------------------- Â
 def self.getservice(serv)
  case serv
  when Numeric
   return serv
  when String
   return getservbyname(serv)
  else
   raise "Please us an interger or string for services."
  end
 end
Â
 #--------------------------------------------------------------------------
 # ◠Returns information about the given hostname.
 #--------------------------------------------------------------------------
 def self.gethostbyname(name)
  raise SocketError::ENOASSOCHOST if (ptr = Winsock.gethostbyname(name)) == 0
  host = ptr.copymem(16).unpack("iissi")
  [host[0].copymem(64).split("\0")[0], [], host[2], host[4].copymem(4).unpack("l")[0].copymem(4)]
 end
Â
 #--------------------------------------------------------------------------
 # ◠Returns the user's hostname.
 #-------------------------------------------------------------------------- Â
 def self.gethostname
  buf = "\0" * 256
  Winsock.gethostname(buf, 256)
  buf.strip
 end
Â
 #--------------------------------------------------------------------------
 # ◠Returns information about the given service.
 #--------------------------------------------------------------------------
 def self.getservbyname(name)
  case name
  when /echo/i
   return 7
  when /daytime/i
   return 13
  when /ftp/i
   return 21
  when /telnet/i
   return 23
  when /smtp/i
   return 25
  when /time/i
   return 37
  when /http/i
   return 80
  when /pop/i
   return 110
  else
   raise "Service not recognized."
  end
 end
Â
 #--------------------------------------------------------------------------
 # ◠Creates an INET-sockaddr struct.
 #-------------------------------------------------------------------------- Â
 def self.sockaddr_in(port, host)
  begin
   [AF_INET, getservice(port)].pack("sn") + gethostbyname(host)[3] + [].pack("x8")
  rescue
   nil
  end
 end
Â
 #--------------------------------------------------------------------------
 # ◠Creates a new socket and connects it to the given host and port.
 #-------------------------------------------------------------------------- Â
 def self.open(*args)
  socket = new(*args)
  if block_given?
   begin
    yield socket
   ensure
    socket.close
   end
  end
  nil
 end
Â
 #--------------------------------------------------------------------------
 # ◠Creates a new socket.
 #-------------------------------------------------------------------------- Â
 def initialize(domain, type, protocol)
  SocketError.check if (@fd = Winsock.socket(domain, type, protocol)) == -1
  @fd
 end
Â
 #--------------------------------------------------------------------------
 # ◠Accepts incoming connections.
 #-------------------------------------------------------------------------- Â
 def accept(flags = 0)
  buf = "\0" * 16
  SocketError.check if Winsock.accept(@fd, buf, flags) == -1
  buf
 end
Â
 #--------------------------------------------------------------------------
 # ◠Binds a socket to the given sockaddr.
 #-------------------------------------------------------------------------- Â
 def bind(sockaddr)
  SocketError.check if (ret = Winsock.bind(@fd, sockaddr, sockaddr.size)) == -1
  ret
 end
Â
 #--------------------------------------------------------------------------
 # ◠Closes a socket.
 #-------------------------------------------------------------------------- Â
 def close
  SocketError.check if (ret = Winsock.closesocket(@fd)) == -1
  ret
 end
Â
 #--------------------------------------------------------------------------
 # ◠Connects a socket to the given sockaddr.
 #-------------------------------------------------------------------------- Â
 def connect(sockaddr)
  ret = Winsock.connect(@fd, sockaddr, sockaddr.size)
  SocketError.check if ret == -1
  ret
 end
Â
 #--------------------------------------------------------------------------
 # ◠Listens for incoming connections.
 #-------------------------------------------------------------------------- Â
 def listen(backlog)
  SocketError.check if (ret = Winsock.listen(@fd, backlog)) == -1
  ret
 end
Â
 #--------------------------------------------------------------------------
 # ◠Checks waiting data's status.
 #-------------------------------------------------------------------------- Â
 def select(timeout)
  SocketError.check if (ret = Winsock.select(1, [1, @fd].pack("ll"), 0, 0, [timeout, timeout * 1000000].pack("ll"))) == -1
  ret
 end
Â
 #--------------------------------------------------------------------------
 # ◠Checks if data is waiting.
 #-------------------------------------------------------------------------- Â
 def ready?
  not select(0) == 0
 end Â
Â
 #--------------------------------------------------------------------------
 # ◠Reads data from socket.
 #-------------------------------------------------------------------------- Â
 def read(len)
  buf = "\0" * len
  Win32API.new("msvcrt", "_read", "lpl", "l").call(@fd, buf, len)
  buf
 end
Â
 #--------------------------------------------------------------------------
 # ◠Returns recieved data.
 #-------------------------------------------------------------------------- Â
 def recv(len, flags = 0)
  buf = "\0" * len
  SocketError.check if Winsock.recv(@fd, buf, buf.size, flags) == -1
  buf
 end
Â
 #--------------------------------------------------------------------------
 # ◠Sends data to a host.
 #-------------------------------------------------------------------------- Â
 def send(data, flags = 0)
  SocketError.check if (ret = Winsock.send(@fd, data, data.size, flags)) == -1
  ret
 end
Â
 #--------------------------------------------------------------------------
 # * Gets
 #--------------------------------------------------------------------------
 def gets
  # Create buffer
  buffer = ""
  # Loop Until "end of line"
  while (char = recv(1)) != "\n"
   buffer += char
  end
  # Return recieved data
  return buffer
 end
Â
 #--------------------------------------------------------------------------
 # ◠Writes data to socket.
 #-------------------------------------------------------------------------- Â
 def write(data)
  Win32API.new("msvcrt", "_write", "lpl", "l").call(@fd, data, 1)
 end
Â
end
Â
Â
#===============================================================================
# ** TCPSocket - Creates and manages TCP sockets.
#-------------------------------------------------------------------------------
# Author   Ruby
# Version  1.8.1
#===============================================================================
Â
class TCPSocket < Socket
Â
 #--------------------------------------------------------------------------
 # ◠Creates a new socket and connects it to the given host and port.
 #-------------------------------------------------------------------------- Â
 def self.open(*args)
  socket = new(*args)
  if block_given?
   begin
    yield socket
   ensure
    socket.close
   end
  end
  nil
 end
Â
 #--------------------------------------------------------------------------
 # ◠Creates a new socket and connects it to the given host and port.
 #-------------------------------------------------------------------------- Â
 def initialize(host, port)
  super(AF_INET, SOCK_STREAM, IPPROTO_TCP)
  connect(Socket.sockaddr_in(port, host))
 end
Â
end
Â
#==============================================================================
# â– SocketError
#------------------------------------------------------------------------------
#  Default exception class for sockets.
#==============================================================================
class SocketError < StandardError
 ENOASSOCHOST = "getaddrinfo: no address associated with hostname."
 def self.check
  errno = Winsock.WSAGetLastError
  errno = Errno.constants.detect { |c| Errno.const_get(c).new.errno == errno }
  if errno != nil
   raise Errno.const_get(errno)
  end
 end
end
Â