Compare commits
25 Commits
Author | SHA1 | Date |
---|---|---|
|
7ccbc81ea4 | ago%!(EXTRA string=1 year) |
|
8fdd4be2ac | ago%!(EXTRA string=1 year) |
|
750f8002e9 | ago%!(EXTRA string=1 year) |
|
a47ef015af | ago%!(EXTRA string=1 year) |
|
705a8875ba | ago%!(EXTRA string=1 year) |
|
ac99458453 | ago%!(EXTRA string=1 year) |
|
3e33fd9729 | ago%!(EXTRA string=1 year) |
|
644fada095 | ago%!(EXTRA string=1 year) |
|
0884bcaf1c | ago%!(EXTRA string=1 year) |
|
71c558d7bf | ago%!(EXTRA string=1 year) |
|
0ad9bedec5 | ago%!(EXTRA string=1 year) |
|
7a0ef3aca8 | ago%!(EXTRA string=1 year) |
|
8195ab166b | ago%!(EXTRA string=1 year) |
|
f384c3fbb3 | ago%!(EXTRA string=1 year) |
|
05855a2d50 | ago%!(EXTRA string=1 year) |
|
9534946adf | ago%!(EXTRA string=1 year) |
|
5656e1ddd7 | ago%!(EXTRA string=1 year) |
|
0196d77f1e | ago%!(EXTRA string=1 year) |
|
9c0f3563a5 | ago%!(EXTRA string=1 year) |
|
0f69d3d862 | ago%!(EXTRA string=1 year) |
|
7958c9eace | ago%!(EXTRA string=1 year) |
|
da0d4cc766 | ago%!(EXTRA string=1 year) |
|
afdcfdc9a8 | ago%!(EXTRA string=1 year) |
|
652ee8138c | ago%!(EXTRA string=1 year) |
|
b5fae8b6e9 | ago%!(EXTRA string=1 year) |
23 changed files with 722 additions and 0 deletions
@ -0,0 +1,10 @@ |
||||
docs/ |
||||
**.log |
||||
bin/ |
||||
bin-int/ |
||||
.vscode/ |
||||
.vs/ |
||||
**.sln |
||||
**Makefile |
||||
**.make |
||||
**.vcxproj* |
@ -0,0 +1,9 @@ |
||||
# Unix socket test |
||||
## Prerequisite |
||||
Use a linux distro |
||||
## Build and Run |
||||
``` |
||||
premake5 gmake |
||||
make |
||||
./bin/path_to_executable/sandbox |
||||
``` |
@ -0,0 +1,6 @@ |
||||
#pragma once |
||||
|
||||
#include <bakanet/ip_address.h> |
||||
#include <bakanet/packet.h> |
||||
#include <bakanet/socket.h> |
||||
#include <bakanet/dns_lookup.h> |
@ -0,0 +1,43 @@ |
||||
#include "dns_lookup.h" |
||||
|
||||
namespace Bk::Net { |
||||
std::vector<std::string> dns_lookup(const std::string &host_name, IpVersion ipv) |
||||
{ |
||||
std::vector<std::string> output; |
||||
|
||||
struct addrinfo hints, *res, *p; |
||||
int status, ai_family; |
||||
char ip_address[INET6_ADDRSTRLEN]; |
||||
|
||||
ai_family = (int)ipv; |
||||
memset(&hints, 0, sizeof hints); |
||||
hints.ai_family = ai_family;
|
||||
hints.ai_socktype = SOCK_STREAM; |
||||
|
||||
if ((status = getaddrinfo(host_name.c_str(), NULL, &hints, &res)) != 0)
|
||||
{ |
||||
output.push_back(""); |
||||
return output; |
||||
} |
||||
|
||||
for(p = res;p != NULL; p = p->ai_next)
|
||||
{ |
||||
void *addr; |
||||
if (p->ai_family == AF_INET)
|
||||
{ |
||||
struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr; |
||||
addr = &(ipv4->sin_addr); |
||||
} else
|
||||
{ |
||||
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr; |
||||
addr = &(ipv6->sin6_addr); |
||||
} |
||||
inet_ntop(p->ai_family, addr, ip_address, sizeof ip_address); |
||||
output.push_back(ip_address); |
||||
} |
||||
|
||||
freeaddrinfo(res); // free the linked list
|
||||
|
||||
return output; |
||||
} |
||||
} |
@ -0,0 +1,15 @@ |
||||
#pragma once |
||||
|
||||
#include <vector> |
||||
#include <iostream> |
||||
#include <cstring> |
||||
#include <string> |
||||
#include <netdb.h> |
||||
#include <arpa/inet.h> |
||||
|
||||
#include "ip_version.h" |
||||
#include "ip_address.h" |
||||
|
||||
namespace Bk::Net { |
||||
std::vector<std::string> dns_lookup(const std::string &host_name, IpVersion ipv); |
||||
} |
@ -0,0 +1,10 @@ |
||||
#include "ip_address.h" |
||||
#include <string.h> |
||||
|
||||
namespace Bk::Net { |
||||
IpAddress::IpAddress(const char* ip, IpVersion ipv) |
||||
: str(ip), version(ipv) |
||||
{ |
||||
if (inet_pton(AF_INET, str, &bytes) <= 0) perror("Bad IP"); |
||||
} |
||||
} |
@ -0,0 +1,23 @@ |
||||
#pragma once |
||||
|
||||
#include <string> |
||||
#include <netinet/in.h> |
||||
#include <arpa/inet.h> |
||||
#include <exception> |
||||
#include <cctype> |
||||
|
||||
#include "ip_version.h" |
||||
|
||||
namespace Bk::Net { |
||||
class IpAddress
|
||||
{ |
||||
public: |
||||
IpAddress(const char* ip, IpVersion ipv = IpVersion::IPv4); |
||||
|
||||
static void from_dns(char* dns); |
||||
|
||||
const char* str; |
||||
in_addr bytes; |
||||
IpVersion version; |
||||
}; |
||||
} |
@ -0,0 +1,11 @@ |
||||
#pragma once |
||||
|
||||
#include <sys/socket.h> |
||||
|
||||
namespace Bk::Net { |
||||
enum class IpProtocol
|
||||
{ |
||||
TCP = SOCK_STREAM, |
||||
UCP, |
||||
}; |
||||
} |
@ -0,0 +1,12 @@ |
||||
#pragma once |
||||
|
||||
#include <sys/socket.h> |
||||
|
||||
namespace Bk::Net { |
||||
enum class IpVersion |
||||
{ |
||||
UnSpec = AF_UNSPEC, |
||||
IPv4 = AF_INET, |
||||
IPv6 = AF_INET6, |
||||
}; |
||||
} |
@ -0,0 +1,62 @@ |
||||
#include <vector> |
||||
#include <array> |
||||
#include <memory> |
||||
#include <cstdint> |
||||
#include <cstring> |
||||
|
||||
namespace Bk::Net { |
||||
class Packet
|
||||
{ |
||||
public: |
||||
Packet() = default; |
||||
Packet(std::vector<char> data) |
||||
: payload(data) {} |
||||
|
||||
int size() { return payload.size(); } |
||||
|
||||
template <typename T> |
||||
void push(const T& data) |
||||
{ |
||||
static_assert(std::is_standard_layout<T>::value, "Data is too complex to be pushed into vector"); |
||||
size_t i = payload.size(); |
||||
payload.resize(i + sizeof(T)); |
||||
std::memcpy(payload.data() + i, &data, sizeof(T)); |
||||
} |
||||
|
||||
template <typename T> |
||||
void push(const T* data, int size) |
||||
{ |
||||
for(int i = 0; i < size; i++) push<T>(data[i]);
|
||||
} |
||||
|
||||
template <typename T> |
||||
T pull() |
||||
{ |
||||
static_assert(std::is_standard_layout<T>::value, "Data is too complex to be pulled from vector"); |
||||
T data; |
||||
size_t i = payload.size() - sizeof(T); |
||||
std::memcpy(&data, payload.data() + i, sizeof(T)); |
||||
payload.resize(i); |
||||
return data; |
||||
} |
||||
|
||||
template <typename T> |
||||
std::unique_ptr<T[]> pull(int size) |
||||
{ |
||||
std::unique_ptr<T[]> data(new T[size]); |
||||
for(int i = size - 1; i >= 0; i--) data[i] = pull<T>(); |
||||
return data; |
||||
} |
||||
|
||||
bool append_data(std::vector<char> data) |
||||
{ |
||||
if (!data.size()) return false; |
||||
size_t i = payload.size(); |
||||
payload.resize(i + data.size()); |
||||
std::memcpy(payload.data() + i, data.data(), sizeof(char) * data.size()); |
||||
return true; |
||||
} |
||||
|
||||
std::vector<char> payload; |
||||
}; |
||||
} |
@ -0,0 +1,87 @@ |
||||
#include "socket.h" |
||||
#include <iostream> |
||||
|
||||
namespace Bk::Net { |
||||
Socket::Socket(IpAddress ip, int port,IpProtocol proto) |
||||
: ip_addr(ip), ip_proto(proto) |
||||
{ |
||||
//Socket creation step
|
||||
if ((socket_id = socket((int)ip_addr.version, (int)ip_proto, 0)) < 0)
|
||||
{ |
||||
perror("socket failed"); |
||||
exit(EXIT_FAILURE); |
||||
} |
||||
addr.sin_addr = ip_addr.bytes; |
||||
addr.sin_family = (int)ip_addr.version; |
||||
addr.sin_port = htons(port); |
||||
} |
||||
|
||||
Socket::~Socket() |
||||
{ |
||||
close(socket_id); |
||||
} |
||||
|
||||
bool Socket::init() |
||||
{ |
||||
//Binding step
|
||||
int status; |
||||
if ((status = bind(socket_id, (struct sockaddr*)&addr, sizeof(addr)) < 0))
|
||||
{ |
||||
perror("bind failed"); |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
bool Socket::start(int cpt_conn) |
||||
{ |
||||
//Listening step
|
||||
if (listen(socket_id, cpt_conn) < 0)
|
||||
{ |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
Connection Socket::ack() |
||||
{ |
||||
|
||||
socklen_t addrlen = sizeof(addr); |
||||
return accept(socket_id, (struct sockaddr*)&addr, &addrlen); |
||||
} |
||||
|
||||
bool Socket::conn() |
||||
{ |
||||
if (connect(socket_id, (struct sockaddr*)&addr, sizeof(addr)) < 0)
|
||||
{ |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
void Socket::send(std::vector<char> packet) |
||||
{ |
||||
write(socket_id, packet.data(), packet.size()); |
||||
} |
||||
|
||||
void Socket::send(Connection conn, std::vector<char> packet) |
||||
{ |
||||
write(conn, packet.data(), packet.size()); |
||||
} |
||||
|
||||
std::vector<char> Socket::recv(int size) |
||||
{ |
||||
std::vector<char> buffer; |
||||
buffer.resize(size); |
||||
int status = read(socket_id, buffer.data(), buffer.size() - 1); |
||||
return status > 0 ? buffer : std::vector<char>(); |
||||
} |
||||
|
||||
std::vector<char> Socket::recv(Connection conn, int size) |
||||
{ |
||||
std::vector<char> buffer; |
||||
buffer.resize(size); |
||||
int status = read(conn, buffer.data(), buffer.size() - 1); |
||||
return status > 0 ? buffer : std::vector<char>(); |
||||
} |
||||
} |
@ -0,0 +1,45 @@ |
||||
#pragma once |
||||
|
||||
#include <netinet/in.h> |
||||
#include <stdlib.h> |
||||
#include <sys/socket.h> |
||||
#include <unistd.h> |
||||
#include <netdb.h> |
||||
#include <arpa/inet.h> |
||||
|
||||
#include <cstring> |
||||
#include <vector> |
||||
#include <string> |
||||
|
||||
#include "ip_address.h" |
||||
#include "ip_protocol.h" |
||||
|
||||
namespace Bk::Net { |
||||
|
||||
using Connection = int; |
||||
|
||||
class Socket
|
||||
{ |
||||
public: |
||||
Socket(IpAddress ip, int port, IpProtocol proto); |
||||
~Socket(); |
||||
|
||||
bool init(); |
||||
bool start(int cpt_conn); |
||||
Connection ack(); |
||||
bool conn(); |
||||
void send(std::vector<char> packet); |
||||
void send(Connection socket, std::vector<char> packet); |
||||
std::vector<char> recv(int size); |
||||
std::vector<char> recv(Connection socket, int size); |
||||
|
||||
|
||||
private: |
||||
Socket(int socket_id); |
||||
|
||||
int socket_id; |
||||
struct sockaddr_in addr; |
||||
IpAddress ip_addr; |
||||
IpProtocol ip_proto; |
||||
}; |
||||
} |
@ -0,0 +1,9 @@ |
||||
clear |
||||
rm -rf ./bin/linux-x86_64-Debug/server |
||||
premake5 gmake2 |
||||
make |
||||
|
||||
if [ "$1" == "-exec" ]; then |
||||
echo STARTING PROGRAM |
||||
./bin/linux-x86_64-Debug/server/server |
||||
fi |
@ -0,0 +1,92 @@ |
||||
workspace "socket_unix" |
||||
architecture "x64" |
||||
configurations { "Debug", "Release" } |
||||
startproject "server" |
||||
flags |
||||
{ |
||||
"MultiProcessorCompile" |
||||
} |
||||
|
||||
outputdir = "%{cfg.system}-%{cfg.architecture}-%{cfg.buildcfg}" |
||||
|
||||
IncludeDirs = {} |
||||
|
||||
IncludeDirs["bakanet"] = "%{wks.location}/bakanet/src/" |
||||
|
||||
project "bakanet" |
||||
location "./bakanet" |
||||
kind "StaticLib" |
||||
language "C++" |
||||
cppdialect "C++17" |
||||
systemversion "latest" |
||||
|
||||
targetdir("%{wks.location}/bin/" .. outputdir .. "/%{prj.name}") |
||||
objdir("%{wks.location}/bin-int/" .. outputdir .. "/%{prj.name}") |
||||
|
||||
includedirs |
||||
{ |
||||
"%{IncludeDirs.bakanet}" |
||||
} |
||||
|
||||
files |
||||
{ |
||||
"%{prj.location}/src/**.h", |
||||
"%{prj.location}/src/**.cpp" |
||||
} |
||||
|
||||
project "server" |
||||
location "./sandbox/server" |
||||
kind "ConsoleApp" |
||||
language "C++" |
||||
cppdialect "C++17" |
||||
systemversion "latest" |
||||
|
||||
targetdir("%{wks.location}/bin/" .. outputdir .. "/%{prj.name}") |
||||
objdir("%{wks.location}/bin-int/" .. outputdir .. "/%{prj.name}") |
||||
|
||||
includedirs |
||||
{ |
||||
"%{IncludeDirs.bakanet}", |
||||
"./sandbox/" |
||||
} |
||||
|
||||
files |
||||
{ |
||||
"%{prj.location}/**.h", |
||||
"%{prj.location}/**.cpp", |
||||
"./sandbox/commun.h" |
||||
} |
||||
|
||||
links |
||||
{ |
||||
"bakanet" |
||||
} |
||||
|
||||
|
||||
|
||||
project "client" |
||||
location "./sandbox/client" |
||||
kind "ConsoleApp" |
||||
language "C++" |
||||
cppdialect "C++17" |
||||
systemversion "latest" |
||||
|
||||
targetdir("%{wks.location}/bin/" .. outputdir .. "/%{prj.name}") |
||||
objdir("%{wks.location}/bin-int/" .. outputdir .. "/%{prj.name}") |
||||
|
||||
includedirs |
||||
{ |
||||
"%{IncludeDirs.bakanet}" |
||||
} |
||||
|
||||
files |
||||
{ |
||||
"%{prj.location}/**.h", |
||||
"%{prj.location}/**.cpp", |
||||
"./sandbox/commun.h" |
||||
} |
||||
|
||||
links |
||||
{ |
||||
"bakanet" |
||||
} |
@ -0,0 +1,32 @@ |
||||
#include <sstream> |
||||
#include "../commun.h" |
||||
|
||||
using namespace Bk::Net; |
||||
|
||||
void http_client(); |
||||
|
||||
int main() |
||||
{ |
||||
http_client(); |
||||
return 0; |
||||
} |
||||
|
||||
void http_client() |
||||
{ |
||||
IpAddress ip("127.0.0.1"); |
||||
Socket sock(ip, PORT, IpProtocol::TCP); |
||||
|
||||
if(!sock.conn())
|
||||
{ |
||||
perror("Couldn't connect to the end point."); |
||||
exit(1); |
||||
} |
||||
|
||||
Packet packet; |
||||
std::string str = "GET / HTTP/1.1 \r\n" |
||||
"Host: 127.0.0.1:10001 \r\n\r\n" |
||||
"Body jylkdkjlkjlkjlkjlkj";
|
||||
|
||||
packet.push<char>(str.c_str(), str.length()); |
||||
sock.send(packet.payload); |
||||
} |
@ -0,0 +1,12 @@ |
||||
#pragma once |
||||
|
||||
#include <unordered_map> |
||||
#include <iostream> |
||||
#include <vector> |
||||
#include <string> |
||||
#include <bakanet.h> |
||||
|
||||
#define log(str) std::cout << str << "\n"; |
||||
#define input(ref) std::cin >> ref; |
||||
|
||||
#define PORT 8080 |
@ -0,0 +1,91 @@ |
||||
#include "http_packet.h" |
||||
#include <iomanip> |
||||
|
||||
HttpRequest::HttpRequest(std::string method, |
||||
std::string url, |
||||
std::string version, |
||||
HttpParams params, |
||||
std::string body)
|
||||
: method(method), url(url), version(version), params(params), body(body) {} |
||||
|
||||
HttpRequest::HttpRequest(std::string data) |
||||
{ |
||||
log(data) |
||||
auto lines = string_split(data, "\n"); |
||||
auto first_line = std::string(lines->at(0)); |
||||
auto req_data = string_split(first_line, " "); |
||||
method = req_data->at(0); |
||||
url = req_data->at(1); |
||||
version = req_data->at(2); |
||||
body = std::string(lines->at(lines->size() - 1)); |
||||
lines->erase(lines->begin()); |
||||
lines->erase(lines->end()); |
||||
int i = 0; |
||||
for (auto line : *lines) |
||||
{ |
||||
log(i << "|" << line)
|
||||
i++; |
||||
} |
||||
log(method << url << version) |
||||
log("BODY|" << body) |
||||
for (auto line : *lines) |
||||
{ |
||||
auto param = string_split(line, ":", 1); |
||||
if (param->size() >= 2)
|
||||
{ |
||||
string_trim(param->at(1)); |
||||
params.insert({param->at(0), param->at(1)}); |
||||
} |
||||
} |
||||
|
||||
for (auto pair : params) |
||||
{ |
||||
log(pair.second) |
||||
} |
||||
} |
||||
|
||||
std::string HttpRequest::to_string() |
||||
{ |
||||
std::string request = ""; |
||||
request += method + " " + url + " " + version; |
||||
std::string param_order[] =
|
||||
{ |
||||
"Host", |
||||
"User-Agent", |
||||
"Accept", |
||||
"Accept-Language", |
||||
"Accept-Encoding", |
||||
"Connection", |
||||
"Upgrade-Insecure-Request", |
||||
"Sec-Fetch-Dest", |
||||
"Sec-Fetch-Mode", |
||||
"Sec-Fetch-Site" |
||||
}; |
||||
if (params.size()) for ( const auto& param : param_order) if (params[param].length()) request += param + ": " + params[param] + "\r\n"; |
||||
request += "\r\n"; |
||||
if (body.length()) request += body; |
||||
return request; |
||||
} |
||||
|
||||
HttpReponse::HttpReponse(std::string status, |
||||
std::string version, |
||||
HttpParams params, |
||||
std::string body) |
||||
: status(status), version(version), params(params), body(body) {} |
||||
|
||||
HttpReponse::HttpReponse(std::string data) |
||||
{ |
||||
status = ""; |
||||
version = ""; |
||||
body = ""; |
||||
} |
||||
|
||||
std::string HttpReponse::to_string() |
||||
{ |
||||
std::string reponse = ""; |
||||
reponse = version + " " + status + " \r\n"; |
||||
if (params.size()) for ( const auto& pair : params) reponse += pair.first + ": " + pair.second + " \r\n"; |
||||
reponse += "\r\n"; |
||||
if (body.length()) reponse += body; |
||||
return reponse; |
||||
} |
@ -0,0 +1,44 @@ |
||||
#pragma once |
||||
|
||||
#include <commun.h> |
||||
#include "http_tools.h" |
||||
|
||||
using HttpParams = std::unordered_map<std::string, std::string>; |
||||
|
||||
class HttpRequest
|
||||
{ |
||||
public: |
||||
HttpRequest(std::string method, |
||||
std::string url, |
||||
std::string version, |
||||
HttpParams params, |
||||
std::string body); |
||||
|
||||
HttpRequest(std::string data); |
||||
|
||||
std::string to_string(); |
||||
|
||||
std::string method; |
||||
std::string url; |
||||
std::string version; |
||||
HttpParams params; |
||||
std::string body; |
||||
}; |
||||
|
||||
class HttpReponse |
||||
{ |
||||
public: |
||||
HttpReponse(std::string status, |
||||
std::string version, |
||||
HttpParams params, |
||||
std::string body); |
||||
|
||||
HttpReponse(std::string data); |
||||
|
||||
std::string to_string(); |
||||
|
||||
std::string status; |
||||
std::string version; |
||||
HttpParams params; |
||||
std::string body; |
||||
}; |
@ -0,0 +1,38 @@ |
||||
#include "http_server.h" |
||||
|
||||
void http_server()
|
||||
{ |
||||
IpAddress ip("127.0.0.1"); |
||||
Socket sock(ip, PORT, IpProtocol::TCP); |
||||
bool running = sock.init() && sock.start(5); |
||||
char input = 'n'; |
||||
|
||||
do |
||||
{ |
||||
Connection conn = sock.ack(); |
||||
if (conn >= 0)
|
||||
{ |
||||
log("New Conn") |
||||
std::string http_request(http_handler(sock, conn)); |
||||
|
||||
if (http_request == "") continue; |
||||
HttpRequest req(http_request); |
||||
log("to string") |
||||
log(req.to_string()) |
||||
close(conn); |
||||
} |
||||
log("Close?") |
||||
input(input); |
||||
} while (input != 'y'); |
||||
|
||||
} |
||||
|
||||
std::string http_handler(Socket& sock, Connection conn)
|
||||
{ |
||||
Packet req; |
||||
while(req.append_data(sock.recv(conn, 4))); |
||||
int req_size = req.size(); |
||||
std::unique_ptr<char[]> req_test = req.pull<char>(req_size); |
||||
if (req_size) return std::string(req_test.release(), req_size); |
||||
return ""; |
||||
} |
@ -0,0 +1,8 @@ |
||||
#pragma once |
||||
|
||||
#include <commun.h> |
||||
#include "http_packet.h" |
||||
|
||||
using namespace Bk::Net; |
||||
void http_server(); |
||||
std::string http_handler(Socket& sock, Connection conn); |
@ -0,0 +1,43 @@ |
||||
#include "http_tools.h" |
||||
|
||||
std::string string_to_lower(std::string& str) |
||||
{ |
||||
for (int i = 0; i < str.length(); i++) |
||||
{ |
||||
str[i] = std::tolower(str[i]); |
||||
} |
||||
return str; |
||||
} |
||||
|
||||
std::string string_to_upper(std::string& str) |
||||
{ |
||||
for (int i = 0; i < str.length(); i++) |
||||
{ |
||||
str[i] = std::toupper(str[i]); |
||||
} |
||||
return str; |
||||
} |
||||
|
||||
std::unique_ptr<std::vector<std::string>> string_split(std::string& str, std::string delimiter, int cpt) |
||||
{ |
||||
std::string s(str); |
||||
std::unique_ptr<std::vector<std::string>> splits(new std::vector<std::string>(0)); |
||||
size_t pos = 0; |
||||
while (((pos = s.find(delimiter)) != std::string::npos) && cpt-- != 0)
|
||||
{ |
||||
splits->push_back(s.substr(0, pos)); |
||||
s.erase(0, pos + delimiter.length()); |
||||
} |
||||
if (s.length()) splits->push_back(s); |
||||
return splits; |
||||
} |
||||
|
||||
void string_trim(std::string& str, const std::string& whitespace) |
||||
{ |
||||
const auto strBegin = str.find_first_not_of(whitespace); |
||||
const auto strEnd = str.find_last_not_of(whitespace); |
||||
if (strBegin != std::string::npos) |
||||
{ |
||||
str.erase(0, strBegin); |
||||
} |
||||
} |
@ -0,0 +1,9 @@ |
||||
#pragma once |
||||
|
||||
#include <cstring> |
||||
#include <commun.h> |
||||
|
||||
std::string string_to_lower(std::string& str); |
||||
std::string string_to_upper(std::string& str); |
||||
std::unique_ptr<std::vector<std::string>> string_split(std::string& str, std::string delimiter, int cpt = -1); |
||||
void string_trim(std::string& str, const std::string& whitespace = " \b\0"); |
@ -0,0 +1,11 @@ |
||||
#include "commun.h" |
||||
#include "http/http_server.h" |
||||
|
||||
int main()
|
||||
{ |
||||
http_server(); |
||||
return 0; |
||||
} |
||||
|
||||
|
||||
|
Loading…
Reference in New Issue