Annotation of embedaddon/php/sapi/tux/php_tux.c, revision 1.1
1.1 ! misho 1: /*
! 2: +----------------------------------------------------------------------+
! 3: | PHP Version 5 |
! 4: +----------------------------------------------------------------------+
! 5: | Copyright (c) 1997-2012 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: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>