headers via ctrl_socket and a php variable
[php-ancillary.git] / php-ancillary.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4 #include "php.h"
5 #include <ancillary.h>
6
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <fcntl.h>
10  
11 #define PHP_ANCILLARY_VERSION "1.0"
12 #define PHP_ANCILLARY_EXTNAME "ancillary"
13  
14 extern zend_module_entry ancillary_module_entry;
15 #define phpext_ancillary_ptr &ancillary_module_entry
16  
17 // declaration of a custom mop_function()
18 PHP_FUNCTION(ancillary_getstream);
19  
20 // list of custom PHP functions provided by this extension
21 // set {NULL, NULL, NULL} as the last record to mark the end of list
22 static function_entry ancillary_getstream[] = {
23     PHP_FE(ancillary_getstream, NULL)
24     {NULL, NULL, NULL}
25 };
26  
27 // the following code creates an entry for the module and registers it with Zend.
28 zend_module_entry ancillary_module_entry = {
29 #if ZEND_MODULE_API_NO >= 20010901
30     STANDARD_MODULE_HEADER,
31 #endif
32     PHP_ANCILLARY_EXTNAME,
33     ancillary_getstream,
34     NULL, // name of the MINIT function or NULL if not applicable
35     NULL, // name of the MSHUTDOWN function or NULL if not applicable
36     NULL, // name of the RINIT function or NULL if not applicable
37     NULL, // name of the RSHUTDOWN function or NULL if not applicable
38     NULL, // name of the MINFO function or NULL if not applicable
39 #if ZEND_MODULE_API_NO >= 20010901
40     PHP_ANCILLARY_VERSION,
41 #endif
42     STANDARD_MODULE_PROPERTIES
43 };
44  
45 ZEND_GET_MODULE(ancillary)
46
47 #define CTRL_BUFF_MAX_SZ (8*1024)
48  
49 // starting from a unix socket receive a socket from an external process
50 PHP_FUNCTION(ancillary_getstream)
51 {
52     zval *zstream;
53     php_stream *stream;
54     int fd_in, fd_out[2], retrecv, curpos = 0;
55     char *headers;
56     zval *zheaders;
57
58     if ((headers = calloc(CTRL_BUFF_MAX_SZ, 1)) == NULL) {
59         return;
60     }
61
62     if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz", &zstream, &zheaders))
63         return;
64     
65     php_stream_from_zval(stream, &zstream);
66
67     if (php_stream_cast(stream, PHP_STREAM_AS_FD, (void*)&fd_in, REPORT_ERRORS) == FAILURE) {
68         RETURN_FALSE;
69     }
70
71     if(ancil_recv_fds(fd_in, fd_out, 2) == 0) {
72         RETURN_FALSE;
73     }
74
75     {
76         char bf[2048];
77
78         sprintf(bf, "zero: [%d]    uno: [%d]\n", fd_out[0], fd_out[1]);
79         write(1, bf, strlen(bf));
80     }
81     while(1) {
82         write(1, "LOOP\n", 5);
83         retrecv = recv(fd_out[1], &(headers[curpos]), CTRL_BUFF_MAX_SZ - curpos - 1, 0);
84         if (retrecv < 0) {
85             RETURN_FALSE;
86         }
87         else if (retrecv == 0) {
88             break;
89         }
90         else {
91             char bf[1024];
92             curpos += retrecv;
93             sprintf(bf, "CURPOS: %d\n", curpos);
94             write(1, bf, strlen(bf));
95             if (curpos == CTRL_BUFF_MAX_SZ - 1) {
96                 free(headers);
97                 RETURN_FALSE;
98             }
99         }
100     }
101     shutdown(fd_out[1], SHUT_RDWR);
102
103     ZVAL_STRING(zheaders, headers, 1);
104     free(headers);
105
106     {
107         int fh;
108
109         if ((fh = open("/tmp/out_php-anc.txt", O_WRONLY | O_CREAT | O_APPEND)) > -1) {
110             write(fh, headers, curpos);
111             close(fh);
112         }
113     }
114
115     if ((stream = php_stream_fopen_from_fd(fd_out[0], "r+b", NULL)) == NULL) {
116         RETURN_FALSE;
117     }
118
119     php_stream_to_zval(stream, return_value);
120 }
121