Ticket #496: socket.patch

File socket.patch, 49.6 KB (added by bacek, 13 years ago)

Sockets patch

  • config/gen/makefiles/root.in

    diff --git a/config/gen/makefiles/root.in b/config/gen/makefiles/root.in
    index 6a1d9ac..7f3e5b9 100644
    a b  
    362362    $(IO_DIR)/unix$(O) \ 
    363363    $(IO_DIR)/win32$(O) \ 
    364364    $(IO_DIR)/portable$(O) \ 
    365     $(IO_DIR)/filehandle$(O) 
     365    $(IO_DIR)/filehandle$(O) \ 
     366    $(IO_DIR)/socket_api$(O) \ 
     367    $(IO_DIR)/socket_unix$(O) 
    366368 
    367369INTERP_O_FILES := \ 
    368370    $(SRC_DIR)/string/api$(O) \ 
  • (a) /dev/null vs. (b) b/examples/io/httpd.pir

    diff --git a/examples/io/httpd.pir b/examples/io/httpd.pir
    new file mode 100644
    index 0000000..2c6a2bc
    a b  
     1# Copyright (C) 2006-2008, Parrot Foundation. 
     2# $Id: httpd.pir 36833 2009-02-17 20:09:26Z allison $ 
     3 
     4=head1 NAME 
     5 
     6examples/io/httpd.pir - HTTP server 
     7 
     8=head1 SYNOPSIS 
     9 
     10  $ ./parrot examples/io/httpd.pir 
     11 
     12=head1 DESCRIPTION 
     13 
     14A very tiny HTTP-Server. It currently only understands the GET method. 
     15It's a nice way of testing pretty much all IO functions. 
     16By default (and not yet configurable) it binds to localhost:1234. 
     17 
     18=head2 Serving Parrot Docs 
     19 
     20If no filename is given it serves the HTML documentation 
     21in ./docs/html. Make sure you have built them with 
     22 
     23  $ make html 
     24 
     25After that you can browse the documentation with 
     26 
     27  http://localhost:1234 
     28 
     29which redirects to 
     30 
     31  http://localhost:1234/docs/html/index.html 
     32 
     33=head2 Serving Other HTML Files 
     34 
     35If a html file is present in the request, this file will be served: 
     36 
     37  http://localhost:1234/index.html 
     38 
     39This will sent F<./index.html> from the directory, where F<httpd.pir> 
     40was started. 
     41 
     42=head2 CGI 
     43 
     44If the file extension is C<.pir> or C<.pbc>, this file will be loaded 
     45below the directory F<cgi-pir> and the function C<cgi_main> will be 
     46invoked with the query as an argument. 
     47This functions should return a plain string, which will be sent to the 
     48browser. 
     49 
     50F<cgi_main> is called with 3 arguments: a todo/reserved PMC, a string 
     51with the original query and a Hash, with C<key=value> items split by 
     52C<'+'>. C<key> and C<value> are already C<urldecoded>. 
     53 
     54  $ cat cgi-pir/foo.pir 
     55  .sub cgi_main 
     56    .param pmc reserved         # TODO 
     57    .param string query         # all after '?':  "foo=1+bar=A" 
     58    .param pmc query_hash       # Hash { foo=>'1', bar=>'A' } 
     59    .return ("<p>foo</p>")      # in practice use a full <html>doc</html> 
     60                                # unless serving XMLHttpRequest's 
     61  .end 
     62 
     63The browser request: 
     64 
     65  http://localhost:1234/foo.pir?foo=1+bar=%61 
     66 
     67will serve, whatever the C<cgi_main> function returned. 
     68 
     69=head1 TODO 
     70 
     71make it work on W32/IE 
     72 
     73Transcode the received string to ascii, in order to have access to an 
     74implemented 'index' op. Or just use unicode instead. 
     75 
     76=head1 SEE ALSO 
     77 
     78RFC2616 
     79 
     80=head1 AUTHOR 
     81 
     82Original author is Markus Amsler - <markus.amsler@oribi.org> 
     83The code was heavily hacked by bernhard and leo. 
     84 
     85=cut 
     86 
     87.const string CRLF     = "\r\n" 
     88.const string CRLFCRLF = "\r\n\r\n" 
     89.const string LFLF     = "\n\n" 
     90.const string CRCR     = "\r\r" 
     91 
     92.const string SERVER_NAME = "Parrot-httpd/0.1" 
     93 
     94.include "stat.pasm" 
     95 
     96.sub main :main 
     97    .local pmc sock, work, fp 
     98    .local pmc fp               # read requested files from disk 
     99    .local int port 
     100    .local pmc address 
     101    .local string host 
     102    .local string buf, req, rep, temp 
     103    .local string meth, url, file_content 
     104    .local int ret 
     105    .local int len, pos, occ1, occ2, dotdot 
     106 
     107    .local string doc_root 
     108    doc_root = "." 
     109    host = "localhost" 
     110    port = 1234 
     111 
     112    # TODO provide sys/socket constants 
     113    socket sock, 2, 1, 6        # PF_INET, SOCK_STREAM, tcp 
     114    unless sock goto ERR_NO_SOCKET 
     115 
     116    # Pack a sockaddr_in structure with IP and port 
     117    address = sockaddr host, port 
     118    ret = bind sock, address 
     119    if ret == -1 goto ERR_bind 
     120    $S0 = port 
     121    print "Running webserver on port " 
     122    print $S0 
     123    print " of " 
     124    print host 
     125    print ".\n" 
     126    print "The Parrot documentation can now be accessed at http://" 
     127    print host 
     128    print ":" 
     129    print $S0 
     130    print "\n" 
     131    print "Be sure that the HTML docs have been generated with 'make html'.\n" 
     132 
     133    listen ret, sock, 1 
     134NEXT: 
     135    accept work, sock 
     136    req = "" 
     137MORE: 
     138    recv ret, work, buf 
     139    # charset I0, buf 
     140    # charsetname S1, I0 
     141    # print "\nret: " 
     142    # print ret 
     143    # print "\ncharset of buf: " 
     144    # print S1 
     145    # print "\nbuf:" 
     146    # print buf 
     147    # print "\nafter buf" 
     148 
     149    if ret <= 0 goto SERVE_REQ 
     150    concat req, buf 
     151    index pos, req, CRLFCRLF 
     152    # print "\npos1:" 
     153    # print pos 
     154    if pos >= 0 goto SERVE_REQ 
     155    index pos, req, LFLF 
     156    # print "\npos2:" 
     157    # print pos 
     158    if pos >= 0 goto SERVE_REQ 
     159    index pos, req, CRCR 
     160    # print "\npos3:" 
     161    # print pos 
     162    if pos >= 0 goto SERVE_REQ 
     163    goto MORE 
     164 
     165SERVE_REQ: 
     166#    print "Request:\n" 
     167#    print req 
     168#    print "*******\n" 
     169 
     170# parse 
     171# GET the_file HTTP* 
     172    index occ1, req, " " 
     173    substr meth, req, 0, occ1 
     174    inc occ1 
     175    index occ2, req, " ", occ1 
     176    len = occ2 - occ1 
     177    substr url, req, occ1, len 
     178 
     179    if meth == "GET" goto SERVE_GET 
     180 
     181    print "unknown method:'" 
     182    print meth 
     183    print "'\n" 
     184    close work 
     185    goto NEXT 
     186 
     187SERVE_GET: 
     188    .local int is_cgi 
     189    (is_cgi, file_content, len) = check_cgi(url) 
     190    if is_cgi goto SERVE_blob 
     191 
     192    # decode the url 
     193    url = urldecode(url) 
     194 
     195    # Security: Don't allow access to the parent dir 
     196    index dotdot, url, ".." 
     197    if dotdot >= 0 goto SERVE_404 
     198 
     199    # redirect instead of serving index.html 
     200    if url == "/" goto SERVE_docroot 
     201 
     202    # Those little pics in the URL field or in tabs 
     203    if url == "/favicon.ico" goto SERVE_favicon 
     204 
     205    # try to serve a file 
     206    goto SERVE_file 
     207 
     208SERVE_file: 
     209    # try to open the file in url 
     210    concat url, doc_root, url 
     211    fp = open url, 'r' 
     212    unless fp goto SERVE_404 
     213    len = stat url, .STAT_FILESIZE 
     214    read file_content, fp, len 
     215 
     216SERVE_blob: 
     217    # TODO make more subs 
     218    # takes: file_content, len 
     219    rep = "HTTP/1.1 200 OK" 
     220    rep .= CRLF 
     221    rep .= "Server: " 
     222    rep .= SERVER_NAME 
     223    rep .= CRLF 
     224    rep .= "Content-Length: " 
     225    temp = to_string (len) 
     226    rep .= temp 
     227    rep .= CRLFCRLF 
     228    rep .= file_content 
     229    send ret, work, rep 
     230    # TODO provide a log method 
     231    print "served file '" 
     232    print url 
     233    print "'\n" 
     234    close work 
     235    goto NEXT 
     236 
     237SERVE_docroot: 
     238    rep = 'HTTP/1.1 301 Moved Permamently' 
     239    rep .= CRLF 
     240    rep .= "Server: " 
     241    rep .= SERVER_NAME 
     242    rep .= CRLF 
     243    rep .= 'Location: /docs/html/index.html' 
     244    rep .= CRLF 
     245    rep .= 'Content-Length: ' 
     246    file_content = "Please go to <a href='docs/html/index.html'>Parrot Documentation</a>." 
     247    length len, file_content 
     248    temp = to_string (len) 
     249    concat rep, temp 
     250    concat rep, CRLFCRLF 
     251    concat rep, file_content 
     252    send ret, work, rep 
     253    print "Redirect to 'docs/html/index.html'\n" 
     254    close work 
     255    goto NEXT 
     256 
     257SERVE_favicon: 
     258    url = urldecode( '/docs/resources/favicon.ico') 
     259    goto SERVE_file 
     260 
     261SERVE_404: 
     262    $S0 = '404 Not found' 
     263    $I0 = length $S0 
     264    rep = 'HTTP/1.1 404 Not Found' 
     265    rep .= CRLF 
     266    rep .= "Server: " 
     267    rep .= SERVER_NAME 
     268    rep .= CRLF 
     269    rep .= 'Content-Length: ' 
     270    $S1 = $I0 
     271    rep .= $S1 
     272    rep .= CRLF 
     273    rep .= 'Content-Type: text/plain' 
     274    rep .= CRLFCRLF 
     275    rep .= $S0 
     276    print "File not found: '" 
     277    print url 
     278    print "'\n" 
     279    send ret, work, rep 
     280    goto NEXT 
     281 
     282ERR_NO_SOCKET: 
     283    print "Could not open socket.\n" 
     284    print "Did you enable PARROT_NET_DEVEL in include/io_private.h?\n" 
     285    end 
     286ERR_bind: 
     287    print "bind failed\n" 
     288    # fall through 
     289END: 
     290    close sock 
     291    end 
     292.end 
     293 
     294.sub to_string 
     295    .param pmc args :slurpy 
     296 
     297    .local string ret 
     298    ret = sprintf "%d", args 
     299    .return( ret ) 
     300.end 
     301 
     302# convert %xx to char 
     303.sub urldecode 
     304    .param string in 
     305 
     306    .local string out, char_in, char_out 
     307    .local int    c_out, pos_in, len 
     308    .local string hex 
     309 
     310    len = length in 
     311    pos_in = 0 
     312    out = "" 
     313START: 
     314    if pos_in >= len goto END 
     315    substr char_in, in, pos_in, 1 
     316    char_out = char_in 
     317    if char_in != "%" goto INC_IN 
     318    # OK this was a escape character, next two are hexadecimal 
     319    inc pos_in 
     320    substr hex, in, pos_in, 2 
     321    c_out = hex_to_int (hex) 
     322    chr char_out, c_out 
     323    inc pos_in 
     324 
     325INC_IN: 
     326    concat out, char_out 
     327    inc pos_in 
     328    goto START 
     329END: 
     330   .return( out ) 
     331.end 
     332 
     333.sub hex_to_int 
     334    .param pmc hex 
     335    .tailcall hex.'to_int'(16) 
     336.end 
     337 
     338# if file is *.pir or *.pbc run it as CGI 
     339.sub check_cgi 
     340    .param string url 
     341    $I0 = index url, ".pir" 
     342    if $I0 > 0 goto cgi_1 
     343    $I0 = index url, ".pbc" 
     344    if $I0 > 0 goto cgi_1 
     345    .return (0, '', 0) 
     346cgi_1: 
     347    # file.pir?foo=1+bar=2 
     348    $I0 = index url, '?' 
     349    if $I0 == -1 goto no_query 
     350    .local string file, query 
     351    .local pmc query_hash 
     352    file = substr url, 0, $I0 
     353    inc $I0 
     354    query = substr url, $I0 
     355    # TODO split into a hash, then decode parts 
     356    query_hash = make_query_hash(query) 
     357    query = urldecode(query) 
     358    goto have_query 
     359no_query: 
     360    file = url 
     361    query = '' 
     362    query_hash = new 'Hash' 
     363have_query: 
     364    # escape % 
     365    file = urldecode(file) 
     366 
     367    # Security: Don't allow access to the parent dir 
     368    .local int dotdot 
     369    index dotdot, file, ".." 
     370    if dotdot < 0 goto cgi_file 
     371    .return (0, '', 0) 
     372 
     373cgi_file: 
     374    print "CGI: '" 
     375    print file 
     376    print "' Q: '" 
     377    print query 
     378    print "'\n" 
     379    file = "cgi-pir/" . file 
     380    # TODO stat the file 
     381    load_bytecode file 
     382    .local string result 
     383    null $P0    # not yet 
     384    # TODO catch ex 
     385    result = 'cgi_main'($P0, query, query_hash) 
     386    $I0 = length result 
     387    .return (1, result, $I0) 
     388.end 
     389 
     390# split query at '+', make hash from foo=bar items 
     391.sub make_query_hash 
     392    .param string query         # the unescapced one 
     393    .local pmc query_hash, items 
     394    .local string kv, k, v 
     395    query_hash = new 'Hash' 
     396    items = split '+', query 
     397    .local int i, n 
     398    i = 0 
     399    n = elements items 
     400lp_items: 
     401    kv = items[i] 
     402    $I0 = index kv, "=" 
     403    if $I0 == -1 goto no_val 
     404    k = substr kv, 0, $I0 
     405    inc $I0 
     406    v = substr kv, $I0 
     407    v = urldecode(v) 
     408    goto set_val 
     409no_val: 
     410    k = kv 
     411    v = 1 
     412set_val: 
     413    k = urldecode(k) 
     414    query_hash[k] = v 
     415 
     416next_item: 
     417    inc i 
     418    if i < n goto lp_items 
     419    .return (query_hash) 
     420.end 
     421 
     422# Local Variables: 
     423#   mode: pir 
     424#   fill-column: 100 
     425# End: 
     426# vim: expandtab shiftwidth=4 ft=pir: 
  • include/parrot/io.h

    diff --git a/include/parrot/io.h b/include/parrot/io.h
    index 9669788..8f0f035 100644
    a b  
    11/* io.h 
    22 *  Copyright (C) 2001-2003, Parrot Foundation. 
    33 *  SVN Info 
    4  *     $Id$ 
     4 *     $Id: io.h 36833 2009-02-17 20:09:26Z allison $ 
    55 *  Overview: 
    66 *      Parrot IO subsystem 
    77 *  Data Structure and Algorithms: 
     
    757757/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */ 
    758758/* HEADERIZER END: src/io/filehandle.c */ 
    759759 
     760/* HEADERIZER BEGIN: src/io/socket_api.c */ 
     761/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */ 
     762 
     763PARROT_EXPORT 
     764PARROT_WARN_UNUSED_RESULT 
     765PARROT_CAN_RETURN_NULL 
     766PMC * Parrot_io_accept(PARROT_INTERP, ARGMOD(PMC *pmc)) 
     767        __attribute__nonnull__(1) 
     768        __attribute__nonnull__(2) 
     769        FUNC_MODIFIES(*pmc); 
     770 
     771PARROT_EXPORT 
     772INTVAL Parrot_io_bind(PARROT_INTERP, ARGMOD(PMC *pmc), ARGMOD(PMC *address)) 
     773        __attribute__nonnull__(1) 
     774        __attribute__nonnull__(2) 
     775        __attribute__nonnull__(3) 
     776        FUNC_MODIFIES(*pmc) 
     777        FUNC_MODIFIES(*address); 
     778 
     779PARROT_EXPORT 
     780INTVAL Parrot_io_connect(PARROT_INTERP, 
     781    ARGMOD(PMC *pmc), 
     782    ARGMOD(PMC *address)) 
     783        __attribute__nonnull__(1) 
     784        __attribute__nonnull__(2) 
     785        __attribute__nonnull__(3) 
     786        FUNC_MODIFIES(*pmc) 
     787        FUNC_MODIFIES(*address); 
     788 
     789PARROT_EXPORT 
     790PARROT_WARN_UNUSED_RESULT 
     791INTVAL Parrot_io_listen(PARROT_INTERP, ARGMOD(PMC *pmc), INTVAL backlog) 
     792        __attribute__nonnull__(1) 
     793        __attribute__nonnull__(2) 
     794        FUNC_MODIFIES(*pmc); 
     795 
     796PARROT_EXPORT 
     797PARROT_WARN_UNUSED_RESULT 
     798PARROT_CANNOT_RETURN_NULL 
     799PMC * Parrot_io_new_socket_pmc(PARROT_INTERP, INTVAL flags) 
     800        __attribute__nonnull__(1); 
     801 
     802PARROT_EXPORT 
     803INTVAL Parrot_io_poll(PARROT_INTERP, 
     804    ARGMOD(PMC *pmc), 
     805    INTVAL which, 
     806    INTVAL sec, 
     807    INTVAL usec) 
     808        __attribute__nonnull__(1) 
     809        __attribute__nonnull__(2) 
     810        FUNC_MODIFIES(*pmc); 
     811 
     812PARROT_EXPORT 
     813INTVAL Parrot_io_recv(PARROT_INTERP, ARGMOD(PMC *pmc), ARGOUT(STRING **buf)) 
     814        __attribute__nonnull__(1) 
     815        __attribute__nonnull__(2) 
     816        __attribute__nonnull__(3) 
     817        FUNC_MODIFIES(*pmc) 
     818        FUNC_MODIFIES(*buf); 
     819 
     820PARROT_EXPORT 
     821PARROT_WARN_UNUSED_RESULT 
     822INTVAL Parrot_io_send(PARROT_INTERP, ARGMOD(PMC *pmc), ARGMOD(STRING *buf)) 
     823        __attribute__nonnull__(1) 
     824        __attribute__nonnull__(2) 
     825        __attribute__nonnull__(3) 
     826        FUNC_MODIFIES(*pmc) 
     827        FUNC_MODIFIES(*buf); 
     828 
     829PARROT_EXPORT 
     830PARROT_WARN_UNUSED_RESULT 
     831PARROT_CANNOT_RETURN_NULL 
     832PMC * Parrot_io_socket(PARROT_INTERP, INTVAL fam, INTVAL type, INTVAL proto) 
     833        __attribute__nonnull__(1); 
     834 
     835PARROT_EXPORT 
     836PARROT_WARN_UNUSED_RESULT 
     837PARROT_CANNOT_RETURN_NULL 
     838INTVAL Parrot_io_socket_is_closed(ARGMOD(PMC *socket)) 
     839        __attribute__nonnull__(1) 
     840        FUNC_MODIFIES(*socket); 
     841 
     842#define ASSERT_ARGS_Parrot_io_accept __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 
     843       PARROT_ASSERT_ARG(interp) \ 
     844    || PARROT_ASSERT_ARG(pmc) 
     845#define ASSERT_ARGS_Parrot_io_bind __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 
     846       PARROT_ASSERT_ARG(interp) \ 
     847    || PARROT_ASSERT_ARG(pmc) \ 
     848    || PARROT_ASSERT_ARG(address) 
     849#define ASSERT_ARGS_Parrot_io_connect __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 
     850       PARROT_ASSERT_ARG(interp) \ 
     851    || PARROT_ASSERT_ARG(pmc) \ 
     852    || PARROT_ASSERT_ARG(address) 
     853#define ASSERT_ARGS_Parrot_io_listen __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 
     854       PARROT_ASSERT_ARG(interp) \ 
     855    || PARROT_ASSERT_ARG(pmc) 
     856#define ASSERT_ARGS_Parrot_io_new_socket_pmc __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 
     857       PARROT_ASSERT_ARG(interp) 
     858#define ASSERT_ARGS_Parrot_io_poll __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 
     859       PARROT_ASSERT_ARG(interp) \ 
     860    || PARROT_ASSERT_ARG(pmc) 
     861#define ASSERT_ARGS_Parrot_io_recv __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 
     862       PARROT_ASSERT_ARG(interp) \ 
     863    || PARROT_ASSERT_ARG(pmc) \ 
     864    || PARROT_ASSERT_ARG(buf) 
     865#define ASSERT_ARGS_Parrot_io_send __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 
     866       PARROT_ASSERT_ARG(interp) \ 
     867    || PARROT_ASSERT_ARG(pmc) \ 
     868    || PARROT_ASSERT_ARG(buf) 
     869#define ASSERT_ARGS_Parrot_io_socket __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 
     870       PARROT_ASSERT_ARG(interp) 
     871#define ASSERT_ARGS_Parrot_io_socket_is_closed __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 
     872       PARROT_ASSERT_ARG(socket) 
     873/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */ 
     874/* HEADERIZER END: src/io/socket_api.c */ 
     875 
    760876/* Put platform specific macros here if you must */ 
    761877#ifdef PIO_OS_WIN32 
    762878extern STRING          *PIO_sockaddr_in(PARROT_INTERP, unsigned short, STRING *); 
  • include/parrot/io_unix.h

    diff --git a/include/parrot/io_unix.h b/include/parrot/io_unix.h
    index 13d5373..4fd5c69 100644
    a b  
    11/* io_unix.h 
    22 *  Copyright (C) 2001-2003, Parrot Foundation. 
    33 *  SVN Info 
    4  *     $Id$ 
     4 *     $Id: io_unix.h 36833 2009-02-17 20:09:26Z allison $ 
    55 *  Overview: 
    66 *      Parrot IO subsystem 
    77 *  Data Structure and Algorithms: 
     
    155155/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */ 
    156156/* HEADERIZER END: src/io/unix.c */ 
    157157 
     158 
     159/* HEADERIZER BEGIN: src/io/socket_unix.c */ 
     160/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */ 
     161 
     162PARROT_WARN_UNUSED_RESULT 
     163PARROT_CAN_RETURN_NULL 
     164PMC * Parrot_io_accept_unix(PARROT_INTERP, ARGMOD(PMC *socket)) 
     165        __attribute__nonnull__(1) 
     166        __attribute__nonnull__(2) 
     167        FUNC_MODIFIES(*socket); 
     168 
     169INTVAL Parrot_io_bind_unix(PARROT_INTERP, 
     170    ARGMOD(PMC *socket), 
     171    ARGMOD(PMC *sockaddr)) 
     172        __attribute__nonnull__(1) 
     173        __attribute__nonnull__(2) 
     174        __attribute__nonnull__(3) 
     175        FUNC_MODIFIES(*socket) 
     176        FUNC_MODIFIES(*sockaddr); 
     177 
     178INTVAL Parrot_io_connect_unix(PARROT_INTERP, 
     179    ARGMOD(PMC *socket), 
     180    ARGIN(PMC *r)) 
     181        __attribute__nonnull__(1) 
     182        __attribute__nonnull__(2) 
     183        __attribute__nonnull__(3) 
     184        FUNC_MODIFIES(*socket); 
     185 
     186INTVAL Parrot_io_listen_unix(SHIM_INTERP, ARGMOD(PMC *socket), INTVAL sec) 
     187        __attribute__nonnull__(2) 
     188        FUNC_MODIFIES(*socket); 
     189 
     190INTVAL Parrot_io_poll_unix(SHIM_INTERP, 
     191    ARGMOD(PMC *socket), 
     192    int which, 
     193    int sec, 
     194    int usec) 
     195        __attribute__nonnull__(2) 
     196        FUNC_MODIFIES(*socket); 
     197 
     198INTVAL Parrot_io_recv_unix(PARROT_INTERP, 
     199    ARGMOD(PMC *socket), 
     200    ARGOUT(STRING **s)) 
     201        __attribute__nonnull__(1) 
     202        __attribute__nonnull__(2) 
     203        __attribute__nonnull__(3) 
     204        FUNC_MODIFIES(*socket) 
     205        FUNC_MODIFIES(*s); 
     206 
     207INTVAL Parrot_io_send_unix(SHIM_INTERP, 
     208    ARGMOD(PMC *socket), 
     209    ARGMOD(STRING *s)) 
     210        __attribute__nonnull__(2) 
     211        __attribute__nonnull__(3) 
     212        FUNC_MODIFIES(*socket) 
     213        FUNC_MODIFIES(*s); 
     214 
     215PARROT_WARN_UNUSED_RESULT 
     216PARROT_CANNOT_RETURN_NULL 
     217PMC * Parrot_io_sockaddr_in(PARROT_INTERP, ARGIN(STRING *addr), INTVAL port) 
     218        __attribute__nonnull__(1) 
     219        __attribute__nonnull__(2); 
     220 
     221PARROT_WARN_UNUSED_RESULT 
     222PARROT_CAN_RETURN_NULL 
     223PMC * Parrot_io_socket_unix(PARROT_INTERP, int fam, int type, int proto) 
     224        __attribute__nonnull__(1); 
     225 
     226#define ASSERT_ARGS_Parrot_io_accept_unix __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 
     227       PARROT_ASSERT_ARG(interp) \ 
     228    || PARROT_ASSERT_ARG(socket) 
     229#define ASSERT_ARGS_Parrot_io_bind_unix __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 
     230       PARROT_ASSERT_ARG(interp) \ 
     231    || PARROT_ASSERT_ARG(socket) \ 
     232    || PARROT_ASSERT_ARG(sockaddr) 
     233#define ASSERT_ARGS_Parrot_io_connect_unix __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 
     234       PARROT_ASSERT_ARG(interp) \ 
     235    || PARROT_ASSERT_ARG(socket) \ 
     236    || PARROT_ASSERT_ARG(r) 
     237#define ASSERT_ARGS_Parrot_io_listen_unix __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 
     238       PARROT_ASSERT_ARG(socket) 
     239#define ASSERT_ARGS_Parrot_io_poll_unix __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 
     240       PARROT_ASSERT_ARG(socket) 
     241#define ASSERT_ARGS_Parrot_io_recv_unix __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 
     242       PARROT_ASSERT_ARG(interp) \ 
     243    || PARROT_ASSERT_ARG(socket) \ 
     244    || PARROT_ASSERT_ARG(s) 
     245#define ASSERT_ARGS_Parrot_io_send_unix __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 
     246       PARROT_ASSERT_ARG(socket) \ 
     247    || PARROT_ASSERT_ARG(s) 
     248#define ASSERT_ARGS_Parrot_io_sockaddr_in __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 
     249       PARROT_ASSERT_ARG(interp) \ 
     250    || PARROT_ASSERT_ARG(addr) 
     251#define ASSERT_ARGS_Parrot_io_socket_unix __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 
     252       PARROT_ASSERT_ARG(interp) 
     253/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */ 
     254/* HEADERIZER END: src/io/socket_unix.c */ 
     255 
     256 
     257 
    158258#define PIO_INIT(interp) Parrot_io_init_unix((interp)) 
    159259#define PIO_OPEN(interp, pmc, file, flags) \ 
    160260    Parrot_io_open_unix((interp), (pmc), (file), (flags)) 
     
    173273#define PIO_FLUSH(interp, pmc) Parrot_io_flush_unix((interp), (pmc)) 
    174274#define PIO_GETBLKSIZE(handle) Parrot_io_getblksize_unix((handle)) 
    175275 
     276#define PIO_POLL(interp, pmc, which, sec, usec) \ 
     277    Parrot_io_poll_unix((interp), (pmc), (which), (sec), (usec)) 
     278#define PIO_NEW_SOCKET(interp, fam, type, proto) \ 
     279    Parrot_io_socket_unix((interp), (fam), (type), (proto)) 
     280#define PIO_RECV(interp, pmc, buf) \ 
     281    Parrot_io_recv_unix((interp), (pmc), (buf)) 
     282#define PIO_SEND(interp, pmc, buf) \ 
     283    Parrot_io_send_unix((interp), (pmc), (buf)) 
     284#define PIO_CONNECT(interp, pmc, address) \ 
     285    Parrot_io_connect_unix((interp), (pmc), (address)) 
     286#define PIO_BIND(interp, pmc, address) \ 
     287    Parrot_io_bind_unix((interp), (pmc), (address)) 
     288#define PIO_LISTEN(interp, pmc, backlog) \ 
     289    Parrot_io_listen_unix((interp), (pmc), (backlog)) 
     290#define PIO_ACCEPT(interp, pmc) \ 
     291    Parrot_io_accept_unix((interp), (pmc)) 
     292 
    176293#endif /* PARROT_IO_UNIX_H_GUARD */ 
    177294 
    178295/* 
  • src/io/socket_api.c

    diff --git a/src/io/socket_api.c b/src/io/socket_api.c
    index 3cb895d..17f5ce5 100644
    a b  
    11/* 
    22Copyright (C) 2001-2008, Parrot Foundation. 
    3 $Id$ 
     3$Id: socket_api.c 36832 2009-02-17 19:58:58Z allison $ 
    44 
    55=head1 NAME 
    66 
     
    2020 
    2121#include "parrot/parrot.h" 
    2222#include "io_private.h" 
    23 #include "io.str" 
     23#include "api.str" 
    2424 
    2525#include <stdarg.h> 
    2626 
     
    3232 
    3333 
    3434=over 4 
     35*/ 
     36 
     37 
     38/* 
     39 
     40=item C<INTVAL Parrot_io_socket_is_closed> 
     41 
     42=cut 
     43 
     44*/ 
     45 
     46PARROT_EXPORT 
     47PARROT_WARN_UNUSED_RESULT 
     48PARROT_CANNOT_RETURN_NULL 
     49INTVAL 
     50Parrot_io_socket_is_closed(ARGMOD(PMC *socket)) 
     51{ 
     52    return 0; 
     53} 
     54 
     55/* 
    3556 
    3657=item C<INTVAL Parrot_io_poll> 
    3758 
     
    7192PMC * 
    7293Parrot_io_socket(PARROT_INTERP, INTVAL fam, INTVAL type, INTVAL proto) 
    7394{ 
    74     ParrotIOLayer * const l = interp->piodata->default_stack; 
    75     return PIO_NEW_SOCKET(interp, l, fam, type, proto); 
     95    return PIO_NEW_SOCKET(interp, fam, type, proto); 
    7696} 
    7797 
    7898/* 
     
    130150 
    131151PARROT_EXPORT 
    132152INTVAL 
    133 Parrot_io_connect(PARROT_INTERP, ARGMOD(PMC *pmc), ARGMOD(STRING *address)) 
     153Parrot_io_connect(PARROT_INTERP, ARGMOD(PMC *pmc), ARGMOD(PMC *address)) 
    134154{ 
    135155    if (Parrot_io_socket_is_closed(pmc)) 
    136156        return -1; 
     
    151171 
    152172PARROT_EXPORT 
    153173INTVAL 
    154 Parrot_io_bind(PARROT_INTERP, ARGMOD(PMC *pmc), ARGMOD(STRING *address)) 
     174Parrot_io_bind(PARROT_INTERP, ARGMOD(PMC *pmc), ARGMOD(PMC *address)) 
    155175{ 
    156176    if (Parrot_io_socket_is_closed(pmc)) 
    157177        return -1; 
    158178 
    159     return PIO_BIND(interp, address); 
     179    return PIO_BIND(interp, pmc, address); 
    160180} 
    161181 
    162182/* 
     
    199219{ 
    200220 
    201221    if (Parrot_io_socket_is_closed(pmc)) 
    202         return -1; 
     222        return PMCNULL; 
    203223 
    204     return PIO_ACCEPT(interp, l, io); 
     224    return PIO_ACCEPT(interp, pmc); 
    205225} 
    206226 
    207227/* 
    208228 
     229=item C<PMC * Parrot_io_new_socket_pmc> 
     230 
     231Creates a new I/O socket object. The value of C<flags> is set 
     232in the returned PMC. 
     233 
     234=cut 
     235 
     236*/ 
     237 
     238PARROT_EXPORT 
     239PARROT_WARN_UNUSED_RESULT 
     240PARROT_CANNOT_RETURN_NULL 
     241PMC * 
     242Parrot_io_new_socket_pmc(PARROT_INTERP, INTVAL flags) 
     243{ 
     244    ASSERT_ARGS(Parrot_io_new_socket_pmc) 
     245    PMC * const new_io = pmc_new(interp, enum_class_Socket); 
     246 
     247    Parrot_io_set_flags(interp, new_io, flags); 
     248 
     249    return new_io; 
     250} 
     251/* 
     252 
    209253=back 
    210254 
    211255=head1 SEE ALSO 
  • src/io/socket_unix.c

    diff --git a/src/io/socket_unix.c b/src/io/socket_unix.c
    index 425a8ae..0a36548 100644
    a b  
    11/* 
    22Copyright (C) 2001-2008, Parrot Foundation. 
    3 $Id$ 
     3$Id: socket_unix.c 36832 2009-02-17 19:58:58Z allison $ 
    44 
    55=head1 NAME 
    66 
     
    2828 
    2929*/ 
    3030 
     31#include <sys/socket.h> 
     32 
    3133#include "parrot/parrot.h" 
    3234#include "io_private.h" 
     35#include "../pmc/pmc_socket.h" 
    3336 
    3437#ifdef PIO_OS_UNIX 
    3538 
     
    3841/* HEADERIZER BEGIN: static */ 
    3942/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */ 
    4043 
     44static void get_sockaddr_in(PARROT_INTERP, 
     45    ARGIN(PMC * sockaddr), 
     46    ARGIN(const char* host), 
     47    int port) 
     48        __attribute__nonnull__(1) 
     49        __attribute__nonnull__(2) 
     50        __attribute__nonnull__(3); 
     51 
     52#define ASSERT_ARGS_get_sockaddr_in __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 
     53       PARROT_ASSERT_ARG(interp) \ 
     54    || PARROT_ASSERT_ARG(sockaddr) \ 
     55    || PARROT_ASSERT_ARG(host) 
    4156/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */ 
    4257/* HEADERIZER END: static */ 
    4358 
    4459/* 
     60static void get_sockaddr_in(PARROT_INTERP, ARGIN(PMC * sockaddr), 
     61    ARGIN(const char* host), ARGIN(int port)); 
     62*/ 
     63 
     64/* 
    4565 
    4666=back 
    4767 
     
    5676 
    5777=over 4 
    5878 
    59 =item C<STRING * Parrot_io_sockaddr_in> 
     79=item C<PMC * Parrot_io_sockaddr_in> 
    6080 
    6181C<Parrot_io_sockaddr_in()> is not part of the layer and so must be C<extern>. 
    6282 
     
    6787 
    6888*/ 
    6989 
     90/* Helper macros to get sockaddr_in */ 
     91#define SOCKADDR(p, t) ((struct sockaddr_in*)VTABLE_get_pointer(interp, PARROT_SOCKET((p))->t)) 
     92 
     93 
    7094PARROT_WARN_UNUSED_RESULT 
    7195PARROT_CANNOT_RETURN_NULL 
    72 STRING * 
    73 Parrot_io_sockaddr_in(PARROT_INTERP, unsigned short port, ARGIN(STRING *addr)) 
     96PMC * 
     97Parrot_io_sockaddr_in(PARROT_INTERP, ARGIN(STRING *addr), INTVAL port) 
    7498{ 
    75     struct sockaddr_in sa; 
    76     /* Hard coded to IPv4 for now */ 
    77     const int family = AF_INET; 
    78  
    79     char * const s = Parrot_str_to_cstring(interp, addr); 
    80     /* 
    81      * due to a bug in OS/X, we've to zero the struct 
    82      * else bind is failing erratically 
    83      */ 
    84     memset(&sa, 0, sizeof (sa)); 
    85 #  ifdef PARROT_DEF_INET_ATON 
    86     if (inet_aton(s, &sa.sin_addr) != 0) { 
    87 #  else 
    88     /* positive retval is success */ 
    89     if (inet_pton(family, s, &sa.sin_addr) > 0) { 
    90 #  endif 
    91         /* Success converting numeric IP */ 
    92     } 
    93     else { 
    94         /* Maybe it is a hostname, try to lookup */ 
    95         /* XXX Check PIO option before doing a name lookup, 
    96          * it may have been toggled off. 
    97          */ 
    98         struct hostent *he = gethostbyname(s); 
    99         /* XXX FIXME - Handle error condition better */ 
    100         if (!he) { 
    101             fprintf(stderr, "gethostbyname failure [%s]\n", s); 
    102             Parrot_str_free_cstring(s); 
    103             return NULL; 
    104         } 
    105         memcpy((char*)&sa.sin_addr, he->h_addr, sizeof (sa.sin_addr)); 
    106     } 
    107     Parrot_str_free_cstring(s); 
    108  
    109     sa.sin_family = family; 
    110     sa.sin_port = htons(port); 
    111  
    112     return string_make(interp, (char *)&sa, sizeof (struct sockaddr_in), 
    113             "binary", 0); 
     99    PMC * sockaddr; 
     100    char * s; 
     101 
     102    s = Parrot_str_to_cstring(interp, addr); 
     103    sockaddr = pmc_new(interp, enum_class_Sockaddr); 
     104    get_sockaddr_in(interp, sockaddr, s, port); 
     105    free(s); 
     106    return sockaddr; 
    114107} 
    115108 
    116109 
     
    130123PARROT_WARN_UNUSED_RESULT 
    131124PARROT_CAN_RETURN_NULL 
    132125PMC * 
    133 Parrot_io_socket_unix(PARROT_INTERP, ARGMOD(PMC *socket), int fam, int type, int proto) 
     126Parrot_io_socket_unix(PARROT_INTERP, int fam, int type, int proto) 
    134127{ 
     128    int i; 
    135129    const int sock = socket(fam, type, proto); 
    136130    if (sock >= 0) { 
    137         ParrotIO * const io = Parrot_io_new(interp, PIO_F_SOCKET, 0, PIO_F_READ|PIO_F_WRITE); 
    138         Parrot_io_set_os_handle(interp, socket, sock); 
    139         memset(&io->local, 0, sizeof (struct sockaddr_in)); 
    140         memset(&io->remote, 0, sizeof (struct sockaddr_in)); 
    141         io->remote.sin_family = fam; 
     131        PMC * io = Parrot_io_new_socket_pmc(interp, PIO_F_SOCKET|PIO_F_READ|PIO_F_WRITE); 
     132        /* Parrot_io_set_os_handle(interp, socket, sock); */ 
     133        PARROT_SOCKET(io)->os_handle = sock; 
     134        setsockopt(PARROT_SOCKET(io)->os_handle, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)); 
     135        SOCKADDR(io, remote)->sin_family = fam; 
    142136        return io; 
    143137    } 
    144     return NULL; 
     138    return PMCNULL; 
    145139} 
    146140 
    147141/* 
     
    155149*/ 
    156150 
    157151INTVAL 
    158 Parrot_io_connect_unix(SHIM_INTERP, SHIM(PMC *socket), ARGMOD(ParrotIO *io), 
    159         ARGIN_NULLOK(STRING *r)) 
     152Parrot_io_connect_unix(PARROT_INTERP, ARGMOD(PMC *socket), ARGIN(PMC *r)) 
    160153{ 
    161     struct sockaddr_in * saddr = &io->remote; 
     154    Parrot_Socket_attributes * io = PARROT_SOCKET(socket); 
    162155 
    163     if (r) 
    164         memcpy(&io->remote, PObj_bufstart(r), sizeof (struct sockaddr_in)); 
     156    if(!r) 
     157        return -1; 
     158 
     159    PARROT_SOCKET(socket)->remote = r; 
    165160 
    166161AGAIN: 
    167     if ((connect(io->fd, (struct sockaddr *)saddr, 
     162    if ((connect(io->os_handle, (struct sockaddr *)SOCKADDR(socket, remote), 
    168163            sizeof (struct sockaddr_in))) != 0) { 
    169164        switch (errno) { 
    170165            case EINTR: 
     
    192187*/ 
    193188 
    194189INTVAL 
    195 Parrot_io_bind_unix(SHIM_INTERP, SHIM(PMC *socket), ARGMOD(ParrotIO *io), 
    196         ARGMOD(STRING *l)) 
     190Parrot_io_bind_unix(PARROT_INTERP, ARGMOD(PMC *socket), ARGMOD(PMC *sockaddr)) 
    197191{ 
    198     struct sockaddr_in * saddr = &io->local; 
     192    Parrot_Socket_attributes * io = PARROT_SOCKET(socket); 
     193    struct sockaddr_in * saddr; 
    199194 
    200     if (!l) 
     195    if (!sockaddr) 
    201196        return -1; 
    202197 
    203     memcpy(&io->local, PObj_bufstart(l), sizeof (struct sockaddr_in)); 
     198    PARROT_SOCKET(socket)->local = sockaddr; 
     199 
     200    saddr = SOCKADDR(socket, local); 
    204201 
    205     if ((bind(io->fd, (struct sockaddr *) saddr, 
     202    if ((bind(io->os_handle, (struct sockaddr *) saddr, 
    206203            sizeof (struct sockaddr_in))) == -1) { 
    207204        return -1; 
    208205    } 
     
    222219*/ 
    223220 
    224221INTVAL 
    225 Parrot_io_listen_unix(SHIM_INTERP, SHIM(PMC *socket), ARGIN(ParrotIO *io), 
    226         INTVAL sec) 
     222Parrot_io_listen_unix(SHIM_INTERP, ARGMOD(PMC *socket), INTVAL sec) 
    227223{ 
    228     if ((listen(io->fd, sec)) == -1) { 
     224    Parrot_Socket_attributes * io = PARROT_SOCKET(socket); 
     225    if ((listen(io->os_handle, sec)) == -1) { 
    229226        return -1; 
    230227    } 
    231228    return 0; 
     
    233230 
    234231/* 
    235232 
    236 =item C<ParrotIO * Parrot_io_accept_unix> 
     233=item C<PMC * Parrot_io_accept_unix> 
    237234 
    238235Accept a new connection and return a newly created C<ParrotIO> socket. 
    239236 
     
    244241PARROT_WARN_UNUSED_RESULT 
    245242PARROT_CAN_RETURN_NULL 
    246243PMC * 
    247 Parrot_io_accept_unix(PARROT_INTERP, SHIM(PMC *socket), ARGMOD(ParrotIO *io)) 
     244Parrot_io_accept_unix(PARROT_INTERP, ARGMOD(PMC *socket)) 
    248245{ 
    249     ParrotIO * const    newio   = Parrot_io_new(interp, PIO_F_SOCKET, 0, 
    250                                     PIO_F_READ|PIO_F_WRITE); 
     246    Parrot_Socket_attributes * io = PARROT_SOCKET(socket); 
     247    PMC * newio   = Parrot_io_new_socket_pmc(interp, 
     248            PIO_F_SOCKET | PIO_F_READ|PIO_F_WRITE); 
    251249    Parrot_Socklen_t    addrlen = sizeof (struct sockaddr_in); 
    252     struct sockaddr_in *saddr   = &newio->remote; 
    253     const int           newsock = accept(io->fd, (struct sockaddr *)saddr, 
    254                                     &addrlen); 
     250    struct sockaddr_in *saddr; 
     251 
     252    PARROT_SOCKET(newio)->local  = PARROT_SOCKET(socket)->local; 
     253    PARROT_SOCKET(newio)->remote = pmc_new(interp, enum_class_Sockaddr); 
     254    saddr                        = SOCKADDR(newio, remote); 
     255 
     256    const int           newsock = accept(io->os_handle, 
     257           (struct sockaddr *)saddr, &addrlen); 
    255258 
    256259    if (newsock == -1) { 
    257         mem_sys_free(newio); 
    258         return NULL; 
     260        return PMCNULL; 
    259261    } 
    260262 
    261     newio->fd = newsock; 
     263    PARROT_SOCKET(newio)->os_handle = newsock; 
    262264 
    263265    /* XXX FIXME: Need to do a getsockname and getpeername here to 
    264266     * fill in the sockaddr_in structs for local and peer */ 
     
    280282*/ 
    281283 
    282284INTVAL 
    283 Parrot_io_send_unix(SHIM_INTERP, SHIM(PMC *socket), ARGMOD(ParrotIO *io), 
    284         ARGMOD(STRING *s)) 
     285Parrot_io_send_unix(SHIM_INTERP, ARGMOD(PMC *socket), ARGMOD(STRING *s)) 
    285286{ 
    286287    int error, bytes, byteswrote; 
     288    Parrot_Socket_attributes * io = PARROT_SOCKET(socket); 
    287289 
    288290    bytes = s->bufused; 
    289291    byteswrote = 0; 
     
    291293    /* 
    292294     * Ignore encoding issues for now. 
    293295     */ 
    294     if ((error = send(io->fd, (char *)s->strstart + byteswrote, 
     296    if ((error = send(io->os_handle, (char *)s->strstart + byteswrote, 
    295297                    bytes, 0)) >= 0) { 
    296298        byteswrote += error; 
    297299        bytes -= error; 
     
    313315#    endif 
    314316            case EPIPE: 
    315317                /* XXX why close it here and not below */ 
    316                 close(io->fd); 
     318                close(io->os_handle); 
    317319                return -1; 
    318320            default: 
    319321                return -1; 
     
    332334*/ 
    333335 
    334336INTVAL 
    335 Parrot_io_recv_unix(PARROT_INTERP, SHIM(PMC *socket), 
    336         ARGMOD(ParrotIO *io), ARGOUT(STRING **s)) 
     337Parrot_io_recv_unix(PARROT_INTERP, ARGMOD(PMC *socket), ARGOUT(STRING **s)) 
    337338{ 
    338339    int error; 
    339340    unsigned int bytesread = 0; 
    340341    char buf[2048]; 
     342    Parrot_Socket_attributes * io = PARROT_SOCKET(socket); 
    341343 
    342344AGAIN: 
    343     if ((error = recv(io->fd, buf, 2048, 0)) >= 0) { 
     345    if ((error = recv(io->os_handle, buf, 2048, 0)) >= 0) { 
    344346        bytesread += error; 
    345347        /* The charset should probably be 'binary', but right now httpd.pir 
    346348         * only works with 'ascii' 
     
    361363#    endif 
    362364            case ECONNRESET: 
    363365                /* XXX why close it on err return result is -1 anyway */ 
    364                 close(io->fd); 
     366                close(io->os_handle); 
    365367                *s = Parrot_str_new_noinit(interp, enum_stringrep_one, 0); 
    366368                return -1; 
    367369            default: 
    368                 close(io->fd); 
     370                close(io->os_handle); 
    369371                *s = Parrot_str_new_noinit(interp, enum_stringrep_one, 0); 
    370372                return -1; 
    371373        } 
     
    393395*/ 
    394396 
    395397INTVAL 
    396 Parrot_io_poll_unix(SHIM_INTERP, SHIM(PMC *socket), ARGMOD(ParrotIO *io), int which, 
    397                int sec, int usec) 
     398Parrot_io_poll_unix(SHIM_INTERP, ARGMOD(PMC *socket), int which, int sec, 
     399    int usec) 
    398400{ 
    399401    int n; 
    400402    fd_set r, w, e; 
    401403    struct timeval t; 
     404    Parrot_Socket_attributes * io = PARROT_SOCKET(socket); 
    402405 
    403406    t.tv_sec = sec; 
    404407    t.tv_usec = usec; 
    405408    FD_ZERO(&r); FD_ZERO(&w); FD_ZERO(&e); 
    406409    /* These should be defined in header */ 
    407     if (which & 1) FD_SET(io->fd, &r); 
    408     if (which & 2) FD_SET(io->fd, &w); 
    409     if (which & 4) FD_SET(io->fd, &e); 
     410    if (which & 1) FD_SET(io->os_handle, &r); 
     411    if (which & 2) FD_SET(io->os_handle, &w); 
     412    if (which & 4) FD_SET(io->os_handle, &e); 
    410413AGAIN: 
    411     if ((select(io->fd+1, &r, &w, &e, &t)) >= 0) { 
    412         n = (FD_ISSET(io->fd, &r) ? 1 : 0); 
    413         n |= (FD_ISSET(io->fd, &w) ? 2 : 0); 
    414         n |= (FD_ISSET(io->fd, &e) ? 4 : 0); 
     414    if ((select(io->os_handle+1, &r, &w, &e, &t)) >= 0) { 
     415        n = (FD_ISSET(io->os_handle, &r) ? 1 : 0); 
     416        n |= (FD_ISSET(io->os_handle, &w) ? 2 : 0); 
     417        n |= (FD_ISSET(io->os_handle, &e) ? 4 : 0); 
    415418        return n; 
    416419    } 
    417420    else { 
     
    422425    } 
    423426} 
    424427 
    425 #  endif 
    426 /* 
    427  
    428 =item C<PMC * Parrot_io_pipe_unix> 
    429  
    430 Very limited C<exec> for now. 
    431  
    432 =cut 
    433  
    434 */ 
    435  
    436 PARROT_WARN_UNUSED_RESULT 
    437 PARROT_CAN_RETURN_NULL 
    438 PMC * 
    439 Parrot_io_pipe_unix(PARROT_INTERP, SHIM(PMC *filehandle), ARGIN(const char *cmd), int flags) 
     428static void 
     429get_sockaddr_in(PARROT_INTERP, ARGIN(PMC * sockaddr), ARGIN(const char* host), 
     430            int port) 
    440431{ 
    441     /* 
    442      * pipe(), fork() should be defined, if this header is present 
    443      *        if that's not true, we need a test 
    444      */ 
    445 #  ifdef PARROT_HAS_HEADER_UNISTD 
    446     int pid, err, fds[2]; 
    447  
    448     err = pipe(fds); 
    449     if (err < 0) { 
    450         return NULL; 
    451     } 
     432    struct sockaddr_in *sa; 
     433    /* Hard coded to IPv4 for now */ 
     434    const int family = AF_INET; 
    452435 
    453     /* Parent - return IO stream */ 
    454     if ((pid = fork()) > 0) { 
    455         ParrotIO * const io = 
    456             Parrot_io_new(interp, PIO_F_PIPE, 0, flags & (PIO_F_READ|PIO_F_WRITE)); 
    457         if (flags & PIO_F_READ) { 
    458             /* close this writer's end of pipe */ 
    459             close(fds[1]); 
    460             io->fd = fds[0]; 
    461             io->fd2 = 0; 
    462         } 
    463         else {  /* assume write only for now */ 
    464             /* close this reader's end */ 
    465             close(fds[0]); 
    466             io->fd = fds[1]; 
    467             io->fd2 = 0; 
    468         } 
    469         return io; 
     436    sa = (struct sockaddr_in*)VTABLE_get_pointer(interp, sockaddr); 
     437#  ifdef PARROT_DEF_INET_ATON 
     438    if (inet_aton(host, &sa->sin_addr) != 0) { 
     439#  else 
     440    /* positive retval is success */ 
     441    if (inet_pton(family, host, &sa->sin_addr) > 0) { 
     442#  endif 
     443        /* Success converting numeric IP */ 
    470444    } 
    471  
    472     /* Child - exec process */ 
    473     if (pid == 0) { 
    474         char *argv[10], *p, *c; 
    475         int n; 
    476  
    477         if (flags & PIO_F_WRITE) { 
    478             /* the other end is writing - we read from the pipe */ 
    479             close(STDIN_FILENO); 
    480             close(fds[1]); 
    481             if (Parrot_dup(fds[0]) != STDIN_FILENO) { 
    482                 exit(EXIT_SUCCESS); 
    483             } 
    484         } 
    485         else { 
    486             /* XXX redirect stdout, stderr to pipe */ 
    487             close(STDIN_FILENO); 
    488             close(STDOUT_FILENO); 
    489             close(STDERR_FILENO); 
    490             if (Parrot_dup(fds[0]) != STDIN_FILENO 
    491              || Parrot_dup(fds[1]) != STDOUT_FILENO 
    492              || Parrot_dup(fds[1]) != STDERR_FILENO) 
    493             { 
    494                 exit(EXIT_SUCCESS); 
    495             } 
    496         } 
    497         /* 
    498          * XXX ugly hack to be able to pass some arguments 
    499          *     split cmd at blanks 
     445    else { 
     446        /* Maybe it is a hostname, try to lookup */ 
     447        /* XXX Check PIO option before doing a name lookup, 
     448         * it may have been toggled off. 
    500449         */ 
    501         c = strdup(cmd); 
    502         for (n = 0, p = strtok(c, " "); n < 9 && p; p = strtok(NULL, " ")) { 
    503             if (n == 0) 
    504                 cmd = p; 
    505             argv[n++] = p; 
     450        struct hostent *he = gethostbyname(host); 
     451        /* XXX FIXME - Handle error condition better */ 
     452        if (!he) { 
     453            fprintf(stderr, "gethostbyname failure [%s]\n", host); 
     454            return; 
    506455        } 
    507         argv[n] = NULL; 
    508         execv(cmd, argv);       /* XXX use execvp ? */ 
    509         /* Will never reach this unless exec fails. */ 
    510         perror("execvp"); 
    511         exit(EXIT_FAILURE); 
     456        memcpy((char*)&sa->sin_addr, he->h_addr, sizeof (sa->sin_addr)); 
    512457    } 
    513458 
    514     perror("fork"); 
    515 #  else 
    516     UNUSED(l); 
    517     UNUSED(cmd); 
    518     UNUSED(flags); 
    519     Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNIMPLEMENTED, 
    520         "pipe() unimplemented"); 
    521 #  endif 
    522     return NULL; 
     459    sa->sin_family = family; 
     460    sa->sin_port = htons(port); 
    523461} 
     462#  endif 
    524463 
    525464 
    526465#endif /* PIO_OS_UNIX */ 
  • src/io/socket_win32.c

    diff --git a/src/io/socket_win32.c b/src/io/socket_win32.c
    index e0e3c54..82ba19d 100644
    a b  
    11/* 
    22Copyright (C) 2001-2003, Parrot Foundation. 
    3 $Id$ 
     3$Id: socket_win32.c 36832 2009-02-17 19:58:58Z allison $ 
    44 
    55=head1 NAME 
    66 
     
    3131 
    3232#ifdef PIO_OS_WIN32 
    3333 
    34 /* HEADERIZER HFILE: none */ 
     34/* HEADERIZER HFILE: include/parrot/io_win32.h */ 
    3535/* HEADERIZER BEGIN: static */ 
    3636/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */ 
    3737 
  • src/ops/io.ops

    diff --git a/src/ops/io.ops b/src/ops/io.ops
    index 47c5dc4..b243819 100644
    a b  
    496496 
    497497######################################## 
    498498 
     499=item B<sockaddr>(out PMC, in STRING, in INT) 
     500 
     501Create new Sockaddr PMC. 
     502 
     503=cut 
     504 
     505op sockaddr(out PMC, in STR, in INT) { 
     506    $1 = Parrot_io_sockaddr_in(interp, $2, $3); 
     507} 
     508 
     509=item B<socket>(out PMC, in INT, in INT, in INT) 
     510 
     511Create new Socket 
     512 
     513=cut 
     514 
     515op socket(out PMC, in INT, in INT, in INT) { 
     516    $1 = Parrot_io_socket(interp, $2, $3, $4); 
     517} 
     518 
     519=item B<bind>(out INT, in PMC, in PMC) 
     520 
     521Bind Socket to address 
     522 
     523=cut 
     524 
     525op bind(out INT, in PMC, in PMC) { 
     526    $1 = Parrot_io_bind(interp, $2, $3); 
     527} 
     528 
     529=item B<listen>(out INT, in PMC, in INT) 
     530 
     531Start listening on previously bounded socket 
     532 
     533=cut 
     534 
     535op listen(out INT, in PMC, in INT) { 
     536    $1 = Parrot_io_listen(interp, $2, $3); 
     537} 
     538 
     539=item B<accept>(out PMC, in PMC) 
     540 
     541Accept incoming connection 
     542 
     543=cut 
     544 
     545op accept(out PMC, in PMC) { 
     546    $1 = Parrot_io_accept(interp, $2); 
     547} 
     548 
     549=item B<recv>(out INT, in PMC, out STR) 
     550 
     551Recive data from socket 
     552 
     553=cut 
     554 
     555op recv(out INT, in PMC, out STR) { 
     556    $1 = Parrot_io_recv(interp, $2, &$3); 
     557} 
     558 
     559=item B<send>(out INT, in PMC, int STR) 
     560 
     561Recive data from socket 
     562 
     563=cut 
     564 
     565op send(out INT, in PMC, in STR) { 
     566    $1 = Parrot_io_send(interp, $2, $3); 
     567} 
     568 
    499569=back 
    500570 
    501571=cut 
  • src/ops/ops.num

    diff --git a/src/ops/ops.num b/src/ops/ops.num
    index 98a337a..d7a956a 100644
    a b  
    12661266find_name_p_sc                 1242 
    12671267find_sub_not_null_p_s          1243 
    12681268find_sub_not_null_p_sc         1244 
     1269socket_p_i_i_i                 1245 
     1270socket_p_ic_i_i                1246 
     1271socket_p_i_ic_i                1247 
     1272socket_p_i_i_ic                1248 
     1273socket_p_ic_i_ic               1249 
     1274socket_p_i_ic_ic               1250 
     1275socket_p_ic_ic_ic              1251 
     1276socket_p_ic_ic_i               1252 
     1277sockaddr_p_s_i                 1253 
     1278sockaddr_p_sc_i                1254 
     1279sockaddr_p_s_ic                1255 
     1280sockaddr_p_sc_ic               1256 
     1281bind_i_p_p                     1257 
     1282bind_i_pc_p                    1258 
     1283bind_i_p_pc                    1259 
     1284bind_i_pc_pc                   1260 
     1285listen_i_p_i                   1261 
     1286listen_i_pc_i                  1262 
     1287listen_i_p_ic                  1263 
     1288listen_i_pc_ic                 1264 
     1289accept_p_p                     1265 
     1290accept_p_pc                    1266 
     1291recv_i_p_s                     1267 
     1292recv_i_pc_s                    1268 
     1293send_i_p_s                     1269 
     1294send_i_pc_s                    1270 
     1295send_i_p_sc                    1271 
     1296send_i_pc_sc                   1272 
  • (a) /dev/null vs. (b) b/src/pmc/sockaddr.pmc

    diff --git a/src/pmc/sockaddr.pmc b/src/pmc/sockaddr.pmc
    new file mode 100644
    index 0000000..d90bc05
    a b  
     1/* 
     2Copyright (C) 2008-2009, Parrot Foundation. 
     3$Id$ 
     4 
     5=head1 NAME 
     6 
     7src/pmc/sockaddr.pmc - sockaddr_in holder 
     8 
     9=head1 DESCRIPTION 
     10 
     11The Sockaddr PMC holds raw c-pointer to sockaddr_in 
     12 
     13 
     14=head2 Vtable Functions 
     15 
     16These are the vtable functions for the Sockaddr class. 
     17 
     18=over 4 
     19 
     20=cut 
     21 
     22*/ 
     23 
     24#include "parrot/parrot.h" 
     25 
     26#ifdef __cplusplus 
     27extern "C" { 
     28#endif 
     29    struct sockaddr_in; 
     30#ifdef __cplusplus 
     31} 
     32#endif 
     33 
     34pmclass Sockaddr need_ext { 
     35    ATTR void   *pointer; /* The stored pointer. */ 
     36 
     37/* 
     38 
     39=item C<void init()> 
     40 
     41Initializes the pointer object. 
     42 
     43=cut 
     44 
     45*/ 
     46 
     47    VTABLE void init() { 
     48        Parrot_Sockaddr_attributes * const pdata_struct = 
     49            mem_allocate_typed(Parrot_Sockaddr_attributes); 
     50 
     51        PMC_data(SELF)        = pdata_struct; 
     52        pdata_struct->pointer = mem_allocate_zeroed_typed(struct sockaddr_in); 
     53    } 
     54 
     55/* 
     56 
     57=item C<void destroy()> 
     58 
     59Destroys the PMC and frees all allocated memory. 
     60 
     61=cut 
     62 
     63*/ 
     64 
     65    VTABLE void destroy() { 
     66        Parrot_Sockaddr_attributes * const data = PARROT_SOCKADDR(SELF); 
     67 
     68        if (data) { 
     69            mem_sys_free(data->pointer); 
     70            mem_sys_free(data); 
     71            PMC_data(SELF) = NULL; 
     72        } 
     73    } 
     74 
     75/* 
     76 
     77=item C<PMC *clone()> 
     78 
     79Creates and returns a clone of the pointer. 
     80 
     81=cut 
     82 
     83*/ 
     84 
     85    VTABLE PMC *clone() { 
     86        PMC * const dest = pmc_new(INTERP, SELF->vtable->base_type); 
     87        memcpy(PARROT_SOCKADDR(dest)->pointer, PARROT_SOCKADDR(SELF)->pointer, 
     88                sizeof(struct sockaddr_in)); 
     89        return dest; 
     90    } 
     91 
     92/* 
     93 
     94=item C<void *get_pointer()> 
     95 
     96Returns the pointer. 
     97 
     98=cut 
     99 
     100*/ 
     101 
     102    VTABLE void *get_pointer() { 
     103        Parrot_Sockaddr_attributes * const data = PARROT_SOCKADDR(SELF); 
     104        return data->pointer; 
     105    } 
     106 
     107/* 
     108 
     109=item C<void set_pointer(void *)> 
     110 
     111Sets the pointer. 
     112 
     113=cut 
     114 
     115*/ 
     116 
     117/* 
     118    VTABLE void set_pointer(void *value) { 
     119        Parrot_Sockaddr_attributes * const data = PARROT_SOCKADDR(SELF); 
     120        return data->pointer; 
     121    } 
     122*/ 
     123 
     124} 
     125 
     126/* 
     127 
     128=back 
     129 
     130=cut 
     131 
     132*/ 
     133 
     134/* 
     135 * Local variables: 
     136 *   c-file-style: "parrot" 
     137 * End: 
     138 * vim: expandtab shiftwidth=4: 
     139 */ 
     140 
  • (a) /dev/null vs. (b) b/src/pmc/socket.pmc

    diff --git a/src/pmc/socket.pmc b/src/pmc/socket.pmc
    new file mode 100644
    index 0000000..90bd3d3
    a b  
     1/* 
     2Copyright (C) 2008, Parrot Foundation. 
     3$Id: filehandle.pmc 36832 2009-02-17 19:58:58Z allison $ 
     4 
     5=head1 NAME 
     6 
     7src/pmc/socket.pmc - Socket PMC 
     8 
     9=head1 DESCRIPTION 
     10 
     11The Socket PMC performs network I/O operations. 
     12 
     13=head2 Vtable Functions 
     14 
     15=over 4 
     16 
     17=cut 
     18 
     19*/ 
     20 
     21#include "parrot/parrot.h" 
     22#include "../src/io/io_private.h" 
     23 
     24//#include <sys/socket.h> 
     25 
     26pmclass Socket extends FileHandle need_ext { 
     27    ATTR PMC *local;           /* Local addr                   */ 
     28    ATTR PMC *remote;          /* Remote addr                  */ 
     29 
     30/* 
     31 
     32=item C<void init()> 
     33 
     34Initializes a newly created Socket object. 
     35 
     36=cut 
     37 
     38*/ 
     39 
     40    VTABLE void init() { 
     41        Parrot_Socket_attributes *data_struct = 
     42                mem_allocate_typed(Parrot_Socket_attributes); 
     43 
     44        PMC_data(SELF)      = data_struct; 
     45        data_struct->local  = PMCNULL; 
     46        data_struct->remote = PMCNULL; 
     47 
     48        /* Initialize the os_handle to the platform-specific value for closed. */ 
     49#ifdef PIO_OS_WIN32 
     50    data_struct->os_handle    = (PIOHANDLE)INVALID_HANDLE_VALUE; 
     51#endif 
     52#ifdef PIO_OS_UNIX 
     53    data_struct->os_handle    = (PIOHANDLE)-1; 
     54#endif 
     55#ifdef PIO_OS_STDIO 
     56    data_struct->os_handle    = (PIOHANDLE)NULL; 
     57#endif 
     58 
     59        PObj_custom_mark_destroy_SETALL(SELF); 
     60    } 
     61 
     62/* 
     63 
     64=item C<PMC *clone()> 
     65 
     66Create a copy of the filehandle. 
     67 
     68=cut 
     69 
     70*/ 
     71 
     72    VTABLE PMC *clone() { 
     73        Parrot_Socket_attributes * const old_struct  = PARROT_SOCKET(SELF); 
     74        PMC * const copy = Parrot_io_new_socket_pmc(interp, old_struct->flags); 
     75        Parrot_Socket_attributes * const data_struct = PARROT_SOCKET(copy); 
     76 
     77        data_struct->os_handle    = Parrot_dup(old_struct->os_handle); 
     78        //memcpy(data_struct->local, old_struct->local, sizeof(struct sockaddr_in)); 
     79        //memcpy(data_struct->remote, old_struct->remote, sizeof(struct sockaddr_in)); 
     80 
     81        return SELF; 
     82    } 
     83 
     84/* 
     85 
     86=item C<void mark()> 
     87 
     88Mark active filehandle data as live. 
     89 
     90=cut 
     91 
     92*/ 
     93 
     94    VTABLE void mark() { 
     95        Parrot_Socket_attributes * const data = PARROT_SOCKET(SELF); 
     96 
     97        if (data) { 
     98            if (data->local) 
     99                pobject_lives(interp, (PObj *)data->local); 
     100 
     101            if (data->remote) 
     102                pobject_lives(interp, (PObj *)data->remote); 
     103        } 
     104    } 
     105/* 
     106 
     107=item C<void destroy()> 
     108 
     109Free structures. 
     110 
     111=cut 
     112 
     113*/ 
     114    VTABLE void destroy() { 
     115        if (PARROT_SOCKET(SELF)) { 
     116            Parrot_Socket_attributes *data_struct = PARROT_SOCKET(SELF); 
     117 
     118            /* TODO Shutdown socket */ 
     119        } 
     120    } 
     121 
     122    METHOD close() { 
     123        INTVAL status = 0; 
     124        close(PARROT_SOCKET(SELF)->os_handle); 
     125        RETURN(INTVAL status); 
     126    } 
     127 
     128 
     129/* 
     130 
     131=back 
     132 
     133=head2 Methods 
     134 
     135=over 4 
     136 
     137 
     138/* 
     139 
     140=item C<connect>  
     141 
     142Connects a socket object to an address. 
     143 
     144The asynchronous version takes an additional final PMC callback 
     145argument, and only returns a status object. When the socket operation is 
     146complete, it invokes the callback, passing it a status object and the 
     147socket object it was called on. [If you want notification when a connect 
     148operation is completed, you probably want to do something with that 
     149connected socket object.] 
     150 
     151=cut 
     152 
     153*/ 
     154 
     155    METHOD connect(PMC * address) { 
     156        INTVAL res = Parrot_io_connect(INTERP, SELF, address); 
     157        RETURN(INTVAL res); 
     158    } 
     159 
     160/* 
     161 
     162=item C<recv>  
     163 
     164Receives a message from a connected socket object. It returns 
     165the message in a string. 
     166 
     167The asynchronous version takes an additional final PMC callback 
     168argument, and only returns a status object. When the recv operation is 
     169complete, it invokes the callback, passing it a status object and a 
     170string containing the received message. 
     171 
     172=cut 
     173 
     174*/ 
     175 
     176    METHOD recv() { 
     177        STRING * result; 
     178        INTVAL read = Parrot_io_recv(INTERP, SELF, &result); 
     179        RETURN(STRING * result); 
     180    } 
     181 
     182/* 
     183 
     184=item C<send> 
     185 
     186Sends a message string to a connected socket object. 
     187 
     188The asynchronous version takes an additional final PMC callback 
     189argument, and only returns a status object. When the send operation is 
     190complete, it invokes the callback, passing it a status object. 
     191 
     192=cut 
     193 
     194*/ 
     195 
     196    METHOD send(STRING *buf) { 
     197        INTVAL res = Parrot_io_send(INTERP, SELF, buf); 
     198        RETURN(INTVAL res); 
     199    } 
     200 
     201    METHOD bind(PMC *host) { 
     202        INTVAL res = Parrot_io_bind(INTERP, SELF, host); 
     203        RETURN(INTVAL res); 
     204    } 
     205 
     206    METHOD listen(INTVAL backlog) { 
     207        INTVAL res = Parrot_io_listen(INTERP, SELF, backlog); 
     208        RETURN(INTVAL res); 
     209    } 
     210 
     211    METHOD accept() { 
     212        PMC * res = Parrot_io_accept(INTERP, SELF); 
     213        RETURN(PMC * res); 
     214    } 
     215 
     216/* 
     217 
     218=back 
     219 
     220=cut 
     221 
     222*/ 
     223 
     224} /* end pmclass */ 
     225 
     226/* 
     227 * Local variables: 
     228 *   c-file-style: "parrot" 
     229 * End: 
     230 * vim: expandtab shiftwidth=4 ft=pmc: 
     231 */ 
  • (a) /dev/null vs. (b) b/t/pmc/sockaddr.t

    diff --git a/t/pmc/sockaddr.t b/t/pmc/sockaddr.t
    new file mode 100644
    index 0000000..43b214d
    a b  
     1#! parrot 
     2# Copyright (C) 2006-2008, Parrot Foundation. 
     3# $Id$ 
     4 
     5=head1 NAME 
     6 
     7t/pmc/sockaddr.t - test the Sockaddr PMC 
     8 
     9=head1 SYNOPSIS 
     10 
     11    % prove t/pmc/sockaddr.t 
     12 
     13=head1 DESCRIPTION 
     14 
     15Tests the SharedRef PMC. 
     16 
     17=cut 
     18 
     19.sub main :main 
     20    .include 'test_more.pir' 
     21 
     22    plan(3) 
     23 
     24    new $P0, ['Sockaddr'] 
     25    ok(1, 'Instantiated a Sockaddr PMC') 
     26 
     27    $P0 = sockaddr "localhost", 1234 
     28    ok(1, 'op sockaddr successful') 
     29 
     30    $I0 = isnull $P0 
     31    $I0 = not $I0 
     32    ok($I0, 'Sockaddr PMC created') 
     33.end 
     34 
     35# Local Variables: 
     36#   mode: pir 
     37#   fill-column: 100 
     38# End: 
     39# vim: expandtab shiftwidth=4 ft=pir: