[svn:parrot] r37769 - in trunk: examples/io include/parrot src/io src/ops src/pmc
Infinoid at svn.parrot.org
Infinoid at svn.parrot.org
Fri Mar 27 22:07:08 UTC 2009
Author: Infinoid
Date: Fri Mar 27 22:07:05 2009
New Revision: 37769
URL: https://trac.parrot.org/parrot/changeset/37769
Log:
Apply patch from bacek++ in TT #514:
* Add a PMC* argument to Parrot_io_socket methods, to prevent spurious reallocation
* Add a Socket.socket() method, use it in the httpd.pir example
* Add a SockAddr.sockaddr() method, use it in the httpd.pir example
* Remove a bunch of unused socket ops from io.ops and ops.num
* Fix up the Socket PMC some, use more inheritance, add POD documentation
Modified:
trunk/examples/io/httpd.pir
trunk/include/parrot/io.h
trunk/include/parrot/io_unix.h
trunk/include/parrot/io_win32.h
trunk/src/io/socket_api.c
trunk/src/io/socket_unix.c
trunk/src/io/socket_win32.c
trunk/src/ops/io.ops
trunk/src/ops/ops.num
trunk/src/pmc/socket.pmc
Modified: trunk/examples/io/httpd.pir
==============================================================================
--- trunk/examples/io/httpd.pir Fri Mar 27 21:43:16 2009 (r37768)
+++ trunk/examples/io/httpd.pir Fri Mar 27 22:07:05 2009 (r37769)
@@ -111,11 +111,13 @@
port = 1234
# TODO provide sys/socket constants
- listener = socket 2, 1, 6 # PF_INET, SOCK_STREAM, tcp
+ .local pmc sock
+ sock = new 'Socket'
+ listener = sock.'socket'(2, 1, 6) # PF_INET, SOCK_STREAM, tcp
unless listener goto ERR_NO_SOCKET
# Pack a sockaddr_in structure with IP and port
- address = sockaddr host, port
+ address = sock.'sockaddr'(host, port)
ret = listener.'bind'(address)
if ret == -1 goto ERR_bind
$S0 = port
Modified: trunk/include/parrot/io.h
==============================================================================
--- trunk/include/parrot/io.h Fri Mar 27 21:43:16 2009 (r37768)
+++ trunk/include/parrot/io.h Fri Mar 27 22:07:05 2009 (r37769)
@@ -829,8 +829,13 @@
PARROT_EXPORT
PARROT_WARN_UNUSED_RESULT
PARROT_CANNOT_RETURN_NULL
-PMC * Parrot_io_socket(PARROT_INTERP, INTVAL fam, INTVAL type, INTVAL proto)
- __attribute__nonnull__(1);
+PMC * Parrot_io_socket(PARROT_INTERP,
+ ARGMOD_NULLOK(PMC * socket),
+ INTVAL fam,
+ INTVAL type,
+ INTVAL proto)
+ __attribute__nonnull__(1)
+ FUNC_MODIFIES(* socket);
PARROT_EXPORT
PARROT_WARN_UNUSED_RESULT
Modified: trunk/include/parrot/io_unix.h
==============================================================================
--- trunk/include/parrot/io_unix.h Fri Mar 27 21:43:16 2009 (r37768)
+++ trunk/include/parrot/io_unix.h Fri Mar 27 22:07:05 2009 (r37769)
@@ -1,7 +1,7 @@
/* io_unix.h
* Copyright (C) 2001-2003, Parrot Foundation.
* SVN Info
- * $Id$
+ * $Id: io_unix.h 36833 2009-02-17 20:09:26Z allison $
* Overview:
* Parrot IO subsystem
* Data Structure and Algorithms:
@@ -220,8 +220,13 @@
PARROT_WARN_UNUSED_RESULT
PARROT_CAN_RETURN_NULL
-PMC * Parrot_io_socket_unix(PARROT_INTERP, int fam, int type, int proto)
- __attribute__nonnull__(1);
+PMC * Parrot_io_socket_unix(PARROT_INTERP,
+ ARGIN(PMC *s),
+ int fam,
+ int type,
+ int proto)
+ __attribute__nonnull__(1)
+ __attribute__nonnull__(2);
#define ASSERT_ARGS_Parrot_io_accept_unix __attribute__unused__ int _ASSERT_ARGS_CHECK = \
PARROT_ASSERT_ARG(interp) \
@@ -249,7 +254,8 @@
PARROT_ASSERT_ARG(interp) \
|| PARROT_ASSERT_ARG(addr)
#define ASSERT_ARGS_Parrot_io_socket_unix __attribute__unused__ int _ASSERT_ARGS_CHECK = \
- PARROT_ASSERT_ARG(interp)
+ PARROT_ASSERT_ARG(interp) \
+ || PARROT_ASSERT_ARG(s)
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
/* HEADERIZER END: src/io/socket_unix.c */
@@ -275,8 +281,8 @@
#define PIO_POLL(interp, pmc, which, sec, usec) \
Parrot_io_poll_unix((interp), (pmc), (which), (sec), (usec))
-#define PIO_NEW_SOCKET(interp, fam, type, proto) \
- Parrot_io_socket_unix((interp), (fam), (type), (proto))
+#define PIO_SOCKET(interp, socket, fam, type, proto) \
+ Parrot_io_socket_unix((interp), (socket), (fam), (type), (proto))
#define PIO_RECV(interp, pmc, buf) \
Parrot_io_recv_unix((interp), (pmc), (buf))
#define PIO_SEND(interp, pmc, buf) \
Modified: trunk/include/parrot/io_win32.h
==============================================================================
--- trunk/include/parrot/io_win32.h Fri Mar 27 21:43:16 2009 (r37768)
+++ trunk/include/parrot/io_win32.h Fri Mar 27 22:07:05 2009 (r37769)
@@ -199,8 +199,13 @@
PARROT_WARN_UNUSED_RESULT
PARROT_CAN_RETURN_NULL
-PMC * Parrot_io_socket_win32(PARROT_INTERP, int fam, int type, int proto)
- __attribute__nonnull__(1);
+PMC * Parrot_io_socket_win32(PARROT_INTERP,
+ ARGIN(PMC * s),
+ int fam,
+ int type,
+ int proto)
+ __attribute__nonnull__(1)
+ __attribute__nonnull__(2);
#define ASSERT_ARGS_Parrot_io_accept_win32 __attribute__unused__ int _ASSERT_ARGS_CHECK = \
PARROT_ASSERT_ARG(interp) \
@@ -228,7 +233,8 @@
PARROT_ASSERT_ARG(interp) \
|| PARROT_ASSERT_ARG(addr)
#define ASSERT_ARGS_Parrot_io_socket_win32 __attribute__unused__ int _ASSERT_ARGS_CHECK = \
- PARROT_ASSERT_ARG(interp)
+ PARROT_ASSERT_ARG(interp) \
+ || PARROT_ASSERT_ARG(s)
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
/* HEADERIZER END: src/io/socket_win32.c */
@@ -252,8 +258,8 @@
#define PIO_POLL(interp, pmc, which, sec, usec) \
Parrot_io_poll_win32((interp), (pmc), (which), (sec), (usec))
-#define PIO_NEW_SOCKET(interp, fam, type, proto) \
- Parrot_io_socket_win32((interp), (fam), (type), (proto))
+#define PIO_SOCKET(interp, socket, fam, type, proto) \
+ Parrot_io_socket_win32((interp), (socket), (fam), (type), (proto))
#define PIO_RECV(interp, pmc, buf) \
Parrot_io_recv_win32((interp), (pmc), (buf))
#define PIO_SEND(interp, pmc, buf) \
Modified: trunk/src/io/socket_api.c
==============================================================================
--- trunk/src/io/socket_api.c Fri Mar 27 21:43:16 2009 (r37768)
+++ trunk/src/io/socket_api.c Fri Mar 27 22:07:05 2009 (r37769)
@@ -83,10 +83,19 @@
PARROT_WARN_UNUSED_RESULT
PARROT_CANNOT_RETURN_NULL
PMC *
-Parrot_io_socket(PARROT_INTERP, INTVAL fam, INTVAL type, INTVAL proto)
+Parrot_io_socket(PARROT_INTERP, ARGMOD_NULLOK(PMC * socket), INTVAL fam,
+ INTVAL type, INTVAL proto)
{
ASSERT_ARGS(Parrot_io_socket)
- return PIO_NEW_SOCKET(interp, fam, type, proto);
+ PMC *new_socket;
+
+ if (PMC_IS_NULL(socket))
+ new_socket = Parrot_io_new_socket_pmc(interp,
+ PIO_F_SOCKET|PIO_F_READ|PIO_F_WRITE);
+ else
+ new_socket = socket;
+
+ return PIO_SOCKET(interp, socket, fam, type, proto);
}
/*
Modified: trunk/src/io/socket_unix.c
==============================================================================
--- trunk/src/io/socket_unix.c Fri Mar 27 21:43:16 2009 (r37768)
+++ trunk/src/io/socket_unix.c Fri Mar 27 22:07:05 2009 (r37769)
@@ -127,17 +127,16 @@
PARROT_WARN_UNUSED_RESULT
PARROT_CAN_RETURN_NULL
PMC *
-Parrot_io_socket_unix(PARROT_INTERP, int fam, int type, int proto)
+Parrot_io_socket_unix(PARROT_INTERP, ARGIN(PMC *s), 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;
+ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &i, sizeof (i));
+ Parrot_io_set_os_handle(interp, s, sock);
+ SOCKADDR_REMOTE(s)->sin_family = fam;
+ return s;
}
return PMCNULL;
}
Modified: trunk/src/io/socket_win32.c
==============================================================================
--- trunk/src/io/socket_win32.c Fri Mar 27 21:43:16 2009 (r37768)
+++ trunk/src/io/socket_win32.c Fri Mar 27 22:07:05 2009 (r37769)
@@ -73,15 +73,14 @@
PARROT_WARN_UNUSED_RESULT
PARROT_CAN_RETURN_NULL
PMC *
-Parrot_io_socket_win32(PARROT_INTERP, int fam, int type, int proto)
+Parrot_io_socket_win32(PARROT_INTERP, ARGIN(PMC * s), 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));
+ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &i, sizeof (i));
+ Parrot_io_set_os_handle(interp, s, sock);
SOCKADDR_REMOTE(io)->sin_family = fam;
return io;
}
Modified: trunk/src/ops/io.ops
==============================================================================
--- trunk/src/ops/io.ops Fri Mar 27 21:43:16 2009 (r37768)
+++ trunk/src/ops/io.ops Fri Mar 27 22:07:05 2009 (r37769)
@@ -508,62 +508,12 @@
=item B<socket>(out PMC, in INT, in INT, in INT)
-Create new socket
+Create new Socket PMC
=cut
op socket(out PMC, in INT, in INT, in INT) {
- $1 = Parrot_io_socket(interp, $2, $3, $4);
-}
-
-=item B<bind>(out INT, in PMC, in PMC)
-
-Bind socket to address
-
-=cut
-
-op bind(out INT, in PMC, in PMC) {
- $1 = Parrot_io_bind(interp, $2, $3);
-}
-
-=item B<listen>(out INT, in PMC, in INT)
-
-Start listening on previously bound socket
-
-=cut
-
-op listen(out INT, in PMC, in INT) {
- $1 = Parrot_io_listen(interp, $2, $3);
-}
-
-=item B<accept>(out PMC, in PMC)
-
-Accept incoming connection
-
-=cut
-
-op accept(out PMC, in PMC) {
- $1 = Parrot_io_accept(interp, $2);
-}
-
-=item B<recv>(out INT, in PMC, out STR)
-
-Receive data from socket
-
-=cut
-
-op recv(out INT, in PMC, out STR) {
- $1 = Parrot_io_recv(interp, $2, &$3);
-}
-
-=item B<send>(out INT, in PMC, in STR)
-
-Send data to socket
-
-=cut
-
-op send(out INT, in PMC, in STR) {
- $1 = Parrot_io_send(interp, $2, $3);
+ $1 = Parrot_io_socket(interp, PMCNULL, $2, $3, $4);
}
=back
Modified: trunk/src/ops/ops.num
==============================================================================
--- trunk/src/ops/ops.num Fri Mar 27 21:43:16 2009 (r37768)
+++ trunk/src/ops/ops.num Fri Mar 27 22:07:05 2009 (r37769)
@@ -1280,19 +1280,3 @@
sockaddr_p_sc_i 1256
sockaddr_p_s_ic 1257
sockaddr_p_sc_ic 1258
-bind_i_p_p 1259
-bind_i_pc_p 1260
-bind_i_p_pc 1261
-bind_i_pc_pc 1262
-listen_i_p_i 1263
-listen_i_pc_i 1264
-listen_i_p_ic 1265
-listen_i_pc_ic 1266
-accept_p_p 1267
-accept_p_pc 1268
-recv_i_p_s 1269
-recv_i_pc_s 1270
-send_i_p_s 1271
-send_i_pc_s 1272
-send_i_p_sc 1273
-send_i_pc_sc 1274
Modified: trunk/src/pmc/socket.pmc
==============================================================================
--- trunk/src/pmc/socket.pmc Fri Mar 27 21:43:16 2009 (r37768)
+++ trunk/src/pmc/socket.pmc Fri Mar 27 22:07:05 2009 (r37769)
@@ -37,23 +37,12 @@
VTABLE void init() {
Parrot_Socket_attributes *data_struct =
- mem_allocate_typed(Parrot_Socket_attributes);
+ mem_allocate_zeroed_typed(Parrot_Socket_attributes);
PMC_data(SELF) = data_struct;
data_struct->local = PMCNULL;
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
-
PObj_custom_mark_destroy_SETALL(SELF);
}
@@ -68,11 +57,12 @@
*/
VTABLE PMC *clone() {
- Parrot_Socket_attributes * const old_struct = PARROT_SOCKET(SELF);
- PMC * const copy = Parrot_io_new_socket_pmc(interp, old_struct->flags);
+ PMC * copy = SUPER();
+ Parrot_Socket_attributes * const old_struct = PARROT_SOCKET(SELF);
Parrot_Socket_attributes * const data_struct = PARROT_SOCKET(copy);
- data_struct->os_handle = Parrot_dup(old_struct->os_handle);
+ data_struct->local = VTABLE_clone(interp, old_struct->local);
+ data_struct->remote = VTABLE_clone(interp, old_struct->remote);
return SELF;
}
@@ -115,12 +105,28 @@
}
}
- METHOD close() {
- INTVAL status = 0;
- close(PARROT_SOCKET(SELF)->os_handle);
- RETURN(INTVAL status);
- }
+/*
+=item C<INTVAL get_bool()>
+
+Returns whether the Socket was successfully created.
+
+=cut
+
+*/
+
+ VTABLE INTVAL get_bool() {
+ /* Initialize the os_handle to the platform-specific value for closed. */
+#ifdef PIO_OS_WIN32
+ return (PARROT_SOCKET(SELF)->os_handle != (PIOHANDLE)INVALID_HANDLE_VALUE);
+#endif
+#ifdef PIO_OS_UNIX
+ return (PARROT_SOCKET(SELF)->os_handle != (PIOHANDLE)-1);
+#endif
+#ifdef PIO_OS_STDIO
+ return (PARROT_SOCKET(SELF)->os_handle != (PIOHANDLE)NULL);
+#endif
+ }
/*
@@ -130,6 +136,36 @@
=over 4
+=item C<socket>
+
+=cut
+
+*/
+
+
+ METHOD socket(INTVAL type, INTVAL fam, INTVAL proto) {
+ PMC * res = Parrot_io_socket(interp, SELF, type, fam, proto);
+ RETURN(PMC * res);
+ }
+
+/*
+
+=item C<sockaddr>
+
+C<sockaddr> returns an object representing a socket address, generated
+from a port number (integer) and an address (string).
+
+=cut
+
+*/
+
+ METHOD sockaddr(STRING * address, INTVAL port) {
+ PMC * res = Parrot_io_sockaddr_in(interp, address, port);
+ RETURN(PMC * res);
+ }
+
+/*
+
=item C<connect>
Connects a socket object to an address.
@@ -191,16 +227,68 @@
RETURN(INTVAL res);
}
+/*
+
+=item C<bind>
+
+C<bind> binds a socket object to the port and address specified by an
+address object (the packed result of C<sockaddr>).
+
+The asynchronous version takes an additional final PMC callback
+argument, and only returns a status object. When the bind operation is
+complete, it invokes the callback, passing it a status object and the
+socket object it was called on. [If you want notification when a bind
+operation is completed, you probably want to do something with that
+bound socket object.]
+
+=cut
+
+*/
+
METHOD bind(PMC *host) {
INTVAL res = Parrot_io_bind(INTERP, SELF, host);
RETURN(INTVAL res);
}
+/*
+
+=item C<listen>
+
+C<listen> specifies that a socket object is willing to accept incoming
+connections. The integer argument gives the maximum size of the queue
+for pending connections.
+
+There is no asynchronous version. C<listen> marks a set of attributes on
+the socket object.
+
+=cut
+
+*/
+
METHOD listen(INTVAL backlog) {
INTVAL res = Parrot_io_listen(INTERP, SELF, backlog);
RETURN(INTVAL res);
}
+/*
+
+=item C<accept>
+
+C<accept> accepts a new connection on a given socket object, and returns
+a newly created socket object for the connection.
+
+The asynchronous version takes an additional final PMC callback
+argument, and only returns a status object. When the accept operation
+receives a new connection, it invokes the callback, passing it a status
+object and a newly created socket object for the connection. [While the
+synchronous C<accept> has to be called repeatedly in a loop (once for
+each connection received), the asynchronous version is only called once,
+but continues to send new connection events until the socket is closed.]
+
+=cut
+
+*/
+
METHOD accept() {
PMC * res = Parrot_io_accept(INTERP, SELF);
RETURN(PMC * res);
More information about the parrot-commits
mailing list