Skip to content

Commit 19537a2

Browse files
committed
Added ssl support
1 parent 2745fea commit 19537a2

File tree

11 files changed

+163
-119
lines changed

11 files changed

+163
-119
lines changed

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,5 +94,4 @@ wget http://localhost/upload.wikimedia.org/wikipedia/commons/3/35/Tux.svg
9494

9595
## TODO
9696
- Add perfomance test
97-
- Add ssl support
98-
97+
- Add error handling on http external request

main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ void ParserArguments(int argc, char** argv) {
5151
continue;
5252
}
5353
if (strcmp(argv[i], "-hls") == 0) {
54-
Settings::UseCache = false;
54+
Settings::HLSMode = true;
5555
continue;
5656
}
5757
}

src/Dns.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ void Dns::AddFetchAAAARequest(struct Request *request, bool isHttps) {
6363
std::size_t pos = host.find("/");
6464
host = host.substr(0, pos);
6565
int port = 80;
66+
if (isHttps) {
67+
port = 443;
68+
}
6669

6770
if (std::regex_match(host, ipv4_regex_)) {
6871
pos = host.find(":");

src/Http.cpp

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
#include "Http.hpp"
22

3-
#pragma GCC diagnostic ignored "-Wpointer-arith"
4-
53
#include <arpa/inet.h>
64
#include <string.h>
75

@@ -38,8 +36,7 @@ void Http::SetStream(Stream *stream) { stream_ = stream; }
3836
void Http::AddFetchDataRequest(struct Request *req) {}
3937

4038
int Http::GetResourceType(char *header, int size) {
41-
// return RESOURCE_TYPE_STREAMING;
42-
return RESOURCE_TYPE_CACHE;
39+
return Settings::HLSMode? RESOURCE_TYPE_STREAMING : RESOURCE_TYPE_CACHE;
4340
}
4441

4542
int Http::FetchHeaderLength(char *header, int size) {
@@ -54,8 +51,3 @@ int Http::FetchHeaderLength(char *header, int size) {
5451
}
5552
return offset;
5653
}
57-
58-
bool Http::IsLastPacket(void *buffer, int size) {
59-
int result = memcmp(buffer + (size - ZERO_LENGTH), zero_, sizeof(zero_));
60-
return result == 0;
61-
}

src/Http.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ class Http {
3636
int GetResourceType(char *header, int size);
3737

3838
int FetchHeaderLength(char *header, int size);
39-
bool IsLastPacket(void *buffer, int size);
4039
private:
4140
void *zero_;
4241
};

src/HttpsClient.cpp

Lines changed: 147 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include "HttpsClient.hpp"
22

3+
#pragma GCC diagnostic ignored "-Wpointer-arith"
4+
35
#include <arpa/inet.h>
46
#include <openssl/err.h>
57
#include <unistd.h>
@@ -15,144 +17,196 @@ HttpsClient::HttpsClient() : Http() {
1517
OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
1618
}
1719

18-
bool HttpsClient::HandleFetchRequest(struct Request *request, bool ipv4) {
19-
/*
20-
std::string url((char *)request->iov[0].iov_base);
20+
bool HttpsClient::HandleFetchRequest(struct Request *inner, bool ipv4) {
21+
std::string url((char *)inner->iov[2].iov_base);
2122
url = url.substr(1);
2223
std::size_t pos = url.find("/");
2324
std::string host = url.substr(0, pos);
2425
std::string query = url.substr(pos);
2526

2627
Log(__FILE__, __LINE__) << query;
2728

28-
struct sockaddr_in6 *client =
29-
(struct sockaddr_in6 *)request->iov[4].iov_base;
30-
3129
const SSL_METHOD *method = TLS_client_method();
3230
SSL_CTX *ctx = SSL_CTX_new(method);
3331
if (!ctx) {
3432
Log(__FILE__, __LINE__, Log::kError) << "Error creating context ssl";
35-
cache_->ReleaseErrorAllWaitingRequest(request, 502);
36-
return 1;
33+
stream_->ReleaseErrorAllWaitingRequest(inner->resource_id, 502);
34+
return false;
3735
}
3836

3937
SSL *ssl = SSL_new(ctx);
4038
if (!ssl) {
4139
CloseSSL(-1, nullptr, ctx);
4240
Log(__FILE__, __LINE__, Log::kError) << "Error creating ssl";
43-
cache_->ReleaseErrorAllWaitingRequest(request, 502);
44-
Utils::ReleaseRequest(request);
45-
return -1;
41+
stream_->ReleaseErrorAllWaitingRequest(inner->resource_id, 502);
42+
return false;
43+
}
44+
45+
int socket_fd = -1;
46+
int is_connected = -1;
47+
48+
if (ipv4) {
49+
struct sockaddr_in *client = (struct sockaddr_in *)inner->iov[4].iov_base;
50+
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
51+
if (socket_fd > 0) {
52+
is_connected = connect(socket_fd, (struct sockaddr *)client,
53+
sizeof(struct sockaddr_in));
54+
}
55+
} else {
56+
struct sockaddr_in6 *client =
57+
(struct sockaddr_in6 *)inner->iov[4].iov_base;
58+
socket_fd = socket(AF_INET6, SOCK_STREAM, 0);
59+
if (socket_fd > 0) {
60+
is_connected = connect(socket_fd, (struct sockaddr *)client,
61+
sizeof(struct sockaddr_in6));
62+
}
4663
}
4764

48-
int socket_fd = socket(AF_INET6, SOCK_STREAM, 0);
4965
if (socket_fd < 0) {
50-
CloseSSL(-1, ssl, ctx);
5166
Log(__FILE__, __LINE__, Log::kError) << "Error creating socket";
52-
cache_->ReleaseErrorAllWaitingRequest(request, 502);
53-
Utils::ReleaseRequest(request);
54-
return 1;
67+
68+
stream_->ReleaseErrorAllWaitingRequest(inner->resource_id, 502);
69+
return false;
5570
}
5671

57-
if (connect(socket_fd, (struct sockaddr *)client,
58-
sizeof(struct sockaddr_in6)) < 0) {
72+
if (is_connected < 0) {
5973
CloseSSL(socket_fd, ssl, ctx);
6074
Log(__FILE__, __LINE__, Log::kError) << "Could not connect ";
61-
cache_->ReleaseErrorAllWaitingRequest(request, 502);
62-
Utils::ReleaseRequest(request);
63-
return 1;
75+
stream_->ReleaseErrorAllWaitingRequest(inner->resource_id, 502);
76+
return false;
6477
}
6578

6679
SSL_set_fd(ssl, socket_fd);
6780
int err = SSL_connect(ssl);
6881
if (err < 1) {
6982
CloseSSL(socket_fd, ssl, ctx);
7083
Log(__FILE__, __LINE__, Log::kError) << "Could not connect ";
71-
cache_->ReleaseErrorAllWaitingRequest(request, 502);
72-
Utils::ReleaseRequest(request);
73-
return 1;
84+
stream_->ReleaseErrorAllWaitingRequest(inner->resource_id, 502);
85+
return false;
7486
}
7587

7688
std::stringstream ss;
7789
ss << "GET " << query << " HTTP/1.2\r\n"
7890
<< "Host: " << host << "\r\n"
79-
<< "Accept: *//*\r\n"
80-
<< "Connection: close\r\n"
81-
<< "\r\n\r\n";
91+
<< (char *)inner->iov[3].iov_base;
8292
std::string request_data = ss.str();
8393

8494
if (SSL_write(ssl, request_data.c_str(), request_data.length()) < 0) {
8595
CloseSSL(socket_fd, ssl, ctx);
8696
Log(__FILE__, __LINE__, Log::kError) << "invalid socket";
87-
cache_->ReleaseErrorAllWaitingRequest(request, 502);
88-
Utils::ReleaseRequest(request);
89-
return 1;
97+
stream_->ReleaseErrorAllWaitingRequest(inner->resource_id, 502);
98+
return false;
9099
}
91100

92-
AddReadRequest(request, ssl, ctx, socket_fd);
93-
return 0;
94-
*/
95-
return false;
101+
struct Request *http = Utils::HttpsExternalRequest(inner);
102+
http->event_type = EVENT_TYPE_HTTP_READ_HEADER;
103+
http->client_socket = socket_fd;
104+
http->pivot = RESOURCE_TYPE_UNDEFINED;
105+
http->iov[0].iov_base = malloc(buffer_size_);
106+
http->iov[0].iov_len = buffer_size_;
107+
memset(http->iov[0].iov_base, 0, buffer_size_);
108+
http->iov[1].iov_base = ssl;
109+
http->iov[2].iov_base = ctx;
110+
111+
struct io_uring_sqe *sqe = io_uring_get_sqe(ring_);
112+
// io_uring_prep_read(sqe, http->client_socket, http->iov[0].iov_base,
113+
// buffer_size_, 0);
114+
io_uring_prep_nop(sqe);
115+
io_uring_sqe_set_data(sqe, http);
116+
io_uring_submit(ring_);
117+
return true;
96118
}
97119

98-
void HttpsClient::AddReadRequest(struct Request *request, SSL *ssl,
99-
SSL_CTX *context, int fd) {
100-
// struct io_uring_sqe *sqe = io_uring_get_sqe(ring_);
120+
int HttpsClient::ReadFromSSL(struct Request *http) {
121+
SSL *ssl = (SSL *)http->iov[1].iov_base;
122+
int readed = SSL_read(ssl, http->iov[0].iov_base, buffer_size_);
123+
if (readed < 1) {
124+
if (!ProcessError(ssl, readed)) {
125+
return -1;
126+
}
127+
if (readed == 0) {
128+
return 0;
129+
}
130+
}
131+
return readed;
132+
}
133+
134+
int HttpsClient::HandleReadHeaderRequest(struct Request *http, int response) {
135+
int readed = ReadFromSSL(http);
136+
if (readed <= 0) {
137+
if (readed < 0) {
138+
stream_->ReleaseErrorAllWaitingRequest(http->resource_id, 502);
139+
} else {
140+
stream_->CloseStream(http->resource_id);
141+
}
142+
ReleaseSocket(http);
143+
return 1;
144+
}
145+
146+
int type = GetResourceType((char *)http->iov[0].iov_base, readed);
101147

102-
// struct HttpRequest *http_request = new HttpRequest();
103-
// http_request->has_header = 0;
104-
// std::pair<int, struct HttpRequest *> item(fd, http_request);
105-
// waiting_read_.insert(item);
148+
if (type == RESOURCE_TYPE_CACHE) {
149+
int header_length =
150+
FetchHeaderLength((char *)http->iov[0].iov_base, readed);
106151

107-
// struct Request *auxiliar = Utils::HttpsExternalRequest();
108-
// auxiliar->event_type = EVENT_TYPE_HTTP_READ;
109-
// auxiliar->client_socket = fd;
110-
// auxiliar->iov[0].iov_base = malloc(buffer_size_);
111-
// auxiliar->iov[0].iov_len = buffer_size_;
112-
// auxiliar->iov[1].iov_base = ssl;
113-
// auxiliar->iov[2].iov_base = context;
152+
http->iov[0].iov_len = header_length;
153+
cache_->GenerateNode(http);
154+
155+
if (header_length < readed) {
156+
cache_->AppendBuffer(http->resource_id,
157+
http->iov[0].iov_base + header_length,
158+
readed - header_length);
159+
}
160+
} else if (type == RESOURCE_TYPE_STREAMING) {
161+
http->iov[0].iov_len = readed;
162+
stream_->SetStreamingResource(http->resource_id, http);
163+
}
114164

115-
// memset(auxiliar->iov[0].iov_base, 0, buffer_size_);
165+
struct io_uring_sqe *sqe = io_uring_get_sqe(ring_);
166+
http->event_type = EVENT_TYPE_HTTP_READ_CONTENT;
167+
http->pivot = type;
168+
io_uring_prep_nop(sqe);
169+
io_uring_sqe_set_data(sqe, http);
170+
io_uring_submit(ring_);
116171

117-
// io_uring_prep_nop(sqe);
118-
// io_uring_sqe_set_data(sqe, auxiliar);
119-
// io_uring_submit(ring_);
172+
return 0;
120173
}
121174

122-
int HttpsClient::HandleReadData(struct Request *request, int response) {
123-
// SSL *ssl = (SSL *)request->iov[1].iov_base;
124-
// int err = SSL_read(ssl, request->iov[0].iov_base, buffer_size_);
125-
// if (err < 1) {
126-
// if (!ProcessError(ssl, err)) {
127-
// struct HttpRequest *http_request =
128-
// waiting_read_.at(request->client_socket);
129-
////TODO(lanstat): verify when is finished
130-
////cache_->ReleaseErrorAllWaitingRequest(http_request->request, 502);
131-
// ReleaseSocket(request);
132-
// return 1;
133-
//}
134-
//}
135-
136-
// struct HttpRequest *http_request =
137-
// waiting_read_.at(request->client_socket); int readed =
138-
// FetchHeader(request->iov[0].iov_base); Log(__FILE__, __LINE__,
139-
// Log::kDebug) << "bytes readed: " << readed; if (readed <= 0) { struct
140-
// Request *client_request = UnifyBuffer(request); ReleaseSocket(request);
141-
// cache_->AddWriteRequest(client_request);
142-
// return 1;
143-
//} else {
144-
// struct iovec data;
145-
// data.iov_base = malloc(readed);
146-
// data.iov_len = readed;
147-
// memcpy(data.iov_base, request->iov[0].iov_base, readed);
148-
//}
149-
150-
// memset(request->iov[0].iov_base, 0, buffer_size_);
151-
152-
// struct io_uring_sqe *sqe = io_uring_get_sqe(ring_);
153-
// io_uring_prep_nop(sqe);
154-
// io_uring_sqe_set_data(sqe, request);
155-
// io_uring_submit(ring_);
175+
int HttpsClient::HandleReadData(struct Request *http, int response) {
176+
int type = http->pivot;
177+
int readed = ReadFromSSL(http);
178+
if (readed <= 0) {
179+
if (readed < 0) {
180+
stream_->ReleaseErrorAllWaitingRequest(http->resource_id, 502);
181+
} else {
182+
if (type == RESOURCE_TYPE_CACHE) {
183+
cache_->CloseBuffer(http->resource_id);
184+
} else if (type == RESOURCE_TYPE_STREAMING) {
185+
stream_->CloseStream(http->resource_id);
186+
}
187+
}
188+
ReleaseSocket(http);
189+
return 1;
190+
}
191+
192+
if (type == RESOURCE_TYPE_CACHE) {
193+
cache_->AppendBuffer(http->resource_id, http->iov[0].iov_base, readed);
194+
} else if (type == RESOURCE_TYPE_STREAMING) {
195+
// If there is no listeners
196+
if (stream_->NotifyStream(http->resource_id, http->iov[0].iov_base,
197+
readed) == 1) {
198+
Log(__FILE__, __LINE__) << "HttpClient empty stream listeners";
199+
ReleaseSocket(http);
200+
return 1;
201+
}
202+
}
203+
204+
memset(http->iov[0].iov_base, 0, buffer_size_);
205+
206+
struct io_uring_sqe *sqe = io_uring_get_sqe(ring_);
207+
io_uring_prep_nop(sqe);
208+
io_uring_sqe_set_data(sqe, http);
209+
io_uring_submit(ring_);
156210

157211
return 0;
158212
}
@@ -170,36 +224,28 @@ void HttpsClient::CloseSSL(int socket_fd, SSL *ssl, SSL_CTX *context) {
170224
}
171225

172226
void HttpsClient::ReleaseSocket(struct Request *request) {
173-
// struct HttpRequest *http_request =
174-
// waiting_read_.at(request->client_socket);
175-
// waiting_read_.erase(request->client_socket);
176-
177-
// free(request->iov[0].iov_base);
178-
// SSL *ssl = (SSL *)request->iov[1].iov_base;
179-
// SSL_CTX *context = (SSL_CTX *)request->iov[2].iov_base;
227+
free(request->iov[0].iov_base);
228+
SSL *ssl = (SSL *)request->iov[1].iov_base;
229+
SSL_CTX *context = (SSL_CTX *)request->iov[2].iov_base;
180230

181-
// CloseSSL(request->client_socket, ssl, context);
231+
CloseSSL(request->client_socket, ssl, context);
182232

183-
// delete http_request;
184-
// free(request);
233+
free(request);
185234
}
186235

187236
bool HttpsClient::ProcessError(SSL *ssl, int last_error) {
188237
int error = SSL_get_error(ssl, last_error);
189-
Log(__FILE__, __LINE__, Log::kWarning) << "SSL error " << error;
190238
if (error == SSL_ERROR_NONE) {
191239
// if (last_error == SSL_ERROR_SYSCALL) {
192240
// return false;
193241
//}
194242
return true;
195243
} else if (error == SSL_ERROR_ZERO_RETURN) {
196244
SSL_shutdown(ssl);
245+
return true;
197246
} else if (error == SSL_ERROR_SYSCALL) {
247+
Log(__FILE__, __LINE__, Log::kWarning) << "SSL error " << error;
198248
return ProcessError(ssl, error);
199249
}
200250
return false;
201251
}
202-
203-
int HttpsClient::HandleReadHeaderRequest(struct Request *http, int readed) {
204-
return 0;
205-
}

0 commit comments

Comments
 (0)