ok
Direktori : /opt/alt/php70/usr/include/php/ext/swoole/ |
Current File : //opt/alt/php70/usr/include/php/ext/swoole/swoole_http.h |
/* +----------------------------------------------------------------------+ | Swoole | +----------------------------------------------------------------------+ | Copyright (c) 2012-2015 The Swoole Group | +----------------------------------------------------------------------+ | This source file is subject to version 2.0 of the Apache license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.apache.org/licenses/LICENSE-2.0.html | | If you did not receive a copy of the Apache2.0 license and are unable| | to obtain it through the world-wide-web, please send a note to | | license@swoole.com so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Tianfeng Han <mikan.tenny@gmail.com> | +----------------------------------------------------------------------+ */ #ifndef SWOOLE_HTTP_H_ #define SWOOLE_HTTP_H_ #ifdef __cplusplus extern "C" { #endif #include "thirdparty/swoole_http_parser.h" #include "thirdparty/multipart_parser.h" #ifdef SW_HAVE_ZLIB #include <zlib.h> #endif #ifdef SW_USE_HTTP2 #include "thirdparty/http2/nghttp2.h" #endif enum http_header_flag { HTTP_HEADER_SERVER = 1u << 1, HTTP_HEADER_CONNECTION = 1u << 2, HTTP_HEADER_CONTENT_LENGTH = 1u << 3, HTTP_HEADER_DATE = 1u << 4, HTTP_HEADER_CONTENT_TYPE = 1u << 5, HTTP_HEADER_TRANSFER_ENCODING = 1u << 6, HTTP_HEADER_ACCEPT_ENCODING = 1u << 7, }; enum http_compress_method { HTTP_COMPRESS_GZIP = 1, HTTP_COMPRESS_DEFLATE, HTTP_COMPRESS_BR, }; typedef struct { enum swoole_http_method method; int version; char *path; uint32_t path_len; const char *ext; uint32_t ext_len; uint8_t post_form_urlencoded; #ifdef SW_USE_HTTP2 swString *post_buffer; #endif uint32_t post_length; zval *zobject; zval *zserver; zval *zheader; zval *zget; zval *zpost; zval *zcookie; zval *zrequest; zval *zfiles; zval *ztmpfiles; zval _zobject; zval _zrequest; zval _zserver; zval _zheader; zval _zget; zval _zpost; zval _zfiles; zval _zcookie; zval _ztmpfiles; } http_request; typedef struct { enum swoole_http_method method; int version; int status; char* reason; zval *zobject; zval *zheader; zval *zcookie; zval *ztrailer; zval _zobject; zval _zheader; zval _zcookie; zval _ztrailer; } http_response; typedef struct { int fd; uint32_t end :1; uint32_t send_header :1; #ifdef SW_HAVE_ZLIB uint32_t enable_compression :1; #endif uint32_t chunk :1; uint32_t keepalive :1; uint32_t upgrade :1; uint32_t detached :1; #ifdef SW_HAVE_ZLIB int8_t compression_level; int8_t compression_method; #endif #ifdef SW_USE_HTTP2 void* stream; #endif http_request request; http_response response; swoole_http_parser parser; multipart_parser *mt_parser; uint16_t input_var_num; char *current_header_name; size_t current_header_name_len; char *current_input_name; char *current_form_data_name; size_t current_form_data_name_len; zval *current_multipart_header; } http_context; /** * WebSocket */ int swoole_websocket_onMessage(swServer *serv, swEventData *); int swoole_websocket_onHandshake(swServer *serv, swListenPort *port, http_context *); void swoole_websocket_onOpen(http_context *); void swoole_websocket_onRequest(http_context *); /** * Http Context */ http_context* swoole_http_context_new(int fd); void swoole_http_context_free(http_context *ctx); int swoole_http_parse_form_data(http_context *ctx, const char *boundary_str, int boundary_len); void swoole_http_parse_cookie(zval *array, const char *at, size_t length); #define swoole_http_server_array_init(name, class) SW_MAKE_STD_ZVAL(z##name);\ array_init(z##name);\ zend_update_property(swoole_http_##class##_ce, z##class##_object, ZEND_STRL(#name), z##name);\ ctx->class.z##name = sw_zend_read_property(swoole_http_##class##_ce, z##class##_object, ZEND_STRL(#name), 0);\ sw_copy_to_stack(ctx->class.z##name, ctx->class._z##name);\ zval_ptr_dtor(z##name);\ z##name = ctx->class.z##name; #define http_strncasecmp(const_str, at, length) ((length >= sizeof(const_str)-1) &&\ (strncasecmp(at, ZEND_STRL(const_str)) == 0)) #ifdef SW_USE_HTTP2 /** * Http v2 */ int swoole_http2_server_onFrame(swConnection *conn, swEventData *req); int swoole_http2_server_do_response(http_context *ctx, swString *body); void swoole_http2_server_session_free(swConnection *conn); int swoole_http2_server_ping(http_context *ctx); #endif extern zend_class_entry *swoole_http_server_ce; extern zend_class_entry *swoole_http_request_ce; extern zend_class_entry *swoole_http_response_ce; extern swString *swoole_http_buffer; #ifdef SW_HAVE_ZLIB extern swString *swoole_zlib_buffer; int swoole_http_response_compress(swString *body, int method, int level); void swoole_http_get_compression_method(http_context *ctx, const char *accept_encoding, size_t length); const char* swoole_http_get_content_encoding(http_context *ctx); static sw_inline voidpf php_zlib_alloc(voidpf opaque, uInt items, uInt size) { return (voidpf) safe_emalloc(items, size, 0); } static sw_inline void php_zlib_free(voidpf opaque, voidpf address) { efree((void *)address); } #endif static int http_parse_set_cookies(const char *at, size_t length, zval *cookies, zval *set_cookie_headers) { const char *key = at; zval val; size_t key_len = 0, val_len = 0; const char *p, *eof = at + length; // key p = (char *) memchr(at, '=', length); if (p) { key_len = p - at; } if (key_len == 0 || key_len >= length - 1) { swWarn("cookie key format is wrong"); return SW_ERR; } if (key_len > SW_HTTP_COOKIE_KEYLEN) { swWarn("cookie[%.8s...] name length %d is exceed the max name len %d", key, key_len, SW_HTTP_COOKIE_KEYLEN); return SW_ERR; } add_assoc_stringl_ex(set_cookie_headers, key, key_len, (char *) at, length); // val p++; eof = (char*) memchr(p, ';', at + length - p); if (!eof) { eof = at + length; } val_len = eof - p; if (val_len > SW_HTTP_COOKIE_VALLEN) { swWarn("cookie[%.*s]'s value[v=%.8s...] length %d is exceed the max value len %d", (int) key_len, key, p, val_len, SW_HTTP_COOKIE_VALLEN); return SW_ERR; } ZVAL_STRINGL(&val, p, val_len); Z_STRLEN(val) = php_url_decode(Z_STRVAL(val), val_len); add_assoc_zval_ex(cookies, at, key_len, &val); return SW_OK; } #ifdef __cplusplus } #endif #ifdef SW_USE_HTTP2 namespace swoole { namespace http2 { class headers { public: headers(size_t size) : size(size), index(0) { nvs = (nghttp2_nv *) ecalloc(size, sizeof(nghttp2_nv)); } inline nghttp2_nv* get() { return nvs; } inline size_t len() { return index; } void reserve_one() { index++; } inline void add( size_t index, const char *name, size_t name_len, const char *value, size_t value_len, const uint8_t flags = NGHTTP2_NV_FLAG_NONE) { if (likely(index < size || nvs[index].name == nullptr)) { nghttp2_nv *nv = &nvs[index]; name = zend_str_tolower_dup(name, name_len); // auto to lower nv->name = (uchar*) name; nv->namelen = name_len; nv->value = (uchar*) emalloc(value_len); memcpy(nv->value, value, value_len); nv->valuelen = value_len; nv->flags = flags | NGHTTP2_NV_FLAG_NO_COPY_NAME | NGHTTP2_NV_FLAG_NO_COPY_VALUE; swTraceLog(SW_TRACE_HTTP2,"name=(%zu)[%.*s], value=(%zu)[%.*s]", name_len, (int) name_len, name, value_len, (int) value_len, value); } else { swoole_php_fatal_error(E_WARNING, "unexpect http2 header [%.*s] (duplicated or overflow)", (int) name_len, name); } } inline void add( const char *name, size_t name_len, const char *value, size_t value_len, const uint8_t flags = NGHTTP2_NV_FLAG_NONE ) { add(index++, name, name_len, value, value_len, flags); } ~headers() { for (size_t i = 0; i < size; ++i) { if (likely(nvs[i].name/* && nvs[i].value */)) { efree((void *) nvs[i].name); efree((void *) nvs[i].value); } } efree(nvs); } private: nghttp2_nv *nvs; size_t size; size_t index; }; } } #endif #endif /* SWOOLE_HTTP_H_ */