[PATCH] Socket: Provide varargs versions of bind and connect

Carl Worth cworth at cworth.org
Sat Feb 2 04:36:50 PST 2008


With this change, the hostname is now not-required, (and even not
allowed), for an AF_UNIX socket. Also, for an AF_INET socket the
port can now be an integer as well as a string service or port.
---
 builtin-sockets.c |  204 ++++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 138 insertions(+), 66 deletions(-)

diff --git a/builtin-sockets.c b/builtin-sockets.c
index 3ad61e4..934d03a 100644
--- a/builtin-sockets.c
+++ b/builtin-sockets.c
@@ -35,8 +35,8 @@ NamespacePtr SocketNamespace;
 Type	     *typeSockaddr;

 Value do_Socket_create (int num, Value *args);
-Value do_Socket_connect (Value s, Value host, Value port);
-Value do_Socket_bind (Value s, Value host, Value port);
+Value do_Socket_connect (int num, Value *args);
+Value do_Socket_bind (int numb, Value *args);
 Value do_Socket_listen (Value s, Value backlog);
 Value do_Socket_accept (Value s);
 Value do_Socket_shutdown (Value s, Value how);
@@ -83,18 +83,6 @@ import_Socket_namespace()
         { 0 }
     };

-    static const struct fbuiltin_3 funcs_3[] = {
-        { do_Socket_connect, "connect", "v", "fss", "\n"
-	    " void connect (file socket, string host, string port)\n"
-	    "\n"
-	    " Connect 'socket' to 'host', 'port'.\n" },
-        { do_Socket_bind, "bind", "v", "fss", "\n"
-	    " void bind (file socket, string host, string port)\n"
-	    "\n"
-	    " Bind 'socket' to 'host', 'port'.\n" },
-        { 0 }
-    };
-
     static const struct fbuiltin_v funcs_v[] = {
         { do_Socket_create, "create", "f", ".i", "\n"
 	    " file create ([int family], int type)\n"
@@ -106,6 +94,24 @@ import_Socket_namespace()
 	    " and where 'type' is one of:\n"
 	    "   SOCK_STREAM:		a stream socket.\n"
 	    "   SOCK_DGRAM:		a datagram socket.\n" },
+        { do_Socket_bind, "bind", "v", "f.p", "\n"
+	    " void bind (file socket, string host, string port)\n"
+	    " void bind (file socket, string host, int port)\n"
+	    "\n"
+	    " Bind AF_INET 'socket' to 'host', 'port'.\n"
+	    "\n"
+	    " void bind (file socket, string local_socket)\n"
+	    "\n"
+	    " Bind AF_UNIX 'socket' to 'localhost'.\n" },
+        { do_Socket_connect, "connect", "v", "f.p", "\n"
+	    " void connect (file socket, string host, string port)\n"
+	    " void connect (file socket, string host, int port)\n"
+	    "\n"
+	    " Connect AF_INET 'socket' to 'host', 'port'.\n"
+	    "\n"
+	    " void connect (file socket, string local_socket)\n"
+	    "\n"
+	    " Connect AF_UNIX 'socket' to 'local_socket'.\n" },
 	{ 0 }
     };

@@ -148,7 +154,6 @@ import_Socket_namespace()
     BuiltinFuncs0 (&SocketNamespace, funcs_0);
     BuiltinFuncs1 (&SocketNamespace, funcs_1);
     BuiltinFuncs2 (&SocketNamespace, funcs_2);
-    BuiltinFuncs3 (&SocketNamespace, funcs_3);
     BuiltinFuncsV (&SocketNamespace, funcs_v);

     BuiltinIntegers (ivars);
@@ -200,81 +205,144 @@ typedef union {
     } align;
 } sockaddr_all_t;

-static Bool address_lookup (Value s, Value hostname, Value portname,
-			    sockaddr_all_t *addr, socklen_t *len)
+#define VerifyArgumentCount(arg, condition, error)			\
+if (! (condition)) {							\
+    RaiseStandardException (exception_invalid_argument,			\
+                            (error), 2, NewInt (0), NewInt (arg));	\
+}
+
+/* Supports the following args from both bind and connect:
+ *	(File::file s, String local_socket)
+ */
+static Bool address_lookup_af_unix (int num, Value *args,
+				    struct sockaddr_un *addr, socklen_t *len)
 {
-    struct hostent *host;
-    struct servent *port;
+    char *local_socket;
+    Value s = args[0];
+
+    VerifyArgumentCount (num, num == 2,
+			 "must have 2 arguments for an AF_UNIX socket");
+    if (aborting)
+	return False;
+
+    local_socket = StrzPart (args[1], "invalid local_socket");
+    if (!local_socket || *local_socket == '\0')
+	return False;
+
+    if (strlen (local_socket) > PATH_MAX)
+	return False;
+
+    addr->sun_family = s->file.sock_family;
+    strcpy (addr->sun_path, local_socket);
+    *len = SUN_LEN (addr);
+
+    return True;
+}
+
+/* Supports the following args from both bind and connect:
+ *	(File::file s, String host, String port)
+ *	(File::file s, String host, int port)
+ */
+static Bool address_lookup_af_inet (int num, Value *args,
+				    struct sockaddr_in *addr, socklen_t *len)
+{
+    Value host, port;
     char *hostchars;
-    char *portchars;
-    char *endptr = 0;
+    struct hostent *hostent;
     long int portnum;
+    struct servent *portent;
+    char *endptr;
+    Value s = args[0];

-    hostchars = StrzPart (hostname, "invalid hostname");
-    if (!hostchars)
+    VerifyArgumentCount (num, num == 3,
+			 "must have 3 arguments for an AF_INET socket");
+    if (aborting)
 	return False;
-    portchars = StrzPart (portname, "invalid portname");
-    if (!portchars)
+
+    host = args[1];
+    port = args[2];
+
+    hostchars = StrzPart (host, "invalid hostname");
+    if (!hostchars || *hostchars == '\0')
 	return False;
-
-    if (*hostchars == '\0' || *portchars == '\0')
-	return False; /* FIXME: more here? */

-    switch (s->file.sock_family) {
-    case AF_UNIX:
-	if (strlen (portchars) > PATH_MAX)
+    if (ValueIsString (port)) {
+	char *portchars = StrzPart (port, "invalid port string");
+	if (!portchars || *portchars == '\0')
 	    return False;
-	*len = SUN_LEN (&addr->un);
-	strcpy (addr->un.sun_path, portchars);
-	break;
-    case AF_INET:
-	/* host lookup */
-	host = gethostbyname (hostchars);
-	if (host == 0)
-	{
-	    herror ("address_lookup");
-	    return False; /* FIXME: more here? */
-	}
-	*len = sizeof (addr->in);
-	memcpy (&addr->in.sin_addr.s_addr, host->h_addr_list[0], sizeof addr->in.sin_addr.s_addr);
-
-	/* port lookup */
 	portnum = strtol (portchars, &endptr, /* base */ 10);
-
 	if (*endptr != '\0') /* non-numeric port specification */
 	{
 	    /* FIXME: this should not always be "tcp"! */
-	    port = getservbyname (portchars, "tcp");
-	    if (port == 0)
+	    portent = getservbyname (portchars, "tcp");
+	    if (portent == 0)
 		return False; /* FIXME: more here? */
-	    addr->in.sin_port = port->s_port;
+	    addr->sin_port = portent->s_port;
 	}
-	else
-	{
-	    if (portnum <= 0 || portnum >= (1 << 16))
-		return False; /* FIXME: more here? */
-	    addr->in.sin_port = htons (portnum);
-	}
-	break;
-#if AF_INET6
+	if (portnum <= 0 || portnum >= (1 << 16))
+	    return False; /* FIXME: more here? */
+    } else {
+	portnum = IntPart (port, "invalid port value");
+	if (portnum <= 0 || portnum >= (1 << 16))
+	    return False; /* FIXME: more here? */
+    }
+
+    addr->sin_family = s->file.sock_family;
+    addr->sin_port = htons (portnum);
+
+    /* host lookup */
+    hostent = gethostbyname (hostchars);
+    if (hostent == 0)
+    {
+	herror ("address_lookup");
+	return False; /* FIXME: more here? */
+    }
+
+    *len = sizeof (*addr);
+    memcpy (&addr->sin_addr.s_addr, hostent->h_addr_list[0],
+	    sizeof (addr->sin_addr.s_addr));
+
+    return True;
+}
+
+/* Supports the following args from both bind and connect:
+ *
+ *	(File::file s, String host, String port)
+ *	(File::file s, String host, int port)
+ *	(File::file s, String local_socket)
+ */
+static Bool address_lookup (int num, Value *args,
+			    sockaddr_all_t *addr, socklen_t *len)
+{
+    Value s = args[0];
+
+    switch (s->file.sock_family) {
+    case AF_UNIX:
+	return address_lookup_af_unix (num, args, &addr->un, len);
+    case AF_INET:
+	return address_lookup_af_inet (num, args, &addr->in, len);
+#ifdef AF_INET6
     case AF_INET6:
+	/* FIXME */
 #endif
     default:
 	return False;
     }
-
-    return True;
 }

-/* void do_Socket_connect (File::file s, String host, String port); */
+/* void do_Socket_connect (File::file s, String host, String port);
+ * void do_Socket_connect (File::file s, String host, int port);
+ * void do_Socket_connect (File::file s, String local_socket;
+ */
 Value
-do_Socket_connect (Value s, Value host, Value port)
+do_Socket_connect (int num, Value *args)
 {
     ENTER ();
     sockaddr_all_t addr;
     socklen_t len;
+    Value s = args[0];

-    if (!address_lookup (s, host, port, &addr, &len))
+    if (!address_lookup (num, args, &addr, &len))
 	RETURN (Void);

     if (!running->thread.partial)
@@ -321,15 +389,19 @@ do_Socket_connect (Value s, Value host, Value port)
     RETURN (Void);
 }

-/* void do_Socket_bind (File::file s, String host, String port); */
+/* void do_Socket_bind (File::file s, String host, String port);
+ * void do_Socket_bind (File::file s, String host, int port);
+ * void do_Socket_bind (File::file s, String local_socket;
+ */
 Value
-do_Socket_bind (Value s, Value host, Value port)
+do_Socket_bind (int num, Value *args)
 {
     ENTER ();
     sockaddr_all_t addr;
     socklen_t len;
+    Value s = args[0];

-    if (!address_lookup (s, host, port, &addr, &len))
+    if (!address_lookup (num, args, &addr, &len))
 	RETURN (Void);

 #ifdef SO_REUSEADDR
--
1.5.3.2


--Multipart_Wed_Feb__6_09:05:02_2008-1--

--pgp-sign-Multipart_Wed_Feb__6_09:05:02_2008-1
Content-Type: application/pgp-signature
Content-Transfer-Encoding: 7bit

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)

iD8DBQBHqei+6JDdNq8qSWgRAsYEAJ0aw6SmEqP4ejvcKweRBGLVWO4XXQCfej9c
W2cyEZ6JPreOh9UbNd+zFUg=
=U3Pg
-----END PGP SIGNATURE-----

--pgp-sign-Multipart_Wed_Feb__6_09:05:02_2008-1--


More information about the Nickle mailing list