Ticket #496: socket.patch
File socket.patch, 49.6 KB (added by bacek, 13 years ago) |
---|
-
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 362 362 $(IO_DIR)/unix$(O) \ 363 363 $(IO_DIR)/win32$(O) \ 364 364 $(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) 366 368 367 369 INTERP_O_FILES := \ 368 370 $(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 6 examples/io/httpd.pir - HTTP server 7 8 =head1 SYNOPSIS 9 10 $ ./parrot examples/io/httpd.pir 11 12 =head1 DESCRIPTION 13 14 A very tiny HTTP-Server. It currently only understands the GET method. 15 It's a nice way of testing pretty much all IO functions. 16 By default (and not yet configurable) it binds to localhost:1234. 17 18 =head2 Serving Parrot Docs 19 20 If no filename is given it serves the HTML documentation 21 in ./docs/html. Make sure you have built them with 22 23 $ make html 24 25 After that you can browse the documentation with 26 27 http://localhost:1234 28 29 which redirects to 30 31 http://localhost:1234/docs/html/index.html 32 33 =head2 Serving Other HTML Files 34 35 If a html file is present in the request, this file will be served: 36 37 http://localhost:1234/index.html 38 39 This will sent F<./index.html> from the directory, where F<httpd.pir> 40 was started. 41 42 =head2 CGI 43 44 If the file extension is C<.pir> or C<.pbc>, this file will be loaded 45 below the directory F<cgi-pir> and the function C<cgi_main> will be 46 invoked with the query as an argument. 47 This functions should return a plain string, which will be sent to the 48 browser. 49 50 F<cgi_main> is called with 3 arguments: a todo/reserved PMC, a string 51 with the original query and a Hash, with C<key=value> items split by 52 C<'+'>. 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 63 The browser request: 64 65 http://localhost:1234/foo.pir?foo=1+bar=%61 66 67 will serve, whatever the C<cgi_main> function returned. 68 69 =head1 TODO 70 71 make it work on W32/IE 72 73 Transcode the received string to ascii, in order to have access to an 74 implemented 'index' op. Or just use unicode instead. 75 76 =head1 SEE ALSO 77 78 RFC2616 79 80 =head1 AUTHOR 81 82 Original author is Markus Amsler - <markus.amsler@oribi.org> 83 The 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 134 NEXT: 135 accept work, sock 136 req = "" 137 MORE: 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 165 SERVE_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 187 SERVE_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 208 SERVE_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 216 SERVE_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 237 SERVE_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 257 SERVE_favicon: 258 url = urldecode( '/docs/resources/favicon.ico') 259 goto SERVE_file 260 261 SERVE_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 282 ERR_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 286 ERR_bind: 287 print "bind failed\n" 288 # fall through 289 END: 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 = "" 313 START: 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 325 INC_IN: 326 concat out, char_out 327 inc pos_in 328 goto START 329 END: 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) 346 cgi_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 359 no_query: 360 file = url 361 query = '' 362 query_hash = new 'Hash' 363 have_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 373 cgi_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 400 lp_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 409 no_val: 410 k = kv 411 v = 1 412 set_val: 413 k = urldecode(k) 414 query_hash[k] = v 415 416 next_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 1 1 /* io.h 2 2 * Copyright (C) 2001-2003, Parrot Foundation. 3 3 * SVN Info 4 * $Id $4 * $Id: io.h 36833 2009-02-17 20:09:26Z allison $ 5 5 * Overview: 6 6 * Parrot IO subsystem 7 7 * Data Structure and Algorithms: … … 757 757 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */ 758 758 /* HEADERIZER END: src/io/filehandle.c */ 759 759 760 /* HEADERIZER BEGIN: src/io/socket_api.c */ 761 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */ 762 763 PARROT_EXPORT 764 PARROT_WARN_UNUSED_RESULT 765 PARROT_CAN_RETURN_NULL 766 PMC * Parrot_io_accept(PARROT_INTERP, ARGMOD(PMC *pmc)) 767 __attribute__nonnull__(1) 768 __attribute__nonnull__(2) 769 FUNC_MODIFIES(*pmc); 770 771 PARROT_EXPORT 772 INTVAL 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 779 PARROT_EXPORT 780 INTVAL 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 789 PARROT_EXPORT 790 PARROT_WARN_UNUSED_RESULT 791 INTVAL Parrot_io_listen(PARROT_INTERP, ARGMOD(PMC *pmc), INTVAL backlog) 792 __attribute__nonnull__(1) 793 __attribute__nonnull__(2) 794 FUNC_MODIFIES(*pmc); 795 796 PARROT_EXPORT 797 PARROT_WARN_UNUSED_RESULT 798 PARROT_CANNOT_RETURN_NULL 799 PMC * Parrot_io_new_socket_pmc(PARROT_INTERP, INTVAL flags) 800 __attribute__nonnull__(1); 801 802 PARROT_EXPORT 803 INTVAL 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 812 PARROT_EXPORT 813 INTVAL 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 820 PARROT_EXPORT 821 PARROT_WARN_UNUSED_RESULT 822 INTVAL 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 829 PARROT_EXPORT 830 PARROT_WARN_UNUSED_RESULT 831 PARROT_CANNOT_RETURN_NULL 832 PMC * Parrot_io_socket(PARROT_INTERP, INTVAL fam, INTVAL type, INTVAL proto) 833 __attribute__nonnull__(1); 834 835 PARROT_EXPORT 836 PARROT_WARN_UNUSED_RESULT 837 PARROT_CANNOT_RETURN_NULL 838 INTVAL 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 760 876 /* Put platform specific macros here if you must */ 761 877 #ifdef PIO_OS_WIN32 762 878 extern 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 1 1 /* io_unix.h 2 2 * Copyright (C) 2001-2003, Parrot Foundation. 3 3 * SVN Info 4 * $Id $4 * $Id: io_unix.h 36833 2009-02-17 20:09:26Z allison $ 5 5 * Overview: 6 6 * Parrot IO subsystem 7 7 * Data Structure and Algorithms: … … 155 155 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */ 156 156 /* HEADERIZER END: src/io/unix.c */ 157 157 158 159 /* HEADERIZER BEGIN: src/io/socket_unix.c */ 160 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */ 161 162 PARROT_WARN_UNUSED_RESULT 163 PARROT_CAN_RETURN_NULL 164 PMC * Parrot_io_accept_unix(PARROT_INTERP, ARGMOD(PMC *socket)) 165 __attribute__nonnull__(1) 166 __attribute__nonnull__(2) 167 FUNC_MODIFIES(*socket); 168 169 INTVAL 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 178 INTVAL 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 186 INTVAL Parrot_io_listen_unix(SHIM_INTERP, ARGMOD(PMC *socket), INTVAL sec) 187 __attribute__nonnull__(2) 188 FUNC_MODIFIES(*socket); 189 190 INTVAL 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 198 INTVAL 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 207 INTVAL 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 215 PARROT_WARN_UNUSED_RESULT 216 PARROT_CANNOT_RETURN_NULL 217 PMC * Parrot_io_sockaddr_in(PARROT_INTERP, ARGIN(STRING *addr), INTVAL port) 218 __attribute__nonnull__(1) 219 __attribute__nonnull__(2); 220 221 PARROT_WARN_UNUSED_RESULT 222 PARROT_CAN_RETURN_NULL 223 PMC * 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 158 258 #define PIO_INIT(interp) Parrot_io_init_unix((interp)) 159 259 #define PIO_OPEN(interp, pmc, file, flags) \ 160 260 Parrot_io_open_unix((interp), (pmc), (file), (flags)) … … 173 273 #define PIO_FLUSH(interp, pmc) Parrot_io_flush_unix((interp), (pmc)) 174 274 #define PIO_GETBLKSIZE(handle) Parrot_io_getblksize_unix((handle)) 175 275 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 176 293 #endif /* PARROT_IO_UNIX_H_GUARD */ 177 294 178 295 /* -
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 1 1 /* 2 2 Copyright (C) 2001-2008, Parrot Foundation. 3 $Id $3 $Id: socket_api.c 36832 2009-02-17 19:58:58Z allison $ 4 4 5 5 =head1 NAME 6 6 … … 20 20 21 21 #include "parrot/parrot.h" 22 22 #include "io_private.h" 23 #include " io.str"23 #include "api.str" 24 24 25 25 #include <stdarg.h> 26 26 … … 32 32 33 33 34 34 =over 4 35 */ 36 37 38 /* 39 40 =item C<INTVAL Parrot_io_socket_is_closed> 41 42 =cut 43 44 */ 45 46 PARROT_EXPORT 47 PARROT_WARN_UNUSED_RESULT 48 PARROT_CANNOT_RETURN_NULL 49 INTVAL 50 Parrot_io_socket_is_closed(ARGMOD(PMC *socket)) 51 { 52 return 0; 53 } 54 55 /* 35 56 36 57 =item C<INTVAL Parrot_io_poll> 37 58 … … 71 92 PMC * 72 93 Parrot_io_socket(PARROT_INTERP, INTVAL fam, INTVAL type, INTVAL proto) 73 94 { 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); 76 96 } 77 97 78 98 /* … … 130 150 131 151 PARROT_EXPORT 132 152 INTVAL 133 Parrot_io_connect(PARROT_INTERP, ARGMOD(PMC *pmc), ARGMOD( STRING*address))153 Parrot_io_connect(PARROT_INTERP, ARGMOD(PMC *pmc), ARGMOD(PMC *address)) 134 154 { 135 155 if (Parrot_io_socket_is_closed(pmc)) 136 156 return -1; … … 151 171 152 172 PARROT_EXPORT 153 173 INTVAL 154 Parrot_io_bind(PARROT_INTERP, ARGMOD(PMC *pmc), ARGMOD( STRING*address))174 Parrot_io_bind(PARROT_INTERP, ARGMOD(PMC *pmc), ARGMOD(PMC *address)) 155 175 { 156 176 if (Parrot_io_socket_is_closed(pmc)) 157 177 return -1; 158 178 159 return PIO_BIND(interp, address);179 return PIO_BIND(interp, pmc, address); 160 180 } 161 181 162 182 /* … … 199 219 { 200 220 201 221 if (Parrot_io_socket_is_closed(pmc)) 202 return -1;222 return PMCNULL; 203 223 204 return PIO_ACCEPT(interp, l, io);224 return PIO_ACCEPT(interp, pmc); 205 225 } 206 226 207 227 /* 208 228 229 =item C<PMC * Parrot_io_new_socket_pmc> 230 231 Creates a new I/O socket object. The value of C<flags> is set 232 in the returned PMC. 233 234 =cut 235 236 */ 237 238 PARROT_EXPORT 239 PARROT_WARN_UNUSED_RESULT 240 PARROT_CANNOT_RETURN_NULL 241 PMC * 242 Parrot_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 209 253 =back 210 254 211 255 =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 1 1 /* 2 2 Copyright (C) 2001-2008, Parrot Foundation. 3 $Id $3 $Id: socket_unix.c 36832 2009-02-17 19:58:58Z allison $ 4 4 5 5 =head1 NAME 6 6 … … 28 28 29 29 */ 30 30 31 #include <sys/socket.h> 32 31 33 #include "parrot/parrot.h" 32 34 #include "io_private.h" 35 #include "../pmc/pmc_socket.h" 33 36 34 37 #ifdef PIO_OS_UNIX 35 38 … … 38 41 /* HEADERIZER BEGIN: static */ 39 42 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */ 40 43 44 static 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) 41 56 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */ 42 57 /* HEADERIZER END: static */ 43 58 44 59 /* 60 static void get_sockaddr_in(PARROT_INTERP, ARGIN(PMC * sockaddr), 61 ARGIN(const char* host), ARGIN(int port)); 62 */ 63 64 /* 45 65 46 66 =back 47 67 … … 56 76 57 77 =over 4 58 78 59 =item C< STRING* Parrot_io_sockaddr_in>79 =item C<PMC * Parrot_io_sockaddr_in> 60 80 61 81 C<Parrot_io_sockaddr_in()> is not part of the layer and so must be C<extern>. 62 82 … … 67 87 68 88 */ 69 89 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 70 94 PARROT_WARN_UNUSED_RESULT 71 95 PARROT_CANNOT_RETURN_NULL 72 STRING*73 Parrot_io_sockaddr_in(PARROT_INTERP, unsigned short port, ARGIN(STRING *addr))96 PMC * 97 Parrot_io_sockaddr_in(PARROT_INTERP, ARGIN(STRING *addr), INTVAL port) 74 98 { 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; 114 107 } 115 108 116 109 … … 130 123 PARROT_WARN_UNUSED_RESULT 131 124 PARROT_CAN_RETURN_NULL 132 125 PMC * 133 Parrot_io_socket_unix(PARROT_INTERP, ARGMOD(PMC *socket),int fam, int type, int proto)126 Parrot_io_socket_unix(PARROT_INTERP, int fam, int type, int proto) 134 127 { 128 int i; 135 129 const int sock = socket(fam, type, proto); 136 130 if (sock >= 0) { 137 P arrotIO * 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; 142 136 return io; 143 137 } 144 return NULL;138 return PMCNULL; 145 139 } 146 140 147 141 /* … … 155 149 */ 156 150 157 151 INTVAL 158 Parrot_io_connect_unix(SHIM_INTERP, SHIM(PMC *socket), ARGMOD(ParrotIO *io), 159 ARGIN_NULLOK(STRING *r)) 152 Parrot_io_connect_unix(PARROT_INTERP, ARGMOD(PMC *socket), ARGIN(PMC *r)) 160 153 { 161 struct sockaddr_in * saddr = &io->remote;154 Parrot_Socket_attributes * io = PARROT_SOCKET(socket); 162 155 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; 165 160 166 161 AGAIN: 167 if ((connect(io-> fd, (struct sockaddr *)saddr,162 if ((connect(io->os_handle, (struct sockaddr *)SOCKADDR(socket, remote), 168 163 sizeof (struct sockaddr_in))) != 0) { 169 164 switch (errno) { 170 165 case EINTR: … … 192 187 */ 193 188 194 189 INTVAL 195 Parrot_io_bind_unix(SHIM_INTERP, SHIM(PMC *socket), ARGMOD(ParrotIO *io), 196 ARGMOD(STRING *l)) 190 Parrot_io_bind_unix(PARROT_INTERP, ARGMOD(PMC *socket), ARGMOD(PMC *sockaddr)) 197 191 { 198 struct sockaddr_in * saddr = &io->local; 192 Parrot_Socket_attributes * io = PARROT_SOCKET(socket); 193 struct sockaddr_in * saddr; 199 194 200 if (! l)195 if (!sockaddr) 201 196 return -1; 202 197 203 memcpy(&io->local, PObj_bufstart(l), sizeof (struct sockaddr_in)); 198 PARROT_SOCKET(socket)->local = sockaddr; 199 200 saddr = SOCKADDR(socket, local); 204 201 205 if ((bind(io-> fd, (struct sockaddr *) saddr,202 if ((bind(io->os_handle, (struct sockaddr *) saddr, 206 203 sizeof (struct sockaddr_in))) == -1) { 207 204 return -1; 208 205 } … … 222 219 */ 223 220 224 221 INTVAL 225 Parrot_io_listen_unix(SHIM_INTERP, SHIM(PMC *socket), ARGIN(ParrotIO *io), 226 INTVAL sec) 222 Parrot_io_listen_unix(SHIM_INTERP, ARGMOD(PMC *socket), INTVAL sec) 227 223 { 228 if ((listen(io->fd, sec)) == -1) { 224 Parrot_Socket_attributes * io = PARROT_SOCKET(socket); 225 if ((listen(io->os_handle, sec)) == -1) { 229 226 return -1; 230 227 } 231 228 return 0; … … 233 230 234 231 /* 235 232 236 =item C<P arrotIO* Parrot_io_accept_unix>233 =item C<PMC * Parrot_io_accept_unix> 237 234 238 235 Accept a new connection and return a newly created C<ParrotIO> socket. 239 236 … … 244 241 PARROT_WARN_UNUSED_RESULT 245 242 PARROT_CAN_RETURN_NULL 246 243 PMC * 247 Parrot_io_accept_unix(PARROT_INTERP, SHIM(PMC *socket), ARGMOD(ParrotIO *io))244 Parrot_io_accept_unix(PARROT_INTERP, ARGMOD(PMC *socket)) 248 245 { 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); 251 249 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); 255 258 256 259 if (newsock == -1) { 257 mem_sys_free(newio); 258 return NULL; 260 return PMCNULL; 259 261 } 260 262 261 newio->fd= newsock;263 PARROT_SOCKET(newio)->os_handle = newsock; 262 264 263 265 /* XXX FIXME: Need to do a getsockname and getpeername here to 264 266 * fill in the sockaddr_in structs for local and peer */ … … 280 282 */ 281 283 282 284 INTVAL 283 Parrot_io_send_unix(SHIM_INTERP, SHIM(PMC *socket), ARGMOD(ParrotIO *io), 284 ARGMOD(STRING *s)) 285 Parrot_io_send_unix(SHIM_INTERP, ARGMOD(PMC *socket), ARGMOD(STRING *s)) 285 286 { 286 287 int error, bytes, byteswrote; 288 Parrot_Socket_attributes * io = PARROT_SOCKET(socket); 287 289 288 290 bytes = s->bufused; 289 291 byteswrote = 0; … … 291 293 /* 292 294 * Ignore encoding issues for now. 293 295 */ 294 if ((error = send(io-> fd, (char *)s->strstart + byteswrote,296 if ((error = send(io->os_handle, (char *)s->strstart + byteswrote, 295 297 bytes, 0)) >= 0) { 296 298 byteswrote += error; 297 299 bytes -= error; … … 313 315 # endif 314 316 case EPIPE: 315 317 /* XXX why close it here and not below */ 316 close(io-> fd);318 close(io->os_handle); 317 319 return -1; 318 320 default: 319 321 return -1; … … 332 334 */ 333 335 334 336 INTVAL 335 Parrot_io_recv_unix(PARROT_INTERP, SHIM(PMC *socket), 336 ARGMOD(ParrotIO *io), ARGOUT(STRING **s)) 337 Parrot_io_recv_unix(PARROT_INTERP, ARGMOD(PMC *socket), ARGOUT(STRING **s)) 337 338 { 338 339 int error; 339 340 unsigned int bytesread = 0; 340 341 char buf[2048]; 342 Parrot_Socket_attributes * io = PARROT_SOCKET(socket); 341 343 342 344 AGAIN: 343 if ((error = recv(io-> fd, buf, 2048, 0)) >= 0) {345 if ((error = recv(io->os_handle, buf, 2048, 0)) >= 0) { 344 346 bytesread += error; 345 347 /* The charset should probably be 'binary', but right now httpd.pir 346 348 * only works with 'ascii' … … 361 363 # endif 362 364 case ECONNRESET: 363 365 /* XXX why close it on err return result is -1 anyway */ 364 close(io-> fd);366 close(io->os_handle); 365 367 *s = Parrot_str_new_noinit(interp, enum_stringrep_one, 0); 366 368 return -1; 367 369 default: 368 close(io-> fd);370 close(io->os_handle); 369 371 *s = Parrot_str_new_noinit(interp, enum_stringrep_one, 0); 370 372 return -1; 371 373 } … … 393 395 */ 394 396 395 397 INTVAL 396 Parrot_io_poll_unix(SHIM_INTERP, SHIM(PMC *socket), ARGMOD(ParrotIO *io), int which,397 int sec,int usec)398 Parrot_io_poll_unix(SHIM_INTERP, ARGMOD(PMC *socket), int which, int sec, 399 int usec) 398 400 { 399 401 int n; 400 402 fd_set r, w, e; 401 403 struct timeval t; 404 Parrot_Socket_attributes * io = PARROT_SOCKET(socket); 402 405 403 406 t.tv_sec = sec; 404 407 t.tv_usec = usec; 405 408 FD_ZERO(&r); FD_ZERO(&w); FD_ZERO(&e); 406 409 /* 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); 410 413 AGAIN: 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); 415 418 return n; 416 419 } 417 420 else { … … 422 425 } 423 426 } 424 427 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) 428 static void 429 get_sockaddr_in(PARROT_INTERP, ARGIN(PMC * sockaddr), ARGIN(const char* host), 430 int port) 440 431 { 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; 452 435 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 */ 470 444 } 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. 500 449 */ 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; 506 455 } 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)); 512 457 } 513 458 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); 523 461 } 462 # endif 524 463 525 464 526 465 #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 1 1 /* 2 2 Copyright (C) 2001-2003, Parrot Foundation. 3 $Id $3 $Id: socket_win32.c 36832 2009-02-17 19:58:58Z allison $ 4 4 5 5 =head1 NAME 6 6 … … 31 31 32 32 #ifdef PIO_OS_WIN32 33 33 34 /* HEADERIZER HFILE: none*/34 /* HEADERIZER HFILE: include/parrot/io_win32.h */ 35 35 /* HEADERIZER BEGIN: static */ 36 36 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */ 37 37 -
src/ops/io.ops
diff --git a/src/ops/io.ops b/src/ops/io.ops index 47c5dc4..b243819 100644
a b 496 496 497 497 ######################################## 498 498 499 =item B<sockaddr>(out PMC, in STRING, in INT) 500 501 Create new Sockaddr PMC. 502 503 =cut 504 505 op 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 511 Create new Socket 512 513 =cut 514 515 op 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 521 Bind Socket to address 522 523 =cut 524 525 op 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 531 Start listening on previously bounded socket 532 533 =cut 534 535 op 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 541 Accept incoming connection 542 543 =cut 544 545 op 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 551 Recive data from socket 552 553 =cut 554 555 op 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 561 Recive data from socket 562 563 =cut 564 565 op send(out INT, in PMC, in STR) { 566 $1 = Parrot_io_send(interp, $2, $3); 567 } 568 499 569 =back 500 570 501 571 =cut -
src/ops/ops.num
diff --git a/src/ops/ops.num b/src/ops/ops.num index 98a337a..d7a956a 100644
a b 1266 1266 find_name_p_sc 1242 1267 1267 find_sub_not_null_p_s 1243 1268 1268 find_sub_not_null_p_sc 1244 1269 socket_p_i_i_i 1245 1270 socket_p_ic_i_i 1246 1271 socket_p_i_ic_i 1247 1272 socket_p_i_i_ic 1248 1273 socket_p_ic_i_ic 1249 1274 socket_p_i_ic_ic 1250 1275 socket_p_ic_ic_ic 1251 1276 socket_p_ic_ic_i 1252 1277 sockaddr_p_s_i 1253 1278 sockaddr_p_sc_i 1254 1279 sockaddr_p_s_ic 1255 1280 sockaddr_p_sc_ic 1256 1281 bind_i_p_p 1257 1282 bind_i_pc_p 1258 1283 bind_i_p_pc 1259 1284 bind_i_pc_pc 1260 1285 listen_i_p_i 1261 1286 listen_i_pc_i 1262 1287 listen_i_p_ic 1263 1288 listen_i_pc_ic 1264 1289 accept_p_p 1265 1290 accept_p_pc 1266 1291 recv_i_p_s 1267 1292 recv_i_pc_s 1268 1293 send_i_p_s 1269 1294 send_i_pc_s 1270 1295 send_i_p_sc 1271 1296 send_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 /* 2 Copyright (C) 2008-2009, Parrot Foundation. 3 $Id$ 4 5 =head1 NAME 6 7 src/pmc/sockaddr.pmc - sockaddr_in holder 8 9 =head1 DESCRIPTION 10 11 The Sockaddr PMC holds raw c-pointer to sockaddr_in 12 13 14 =head2 Vtable Functions 15 16 These 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 27 extern "C" { 28 #endif 29 struct sockaddr_in; 30 #ifdef __cplusplus 31 } 32 #endif 33 34 pmclass Sockaddr need_ext { 35 ATTR void *pointer; /* The stored pointer. */ 36 37 /* 38 39 =item C<void init()> 40 41 Initializes 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 59 Destroys 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 79 Creates 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 96 Returns 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 111 Sets 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 /* 2 Copyright (C) 2008, Parrot Foundation. 3 $Id: filehandle.pmc 36832 2009-02-17 19:58:58Z allison $ 4 5 =head1 NAME 6 7 src/pmc/socket.pmc - Socket PMC 8 9 =head1 DESCRIPTION 10 11 The 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 26 pmclass 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 34 Initializes 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 66 Create 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 88 Mark 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 109 Free 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 142 Connects a socket object to an address. 143 144 The asynchronous version takes an additional final PMC callback 145 argument, and only returns a status object. When the socket operation is 146 complete, it invokes the callback, passing it a status object and the 147 socket object it was called on. [If you want notification when a connect 148 operation is completed, you probably want to do something with that 149 connected 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 164 Receives a message from a connected socket object. It returns 165 the message in a string. 166 167 The asynchronous version takes an additional final PMC callback 168 argument, and only returns a status object. When the recv operation is 169 complete, it invokes the callback, passing it a status object and a 170 string 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 186 Sends a message string to a connected socket object. 187 188 The asynchronous version takes an additional final PMC callback 189 argument, and only returns a status object. When the send operation is 190 complete, 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 7 t/pmc/sockaddr.t - test the Sockaddr PMC 8 9 =head1 SYNOPSIS 10 11 % prove t/pmc/sockaddr.t 12 13 =head1 DESCRIPTION 14 15 Tests 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: