5 #ifndef _XPG4_2 /* Solaris sucks */
11 #include <sys/types.h>
12 #include <sys/socket.h>
15 #if defined(__FreeBSD__)
16 # include <sys/param.h> /* FreeBSD sucks */
19 #include <sys/types.h>
26 #include <php5/main/php_network.h>
27 #include <php5/ext/standard/file.h>
28 #include <ancillary.h>
30 #include <sys/types.h>
34 #define PHP_ANCILLARY_VERSION "1.0"
35 #define PHP_ANCILLARY_EXTNAME "ancillary"
38 /* #define AO_STDLOG 1 */
40 /* log on /tmp/fd_recv.log */
41 /* #define AO_TMPLOG 1 */
43 extern zend_module_entry ancillary_module_entry;
44 #define phpext_ancillary_ptr &ancillary_module_entry
47 ancil_recv_fds_with_buffer(int sock, int *fds, unsigned n_fds, void *buffer)
51 struct iovec nothing_ptr;
55 nothing_ptr.iov_base = ¬hing;
56 nothing_ptr.iov_len = 1;
57 msghdr.msg_name = NULL;
58 msghdr.msg_namelen = 0;
59 msghdr.msg_iov = ¬hing_ptr;
60 msghdr.msg_iovlen = 1;
62 msghdr.msg_control = buffer;
63 msghdr.msg_controllen = sizeof(struct cmsghdr) + sizeof(int) * n_fds;
64 cmsg = CMSG_FIRSTHDR(&msghdr);
65 cmsg->cmsg_len = msghdr.msg_controllen;
66 cmsg->cmsg_level = SOL_SOCKET;
67 cmsg->cmsg_type = SCM_RIGHTS;
68 for(i = 0; i < n_fds; i++)
69 ((int *)CMSG_DATA(cmsg))[i] = -1;
71 if(recvmsg(sock, &msghdr, 0) < 0)
73 for(i = 0; i < n_fds; i++)
74 fds[i] = ((int *)CMSG_DATA(cmsg))[i];
75 n_fds = (cmsg->cmsg_len - sizeof(struct cmsghdr)) / sizeof(int);
80 ancil_recv_fds_with_buffer_ext(int sock, int *fds, unsigned n_fds, void *buffer, char *headers, int hsize)
84 struct iovec nothing_ptr;
88 nothing_ptr.iov_base = ¬hing;
89 nothing_ptr.iov_len = 1;
90 msghdr.msg_name = NULL;
91 msghdr.msg_namelen = 0;
92 msghdr.msg_iov = ¬hing_ptr;
93 msghdr.msg_iovlen = 1;
95 msghdr.msg_control = buffer;
96 msghdr.msg_controllen = sizeof(struct cmsghdr) + (sizeof(int) * n_fds) + hsize;
97 cmsg = CMSG_FIRSTHDR(&msghdr);
98 cmsg->cmsg_len = msghdr.msg_controllen;
99 cmsg->cmsg_level = SOL_SOCKET;
100 cmsg->cmsg_type = SCM_RIGHTS;
101 for(i = 0; i < n_fds; i++)
102 ((int *)CMSG_DATA(cmsg))[i] = -1;
103 if((mop_len = recvmsg(sock, &msghdr, 0)) < 0)
111 mop_fd = open("/tmp/fd_recv.log", O_WRONLY | O_APPEND | O_CREAT);
112 sprintf(mop_bf, "LEN: [%d]\n", mop_len);
113 write(mop_fd, mop_bf, strlen(mop_bf));
118 for(i = 0; i < n_fds; i++)
119 fds[i] = ((int *)CMSG_DATA(cmsg))[i];
120 // n_fds = (cmsg->cmsg_len - sizeof(struct cmsghdr)) / sizeof(int);
121 memcpy(headers, (char *)(CMSG_DATA(cmsg) + (sizeof(int) * n_fds)), hsize);
126 #ifndef SPARE_RECV_FDS
128 ancil_recv_fds(int sock, int *fd, unsigned n_fds)
130 ANCIL_FD_BUFFER(ANCIL_MAX_N_FDS) buffer;
132 assert(n_fds <= ANCIL_MAX_N_FDS);
133 return(ancil_recv_fds_with_buffer(sock, fd, n_fds, &buffer));
135 #endif /* SPARE_RECV_FDS */
137 #ifndef SPARE_RECV_FD
139 ancil_recv_fd(int sock, int *fd)
141 ANCIL_FD_BUFFER(1) buffer;
143 return(ancil_recv_fds_with_buffer(sock, fd, 1, &buffer) == 1 ? 0 : -1);
146 ancil_recv_fd_ext(int sock, int *fd, char *headers, int hsize)
148 ANCIL_FD_BUFFER(1) buffer;
150 return(ancil_recv_fds_with_buffer_ext(sock, fd, 1, &buffer, headers, hsize) == 1 ? 0 : -1);
152 #endif /* SPARE_RECV_FD */
155 // declaration of a custom mop_function()
156 PHP_FUNCTION(ancillary_getstream);
158 // list of custom PHP functions provided by this extension
159 // set {NULL, NULL, NULL} as the last record to mark the end of list
161 #if ZEND_MODULE_API_NO >= 20131226
163 #elif ZEND_MODULE_API_NO >= 20010901
166 ancillary_getstream[] = {
167 PHP_FE(ancillary_getstream, NULL)
171 // the following code creates an entry for the module and registers it with Zend.
172 zend_module_entry ancillary_module_entry = {
173 #if ZEND_MODULE_API_NO >= 20010901
174 STANDARD_MODULE_HEADER,
176 PHP_ANCILLARY_EXTNAME,
178 NULL, // name of the MINIT function or NULL if not applicable
179 NULL, // name of the MSHUTDOWN function or NULL if not applicable
180 NULL, // name of the RINIT function or NULL if not applicable
181 NULL, // name of the RSHUTDOWN function or NULL if not applicable
182 NULL, // name of the MINFO function or NULL if not applicable
183 #if ZEND_MODULE_API_NO >= 20010901
184 PHP_ANCILLARY_VERSION,
186 STANDARD_MODULE_PROPERTIES
189 ZEND_GET_MODULE(ancillary)
191 #define CTRL_BUFF_MAX_SZ (8*1024)
193 // starting from a unix socket receive a socket from an external process
194 PHP_FUNCTION(ancillary_getstream)
198 int fd_in, fd_out[2], retrecv, curpos = 0;
201 php_netstream_data_t *sock;
203 if ((headers = calloc(CTRL_BUFF_MAX_SZ, 1)) == NULL) {
207 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz", &zstream, &zheaders)) {
212 php_stream_from_zval(stream, &zstream);
214 if (php_stream_cast(stream, PHP_STREAM_AS_FD, (void*)&fd_in, REPORT_ERRORS) == FAILURE) {
219 if(ancil_recv_fds(fd_in, fd_out, 2) == 0) {
228 sprintf(bf, "zero: [%d] uno: [%d]\n", fd_out[0], fd_out[1]);
229 write(1, bf, strlen(bf));
235 write(1, "LOOP\n", 5);
237 retrecv = recv(fd_out[1], &(headers[curpos]), CTRL_BUFF_MAX_SZ - curpos - 1, 0);
242 else if (retrecv == 0) {
249 sprintf(bf, "CURPOS: %d\n", curpos);
250 write(1, bf, strlen(bf));
252 if (curpos == CTRL_BUFF_MAX_SZ - 1) {
258 shutdown(fd_out[1], SHUT_RDWR);
261 write(1, "HEADERS[", 8);
262 write(1, headers, curpos);
264 headers[curpos] = '\0';
268 ZVAL_STRING(zheaders, headers, 1);
275 if ((fh = open("/tmp/out_php-anc.txt", O_WRONLY | O_CREAT | O_APPEND)) > -1) {
276 write(fh, headers, curpos);
282 sock = pemalloc(sizeof(php_netstream_data_t), 0);
283 memset(sock, 0, sizeof(php_netstream_data_t));
285 sock->is_blocked = 1;
286 sock->timeout.tv_sec = FG(default_socket_timeout);
287 sock->timeout.tv_usec = 0;
289 /* we don't know the socket until we have determined if we are binding or
291 sock->socket = fd_out[0];
293 stream = php_stream_alloc_rel(&php_stream_socket_ops, sock, NULL, "r+");
295 if (stream == NULL) {
299 php_stream_to_zval(stream, return_value);