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"
37 extern zend_module_entry ancillary_module_entry;
38 #define phpext_ancillary_ptr &ancillary_module_entry
41 ancil_recv_fds_with_buffer(int sock, int *fds, unsigned n_fds, void *buffer)
45 struct iovec nothing_ptr;
49 nothing_ptr.iov_base = ¬hing;
50 nothing_ptr.iov_len = 1;
51 msghdr.msg_name = NULL;
52 msghdr.msg_namelen = 0;
53 msghdr.msg_iov = ¬hing_ptr;
54 msghdr.msg_iovlen = 1;
56 msghdr.msg_control = buffer;
57 msghdr.msg_controllen = sizeof(struct cmsghdr) + sizeof(int) * n_fds;
58 cmsg = CMSG_FIRSTHDR(&msghdr);
59 cmsg->cmsg_len = msghdr.msg_controllen;
60 cmsg->cmsg_level = SOL_SOCKET;
61 cmsg->cmsg_type = SCM_RIGHTS;
62 for(i = 0; i < n_fds; i++)
63 ((int *)CMSG_DATA(cmsg))[i] = -1;
65 if(recvmsg(sock, &msghdr, 0) < 0)
67 for(i = 0; i < n_fds; i++)
68 fds[i] = ((int *)CMSG_DATA(cmsg))[i];
69 n_fds = (cmsg->cmsg_len - sizeof(struct cmsghdr)) / sizeof(int);
74 ancil_recv_fds_with_buffer_ext(int sock, int *fds, unsigned n_fds, void *buffer, char *headers, int hsize)
78 struct iovec nothing_ptr;
82 nothing_ptr.iov_base = ¬hing;
83 nothing_ptr.iov_len = 1;
84 msghdr.msg_name = NULL;
85 msghdr.msg_namelen = 0;
86 msghdr.msg_iov = ¬hing_ptr;
87 msghdr.msg_iovlen = 1;
89 msghdr.msg_control = buffer;
90 msghdr.msg_controllen = sizeof(struct cmsghdr) + (sizeof(int) * n_fds) + hsize;
91 cmsg = CMSG_FIRSTHDR(&msghdr);
92 cmsg->cmsg_len = msghdr.msg_controllen;
93 cmsg->cmsg_level = SOL_SOCKET;
94 cmsg->cmsg_type = SCM_RIGHTS;
95 for(i = 0; i < n_fds; i++)
96 ((int *)CMSG_DATA(cmsg))[i] = -1;
97 if((mop_len = recvmsg(sock, &msghdr, 0)) < 0)
104 mop_fd = open("/tmp/fd_recv.log", O_WRONLY | O_APPEND | O_CREAT);
105 sprintf(mop_bf, "LEN: [%d]\n", mop_len);
106 write(mop_fd, mop_bf, strlen(mop_bf));
110 for(i = 0; i < n_fds; i++)
111 fds[i] = ((int *)CMSG_DATA(cmsg))[i];
112 // n_fds = (cmsg->cmsg_len - sizeof(struct cmsghdr)) / sizeof(int);
113 memcpy(headers, (char *)(CMSG_DATA(cmsg) + (sizeof(int) * n_fds)), hsize);
118 #ifndef SPARE_RECV_FDS
120 ancil_recv_fds(int sock, int *fd, unsigned n_fds)
122 ANCIL_FD_BUFFER(ANCIL_MAX_N_FDS) buffer;
124 assert(n_fds <= ANCIL_MAX_N_FDS);
125 return(ancil_recv_fds_with_buffer(sock, fd, n_fds, &buffer));
127 #endif /* SPARE_RECV_FDS */
129 #ifndef SPARE_RECV_FD
131 ancil_recv_fd(int sock, int *fd)
133 ANCIL_FD_BUFFER(1) buffer;
135 return(ancil_recv_fds_with_buffer(sock, fd, 1, &buffer) == 1 ? 0 : -1);
138 ancil_recv_fd_ext(int sock, int *fd, char *headers, int hsize)
140 ANCIL_FD_BUFFER(1) buffer;
142 return(ancil_recv_fds_with_buffer_ext(sock, fd, 1, &buffer, headers, hsize) == 1 ? 0 : -1);
144 #endif /* SPARE_RECV_FD */
147 // declaration of a custom mop_function()
148 PHP_FUNCTION(ancillary_getstream);
150 // list of custom PHP functions provided by this extension
151 // set {NULL, NULL, NULL} as the last record to mark the end of list
152 static function_entry ancillary_getstream[] = {
153 PHP_FE(ancillary_getstream, NULL)
157 // the following code creates an entry for the module and registers it with Zend.
158 zend_module_entry ancillary_module_entry = {
159 #if ZEND_MODULE_API_NO >= 20010901
160 STANDARD_MODULE_HEADER,
162 PHP_ANCILLARY_EXTNAME,
164 NULL, // name of the MINIT function or NULL if not applicable
165 NULL, // name of the MSHUTDOWN function or NULL if not applicable
166 NULL, // name of the RINIT function or NULL if not applicable
167 NULL, // name of the RSHUTDOWN function or NULL if not applicable
168 NULL, // name of the MINFO function or NULL if not applicable
169 #if ZEND_MODULE_API_NO >= 20010901
170 PHP_ANCILLARY_VERSION,
172 STANDARD_MODULE_PROPERTIES
175 ZEND_GET_MODULE(ancillary)
177 #define CTRL_BUFF_MAX_SZ (8*1024)
179 // starting from a unix socket receive a socket from an external process
180 PHP_FUNCTION(ancillary_getstream)
184 int fd_in, fd_out[2], retrecv, curpos = 0;
187 php_netstream_data_t *sock;
189 if ((headers = calloc(CTRL_BUFF_MAX_SZ, 1)) == NULL) {
193 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz", &zstream, &zheaders)) {
198 php_stream_from_zval(stream, &zstream);
200 if (php_stream_cast(stream, PHP_STREAM_AS_FD, (void*)&fd_in, REPORT_ERRORS) == FAILURE) {
205 if(ancil_recv_fds(fd_in, fd_out, 2) == 0) {
213 sprintf(bf, "zero: [%d] uno: [%d]\n", fd_out[0], fd_out[1]);
214 write(1, bf, strlen(bf));
217 write(1, "LOOP\n", 5);
218 retrecv = recv(fd_out[1], &(headers[curpos]), CTRL_BUFF_MAX_SZ - curpos - 1, 0);
223 else if (retrecv == 0) {
229 sprintf(bf, "CURPOS: %d\n", curpos);
230 write(1, bf, strlen(bf));
231 if (curpos == CTRL_BUFF_MAX_SZ - 1) {
237 shutdown(fd_out[1], SHUT_RDWR);
239 ZVAL_STRING(zheaders, headers, 1);
245 if ((fh = open("/tmp/out_php-anc.txt", O_WRONLY | O_CREAT | O_APPEND)) > -1) {
246 write(fh, headers, curpos);
251 sock = pemalloc(sizeof(php_netstream_data_t), 0);
252 memset(sock, 0, sizeof(php_netstream_data_t));
254 sock->is_blocked = 1;
255 sock->timeout.tv_sec = FG(default_socket_timeout);
256 sock->timeout.tv_usec = 0;
258 /* we don't know the socket until we have determined if we are binding or
260 sock->socket = fd_out[0];
262 stream = php_stream_alloc_rel(&php_stream_socket_ops, sock, NULL, "r+");
264 if (stream == NULL) {
268 php_stream_to_zval(stream, return_value);