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>