1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
|
/* HTTP/HTTP2 Protocol Handler
*
* Author: Lu Qiuwen<[email protected]>
* Date: 2018-04-08
*
*/
#include <assert.h>
#include <http_parser.h>
#include <event2/bufferevent.h>
#include <evdns.h>
#include "pxyhttp.h"
#include "pxyconn.h"
static int __http_request_cb_on_url(http_parser *parser, const char *at, size_t length)
{
pxy_conn_ctx_t *ctx = (pxy_conn_ctx_t *) parser->data;
/* 复制URI,注意补齐String的\0结尾 */
ctx->http_uri = (char *) malloc(length + 1);
strncpy(ctx->http_uri, at, length);
ctx->http_uri[length] = '\0';
return 0;
}
static int __http_request_cb_on_header_field(http_parser *parser, const char *at, size_t length)
{
pxy_conn_ctx_t *ctx = (pxy_conn_ctx_t *) parser->data;
assert(ctx != NULL && at != NULL);
/* 处理Host字段,置Host为0xffffffff,在value回调函数中处理的value即为host字段 */
if (strncasecmp(at, "Host", length) == 0)
{
ctx->http_host = (char *) 0xffffffff;
goto __leave;
}
__leave:
return 0;
}
static int __http_request_cb_on_header_value(http_parser *parser, const char *at, size_t length)
{
pxy_conn_ctx_t *ctx = (pxy_conn_ctx_t *) parser->data;
assert(ctx != NULL && at != NULL);
/* 处理Host字段的值 */
if (ctx->http_host == (void *) 0xffffffff)
{
ctx->http_host = (char *) malloc(length + 1);
strncpy(ctx->http_host, at, length);
ctx->http_host[length] = '\0';
}
return 0;
}
static int __http_request_cb_on_headers_complete(http_parser *parser)
{
pxy_conn_ctx_t *ctx = (pxy_conn_ctx_t *) parser->data;
ctx->seen_req_header = 1;
return 0;
}
static int __http_resp_cb_on_status(http_parser *parser, const char *at, size_t length)
{
return 0;
}
static int __http_resp_cb_on_headers_complete(http_parser *parser)
{
pxy_conn_ctx_t *ctx = (pxy_conn_ctx_t *) parser->data;
/* HTTP状态码 */
asprintf(&ctx->http_status_code, "%d", parser->status_code);
ctx->seen_resp_header = 1;
return 0;
}
/* HTTP Request Handlers */
const static struct http_parser_settings __setting_http_parser_request =
{
nullptr, /* on_message_begin */
__http_request_cb_on_url, /* on_url */
nullptr, /* on_status */
__http_request_cb_on_header_field, /* on_header_field */
__http_request_cb_on_header_value, /* on_header_value */
__http_request_cb_on_headers_complete, /* on_headers_complete */
nullptr, /* on_body */
nullptr /* on_message_complete */
};
/* HTTP Response Handlers */
const static struct http_parser_settings __setting_http_parser_resp =
{
nullptr, /* on_message_begin */
nullptr, /* on_url */
__http_resp_cb_on_status, /* on_status */
nullptr, /* on_header_field */
nullptr, /* on_header_value */
__http_resp_cb_on_headers_complete, /* on_headers_complete */
nullptr, /* on_body */
nullptr /* on_message_complete */
};
int pxy_http_read_cb(pxy_conn_ctx_t *ctx, struct bufferevent *bev)
{
pxy_conn_desc_t *other = (bev == ctx->src.bev) ? &ctx->dst : &ctx->src;
int is_http_request = (bev == ctx->src.bev);
/* HTTP Parser Handler */
http_parser *http_parser_ctx = is_http_request ?
(http_parser *)ctx->http_request_parser_ctx :
(http_parser *)ctx->http_response_parser_ctx;
void **http_parser_ctx_ref = is_http_request ?
&ctx->http_request_parser_ctx :
&ctx->http_response_parser_ctx;
/* HTTP Passer Type */
enum http_parser_type http_parser_work_mode = is_http_request ?
HTTP_REQUEST :
HTTP_RESPONSE;
const struct http_parser_settings *http_parser_cb = is_http_request ?
&__setting_http_parser_request :
&__setting_http_parser_resp;
/* 第一次请求,解析器句柄为空,创建新的解析器上下文 */
if (http_parser_ctx == NULL)
{
http_parser_ctx = (http_parser *)malloc(sizeof(http_parser));
*http_parser_ctx_ref = http_parser_ctx;
http_parser_ctx->data = ctx;
http_parser_init(http_parser_ctx, http_parser_work_mode);
}
/* 已经处理了HTTP Header,转发其他数据 */
if (is_http_request && ctx->seen_req_header)
return 0;
if (!is_http_request && ctx->seen_resp_header)
return 0;
struct evbuffer *input_buffer = bufferevent_get_input(bev);
size_t input_buffer_len = evbuffer_get_length(input_buffer);
if (input_buffer_len == 0)
return 0;
/* 连续的副本,供http_parser扫描使用 */
char *__buffer_copy = (char *)malloc(input_buffer_len);
assert(__buffer_copy != NULL);
/* 从buffer中拷贝出来一个副本 */
ssize_t __buffer_len = evbuffer_copyout(input_buffer, __buffer_copy, input_buffer_len);
if (__buffer_len < 0) goto __error;
/* 送入HTTP解析器处理 */
if (http_parser_execute(http_parser_ctx, http_parser_cb, __buffer_copy, __buffer_len)
!= __buffer_len)
{
goto __error;
}
/* 判断此时HTTP头部是否完整,若完整,即可调用业务层处理,
* 每个HTTP事务仅在此调用一次业务层处理逻辑,调用结束后即可进入转发流程 */
if(is_http_request && ctx->seen_req_header)
{
//TODO: Call Biz
}
if(!is_http_request && ctx->seen_resp_header)
{
//TODO: Call Biz
}
__error:
free(__buffer_copy);
return -1;
}
|