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
