Allison Randal wrote:
> So, methods or vtable functions for those behaviors need to be added.
> 
> In the pdd, the Socket PMC has a 'socket' method (essentially parallel
> to the 'open' method on the FileHandle PMC). You should be able to
> create a Socket PMC with the standard 'new':
> 
>   $P0 = new 'Socket'
>   $P1 = new 'Socket', init_hash

And $P0."socket"(2, 1, 6) # still need to define some constants

So I'm working on adding an init_pmc vtable and a socket method, the
former calls the latter.  One problem I've run into is that the PIO
routines expect to allocate the PMC, whereas the above API implies the
PMC should allocate the underlying PIO socket as needed.  Are we somehow
married to the current design, or is it ok if I switch them around?
(The above API to me looks like Parrot_io_socket() should be called by
the Socket PMC, and should return an integer.)

The attached patch implements this for the Socket PMC (I haven't done
SockAddr yet), and the updated httpd example works correctly under
linux.  I haven't tested it on win32 yet, and I don't know how sockets
are supposed to work on PIO_OS_STDIO platforms.  But is this a valid
approach?

Mark

P.S.  I also noticed in Parrot_io_socket_win32 and Parrot_io_socket_unix
 that the setsockopt for SO_REUSEADDR was called with an uninitialized
integer, I fixed that too.
commit 722d303fdc139f1275b68102250d583b955eef24
Author: Mark Glines <[email protected]>
Date:   Fri Mar 27 08:53:02 2009 -0700

    Stop using the "socket" opcode; add some inithash handling to the Socket 
PMC instead.

diff --git a/examples/io/httpd.pir b/examples/io/httpd.pir
index fe6a1c1..fbbb89d 100644
--- a/examples/io/httpd.pir
+++ b/examples/io/httpd.pir
@@ -98,7 +98,7 @@ The code was heavily hacked by bernhard and leo.
     .local pmc listener, work, fp
     .local pmc fp               # read requested files from disk
     .local int port
-    .local pmc address
+    .local pmc address, socket_init_hash
     .local string host
     .local string buf, req, rep, temp
     .local string meth, url, file_content
@@ -110,8 +110,13 @@ The code was heavily hacked by bernhard and leo.
     host = "localhost"
     port = 1234
 
+    socket_init_hash = new 'Hash'
     # TODO provide sys/socket constants
-    listener = socket 2, 1, 6  # PF_INET, SOCK_STREAM, tcp
+    # PF_INET, SOCK_STREAM, tcp
+    socket_init_hash['family']   = 2
+    socket_init_hash['type']     = 1
+    socket_init_hash['protocol'] = 6
+    listener = new 'Socket', socket_init_hash
     unless listener goto ERR_NO_SOCKET
 
     # Pack a sockaddr_in structure with IP and port
diff --git a/include/parrot/io.h b/include/parrot/io.h
index 88953ab..f736b9e 100644
--- a/include/parrot/io.h
+++ b/include/parrot/io.h
@@ -829,7 +829,10 @@ INTVAL Parrot_io_send(PARROT_INTERP, ARGMOD(PMC *pmc), 
ARGMOD(STRING *buf))
 PARROT_EXPORT
 PARROT_WARN_UNUSED_RESULT
 PARROT_CANNOT_RETURN_NULL
-PMC * Parrot_io_socket(PARROT_INTERP, INTVAL fam, INTVAL type, INTVAL proto)
+INTVAL Parrot_io_socket(PARROT_INTERP,
+    INTVAL fam,
+    INTVAL type,
+    INTVAL proto)
         __attribute__nonnull__(1);
 
 PARROT_EXPORT
diff --git a/include/parrot/io_portable.h b/include/parrot/io_portable.h
index f2c0808..2ab5cdf 100644
--- a/include/parrot/io_portable.h
+++ b/include/parrot/io_portable.h
@@ -152,6 +152,8 @@ size_t Parrot_io_write_portable(PARROT_INTERP,
 #define PIO_FLUSH(interp, pmc) Parrot_io_flush_portable((interp), (pmc))
 #define PIO_GETBLKSIZE(handle) Parrot_io_getblksize_portable((handle))
 
+#define PIO_INVALID_HANDLE_VALUE NULL
+
 #endif /* PARROT_IO_PORTABLE_H_GUARD */
 
 /*
diff --git a/include/parrot/io_unix.h b/include/parrot/io_unix.h
index 4dd53cb..a00f578 100644
--- a/include/parrot/io_unix.h
+++ b/include/parrot/io_unix.h
@@ -220,7 +220,7 @@ PMC * Parrot_io_sockaddr_in(PARROT_INTERP, ARGIN(STRING 
*addr), INTVAL port)
 
 PARROT_WARN_UNUSED_RESULT
 PARROT_CAN_RETURN_NULL
-PMC * Parrot_io_socket_unix(PARROT_INTERP, int fam, int type, int proto)
+INTVAL Parrot_io_socket_unix(PARROT_INTERP, int fam, int type, int proto)
         __attribute__nonnull__(1);
 
 #define ASSERT_ARGS_Parrot_io_accept_unix __attribute__unused__ int 
_ASSERT_ARGS_CHECK = \
@@ -290,6 +290,8 @@ PMC * Parrot_io_socket_unix(PARROT_INTERP, int fam, int 
type, int proto)
 #define PIO_ACCEPT(interp, pmc) \
     Parrot_io_accept_unix((interp), (pmc))
 
+#define PIO_INVALID_HANDLE_VALUE -1
+
 #endif /* PARROT_IO_UNIX_H_GUARD */
 
 /*
diff --git a/include/parrot/io_win32.h b/include/parrot/io_win32.h
index 96f943f..ad91773 100644
--- a/include/parrot/io_win32.h
+++ b/include/parrot/io_win32.h
@@ -199,7 +199,7 @@ PMC * Parrot_io_sockaddr_in(PARROT_INTERP, ARGIN(STRING 
*addr), INTVAL port)
 
 PARROT_WARN_UNUSED_RESULT
 PARROT_CAN_RETURN_NULL
-PMC * Parrot_io_socket_win32(PARROT_INTERP, int fam, int type, int proto)
+INTVAL Parrot_io_socket_win32(PARROT_INTERP, int fam, int type, int proto)
         __attribute__nonnull__(1);
 
 #define ASSERT_ARGS_Parrot_io_accept_win32 __attribute__unused__ int 
_ASSERT_ARGS_CHECK = \
@@ -267,6 +267,8 @@ PMC * Parrot_io_socket_win32(PARROT_INTERP, int fam, int 
type, int proto)
 #define PIO_ACCEPT(interp, pmc) \
     Parrot_io_accept_win32((interp), (pmc))
 
+#define PIO_INVALID_HANDLE_VALUE INVALID_HANDLE_VALUE
+
 #endif /* PARROT_IO_WIN32_H_GUARD */
 
 /*
diff --git a/src/io/socket_api.c b/src/io/socket_api.c
index fe25f94..1ab180f 100644
--- a/src/io/socket_api.c
+++ b/src/io/socket_api.c
@@ -69,7 +69,7 @@ Parrot_io_poll(PARROT_INTERP, ARGMOD(PMC *pmc), INTVAL which, 
INTVAL sec, INTVAL
 
 /*
 
-=item C<PMC * Parrot_io_socket>
+=item C<INTVAL Parrot_io_socket>
 
 Creates and returns a socket using the specified address family, socket type,
 and protocol number. Check the returned PMC with a boolean test to see whether
@@ -82,7 +82,7 @@ the socket was successfully created.
 PARROT_EXPORT
 PARROT_WARN_UNUSED_RESULT
 PARROT_CANNOT_RETURN_NULL
-PMC *
+INTVAL
 Parrot_io_socket(PARROT_INTERP, INTVAL fam, INTVAL type, INTVAL proto)
 {
     ASSERT_ARGS(Parrot_io_socket)
diff --git a/src/io/socket_unix.c b/src/io/socket_unix.c
index db52817..41b993b 100644
--- a/src/io/socket_unix.c
+++ b/src/io/socket_unix.c
@@ -115,7 +115,7 @@ Parrot_io_sockaddr_in(PARROT_INTERP, ARGIN(STRING *addr), 
INTVAL port)
 
 /*
 
-=item C<PMC * Parrot_io_socket_unix>
+=item C<INTVAL Parrot_io_socket_unix>
 
 Uses C<socket()> to create a socket with the specified address family,
 socket type and protocol number.
@@ -126,20 +126,17 @@ socket type and protocol number.
 
 PARROT_WARN_UNUSED_RESULT
 PARROT_CAN_RETURN_NULL
-PMC *
+INTVAL
 Parrot_io_socket_unix(PARROT_INTERP, int fam, int type, int proto)
 {
     ASSERT_ARGS(Parrot_io_socket_unix)
-    int i;
     const int sock = socket(fam, type, proto);
     if (sock >= 0) {
-        PMC * io = Parrot_io_new_socket_pmc(interp, 
PIO_F_SOCKET|PIO_F_READ|PIO_F_WRITE);
-        PARROT_SOCKET(io)->os_handle = sock;
-        setsockopt(PARROT_SOCKET(io)->os_handle, SOL_SOCKET, SO_REUSEADDR, &i, 
sizeof (i));
-        SOCKADDR_REMOTE(io)->sin_family = fam;
-        return io;
+        int i = 1;
+        setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &i, sizeof (i));
+        return sock;
     }
-    return PMCNULL;
+    return PIO_INVALID_HANDLE_VALUE;
 }
 
 /*
diff --git a/src/io/socket_win32.c b/src/io/socket_win32.c
index 1f07d5b..b56c5a6 100644
--- a/src/io/socket_win32.c
+++ b/src/io/socket_win32.c
@@ -61,7 +61,7 @@ static void get_sockaddr_in(PARROT_INTERP,
 
 /*
 
-=item C<PMC * Parrot_io_socket_win32>
+=item C<INTVAL Parrot_io_socket_win32>
 
 Uses C<socket()> to create a socket with the specified address family,
 socket type and protocol number.
@@ -72,20 +72,17 @@ socket type and protocol number.
 
 PARROT_WARN_UNUSED_RESULT
 PARROT_CAN_RETURN_NULL
-PMC *
+INTVAL
 Parrot_io_socket_win32(PARROT_INTERP, int fam, int type, int proto)
 {
     ASSERT_ARGS(Parrot_io_socket_win32)
-    int i;
     const int sock = socket(fam, type, proto);
     if (sock >= 0) {
-        PMC * io = Parrot_io_new_socket_pmc(interp, 
PIO_F_SOCKET|PIO_F_READ|PIO_F_WRITE);
-        PARROT_SOCKET(io)->os_handle = (void*)sock;
-        setsockopt((int)PARROT_SOCKET(io)->os_handle, SOL_SOCKET, 
SO_REUSEADDR, &i, sizeof (i));
-        SOCKADDR_REMOTE(io)->sin_family = fam;
-        return io;
+        int i = 1;
+        setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &i, sizeof (i));
+        return sock;
     }
-    return PMCNULL;
+    return PIO_INVALID_HANDLE_VALUE;
 }
 
 /*
diff --git a/src/pmc/socket.pmc b/src/pmc/socket.pmc
index 9f71c17..865945d 100644
--- a/src/pmc/socket.pmc
+++ b/src/pmc/socket.pmc
@@ -44,17 +44,71 @@ Initializes a newly created Socket object.
         data_struct->remote = PMCNULL;
 
         /* Initialize the os_handle to the platform-specific value for closed. 
*/
-#ifdef PIO_OS_WIN32
-    data_struct->os_handle    = (PIOHANDLE)INVALID_HANDLE_VALUE;
-#endif
-#ifdef PIO_OS_UNIX
-    data_struct->os_handle    = (PIOHANDLE)-1;
-#endif
-#ifdef PIO_OS_STDIO
-    data_struct->os_handle    = (PIOHANDLE)NULL;
-#endif
+        data_struct->os_handle    = (PIOHANDLE)PIO_INVALID_HANDLE_VALUE;
 
         PObj_custom_mark_destroy_SETALL(SELF);
+        Parrot_io_set_flags(interp, SELF, PIO_F_SOCKET|PIO_F_READ|PIO_F_WRITE);
+    }
+
+
+/*
+
+=item C<void init_pmc(PMC *init_hash)>
+
+Initializes a newly created Socket object with the specified parameters.
+
+=cut
+
+*/
+
+    VTABLE void init_pmc(PMC *initializer) {
+        const INTVAL arg_type = VTABLE_type(interp, initializer);
+        int domain = -1, type = -1, protocol = -1;
+        PMC *temp_value;
+
+        SELF.init();
+        switch (arg_type) {
+            case enum_class_FixedFloatArray:
+            case enum_class_ResizableFloatArray:
+            case enum_class_FixedIntegerArray:
+            case enum_class_ResizableIntegerArray:
+                if(VTABLE_get_integer(interp, initializer) >= 1)
+                    domain   = VTABLE_get_integer_keyed_int(interp, 
initializer, 0);
+                if(VTABLE_get_integer(interp, initializer) >= 2)
+                    type     = VTABLE_get_integer_keyed_int(interp, 
initializer, 1);
+                if(VTABLE_get_integer(interp, initializer) >= 3)
+                    protocol = VTABLE_get_integer_keyed_int(interp, 
initializer, 2);
+                break;
+
+            case enum_class_Hash:
+                /* "family" and "domain" are both common names for the first 
argument. */
+                /* accept either one. */
+                temp_value = VTABLE_get_pmc_keyed_str(interp, initializer,
+                                                      
string_from_literal(interp, "domain"));
+                if(!PMC_IS_NULL(temp_value))
+                    domain   = VTABLE_get_integer(interp, temp_value);
+                temp_value = VTABLE_get_pmc_keyed_str(interp, initializer,
+                                                      
string_from_literal(interp, "family"));
+                if(!PMC_IS_NULL(temp_value))
+                    domain   = VTABLE_get_integer(interp, temp_value);
+
+                temp_value = VTABLE_get_pmc_keyed_str(interp, initializer,
+                                                      
string_from_literal(interp, "type"));
+                if(!PMC_IS_NULL(temp_value))
+                    type     = VTABLE_get_integer(interp, temp_value);
+
+                temp_value = VTABLE_get_pmc_keyed_str(interp, initializer,
+                                                      
string_from_literal(interp, "protocol"));
+                if(!PMC_IS_NULL(temp_value))
+                    protocol = VTABLE_get_integer(interp, temp_value);
+                break;
+
+            default:
+                Parrot_ex_throw_from_c_args(interp, NULL, 
EXCEPTION_INVALID_OPERATION,
+                                            "Cannot parse arguments to Socket 
initializer.");
+        }
+
+        PCCINVOKE(INTERP, SELF, "socket", INTVAL domain, INTVAL type, INTVAL 
protocol);
     }
 
 /*
@@ -117,7 +171,10 @@ Free structures.
 
     METHOD close() {
         INTVAL status = 0;
-        close(PARROT_SOCKET(SELF)->os_handle);
+        if(PARROT_SOCKET(SELF)->os_handle != PIO_INVALID_HANDLE_VALUE) {
+            close(PARROT_SOCKET(SELF)->os_handle);
+            PARROT_SOCKET(SELF)->os_handle = PIO_INVALID_HANDLE_VALUE;
+        }
         RETURN(INTVAL status);
     }
 
@@ -130,6 +187,21 @@ Free structures.
 
 =over 4
 
+=item C<socket>
+
+Create a socket with the specified parameters.
+
+=cut
+
+*/
+
+    METHOD socket(int domain, int type, int protocol) {
+        int sock = Parrot_io_socket(interp, domain, type, protocol);
+        PARROT_SOCKET(SELF)->os_handle = sock;
+    }
+
+/*
+
 =item C<connect>
 
 Connects a socket object to an address.
_______________________________________________
http://lists.parrot.org/mailman/listinfo/parrot-dev

Reply via email to