acl/app/wizard_demo/httpd_proxy/http_transfer.cpp

283 lines
6.3 KiB
C++
Raw Normal View History

2022-01-19 23:47:53 +08:00
#include "stdafx.h"
#include "http_transfer.h"
2022-08-26 17:51:41 +08:00
http_transfer::http_transfer(acl::sslbase_conf* ssl_conf, acl::http_method_t method,
request_t& req, response_t& res, int port)
: ssl_conf_(ssl_conf)
2022-01-24 18:36:08 +08:00
, method_(method)
, req_(req)
2022-01-19 23:47:53 +08:00
, res_(res)
2022-08-26 17:51:41 +08:00
, port_(port)
2022-01-24 18:36:08 +08:00
, client_(NULL)
2022-03-31 18:35:14 +08:00
{
box_ = new acl::fiber_tbox<bool>;
res_client_ = res_.getClient();
2022-03-31 18:35:14 +08:00
}
2022-01-19 23:47:53 +08:00
2022-01-24 18:36:08 +08:00
http_transfer::~http_transfer(void) {
delete client_;
2022-03-31 18:35:14 +08:00
delete box_;
2022-01-19 23:47:53 +08:00
}
2022-01-24 18:36:08 +08:00
void http_transfer::wait(bool* keep_alive) {
2022-03-31 18:35:14 +08:00
bool* res = box_->pop();
2022-01-24 18:36:08 +08:00
assert(res);
*keep_alive = *res;
delete res;
2022-01-19 23:47:53 +08:00
}
2022-08-26 21:42:14 +08:00
static int nwait = 0;
2022-01-19 23:47:53 +08:00
void http_transfer::run(void) {
2022-08-29 17:09:02 +08:00
nwait++;
2022-01-24 18:36:08 +08:00
bool* res = new bool;
switch (method_) {
case acl::HTTP_METHOD_GET:
*res = transfer_get();
break;
case acl::HTTP_METHOD_POST:
*res = transfer_post();
break;
default:
logger_error("not support method: %d", (int) method_);
*res = false;
break;
}
2022-08-29 17:09:02 +08:00
nwait--;
2022-08-26 21:42:14 +08:00
printf(">>>>nwait=%d\n", nwait);
2022-03-31 18:35:14 +08:00
box_->push(res);
2022-01-24 18:36:08 +08:00
}
2022-08-26 17:51:41 +08:00
bool http_transfer::setup_ssl(acl::socket_stream& conn,
acl::sslbase_conf& ssl_conf, const char* host)
{
acl::sslbase_io* hook = (acl::sslbase_io*) conn.get_hook();
if (hook != NULL) {
logger("fd=%d, already in ssl status", conn.sock_handle());
return true;
}
2022-09-06 09:48:25 +08:00
// <20><><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9> SSL <20><>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA> SSL IO <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD> ssl io <20>滻 stream <20><>Ĭ<EFBFBD>ϵĵײ<C4B5> IO <20><><EFBFBD><EFBFBD>
2022-08-26 17:51:41 +08:00
logger("begin setup ssl hook...");
2022-09-06 09:48:25 +08:00
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> SSL <20><><EFBFBD>ַ<EFBFBD>ʽ
2022-08-26 17:51:41 +08:00
acl::sslbase_io* ssl = ssl_conf.create(false);
2022-09-06 09:48:25 +08:00
// <20><><EFBFBD><EFBFBD> SSL SNI, <20>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>֤<EFBFBD><D6A4>
2022-08-26 17:51:41 +08:00
ssl->set_sni_host(host);
if (conn.setup_hook(ssl) == ssl) {
logger_error("setup_hook error, fd=%d", conn.sock_handle());
ssl->destroy();
return false;
}
if (!ssl->handshake()) {
logger_error("ssl handshake failed, fd=%d", conn.sock_handle());
2022-08-26 21:42:14 +08:00
ssl->destroy();
2022-08-26 17:51:41 +08:00
return false;
}
if (!ssl->handshake_ok()) {
logger("handshake trying again, fd=%d", conn.sock_handle());
2022-08-26 21:42:14 +08:00
ssl->destroy();
2022-08-26 17:51:41 +08:00
return false;
}
logger("handshake_ok, fd=%d", conn.sock_handle());
return true;
}
bool http_transfer::open_peer(request_t& req, acl::socket_stream& conn)
2022-01-24 18:36:08 +08:00
{
const char* host = req.getRemoteHost();
2022-01-24 18:36:08 +08:00
if (host == NULL || *host == 0) {
logger_error("no Host in request head");
return false;
}
acl::string buf(host);
char* ptr = strrchr(buf.c_str(), ':');
if (ptr != NULL && *(ptr + 1) != 0) {
*ptr++ = 0;
int port = atoi(ptr);
if (port > 0 && port < 65535) {
port_ = port;
}
}
acl::string addr;
addr.format("%s|%d", buf.c_str(), port_);
2022-08-26 21:42:14 +08:00
if (!conn.open(addr, 5, 5)) {
logger_error("connect %s error %s",
addr.c_str(), acl::last_serror());
return false;
2022-01-24 18:36:08 +08:00
}
2022-08-26 17:51:41 +08:00
logger("connect %s ok, fd=%d, use ssl=%s", addr.c_str(),
conn.sock_handle(), ssl_conf_ ? "yes" : "no");
if (ssl_conf_ && !setup_ssl(conn, *ssl_conf_, host)) {
logger_error("setup ssl error!");
return false;
}
bool is_request = true, unzip = false, fixed_stream = true;
client_ = new acl::http_client(&conn, is_request, unzip, fixed_stream);
return true;
2022-01-24 18:36:08 +08:00
}
bool http_transfer::transfer_request_head(acl::socket_stream& conn) {
2022-01-24 18:36:08 +08:00
acl::string header;
req_.sprint_header(header, NULL);
2022-01-24 18:36:08 +08:00
if (header.empty()) {
logger_error("http request head empty");
return false;
}
header += "\r\n";
if (conn.write(header) == -1) {
2022-01-24 18:36:08 +08:00
logger_error("write request header error");
return false;
}
2022-08-29 17:09:02 +08:00
logger_debug(DEBUG_REQ, 2, ">>>send head: [%s]", header.c_str());
2022-01-24 18:36:08 +08:00
return true;
}
bool http_transfer::transfer_request_body(acl::socket_stream& conn) {
long long length = req_.getContentLength();
2022-01-24 18:36:08 +08:00
if (length <= 0) {
return true;
}
long long n = 0;
char buf[8192];
2022-08-26 17:51:41 +08:00
acl::istream* in = &req_.getInputStream();
2022-01-24 18:36:08 +08:00
while (n < length) {
2022-08-26 17:51:41 +08:00
int ret = in->read(buf, sizeof(buf), false);
2022-01-24 18:36:08 +08:00
if (ret == -1) {
logger_error("read request body error");
return false;
}
if (conn.write(buf, ret) == -1) {
2022-01-24 18:36:08 +08:00
logger_error("send request body error");
return false;
}
n += ret;
}
return true;
}
bool http_transfer::transfer_get(void) {
if (!open_peer(req_, conn_)) {
2022-01-24 18:36:08 +08:00
logger_error("open server error");
return false;
}
if (!transfer_request_head(conn_)) {
2022-01-24 18:36:08 +08:00
logger_error("transfer_request_head error");
return false;
} else {
return transfer_response();
}
}
bool http_transfer::transfer_post(void) {
if (!open_peer(req_, conn_)) {
2022-01-24 18:36:08 +08:00
logger_error("open server error");
return false;
}
if (!transfer_request_head(conn_)) {
2022-01-24 18:36:08 +08:00
logger_error("transfer_request_head error");
return false;
} else if (!transfer_request_body(conn_)) {
2022-01-24 18:36:08 +08:00
logger_error("transfer_request_body error");
return false;
} else {
return transfer_response();
}
}
bool http_transfer::transfer_response(void) {
assert(client_);
if (!client_->read_head()) {
logger_error("read response head error");
return false;
}
2022-03-31 18:35:14 +08:00
bool keep_alive = false; // xxxx
client_->header_update("Connection", "Close");
2022-01-24 18:36:08 +08:00
acl::string header;
client_->sprint_header(header, NULL);
if (header.empty()) {
logger_error("response header empty");
return false;
}
header += "\r\n";
2022-08-29 17:09:02 +08:00
logger_debug(DEBUG_RES, 2, "response head:\r\n[%s]", header.c_str());
2022-01-24 18:36:08 +08:00
2022-08-26 17:51:41 +08:00
acl::ostream* out = &res_.getOutputStream();
if (out->write(header) == -1) {
2022-08-29 17:09:02 +08:00
logger_error("send response head error=%s", acl::last_serror());
2022-01-24 18:36:08 +08:00
return false;
}
2022-03-31 18:35:14 +08:00
//acl::http_client* out_client = res_->getClient();
//assert(out_client);
2022-01-24 18:36:08 +08:00
long long length = client_->body_length();
if (length == 0) {
2022-03-31 18:35:14 +08:00
return client_->is_server_keep_alive() && keep_alive;
2022-01-24 18:36:08 +08:00
}
HTTP_HDR_RES* hdr_res = client_->get_respond_head(NULL);
assert(hdr_res);
bool chunked = hdr_res->hdr.chunked ? true : false;
2022-01-24 18:36:08 +08:00
char buf[8192];
2022-01-24 18:36:08 +08:00
while (true) {
int ret = client_->read_body(buf, sizeof(buf));
if (ret <= 0) {
break;
2022-08-26 21:42:14 +08:00
} else if (!chunked) {
if (out->write(buf, ret) == -1) {
2022-08-29 17:09:02 +08:00
logger_error("send response body error=%s, rfd=%d, wfd=%d",
acl::last_serror(), client_->get_stream().sock_handle(),
res_client_->get_stream().sock_handle());
return false;
}
2022-08-26 21:42:14 +08:00
} else if (!res_client_->write_chunk(*out, buf, ret)) {
2022-08-29 17:09:02 +08:00
logger_error("reply chunk body error=%s, rfd=%d, wfd=%d",
acl::last_serror(), client_->get_stream().sock_handle(),
res_client_->get_stream().sock_handle());
2022-01-24 18:36:08 +08:00
return false;
}
}
if (chunked) {
2022-08-26 17:51:41 +08:00
if (!res_client_->write_chunk_trailer(*out)) {
2022-08-29 17:09:02 +08:00
logger_error("write chunked trailer error=%s, rfd=%d, wfd=%d",
acl::last_serror(), client_->get_stream().sock_handle(),
res_client_->get_stream().sock_handle());
return false;
}
2022-01-19 23:47:53 +08:00
}
return client_->is_server_keep_alive() && false;
2022-01-19 23:47:53 +08:00
}