root/sapi/tux/php_tux.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sapi_tux_ub_write
  2. sapi_tux_send_headers
  3. sapi_tux_read_post
  4. sapi_tux_read_cookies
  5. sapi_tux_register_variables
  6. php_tux_startup
  7. tux_module_main
  8. tux_request_ctor
  9. tux_request_dtor
  10. separate_thread
  11. TUXAPI_handle_events
  12. tux_register_on_close
  13. tux_closed_conn
  14. tux_get_fd
  15. tux_set_dont_close
  16. TUXAPI_init
  17. doesnotmatter_fini

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 5                                                        |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1997-2016 The PHP Group                                |
   6    +----------------------------------------------------------------------+
   7    | This source file is subject to version 3.01 of the PHP license,      |
   8    | that is bundled with this package in the file LICENSE, and is        |
   9    | available through the world-wide-web at the following url:           |
  10    | http://www.php.net/license/3_01.txt                                  |
  11    | If you did not receive a copy of the PHP license and are unable to   |
  12    | obtain it through the world-wide-web, please send a note to          |
  13    | license@php.net so we can mail you a copy immediately.               |
  14    +----------------------------------------------------------------------+
  15    | Author: Sascha Schumann <sascha@schumann.cx>                         |
  16    +----------------------------------------------------------------------+
  17 */
  18 
  19 #include "php.h"
  20 #include "SAPI.h"
  21 #include "php_main.h"
  22 #include "php_variables.h"
  23 
  24 #include "ext/standard/php_smart_str.h"
  25 
  26 #include "tuxmodule.h"
  27 
  28 #include <sys/uio.h>
  29 
  30 #if 0
  31 #include <pthread.h>
  32 #endif
  33 
  34 void tux_closed_conn(int fd);
  35 
  36 enum {
  37         PHP_TUX_BACKGROUND_CONN = 1
  38 };
  39 
  40 typedef struct {
  41         user_req_t *req;
  42         void (*on_close)(int);
  43         int tux_action;
  44         struct iovec *header_vec;
  45         int number_vec;
  46 } php_tux_globals;
  47 
  48 static php_tux_globals tux_globals;
  49 
  50 #define TG(v) (tux_globals.v)
  51 
  52 static int sapi_tux_ub_write(const char *str, uint str_length TSRMLS_DC)
  53 {
  54         int n;
  55         int m;
  56         const char *estr;
  57         
  58         /* combine headers and body */
  59         if (TG(number_vec)) {
  60                 struct iovec *vec = TG(header_vec);
  61                 
  62                 n = TG(number_vec);
  63                 vec[n].iov_base = (void *) str;
  64                 vec[n++].iov_len = str_length;
  65                 
  66                 /* XXX: this might need more complete error handling */
  67                 if ((m = writev(TG(req)->sock, vec, n)) == -1 && errno == EPIPE)
  68                         php_handle_aborted_connection();
  69 
  70                 if (m > 0)
  71                         TG(req)->bytes_sent += str_length;
  72 
  73                 TG(number_vec) = 0;
  74                 return str_length;
  75         }
  76 
  77         estr = str + str_length;
  78         
  79         while (str < estr) {
  80                 n = send(TG(req)->sock, str, estr - str, 0);
  81 
  82                 if (n == -1 && errno == EPIPE)
  83                         php_handle_aborted_connection();
  84                 if (n == -1 && errno == EAGAIN)
  85                         continue;
  86                 if (n <= 0) 
  87                         return n;
  88 
  89                 str += n;
  90         }
  91 
  92         n = str_length - (estr - str);
  93         
  94         TG(req)->bytes_sent += n;
  95 
  96         return n;
  97 }
  98 
  99 static int sapi_tux_send_headers(sapi_headers_struct *sapi_headers)
 100 {
 101         char buf[1024];
 102         struct iovec *vec;
 103         int n;
 104         int max_headers;
 105         zend_llist_position pos;
 106         sapi_header_struct *h;
 107         size_t len;
 108         char *status_line;
 109         int locate_cl;
 110         TSRMLS_FETCH();
 111         
 112         max_headers = 30;
 113         n = 1;
 114         
 115         vec = malloc(sizeof(struct iovec) * max_headers);
 116         status_line = malloc(30);
 117         
 118         /* safe sprintf use */
 119         len = slprintf(status_line, 30, "HTTP/1.1 %d NA\r\n", SG(sapi_headers).http_response_code);
 120         
 121         vec[0].iov_base = status_line;
 122         vec[0].iov_len = len;
 123         
 124         TG(req)->http_status = SG(sapi_headers).http_response_code;
 125 
 126         if (TG(tux_action) == TUX_ACTION_FINISH_CLOSE_REQ && TG(req)->http_version == HTTP_1_1)
 127                 locate_cl = 1;
 128         else
 129                 locate_cl = 0;
 130         
 131         h = zend_llist_get_first_ex(&sapi_headers->headers, &pos);
 132         while (h) {
 133                 if (locate_cl 
 134                                 && strncasecmp(h->header, "Content-length:", sizeof("Content-length:")-1) == 0) {
 135                         TG(tux_action) = TUX_ACTION_FINISH_REQ;
 136                         locate_cl = 0;
 137                 }
 138                         
 139                 vec[n].iov_base = h->header;
 140                 vec[n++].iov_len = h->header_len;
 141                 if (n >= max_headers - 3) {
 142                         max_headers *= 2;
 143                         vec = realloc(vec, sizeof(struct iovec) * max_headers);
 144                 }
 145                 vec[n].iov_base = "\r\n";
 146                 vec[n++].iov_len = 2;
 147                 
 148                 h = zend_llist_get_next_ex(&sapi_headers->headers, &pos);
 149         }
 150 
 151         vec[n].iov_base = "\r\n";
 152         vec[n++].iov_len = 2;
 153 
 154         TG(number_vec) = n;
 155         TG(header_vec) = vec;
 156 
 157         
 158         return SAPI_HEADER_SENT_SUCCESSFULLY;
 159 }
 160 
 161 static int sapi_tux_read_post(char *buffer, uint count_bytes)
 162 {
 163 #if 0
 164         int amount = 0;
 165         TSRMLS_FETCH();
 166 
 167         TG(req)->objectlen = count_bytes;
 168         TG(req)->object_addr = buffer;
 169         if (tux(TUX_ACTION_READ_POST_DATA, TG(req)))
 170                 return 0;
 171 
 172         TG(read_post_data) = 1;
 173         
 174         return TG(req)->objectlen;
 175 #else
 176         return 0;
 177 #endif
 178 }
 179 
 180 static char *sapi_tux_read_cookies(void)
 181 {
 182         TSRMLS_FETCH();
 183         
 184         return TG(req)->cookies;
 185 }
 186 
 187 #define BUF_SIZE 512
 188 #define ADD_STRING(name)                                                                                \
 189         php_register_variable(name, buf, track_vars_array TSRMLS_CC)
 190 
 191 static void sapi_tux_register_variables(zval *track_vars_array TSRMLS_DC)
 192 {
 193         char buf[BUF_SIZE + 1];
 194         char *p;
 195         sapi_header_line ctr = {0};
 196         
 197         ctr.line = buf;
 198         ctr.line_len = slprintf(buf, sizeof(buf), "Server: %s", TUXAPI_version);
 199         sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC);
 200         
 201         php_register_variable("PHP_SELF", SG(request_info).request_uri, track_vars_array TSRMLS_CC);
 202         php_register_variable("SERVER_SOFTWARE", TUXAPI_version, track_vars_array TSRMLS_CC);
 203         php_register_variable("GATEWAY_INTERFACE", "CGI/1.1", track_vars_array TSRMLS_CC);
 204         php_register_variable("REQUEST_METHOD", (char *) SG(request_info).request_method, track_vars_array TSRMLS_CC);
 205         php_register_variable("DOCUMENT_ROOT", TUXAPI_docroot, track_vars_array TSRMLS_CC);
 206         php_register_variable("SERVER_NAME", TUXAPI_servername, track_vars_array TSRMLS_CC);
 207         php_register_variable("REQUEST_URI", SG(request_info).request_uri, track_vars_array TSRMLS_CC);
 208         php_register_variable("PATH_TRANSLATED", SG(request_info).path_translated, track_vars_array TSRMLS_CC);
 209 
 210         p = inet_ntoa(TG(req)->client_host);
 211         /* string representation of IPs are never larger than 512 bytes */
 212         if (p) {
 213                 memcpy(buf, p, strlen(p) + 1);
 214                 ADD_STRING("REMOTE_ADDR");
 215                 ADD_STRING("REMOTE_HOST");
 216         }
 217 
 218         snprintf(buf, sizeof(buf), "%d", CGI_SERVER_PORT(TG(req)));
 219         ADD_STRING("SERVER_PORT");
 220 
 221 #if 0
 222         snprintf(buf, BUF_SIZE, "/%s", TG(hc)->pathinfo);
 223         ADD_STRING("PATH_INFO");
 224 
 225         snprintf(buf, BUF_SIZE, "/%s", TG(hc)->origfilename);
 226         ADD_STRING("SCRIPT_NAME");
 227 #endif
 228 
 229 #define CONDADD(name, field)                                                    \
 230         if (TG(req)->field[0]) {                                                                \
 231                 php_register_variable(#name, TG(req)->field, track_vars_array TSRMLS_CC); \
 232         }
 233 
 234         CONDADD(HTTP_REFERER, referer);
 235         CONDADD(HTTP_USER_AGENT, user_agent);
 236         CONDADD(HTTP_ACCEPT, accept);
 237         CONDADD(HTTP_ACCEPT_ENCODING, accept_encoding);
 238         CONDADD(HTTP_ACCEPT_LANGUAGE, accept_language);
 239         CONDADD(HTTP_COOKIE, cookies);
 240         CONDADD(CONTENT_TYPE, content_type);
 241 
 242 #if 0
 243         if (TG(hc)->contentlength != -1) {
 244                 snprintf(buf, sizeof(buf), "%ld", (long) TG(hc)->contentlength);
 245                 ADD_STRING("CONTENT_LENGTH");
 246         }
 247 #endif
 248 
 249 #if 0
 250         if (TG(hc)->authorization[0])
 251                 php_register_variable("AUTH_TYPE", "Basic", track_vars_array TSRMLS_CC);
 252 #endif
 253 }
 254 
 255 
 256 static int php_tux_startup(sapi_module_struct *sapi_module)
 257 {
 258         if (php_module_startup(sapi_module, NULL, 0)==FAILURE) {
 259                 return FAILURE;
 260         } else {
 261                 return SUCCESS;
 262         }
 263 }
 264 
 265 static sapi_module_struct tux_sapi_module = {
 266         "tux",
 267         "tux",
 268         
 269         php_tux_startup,
 270         php_module_shutdown_wrapper,
 271         
 272         NULL,                                                                   /* activate */
 273         NULL,                                                                   /* deactivate */
 274 
 275         sapi_tux_ub_write,
 276         NULL,
 277         NULL,                                                                   /* get uid */
 278         NULL,                                                                   /* getenv */
 279 
 280         php_error,
 281         
 282         NULL,
 283         sapi_tux_send_headers,
 284         NULL,
 285         sapi_tux_read_post,
 286         sapi_tux_read_cookies,
 287 
 288         sapi_tux_register_variables,
 289         NULL,                                                                   /* Log message */
 290         NULL,                                                                   /* Get request time */
 291         NULL,                                                                   /* Child terminate */
 292 
 293         STANDARD_SAPI_MODULE_PROPERTIES
 294 };
 295 
 296 static void tux_module_main(TSRMLS_D)
 297 {
 298         zend_file_handle file_handle;
 299 
 300         file_handle.type = ZEND_HANDLE_FILENAME;
 301         file_handle.filename = SG(request_info).path_translated;
 302         file_handle.free_filename = 0;
 303         file_handle.opened_path = NULL;
 304 
 305         if (php_request_startup(TSRMLS_C) == FAILURE) {
 306                 return;
 307         }
 308         
 309         php_execute_script(&file_handle TSRMLS_CC);
 310         php_request_shutdown(NULL);
 311 }
 312 
 313 static void tux_request_ctor(TSRMLS_D)
 314 {
 315         char buf[1024];
 316         int offset;
 317         size_t filename_len;
 318         size_t cwd_len;
 319         smart_str s = {0};
 320         char *p;
 321 
 322         TG(number_vec) = 0;     
 323         TG(header_vec) = NULL;
 324         SG(request_info).query_string = strdup(TG(req)->query);
 325 
 326         smart_str_appends_ex(&s, "/", 1);
 327         smart_str_appends_ex(&s, TG(req)->query, 1);
 328         smart_str_0(&s);
 329         p = strchr(s.c, '&');
 330         if (p)
 331                 *p = '\0';
 332         SG(request_info).path_translated = s.c;
 333         
 334         s.c = NULL;
 335         smart_str_appendc_ex(&s, '/', 1);
 336         smart_str_appends_ex(&s, TG(req)->objectname, 1);
 337         smart_str_0(&s);
 338         SG(request_info).request_uri = s.c;
 339         SG(request_info).request_method = CGI_REQUEST_METHOD(TG(req));
 340         if(TG(req)->http_version == HTTP_1_1) SG(request_info).proto_num = 1001;
 341         else SG(request_info).proto_num = 1000;
 342         SG(sapi_headers).http_response_code = 200;
 343         SG(request_info).content_type = TG(req)->content_type;
 344         SG(request_info).content_length = 0; /* TG(req)->contentlength; */
 345 
 346 #if 0
 347         php_handle_auth_data(TG(hc)->authorization TSRMLS_CC);
 348 #endif
 349 }
 350 
 351 static void tux_request_dtor(TSRMLS_D)
 352 {
 353         if (TG(header_vec)) {
 354                 /* free status_line */
 355                 free(TG(header_vec)[0].iov_base);
 356                 free(TG(header_vec));
 357         }
 358         if (SG(request_info).query_string)
 359                 free(SG(request_info).query_string);
 360         free(SG(request_info).request_uri);
 361         free(SG(request_info).path_translated);
 362 }
 363 
 364 #if 0
 365 static void *separate_thread(void *bla)
 366 {
 367         int fd;
 368         int i = 0;
 369         
 370         fd = (int) bla;
 371 
 372         while (i++ < 5) {
 373                 send(fd, "test<br />\n", 9, 0);
 374                 sleep(1);
 375         }
 376         
 377         tux(TUX_ACTION_CONTINUE_REQ, (user_req_t *) fd);
 378         /* We HAVE to trigger some event on the fd. Otherwise
 379            fast_thread won't wake up, so that the eventloop
 380            won't be entered -> TUX hangs */
 381         shutdown(fd, 2);
 382         pthread_exit(NULL);
 383 }
 384 #endif
 385 
 386 int TUXAPI_handle_events(user_req_t *req)
 387 {
 388         TSRMLS_FETCH();
 389 
 390         if (req->event == PHP_TUX_BACKGROUND_CONN) {
 391                 tux_closed_conn(req->sock);
 392                 return tux(TUX_ACTION_FINISH_CLOSE_REQ, req);
 393         }
 394         
 395         TG(req) = req;
 396         TG(tux_action) = TUX_ACTION_FINISH_CLOSE_REQ;
 397         
 398         tux_request_ctor(TSRMLS_C);
 399 
 400         tux_module_main(TSRMLS_C);
 401 
 402         tux_request_dtor(TSRMLS_C);
 403 
 404         return tux(TG(tux_action), req);
 405 }
 406 
 407 void tux_register_on_close(void (*arg)(int)) 
 408 {
 409         TG(on_close) = arg;
 410 }
 411 
 412 void tux_closed_conn(int fd)
 413 {
 414         TSRMLS_FETCH();
 415 
 416         if (TG(on_close)) TG(on_close)(fd);
 417 }
 418 
 419 int tux_get_fd(void)
 420 {
 421         TSRMLS_FETCH();
 422         
 423         return TG(req)->sock;
 424 }
 425 
 426 void tux_set_dont_close(void)
 427 {
 428         TSRMLS_FETCH();
 429 
 430         TG(req)->event = PHP_TUX_BACKGROUND_CONN;
 431         tux(TUX_ACTION_POSTPONE_REQ, TG(req));
 432         TG(tux_action) = TUX_ACTION_EVENTLOOP;
 433 }
 434 
 435 void TUXAPI_init(void)
 436 {
 437         sapi_startup(&tux_sapi_module);
 438         tux_sapi_module.startup(&tux_sapi_module);
 439         SG(server_context) = (void *) 1;
 440 }
 441 
 442 void doesnotmatter_fini(void)
 443 {
 444         if (SG(server_context) != NULL) {
 445                 tux_sapi_module.shutdown(&tux_sapi_module);
 446                 sapi_shutdown();
 447         }
 448 }
 449 
 450 /*
 451  * Local variables:
 452  * tab-width: 4
 453  * c-basic-offset: 4
 454  * End:
 455  * vim600: sw=4 ts=4 fdm=marker
 456  * vim<600: sw=4 ts=4
 457  */

/* [<][>][^][v][top][bottom][index][help] */