ssl client improvements

This commit is contained in:
vaclavt 2022-01-15 13:16:27 +01:00
parent bab67f70f9
commit f0eda085f0
1 changed files with 22 additions and 25 deletions

View File

@ -1,16 +1,11 @@
//============================================================================
// clang++ -o sslclient sslclient.cpp -lssl -lcrypto -L/usr/local/opt/openssl/lib -I/usr/local/opt/openssl/include
//============================================================================
//
#include "sslclient.h" #include "sslclient.h"
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netdb.h> #include <netdb.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <cstdio>
#include <sys/socket.h> #include <sys/socket.h>
#include <cstdio>
#include <iostream> #include <iostream>
#include <regex> #include <regex>
#include <sstream> #include <sstream>
@ -20,8 +15,10 @@
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST // https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET // https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET
std::pair<int, std::string> HttpClient::doRequest(const std::string &method, const std::string &url, const std::map<std::string, std::string> &headers, const std::string &request_body) {
// TODO user streams instead of printf's
std::pair<int, std::string> HttpClient::doRequest(const std::string &method, const std::string &url, const std::map<std::string, std::string> &headers, const std::string &request_body) {
// split url to parts // split url to parts
parseURL(url); parseURL(url);
if (proto != "https") if (proto != "https")
@ -36,7 +33,7 @@ std::pair<int, std::string> HttpClient::doRequest(const std::string &method, con
request.append(request_body); request.append(request_body);
// read response // read response
int bytes_read = sslRequest(server, request); // TODO memory leaks ??? int bytes_read = sslRequest(server, request);
if (bytes_read <= 0) { if (bytes_read <= 0) {
std::cerr << "no data read" << std::endl; std::cerr << "no data read" << std::endl;
return std::make_pair(403, ""); return std::make_pair(403, "");
@ -45,19 +42,18 @@ std::pair<int, std::string> HttpClient::doRequest(const std::string &method, con
// get headers // get headers
std::string::size_type position = ssl_read_packet.find("\r\n\r\n"); std::string::size_type position = ssl_read_packet.find("\r\n\r\n");
if (position == std::string::npos) { if (position == std::string::npos)
std::cerr << "end of headers not found" << std::endl; throw std::runtime_error("invalid reply, end of headers not found");
// TODO invalid packet, throw exception
}
const std::string hdr = ssl_read_packet.substr(0, position);
auto status_pos = hdr.find("\r\n");
const std::string status_str = hdr.substr(0, status_pos); const std::string response = ssl_read_packet.substr(0, position);
const std::string response_headers = hdr.substr(status_pos + 2, hdr.length() - 2 - status_pos); auto status_pos = response.find("\r\n");
const std::string response_headers = response.substr(status_pos + 2, response.length() - 2 - status_pos);
const std::string status_string = response.substr(0, status_pos);
// parse status code // parse status code
const int resp_status = responseStatusCode(status_str); const int resp_status = responseStatusCode(status_string);
// parse headers // parse headers
responseHeaders(response_headers); responseHeaders(response_headers);
@ -69,19 +65,19 @@ std::pair<int, std::string> HttpClient::doRequest(const std::string &method, con
return std::make_pair(resp_status, body); return std::make_pair(resp_status, body);
} }
void HttpClient::responseHeaders(const std::string &hdr) { void HttpClient::responseHeaders(const std::string &headers) {
std::istringstream resp(hdr); std::istringstream resp(headers);
std::string header; std::string header;
std::string::size_type index;
while (std::getline(resp, header) && header != "\r") { while (std::getline(resp, header) && header != "\r") {
index = header.find(": ", 0); auto index = header.find(": ", 0);
if (index != std::string::npos) if (index != std::string::npos)
headers_map.insert(std::make_pair(header.substr(0, index), header.substr(index + 1))); headers_map.insert(std::make_pair(header.substr(0, index), header.substr(index + 1)));
} }
} }
int HttpClient::responseStatusCode(const std::string &status_str) const { int HttpClient::responseStatusCode(const std::string &status_str) const {
int resp_status = 200; // default is OK auto resp_status = 200; // default is OK
std::regex status_rgx{"^HTTP/\\d\\.\\d (\\d{3}) .+$"}; std::regex status_rgx{"^HTTP/\\d\\.\\d (\\d{3}) .+$"};
std::smatch status_matches; std::smatch status_matches;
@ -89,15 +85,15 @@ int HttpClient::responseStatusCode(const std::string &status_str) const {
if (status_matches.size() > 1) if (status_matches.size() > 1)
resp_status = std::stoi(status_matches[1].str()); resp_status = std::stoi(status_matches[1].str());
} }
return resp_status; return resp_status;
} }
std::string HttpClient::createRequestHeaders(const std::map<std::string, std::string> &headers) { std::string HttpClient::createRequestHeaders(const std::map<std::string, std::string> &headers) {
std::string headers_string; std::string headers_string;
for (const auto & header : headers) { for (const auto & header : headers)
headers_string.append("\r\n" + header.first + ": " + header.second); headers_string.append("\r\n" + header.first + ": " + header.second);
// std::cerr << "KEY: `" << it->first << "`, VALUE: `" << it->second << '`' << std::endl;
}
return headers_string; return headers_string;
} }
@ -154,6 +150,7 @@ int HttpClient::sslRecvPacket() {
int len = 16384; int len = 16384;
char buf[len + 1]; char buf[len + 1];
memset(buf, 0, sizeof(buf));
do { do {
len = SSL_read(ssl, buf, len); len = SSL_read(ssl, buf, len);
if (len >= 0) { if (len >= 0) {