diff options
author | Sascha Schumann <sas@php.net> | 2001-05-26 23:58:38 +0000 |
---|---|---|
committer | Sascha Schumann <sas@php.net> | 2001-05-26 23:58:38 +0000 |
commit | d342acc3a924240e069e785321f3c3b087206132 (patch) | |
tree | 053e1d77d031d8f821af0be1eab341c94a50f232 /sapi/tux/php_tux.c | |
parent | e264a407ebf338744f76a0dcf6759625c4793ebf (diff) | |
download | php-git-d342acc3a924240e069e785321f3c3b087206132.tar.gz |
Add TUX SAPI module
Diffstat (limited to 'sapi/tux/php_tux.c')
-rw-r--r-- | sapi/tux/php_tux.c | 431 |
1 files changed, 431 insertions, 0 deletions
diff --git a/sapi/tux/php_tux.c b/sapi/tux/php_tux.c new file mode 100644 index 0000000000..d083a1c3de --- /dev/null +++ b/sapi/tux/php_tux.c @@ -0,0 +1,431 @@ +/* + +----------------------------------------------------------------------+ + | PHP version 4.0 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2001 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Sascha Schumann <sascha@schumann.cx> | + +----------------------------------------------------------------------+ +*/ + +#include "php.h" +#include "SAPI.h" +#include "php_main.h" +#include "php_variables.h" + +#include "ext/standard/php_smart_str.h" + +#include "tuxmodule.h" + +#include <sys/uio.h> + +#if 0 +#include <pthread.h> +#endif + +void tux_closed_conn(int fd); + +enum { + PHP_TUX_BACKGROUND_CONN = 1 +}; + +typedef struct { + user_req_t *req; + void (*on_close)(int); + int tux_action; + struct iovec *header_vec; + int number_vec; +} php_tux_globals; + +static php_tux_globals tux_globals; + +#define TLS_D +#define TLS_DC +#define TLS_C +#define TLS_CC +#define TG(v) (tux_globals.v) +#define TLS_FETCH() + +static int sapi_tux_ub_write(const char *str, uint str_length) +{ + int n; + uint sent = 0; + TLS_FETCH(); + + /* combine headers and body */ + if (TG(number_vec)) { + struct iovec *vec = TG(header_vec); + + n = TG(number_vec); + vec[n].iov_base = (void *) str; + vec[n++].iov_len = str_length; + + if (writev(TG(req)->sock, vec, n) == -1 && errno == EPIPE) + php_handle_aborted_connection(); + + TG(number_vec) = 0; + return str_length; + } + + while (str_length > 0) { + n = send(TG(req)->sock, str, str_length, 0); + + if (n == -1 && errno == EPIPE) + php_handle_aborted_connection(); + if (n == -1 && errno == EAGAIN) + continue; + if (n <= 0) + return n; + + TG(req)->bytes_sent += n; + str += n; + sent += n; + str_length -= n; + } + + return sent; +} + +static int sapi_tux_send_headers(sapi_headers_struct *sapi_headers SLS_DC) +{ + char buf[1024]; + struct iovec *vec; + int n = 0; + int max_headers; + zend_llist_position pos; + sapi_header_struct *h; + size_t len; + char *status_line; + int locate_cl; + TLS_FETCH(); + + max_headers = 30; + snprintf(buf, 1023, "HTTP/1.1 %d NA\r\n", SG(sapi_headers).http_response_code); + + vec = malloc(sizeof(struct iovec) * max_headers); + + vec[n].iov_base = strdup(buf); + vec[n++].iov_len = strlen(buf); + + TG(req)->http_status = SG(sapi_headers).http_response_code; + TG(req)->bytes_sent += len; + + if (TG(tux_action) == TUX_ACTION_FINISH_CLOSE_REQ && TG(req)->http_version == HTTP_1_1) + locate_cl = 1; + else + locate_cl = 0; + + h = zend_llist_get_first_ex(&sapi_headers->headers, &pos); + while (h) { + if (locate_cl + && strncasecmp(h->header, "Content-length:", sizeof("Content-length:")-1) == 0) { + TG(tux_action) = TUX_ACTION_FINISH_REQ; + locate_cl = 0; + } + + vec[n].iov_base = h->header; + vec[n++].iov_len = h->header_len; + if (n >= max_headers - 3) { + max_headers *= 2; + vec = realloc(vec, sizeof(struct iovec) * max_headers); + } + vec[n].iov_base = "\r\n"; + vec[n++].iov_len = 2; + + h = zend_llist_get_next_ex(&sapi_headers->headers, &pos); + } + + vec[n].iov_base = "\r\n"; + vec[n++].iov_len = 2; + + TG(number_vec) = n; + TG(header_vec) = vec; + + + return SAPI_HEADER_SENT_SUCCESSFULLY; +} + +static int sapi_tux_read_post(char *buffer, uint count_bytes SLS_DC) +{ +#if 0 + int amount = 0; + TLS_FETCH(); + + TG(req)->objectlen = count_bytes; + TG(req)->object_addr = buffer; + if (tux(TUX_ACTION_READ_POST_DATA, TG(req))) + return 0; + + TG(read_post_data) = 1; + + return TG(req)->objectlen; +#else + return 0; +#endif +} + +static char *sapi_tux_read_cookies(SLS_D) +{ + TLS_FETCH(); + + return TG(req)->cookies; +} + +#define BUF_SIZE 512 +#define ADD_STRING(name) \ + php_register_variable(name, buf, track_vars_array ELS_CC PLS_CC) + +static void sapi_tux_register_variables(zval *track_vars_array ELS_DC SLS_DC PLS_DC) +{ + char buf[BUF_SIZE + 1]; + char *p; + TLS_FETCH(); + + + sprintf(buf, "Server: %s", TUXAPI_version); + sapi_add_header_ex(buf, strlen(buf), 1, 0); + php_register_variable("PHP_SELF", SG(request_info).request_uri, track_vars_array ELS_CC PLS_CC); + php_register_variable("SERVER_SOFTWARE", TUXAPI_version, track_vars_array ELS_CC PLS_CC); + php_register_variable("GATEWAY_INTERFACE", "CGI/1.1", track_vars_array ELS_CC PLS_CC); + php_register_variable("REQUEST_METHOD", (char *) SG(request_info).request_method, track_vars_array ELS_CC PLS_CC); + php_register_variable("DOCUMENT_ROOT", TUXAPI_docroot, track_vars_array ELS_CC PLS_CC); + php_register_variable("SERVER_NAME", TUXAPI_servername, track_vars_array ELS_CC PLS_CC); + php_register_variable("REQUEST_URI", SG(request_info).request_uri, track_vars_array ELS_CC PLS_CC); + php_register_variable("PATH_TRANSLATED", SG(request_info).path_translated, track_vars_array ELS_CC PLS_CC); + + p = inet_ntoa(TG(req)->client_host); + /* string representation of IPs are never larger than 512 bytes */ + if (p) { + memcpy(buf, p, strlen(p) + 1); + ADD_STRING("REMOTE_ADDR"); + ADD_STRING("REMOTE_HOST"); + } + + sprintf(buf, "%d", CGI_SERVER_PORT(TG(req))); + ADD_STRING("SERVER_PORT"); + +#if 0 + snprintf(buf, BUF_SIZE, "/%s", TG(hc)->pathinfo); + ADD_STRING("PATH_INFO"); + + snprintf(buf, BUF_SIZE, "/%s", TG(hc)->origfilename); + ADD_STRING("SCRIPT_NAME"); +#endif + +#define CONDADD(name, field) \ + if (TG(req)->field[0]) { \ + php_register_variable(#name, TG(req)->field, track_vars_array ELS_CC PLS_C); \ + } + + CONDADD(HTTP_REFERER, referer); + CONDADD(HTTP_USER_AGENT, user_agent); + CONDADD(HTTP_ACCEPT, accept); + CONDADD(HTTP_ACCEPT_ENCODING, accept_encoding); + CONDADD(HTTP_ACCEPT_LANGUAGE, accept_language); + CONDADD(HTTP_COOKIE, cookies); + CONDADD(CONTENT_TYPE, content_type); + +#if 0 + if (TG(hc)->contentlength != -1) { + sprintf(buf, "%ld", (long) TG(hc)->contentlength); + ADD_STRING("CONTENT_LENGTH"); + } +#endif + +#if 0 + if (TG(hc)->authorization[0]) + php_register_variable("AUTH_TYPE", "Basic", track_vars_array ELS_CC PLS_C); +#endif +} + +static sapi_module_struct tux_sapi_module = { + "tux", + "tux", + + php_module_startup, + php_module_shutdown_wrapper, + + NULL, /* activate */ + NULL, /* deactivate */ + + sapi_tux_ub_write, + NULL, + NULL, /* get uid */ + NULL, /* getenv */ + + php_error, + + NULL, + sapi_tux_send_headers, + NULL, + sapi_tux_read_post, + sapi_tux_read_cookies, + + sapi_tux_register_variables, + NULL, /* Log message */ + + NULL, /* Block interruptions */ + NULL, /* Unblock interruptions */ + + STANDARD_SAPI_MODULE_PROPERTIES +}; + +static void tux_module_main(TLS_D SLS_DC) +{ + zend_file_handle file_handle; + CLS_FETCH(); + ELS_FETCH(); + PLS_FETCH(); + + file_handle.type = ZEND_HANDLE_FILENAME; + file_handle.filename = SG(request_info).path_translated; + file_handle.free_filename = 0; + file_handle.opened_path = NULL; + + if (php_request_startup(CLS_C ELS_CC PLS_CC SLS_CC) == FAILURE) { + return; + } + + php_execute_script(&file_handle CLS_CC ELS_CC PLS_CC); + php_request_shutdown(NULL); +} + +static void tux_request_ctor(TLS_D SLS_DC) +{ + char buf[1024]; + int offset; + size_t filename_len; + size_t cwd_len; + smart_str s = {0}; + char *p; + + TG(header_vec) = NULL; + SG(request_info).query_string = strdup(TG(req)->query); + + smart_str_appends_ex(&s, "/", 1); + smart_str_appends_ex(&s, TG(req)->query, 1); + smart_str_0(&s); + p = strchr(s.c, '&'); + if (p) + *p = '\0'; + SG(request_info).path_translated = s.c; + + s.c = NULL; + smart_str_appendc_ex(&s, '/', 1); + smart_str_appends_ex(&s, TG(req)->objectname, 1); + smart_str_0(&s); + SG(request_info).request_uri = s.c; + SG(request_info).request_method = CGI_REQUEST_METHOD(TG(req)); + SG(sapi_headers).http_response_code = 200; + SG(request_info).content_type = TG(req)->content_type; + SG(request_info).content_length = 0; // TG(req)->contentlength; + +#if 0 + php_handle_auth_data(TG(hc)->authorization SLS_CC); +#endif +} + +static void tux_request_dtor(TLS_D SLS_DC) +{ + if (TG(header_vec)) + free(TG(header_vec)); + if (SG(request_info).query_string) + free(SG(request_info).query_string); + free(SG(request_info).request_uri); + free(SG(request_info).path_translated); +} + +#if 0 +static void *separate_thread(void *bla) +{ + int fd; + int i = 0; + + fd = (int) bla; + + while (i++ < 5) { + send(fd, "test<br>\n", 9, 0); + sleep(1); + } + + tux(TUX_ACTION_CONTINUE_REQ, (user_req_t *) fd); + /* We HAVE to trigger some event on the fd. Otherwise + fast_thread won't wake up, so that the eventloop + won't be entered -> TUX hangs */ + shutdown(fd, 2); + pthread_exit(NULL); +} +#endif + +int TUXAPI_handle_events(user_req_t *req) +{ + SLS_FETCH(); + TLS_FETCH(); + + if (req->event == PHP_TUX_BACKGROUND_CONN) { + tux_closed_conn(req->sock); + return tux(TUX_ACTION_FINISH_CLOSE_REQ, req); + } + + TG(req) = req; + TG(tux_action) = TUX_ACTION_FINISH_CLOSE_REQ; + + tux_request_ctor(TLS_C SLS_CC); + + tux_module_main(TLS_C SLS_CC); + + tux_request_dtor(TLS_C SLS_CC); + + return tux(TG(tux_action), req); +} + +void tux_register_on_close(void (*arg)(int)) +{ + TG(on_close) = arg; +} + +void tux_closed_conn(int fd) +{ + TLS_FETCH(); + + if (TG(on_close)) TG(on_close)(fd); +} + +int tux_get_fd(void) +{ + TLS_FETCH(); + + return TG(req)->sock; +} + +void tux_set_dont_close(void) +{ + TLS_FETCH(); + + TG(req)->event = PHP_TUX_BACKGROUND_CONN; + tux(TUX_ACTION_POSTPONE_REQ, TG(req)); + TG(tux_action) = TUX_ACTION_EVENTLOOP; +} + +void TUXAPI_init(void) +{ + sapi_startup(&tux_sapi_module); + tux_sapi_module.startup(&tux_sapi_module); + SG(server_context) = (void *) 1; +} + +void doesnotmatter_fini(void) +{ + if (SG(server_context) != NULL) { + tux_sapi_module.shutdown(&tux_sapi_module); + sapi_shutdown(); + } +} |