Skip to content

Commit 0b6ff7e

Browse files
committed
Fixed bugs in the HTTP/2 protocol
1 parent 8a12878 commit 0b6ff7e

File tree

13 files changed

+193
-57
lines changed

13 files changed

+193
-57
lines changed

src/Init.cpp

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,18 @@ void destroySocketAdapter(Socket::Adapter *adapter)
2828
}
2929
}
3030

31+
std::string getClearPath(const std::string &path)
32+
{
33+
const size_t pos = path.find_first_of("?#");
34+
35+
if (std::string::npos == pos)
36+
{
37+
return path;
38+
}
39+
40+
return std::string(path.cbegin(), path.cbegin() + pos);
41+
}
42+
3143
static void getIncomingVars(std::unordered_multimap<std::string, std::string> &params, const std::string &uri)
3244
{
3345
const size_t start = uri.find('?');
@@ -37,10 +49,22 @@ static void getIncomingVars(std::unordered_multimap<std::string, std::string> &p
3749
return;
3850
}
3951

52+
const size_t finish = uri.find('#');
53+
54+
if (finish < start)
55+
{
56+
return;
57+
}
58+
4059
for (size_t var_pos = start + 1, var_end = 0; std::string::npos != var_end; var_pos = var_end + 1)
4160
{
4261
var_end = uri.find('&', var_pos);
4362

63+
if (var_end > finish)
64+
{
65+
var_end = std::string::npos;
66+
}
67+
4468
size_t delimiter = uri.find('=', var_pos);
4569

4670
if (delimiter >= var_end)
@@ -140,13 +164,16 @@ bool initServerObjects(HttpClient::Request *procRequest, HttpClient::Response *p
140164
std::deque<std::pair<std::string, std::string> > dynamic_table;
141165
src = Utils::unpackVector(dynamic_table, src);
142166

167+
std::mutex *mtx = nullptr;
168+
src = Utils::unpackPointer(reinterpret_cast<void **>(&mtx), src);
169+
143170
src = Utils::unpackContainer(headers, src);
144171
src = Utils::unpackContainer(data, src);
145172
src = Utils::unpackFilesIncoming(files, src);
146173

147174
getIncomingVars(params, path);
148175

149-
Http2::OutStream *stream = new Http2::OutStream(stream_id, settings, Http2::DynamicTable(settings.header_table_size, settings.max_header_list_size, std::move(dynamic_table) ) );
176+
Http2::OutStream *stream = new Http2::OutStream(stream_id, settings, Http2::DynamicTable(settings.header_table_size, settings.max_header_list_size, std::move(dynamic_table) ), mtx);
150177

151178
prot = new HttpClient::ClientHttp2(socket_adapter, stream);
152179

src/Init.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
Socket::Adapter *createSocketAdapter(Transfer::app_request *request, void *addr);
99
void destroySocketAdapter(Socket::Adapter *adapter);
1010

11+
std::string getClearPath(const std::string &path);
12+
1113
bool initServerObjects(HttpClient::Request *procRequest, HttpClient::Response *procResponse, const Transfer::app_request *request, Socket::Adapter *socket_adapter);
1214
void cleanProtocolData(HttpClient::Response *response);
1315

src/Main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ DLLEXPORT int application_call(Transfer::app_request *request, Transfer::app_res
2727
return EXIT_FAILURE;
2828
}
2929

30-
const std::string absolute_path = proc_request.document_root + proc_request.path;
30+
const std::string absolute_path = proc_request.document_root + getClearPath(proc_request.path);
3131

3232
int result = EXIT_SUCCESS;
3333

src/client/protocol/ClientHttp2.cpp

Lines changed: 39 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -42,50 +42,54 @@ namespace HttpClient
4242
{
4343
std::vector<char> buf;
4444
buf.reserve(4096);
45+
buf.resize(Http2::FRAME_HEADER_SIZE + sizeof(uint8_t) );
4546

4647
headers.emplace(headers.begin(), ":status", std::to_string(static_cast<int>(status) ) );
4748

4849
HPack::pack(buf, headers, this->stream->dynamic_table);
4950

50-
uint32_t data_size = buf.size();
51+
uint32_t data_size = buf.size() - Http2::FRAME_HEADER_SIZE - sizeof(uint8_t);
5152

5253
const uint8_t padding = getPaddingSize(data_size);
5354
const uint16_t padding_size = padding + sizeof(uint8_t);
5455

55-
if (padding_size)
56+
if (data_size + padding_size > this->stream->settings.max_frame_size)
5657
{
57-
if (data_size + padding_size > this->stream->settings.max_frame_size)
58-
{
59-
data_size = this->stream->settings.max_frame_size - padding_size;
60-
}
58+
data_size = this->stream->settings.max_frame_size - padding_size;
6159
}
6260

6361
const size_t frame_size = data_size + padding_size;
6462

63+
buf.resize(frame_size + Http2::FRAME_HEADER_SIZE);
64+
6565
Http2::FrameFlag flags = Http2::FrameFlag::END_HEADERS;
6666

6767
if (endStream)
6868
{
6969
flags |= Http2::FrameFlag::END_STREAM;
7070
}
7171

72-
if (padding_size)
73-
{
74-
flags |= Http2::FrameFlag::PADDED;
72+
flags |= Http2::FrameFlag::PADDED;
7573

76-
buf.insert(buf.begin(), sizeof(uint8_t), padding);
74+
buf[Http2::FRAME_HEADER_SIZE] = padding;
7775

78-
if (padding)
79-
{
80-
buf.insert(buf.end(), padding, 0);
81-
}
76+
if (padding)
77+
{
78+
std::fill(buf.end() - padding, buf.end(), 0);
8279
}
8380

84-
buf.insert(buf.begin(), Http2::FRAME_HEADER_SIZE, 0);
85-
8681
this->stream->setHttp2FrameHeader(reinterpret_cast<uint8_t *>(buf.data() ), frame_size, Http2::FrameType::HEADERS, flags);
8782

88-
return this->sock->nonblock_send(buf.data(), buf.size(), timeout) > 0;
83+
this->stream->lock();
84+
85+
auto const is_sended = this->sock->nonblock_send(buf.data(), buf.size(), timeout) > 0;
86+
87+
if (endStream || false == is_sended)
88+
{
89+
this->stream->unlock();
90+
}
91+
92+
return is_sended;
8993
}
9094

9195
void ClientHttp2::sendWindowUpdate(const uint32_t size, const std::chrono::milliseconds &timeout) const
@@ -111,23 +115,20 @@ namespace HttpClient
111115

112116
while (total < size)
113117
{
114-
buf.resize(0);
115-
116118
size_t data_size = (size - total < this->stream->settings.max_frame_size) ? size - total : this->stream->settings.max_frame_size;
117119

118120
const uint8_t padding = getPaddingSize(data_size);
119121
const uint16_t padding_size = padding + sizeof(uint8_t);
120122

121-
if (padding_size)
123+
if (data_size + padding_size > this->stream->settings.max_frame_size)
122124
{
123-
if (data_size + padding_size > this->stream->settings.max_frame_size)
124-
{
125-
data_size = this->stream->settings.max_frame_size - padding_size;
126-
}
125+
data_size = this->stream->settings.max_frame_size - padding_size;
127126
}
128127

129128
const size_t frame_size = data_size + padding_size;
130129

130+
buf.resize(frame_size + Http2::FRAME_HEADER_SIZE);
131+
131132
if (static_cast<int32_t>(this->stream->window_size_out - this->stream->settings.max_frame_size) <= 0)
132133
{
133134
size_t update_size = this->stream->settings.initial_window_size + (size - total) - this->stream->window_size_out;
@@ -149,30 +150,33 @@ namespace HttpClient
149150
flags |= Http2::FrameFlag::END_STREAM;
150151
}
151152

153+
size_t cur = Http2::FRAME_HEADER_SIZE;
154+
152155
if (padding_size)
153156
{
154157
flags |= Http2::FrameFlag::PADDED;
155158

156-
buf.insert(buf.begin(), sizeof(uint8_t), padding);
157-
}
159+
buf[cur] = padding;
158160

159-
buf.insert(buf.begin(), Http2::FRAME_HEADER_SIZE, 0);
161+
++cur;
162+
}
160163

161164
const Http2::FrameType frame_type = Http2::FrameType::DATA;
162165

163166
this->stream->setHttp2FrameHeader(buf.data(), frame_size, frame_type, flags);
164167

165-
std::copy(data, data + data_size, std::back_inserter(buf) );
168+
std::copy(data, data + data_size, buf.begin() + cur);
166169

167170
if (padding)
168171
{
169-
buf.insert(buf.end(), padding, 0);
172+
std::fill(buf.end() - padding, buf.end(), 0);
170173
}
171174

172175
long sended = this->sock->nonblock_send(buf.data(), buf.size(), timeout);
173176

174177
if (sended <= 0)
175178
{
179+
total = 0;
176180
break;
177181
}
178182

@@ -182,6 +186,11 @@ namespace HttpClient
182186
total += data_size;
183187
}
184188

185-
return total;
189+
if (total == 0 || endStream)
190+
{
191+
this->stream->unlock();
192+
}
193+
194+
return static_cast<long>(total);
186195
}
187196
};

src/socket/AdapterTls.cpp

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,25 +63,36 @@ namespace Socket
6363

6464
long AdapterTls::nonblock_send_all(const void *buf, const size_t length, const std::chrono::milliseconds &timeout) const noexcept
6565
{
66-
size_t record_size = ::gnutls_record_get_max_size(this->session);
66+
// size_t record_size = ::gnutls_record_get_max_size(this->session);
67+
size_t record_size = length;
6768

6869
if (0 == record_size)
6970
{
7071
return -1;
7172
}
7273

74+
Socket sock(this->get_handle() );
75+
76+
// ::gnutls_record_set_timeout(this->session, static_cast<unsigned int>(timeout.count() ) );
77+
7378
size_t total = 0;
7479

7580
while (total < length)
7681
{
77-
::gnutls_record_set_timeout(this->session, static_cast<unsigned int>(timeout.count() ) );
78-
7982
if (record_size > length - total)
8083
{
8184
record_size = length - total;
8285
}
8386

84-
const long send_size = ::gnutls_record_send(this->session, reinterpret_cast<const uint8_t *>(buf) + total, record_size);
87+
// const long send_size = ::gnutls_record_send(this->session, reinterpret_cast<const uint8_t *>(buf) + total, record_size);
88+
89+
long send_size = 0;
90+
91+
do
92+
{
93+
sock.nonblock_send_sync();
94+
}
95+
while (GNUTLS_E_AGAIN == (send_size = ::gnutls_record_send(this->session, reinterpret_cast<const uint8_t *>(buf) + total, record_size) ) );
8596

8697
if (send_size < 0)
8798
{
@@ -111,7 +122,11 @@ namespace Socket
111122

112123
long AdapterTls::nonblock_recv(void *buf, const size_t length, const std::chrono::milliseconds &timeout) const noexcept
113124
{
114-
::gnutls_record_set_timeout(this->session, static_cast<const unsigned int>(timeout.count() ) );
125+
// ::gnutls_record_set_timeout(this->session, static_cast<const unsigned int>(timeout.count() ) );
126+
127+
Socket sock(this->get_handle() );
128+
sock.nonblock_recv_sync();
129+
115130
return ::gnutls_record_recv(this->session, buf, length);
116131
}
117132

src/socket/List.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ namespace Socket
265265

266266
do
267267
{
268-
struct ::sockaddr_in client_addr = {};
268+
::sockaddr_in client_addr {};
269269
socklen_t client_addr_len = sizeof(client_addr);
270270

271271
client_socket = ::accept(event.fd, reinterpret_cast<::sockaddr *>(&client_addr), &client_addr_len);
@@ -299,7 +299,7 @@ namespace Socket
299299

300300
do
301301
{
302-
struct ::sockaddr_in client_addr = {};
302+
::sockaddr_in client_addr {};
303303
socklen_t client_addr_len = sizeof(client_addr);
304304

305305
client_socket = ::accept(event.data.fd, reinterpret_cast<::sockaddr *>(&client_addr), &client_addr_len);

src/socket/Socket.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,29 @@ namespace Socket
314314
return recv_len;
315315
}
316316

317+
void Socket::nonblock_recv_sync() const noexcept
318+
{
319+
#ifdef WIN32
320+
WSAPOLLFD event = {
321+
this->socket_handle,
322+
POLLRDNORM | POLLRDBAND,
323+
0
324+
};
325+
326+
::WSAPoll(&event, 1, ~0);
327+
#elif POSIX
328+
struct ::pollfd event = {
329+
this->socket_handle,
330+
POLLIN,
331+
0
332+
};
333+
334+
::poll(&event, 1, ~0);
335+
#else
336+
#error "Undefine platform"
337+
#endif
338+
}
339+
317340
static long send_all(const System::native_socket_type socket_handle, const void *data, const size_t length) noexcept
318341
{
319342
size_t total = 0;

src/socket/Socket.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ namespace Socket
5151
long nonblock_recv(std::vector<std::string::value_type> &buf, const std::chrono::milliseconds &timeout) const noexcept;
5252
long nonblock_recv(void *buf, const size_t length, const std::chrono::milliseconds &timeout) const noexcept;
5353

54+
void nonblock_recv_sync() const noexcept;
55+
5456
long send(const std::string &buf) const noexcept;
5557
long send(const void *buf, const size_t length) const noexcept;
5658

src/system/System.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ namespace System
228228

229229
::FileTimeToSystemTime(&ftWrite, &stUtc);
230230

231-
struct ::tm tm_time {
231+
std::tm tm_time {
232232
stUtc.wSecond,
233233
stUtc.wMinute,
234234
stUtc.wHour,
@@ -240,11 +240,11 @@ namespace System
240240
-1
241241
};
242242

243-
*fileTime = ::mktime(&tm_time);
243+
*fileTime = std::mktime(&tm_time);
244244

245245
return true;
246246
#elif POSIX
247-
struct ::stat attrib;
247+
struct ::stat attrib {};
248248

249249
if (-1 == ::stat(filePath.c_str(), &attrib) )
250250
{
@@ -253,11 +253,11 @@ namespace System
253253

254254
*fileSize = attrib.st_size;
255255

256-
struct ::tm clock = {};
256+
std::tm clock {};
257257

258258
::gmtime_r(&(attrib.st_mtime), &clock);
259259

260-
*fileTime = ::mktime(&clock);
260+
*fileTime = std::mktime(&clock);
261261

262262
return true;
263263
#else
@@ -284,7 +284,7 @@ namespace System
284284
memory_name.erase(memory_name.begin() + pos, memory_name.end() );
285285
}
286286

287-
::TCHAR buf[MAX_PATH + 1] = {};
287+
::TCHAR buf[MAX_PATH + 1] {};
288288
::GetFullPathName(memory_name.c_str(), MAX_PATH, buf, nullptr);
289289

290290
#ifdef UNICODE

0 commit comments

Comments
 (0)