Skip to content

Commit cdc448f

Browse files
committed
Optimization of synchronization when sending HTTP/2 frames
1 parent 34afd97 commit cdc448f

File tree

2 files changed

+41
-54
lines changed

2 files changed

+41
-54
lines changed

src/server/protocol/ServerHttp2.cpp

Lines changed: 33 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ namespace HttpServer
4040
return streams.emplace(streamId, Http2::IncStream(streamId, conn) ).first->second;
4141
}
4242

43-
static void sendWindowUpdate(const Socket::Adapter &sock, const std::chrono::milliseconds &timeout, Http2::IncStream &stream, const uint32_t size) noexcept
43+
static void sendWindowUpdate(const Socket::Adapter &sock, const std::chrono::milliseconds &timeout, const Http2::IncStream &stream, const uint32_t size) noexcept
4444
{
4545
std::array<uint8_t, Http2::FRAME_HEADER_SIZE + sizeof(uint32_t)> buf;
4646
uint8_t *addr = buf.data();
@@ -49,6 +49,8 @@ namespace HttpServer
4949

5050
*reinterpret_cast<uint32_t *>(addr) = ::htonl(size);
5151

52+
const std::unique_lock<std::mutex> lock(stream.conn.sync.mtx);
53+
5254
sock.nonblock_send(buf.data(), buf.size(), timeout);
5355
}
5456

@@ -305,18 +307,22 @@ namespace HttpServer
305307
return Http2::ErrorCode::NO_ERROR;
306308
}
307309

308-
static void ping(const Socket::Adapter &sock, const struct Request &req, const uint64_t pingData)
310+
static void ping(const Socket::Adapter &sock, const std::chrono::milliseconds &timeout, Http2::ConnectionData &conn, const uint64_t pingData)
309311
{
310312
constexpr uint32_t frame_size = sizeof(uint64_t);
311313

312314
std::array<uint8_t, Http2::FRAME_HEADER_SIZE + frame_size> buf;
313315
uint8_t *addr = buf.data();
314316

315-
addr = setHttp2FrameHeader(addr, frame_size, Http2::FrameType::PING, Http2::FrameFlag::ACK, 0);
317+
constexpr uint32_t stream_id = 0;
318+
319+
addr = setHttp2FrameHeader(addr, frame_size, Http2::FrameType::PING, Http2::FrameFlag::ACK, stream_id);
316320

317321
*reinterpret_cast<uint64_t *>(addr) = pingData;
318322

319-
sock.nonblock_send(buf.data(), buf.size(), req.timeout);
323+
const std::unique_lock<std::mutex> lock(conn.sync.mtx);
324+
325+
sock.nonblock_send(buf.data(), buf.size(), timeout);
320326
}
321327

322328
static Http2::ErrorCode parseHttp2Ping(Http2::FrameMeta &meta)
@@ -374,21 +380,23 @@ namespace HttpServer
374380
return Http2::ErrorCode::NO_ERROR;
375381
}
376382

377-
static void rstStream(const Socket::Adapter &sock, const std::chrono::milliseconds &timeout, const uint32_t streamId, const Http2::ErrorCode errorCode)
383+
static void rstStream(const Socket::Adapter &sock, const std::chrono::milliseconds &timeout, Http2::IncStream &stream, const Http2::ErrorCode errorCode)
378384
{
379385
constexpr uint32_t frame_size = sizeof(uint32_t);
380386

381387
std::array<uint8_t, Http2::FRAME_HEADER_SIZE + frame_size> buf;
382388
uint8_t *addr = buf.data();
383389

384-
addr = setHttp2FrameHeader(addr, frame_size, Http2::FrameType::RST_STREAM, Http2::FrameFlag::EMPTY, streamId);
390+
addr = setHttp2FrameHeader(addr, frame_size, Http2::FrameType::RST_STREAM, Http2::FrameFlag::EMPTY, stream.stream_id);
385391

386392
*reinterpret_cast<uint32_t *>(addr) = ::htonl(static_cast<const uint32_t>(errorCode) );
387393

394+
const std::unique_lock<std::mutex> lock(stream.conn.sync.mtx);
395+
388396
sock.nonblock_send(buf.data(), buf.size(), timeout);
389397
}
390398

391-
static void sendSettings(const Socket::Adapter &sock, const struct Request &req, const uint8_t *src, const uint8_t *end)
399+
static void sendSettings(const Socket::Adapter &sock, const std::chrono::milliseconds &timeout, Http2::ConnectionData &conn, const uint8_t *src, const uint8_t *end)
392400
{
393401
const uint32_t frame_size = end - src;
394402

@@ -402,10 +410,12 @@ namespace HttpServer
402410

403411
std::copy(src, end, addr);
404412

405-
sock.nonblock_send(buf.data(), buf.size(), req.timeout);
413+
const std::unique_lock<std::mutex> lock(conn.sync.mtx);
414+
415+
sock.nonblock_send(buf.data(), buf.size(), timeout);
406416
}
407417

408-
static void goAway(const Socket::Adapter &sock, const std::chrono::milliseconds &timeout, const uint32_t lastStreamId, const Http2::ErrorCode errorCode)
418+
static void goAway(const Socket::Adapter &sock, const std::chrono::milliseconds &timeout, Http2::ConnectionData &conn, const uint32_t lastStreamId, const Http2::ErrorCode errorCode)
409419
{
410420
constexpr uint32_t frame_size = sizeof(uint32_t) * 2;
411421

@@ -418,6 +428,8 @@ namespace HttpServer
418428
*reinterpret_cast<uint32_t *>(addr) = ::htonl(static_cast<const uint32_t>(lastStreamId) );
419429
*reinterpret_cast<uint32_t *>(addr + sizeof(uint32_t) ) = ::htonl(static_cast<const uint32_t>(errorCode) );
420430

431+
const std::unique_lock<std::mutex> lock(conn.sync.mtx);
432+
421433
sock.nonblock_send(buf.data(), buf.size(), timeout);
422434
}
423435

@@ -446,7 +458,7 @@ namespace HttpServer
446458
return 0 == compare;
447459
}
448460

449-
static void sendEmptySettings(const Socket::Adapter &sock, const std::chrono::milliseconds &timeout, const Http2::FrameFlag flags)
461+
static void sendEmptySettings(const Socket::Adapter &sock, const std::chrono::milliseconds &timeout, Http2::ConnectionData &conn, const Http2::FrameFlag flags)
450462
{
451463
constexpr uint32_t frame_size = 0;
452464

@@ -457,21 +469,7 @@ namespace HttpServer
457469

458470
addr = setHttp2FrameHeader(addr, frame_size, Http2::FrameType::SETTINGS, flags, stream_id);
459471

460-
sock.nonblock_send(buf.data(), buf.size(), timeout);
461-
}
462-
463-
static void windowUpdate(const Socket::Adapter &sock, const std::chrono::milliseconds &timeout)
464-
{
465-
constexpr uint32_t frame_size = 4;
466-
467-
std::array<uint8_t, Http2::FRAME_HEADER_SIZE + frame_size> buf;
468-
uint8_t *addr = buf.data();
469-
470-
constexpr uint32_t stream_id = 0;
471-
472-
addr = setHttp2FrameHeader(addr, frame_size, Http2::FrameType::WINDOW_UPDATE, Http2::FrameFlag::EMPTY, stream_id);
473-
474-
*reinterpret_cast<uint32_t *>(addr) = ::htonl(static_cast<const uint32_t>(1 << 16) - 1);
472+
const std::unique_lock<std::mutex> lock(conn.sync.mtx);
475473

476474
sock.nonblock_send(buf.data(), buf.size(), timeout);
477475
}
@@ -512,22 +510,22 @@ namespace HttpServer
512510
ServerProtocol *ServerHttp2::process()
513511
{
514512
struct Request req;
515-
req.timeout = std::chrono::milliseconds(5000);
513+
req.timeout = std::chrono::milliseconds(15000);
516514
req.protocol_variant = Transfer::ProtocolVariant::HTTP_2;
517515

518-
sendEmptySettings(this->sock, req.timeout, Http2::FrameFlag::EMPTY);
516+
Http2::ConnectionData conn;
517+
518+
sendEmptySettings(this->sock, req.timeout, conn, Http2::FrameFlag::EMPTY);
519519

520520
if (false == getClientPreface(this->sock, req.timeout) )
521521
{
522522
constexpr uint32_t last_stream_id = 0;
523523

524-
goAway(this->sock, req.timeout, last_stream_id, Http2::ErrorCode::PROTOCOL_ERROR);
524+
goAway(this->sock, req.timeout, conn, last_stream_id, Http2::ErrorCode::PROTOCOL_ERROR);
525525

526526
return this;
527527
}
528528

529-
Http2::ConnectionData conn;
530-
531529
conn.client_settings = Http2::ConnectionSettings::defaultSettings();
532530
conn.server_settings = Http2::ConnectionSettings::defaultSettings();
533531

@@ -565,7 +563,7 @@ namespace HttpServer
565563

566564
if (Http2::StreamState::CLOSED == stream.state)
567565
{
568-
rstStream(this->sock, req.timeout, stream.stream_id, Http2::ErrorCode::STREAM_CLOSED);
566+
rstStream(this->sock, req.timeout, stream, Http2::ErrorCode::STREAM_CLOSED);
569567

570568
continue;
571569
}
@@ -646,7 +644,7 @@ namespace HttpServer
646644
conn.decoding_dynamic_table.changeHeaderTableSize(conn.client_settings.header_table_size);
647645
conn.decoding_dynamic_table.changeMaxHeaderListSize(conn.client_settings.max_header_list_size);
648646

649-
sendEmptySettings(this->sock, req.timeout, Http2::FrameFlag::ACK);
647+
sendEmptySettings(this->sock, req.timeout, conn, Http2::FrameFlag::ACK);
650648
}
651649

652650
break;
@@ -664,7 +662,7 @@ namespace HttpServer
664662
{
665663
const uint64_t ping_data = *reinterpret_cast<const uint64_t *>(addr);
666664

667-
ping(this->sock, req, ping_data);
665+
ping(this->sock, req.timeout, conn, ping_data);
668666
}
669667

670668
break;
@@ -687,7 +685,7 @@ namespace HttpServer
687685
{
688686
stream.state = Http2::StreamState::CLOSED;
689687

690-
rstStream(this->sock, req.timeout, meta.stream_id, result);
688+
rstStream(this->sock, req.timeout, stream, result);
691689

692690
// TODO: remove closed stream(s) from unordered map
693691
}
@@ -718,7 +716,7 @@ namespace HttpServer
718716
conn.sync.event.wait();
719717
}
720718

721-
goAway(this->sock, req.timeout, last_stream_id, Http2::ErrorCode::NO_ERROR);
719+
goAway(this->sock, req.timeout, conn, last_stream_id, Http2::ErrorCode::NO_ERROR);
722720

723721
for (auto &pair : streams)
724722
{

src/server/protocol/ServerHttp2Protocol.cpp

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -53,16 +53,9 @@ namespace HttpServer
5353

5454
this->stream->setHttp2FrameHeader(reinterpret_cast<uint8_t *>(buf.data() ), frame_size, Http2::FrameType::HEADERS, flags);
5555

56-
this->stream->lock();
56+
const std::unique_lock<std::mutex> lock(this->stream->conn.sync.mtx);
5757

58-
auto const is_sended = this->sock.nonblock_send(buf.data(), buf.size(), timeout) > 0; // >= 0;
59-
60-
if (endStream || false == is_sended)
61-
{
62-
this->stream->unlock();
63-
}
64-
65-
return is_sended;
58+
return this->sock.nonblock_send(buf.data(), buf.size(), timeout) > 0; // >= 0;
6659
}
6760

6861
long ServerHttp2Protocol::sendData(const void *src, size_t size, const std::chrono::milliseconds &timeout, DataTransfer *dt) const
@@ -128,9 +121,7 @@ namespace HttpServer
128121
++cur;
129122
}
130123

131-
const Http2::FrameType frame_type = Http2::FrameType::DATA;
132-
133-
this->stream->setHttp2FrameHeader(buf.data(), frame_size, frame_type, flags);
124+
this->stream->setHttp2FrameHeader(buf.data(), frame_size, Http2::FrameType::DATA, flags);
134125

135126
std::copy(data, data + data_size, buf.begin() + cur);
136127

@@ -139,7 +130,11 @@ namespace HttpServer
139130
std::fill(buf.end() - padding, buf.end(), 0);
140131
}
141132

142-
long sended = this->sock.nonblock_send(buf.data(), buf.size(), timeout);
133+
this->stream->lock();
134+
135+
const long sended = this->sock.nonblock_send(buf.data(), buf.size(), timeout);
136+
137+
this->stream->unlock();
143138

144139
if (sended <= 0)
145140
{
@@ -155,11 +150,6 @@ namespace HttpServer
155150
size -= data_size;
156151
}
157152

158-
if (0 >= send_size || dt->full_size == dt->send_total)
159-
{
160-
this->stream->unlock();
161-
}
162-
163153
return send_size;
164154
}
165155

@@ -192,4 +182,3 @@ namespace HttpServer
192182
Utils::unpackContainer(req.outgoing_headers, reinterpret_cast<const uint8_t *>(src) );
193183
}
194184
};
195-

0 commit comments

Comments
 (0)