From 573a746cfbbd57e782acb3d540b2f5232bc3cac3 Mon Sep 17 00:00:00 2001 From: ltmit Date: Mon, 4 Jul 2022 20:21:36 +0800 Subject: [PATCH 1/2] add HTTP long-conn-session support --- include/co/http.h | 13 ++++++++++--- src/so/http.cc | 48 +++++++++++++++++++++++++++++++++++++++-------- src/so/http.h | 20 +++++++++++++++++++- 3 files changed, 69 insertions(+), 12 deletions(-) diff --git a/include/co/http.h b/include/co/http.h index 2a5a49a5a..e649c04ba 100644 --- a/include/co/http.h +++ b/include/co/http.h @@ -273,10 +273,17 @@ class __coapi Res { /** * set body of the response * - The body length will be zero if no body was set. + * @return success or not (If use 'send_body') */ - void set_body(const void* s, size_t n); - void set_body(const char* s) { this->set_body(s, strlen(s)); } - void set_body(const fastring& s) { this->set_body(s.data(), s.size()); } + bool set_body(const void* s, size_t n); + bool set_body(const char* s) { return this->set_body(s, strlen(s)); } + bool set_body(const fastring& s) { return this->set_body(s.data(), s.size()); } + + /** + * complete header generate and send http-body data + * @return 0: no error; -1: not support ; -2: IO error + */ + int send_body(const void* data, size_t n); private: http_res_t* _p; diff --git a/src/so/http.cc b/src/so/http.cc index 62bc5d328..ebf642612 100644 --- a/src/so/http.cc +++ b/src/so/http.cc @@ -471,7 +471,8 @@ const char* http_req_t::header(const char* key) const { } -void http_res_t::set_body(const void* s, size_t n) { +bool http_res_t::set_body(const void* s, size_t n) { + if(header_send>0) return false; body_size = n; if (status == 0) status = 200; buf->clear(); @@ -479,6 +480,25 @@ void http_res_t::set_body(const void* s, size_t n) { << "Content-Length: " << n << "\r\n" << header << "\r\n"; buf->append(s, n); + header_send=-1; // cannot call 'send_body' anymore + return true; +} + +int http_res_t::send_body(const void* data, size_t n) { + assert(pc_); + if(header_send<0) { + //use 'set_body', cannot use long-connection mode + return -1; + } + if(header_send==0) { //headers has not send yet + if (status == 0) status = 200; + (*buf) << version_str(version) << ' ' << status << ' ' << status_str(status) << "\r\n" + << header << "\r\n"; + if(pc_->send(buf->data(),buf->size(),FLG_http_send_timeout)<0) s_err=-1; + header_send=1; + } + if(pc_->send(data,n,FLG_http_send_timeout)<0) s_err=-1; + return s_err==0? 0 : -2; } const char* Req::header(const char* key) const { @@ -506,10 +526,15 @@ void Res::add_header(const char* k, int v) { _p->add_header(k, v); } -void Res::set_body(const void* s, size_t n) { - _p->set_body(s, n); +bool Res::set_body(const void* s, size_t n) { + return _p->set_body(s, n); } +int Res::send_body(const void* s, size_t n) { + return _p->send_body(s, n); +} + + Res::~Res() { if (_p) { _p->header.~fastring(); @@ -872,14 +897,21 @@ void ServerImpl::on_connection(tcp::Connection conn) { s.clear(); pres->buf = &s; + pres->pc_ = &conn; _on_req(req, res); - if (s.empty()) pres->set_body("", 0); + + if(pres->header_send!=1) { //no use http-long-connection Mode. + if (s.empty()) pres->set_body("", 0); - r = conn.send(s.data(), (int)s.size(), FLG_http_send_timeout); - if (r <= 0) goto send_err; + r = conn.send(s.data(), (int)s.size(), FLG_http_send_timeout); + if (r <= 0) goto send_err; + + s.resize(s.size() - pres->body_size); + HTTPLOG << "http send res: " << s; + }else { + need_close=true; + } - s.resize(s.size() - pres->body_size); - HTTPLOG << "http send res: " << s; if (need_close) { conn.close(); goto end; } }; diff --git a/src/so/http.h b/src/so/http.h index c06408067..c9fdc3bc4 100644 --- a/src/so/http.h +++ b/src/so/http.h @@ -2,6 +2,10 @@ #include "co/fastring.h" +namespace tcp{ +struct Connection; +} + namespace http { struct http_req_t { @@ -44,21 +48,35 @@ struct http_res_t { header << k << ": " << v << "\r\n"; } - void set_body(const void* s, size_t n); + bool set_body(const void* s, size_t n); void clear() { status = 0; buf = 0; header.clear(); body_size = 0; + + header_send=0; + s_err=-1; + pc_=nullptr; } + //for http long connection session + //User can call multiple times of 'send_body'. + //The 1st call will also pack response Header data and send! + int send_body(const void* data, size_t n); + // DO NOT change orders of the members here. uint32 status; uint32 version; fastring* buf; fastring header; size_t body_size; + + // new members for http long connection session implementation (like 'send_body') + tcp::Connection* pc_; + int header_send; + int s_err; }; int parse_http_req(fastring* buf, size_t size, http_req_t* req); From 27e1ccb923437e8cdae70656c00631d505cfcfa9 Mon Sep 17 00:00:00 2001 From: ltmit Date: Wed, 6 Jul 2022 10:58:10 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=A4=9A=E7=BA=BF?= =?UTF-8?q?=E7=A8=8B=E7=8E=AF=E5=A2=83unitest=E4=B8=ADmem-small=E5=A4=B1?= =?UTF-8?q?=E8=B4=A5=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- unitest/mem.cc | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/unitest/mem.cc b/unitest/mem.cc index 81b297075..7f4ba5c2e 100644 --- a/unitest/mem.cc +++ b/unitest/mem.cc @@ -17,24 +17,22 @@ DEF_test(mem) { } DEF_case(small) { - void* p = co::alloc(8); + void* p = co::alloc(2048); EXPECT_NE(p, (void*)0); *(uint32*)p = 7; EXPECT_EQ(*(uint32*)p, 7); + co::free(p, 2048); void* x = p; + p = co::alloc(8); + EXPECT_EQ(p, x); co::free(p, 8); p = co::alloc(72); - EXPECT_NE(p, (void*)0); EXPECT_EQ(p, x); co::free(p, 72); - p = co::alloc(2048); - EXPECT_EQ(p, x); - co::free(p, 2048); - p = co::alloc(4096); EXPECT_NE(p, (void*)0); EXPECT_NE(p, x);