Created multi-platform architecture

multi_plaform
ambigipathyv ago%!(EXTRA string=1 year)
parent 89a1b75bd2
commit d9659374c7
  1. 51
      bakanet/premake5.lua
  2. 6
      bakanet/src/bakanet.h
  3. 42
      bakanet/src/bakanet/http/http_parser.cpp
  4. 26
      bakanet/src/bakanet/http/http_parser.h
  5. 48
      bakanet/src/bakanet/http/http_server.cpp
  6. 7
      bakanet/src/bakanet/http/http_server.h
  7. 34
      bakanet/src/bakanet/http/http_tools.cpp
  8. 7
      bakanet/src/bakanet/http/http_tools.h
  9. 9
      bakanet/src/bakanet/sock_layer/dns_lookup.h
  10. 15
      bakanet/src/bakanet/sock_layer/ip_address.h
  11. 11
      bakanet/src/bakanet/sock_layer/ip_protocol.h
  12. 10
      bakanet/src/bakanet/sock_layer/ip_version.h
  13. 57
      bakanet/src/bakanet/sock_layer/packet.h
  14. 27
      bakanet/src/bakanet/sock_layer/socket.h
  15. 26
      bakanet/src/bakanetpch.h
  16. 43
      bakanet/src/plaform/linux/linux_dns_lookup.cpp
  17. 14
      bakanet/src/plaform/linux/linux_ip_address.cpp
  18. 93
      bakanet/src/plaform/linux/linux_socket.cpp
  19. 27
      bakanet/src/plaform/linux/linux_socket.h
  20. 0
      bakanet/src/plaform/windows/windows_dns_lookup.cpp
  21. 0
      bakanet/src/plaform/windows/windows_ip_adress.cpp
  22. 0
      bakanet/src/plaform/windows/windows_socket.cpp
  23. 0
      bakanet/src/plaform/windows/windows_socket.h
  24. 3
      build
  25. 71
      premake5.lua

@ -0,0 +1,51 @@
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/bakanet/**.h",
"%{prj.location}/src/bakanet/**.cpp",
"%{prj.location}/src/bakanet.h",
"%{prj.location}/src/baknetpch.h",
}
filter "system:windows"
defines
{
"BK_PLAFORM_WINDOWS"
}
files
{
"%{prj.location}/src/plaform/windows/**.h",
"%{prj.location}/src/plaform/windows/**.cpp",
}
links
{
"WS2_32.lib"
}
filter "system:linux"
defines
{
"BK_PLAFORM_LINUX"
}
files
{
"%{prj.location}/src/plaform/linux/**.h",
"%{prj.location}/src/plaform/linux/**.cpp",
}

@ -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,42 @@
#include "http_parser.h"
HttpRequest http_parser(std::string req)
{
std::string url = "", method = "", body = "";
std::unordered_map<std::string, std::string> params;
auto lines = string_split(req, "\n");
auto first_line = string_split(lines->at(0), " ");
method = string_to_upper(first_line->at(0));
url = first_line->at(1);
body = lines->at(lines->size() - 1);
lines->erase(lines->begin());
lines->pop_back();
for (auto line : *lines)
{
auto param = string_split(line, ":", 1);
if (param->size() == 2)
{
params.insert({ param->at(0), string_trim(param->at(1))});
}
}
return HttpRequest {
http_resolve_methode(method),
url,
params,
body
};
}
HttpMethod http_resolve_methode(std::string method)
{
if (method.compare("GET")) return HttpMethod::GET;
else if (method.compare("POST")) return HttpMethod::POST;
else if (method.compare("PUT")) return HttpMethod::PUT;
else if (method.compare("DELETE")) return HttpMethod::DELETE;
else return HttpMethod::NONE;
}

@ -0,0 +1,26 @@
#include <unordered_map>
#include <commun.h>
#include "http_tools.h"
enum class HttpMethod
{
NONE = 0,
GET = 1,
POST = 2,
PUT = 3,
DELETE = 4,
};
class HttpRequest
{
public:
HttpMethod method;
std::string url;
std::unordered_map<std::string, std::string> params;
std::string body;
};
HttpRequest http_parser(std::string req);
HttpMethod http_resolve_methode(std::string method);

@ -0,0 +1,48 @@
#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)
{
std::string http_request(http_handler(sock, conn));
if (http_request == "") continue;
HttpRequest req = http_parser(http_request);
log("Http request");
log("Method " << (int)req.method)
log("URL " << req.url)
log("Body " << req.body)
}
log("Close?")
input(input);
} while (input != 'y');
}
std::string http_handler(Socket& sock, Connection conn)
{
Packet req;
bool reading = true;
while(reading)
{
std::vector<char> raw_data;
raw_data = sock.recv(conn, 4);
reading = req.append_data(raw_data);
}
close(conn);
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,7 @@
#include <commun.h>
#include "http_parser.h"
using namespace Bk::Net;
void http_server();
std::string http_handler(Socket& sock, Connection conn);

@ -0,0 +1,34 @@
#include "http_tools.h"
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 s, std::string delimiter, int cpt)
{
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());
}
splits->push_back(s);
return splits;
}
std::string string_trim(const std::string& str, const std::string& whitespace)
{
const auto strBegin = str.find_first_not_of(whitespace);
if (strBegin == std::string::npos)
return ""; // no content
const auto strEnd = str.find_last_not_of(whitespace);
const auto strRange = strEnd - strBegin + 1;
return str.substr(strBegin, strRange);
}

@ -0,0 +1,7 @@
#include <cstring>
#include <commun.h>
std::string string_to_upper(std::string& str);
std::unique_ptr<std::vector<std::string>> string_split(std::string s, std::string delimiter, int cpt = -1);
std::string string_trim(const std::string& str, const std::string& whitespace = " ");

@ -0,0 +1,9 @@
#pragma once
#include <bakanetpch.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,15 @@
#pragma once
#include <bakanetpch.h>
#include "ip_version.h"
namespace Bk::Net {
class IpAddress
{
public:
IpAddress(std::string ip, IpVersion ipv = IpVersion::IPv4);
void* get_data();
std::string str;
IpVersion version;
};
}

@ -0,0 +1,11 @@
#pragma once
#include <bakanetpch.h>
namespace Bk::Net {
enum class IpProtocol
{
TCP = SOCK_STREAM,
UCP = SOCK_DGRAM,
};
}

@ -0,0 +1,10 @@
#pragma once
namespace Bk::Net {
enum class IpVersion
{
UnSpec = AF_UNSPEC,
IPv4 = AF_INET,
IPv6 = AF_INET6,
};
}

@ -0,0 +1,57 @@
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,27 @@
#pragma once
#include <bakanetpch.h>
#include "ip_address.h"
#include "ip_protocol.h"
namespace Bk::Net {
using Connection = int;
class Socket
{
public:
virtual ~Socket() { }
virtual bool init() = 0;
virtual bool start(int cpt_conn) = 0;
virtual Connection ack() = 0;
virtual bool conn() = 0;
virtual void emit(std::vector<char> packet) = 0;
virtual void emit(Connection socket, std::vector<char> packet) = 0;
virtual std::vector<char> obtain(int size) = 0;
virtual std::vector<char> obtain(Connection socket, int size) = 0;
static std::unique_ptr<Socket> Create(IpAddress ip, int port, IpProtocol proto);
};
}

@ -0,0 +1,26 @@
#pragma once
#include <cstring>
#include <vector>
#include <string>
#include <exception>
#include <memory>
#include <cstdint>
#include <cctype>
#include <string>
#ifdef BK_PLAFORM_WINDOWS
#include <Ws2tcpip.h>
#include <WinSock2.h>
#include <tchar.h>
#pragma comment(lib,"WS2_32.lib")
#elif BK_PLAFORM_LINUX
#include <netinet/in.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netdb.h>
#include <arpa/inet.h>
#else
#error "Plaform not supported"
#endif

@ -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,14 @@
#include <bakanet/sock_layer/ip_address.h>
#include <string.h>
namespace Bk::Net {
IpAddress::IpAddress(std::string ip, IpVersion ipv)
: str(ip), version(ipv) { }
void* IpAddress::get_data()
{
struct in_addr addr;
if (inet_pton(AF_INET, str.c_str(), &addr) <= 0) perror("Bad IP");
return (void*)addr;
}
}

@ -0,0 +1,93 @@
#include "socket.h"
#include <iostream>
namespace Bk::Net {
LinuxSocket::LinuxSocket(IpAddress ip, int port, IpProtocol proto)
: ip_addr(ip), ip_proto(proto)
{
//LinuxSocket creation step
if ((socket_id = socket((int)ip_addr.version, (int)ip_proto, 0)) < 0)
{
perror("socket failed");
exit(EXIT_FAILURE);
}
addr.sin_addr = (struct in_addr)ip_addr.get_data();
addr.sin_family = (int)ip_addr.version;
addr.sin_port = htons(port);
}
LinuxSocket::~LinuxSocket()
{
close(socket_id);
}
bool LinuxSocket::init()
{
//Binding step
int status;
if ((status = bind(socket_id, (struct sockaddr*)&addr, sizeof(addr)) < 0))
{
perror("bind failed");
return false;
}
return true;
}
bool LinuxSocket::start(int cpt_conn)
{
//Listening step
if (listen(socket_id, cpt_conn) < 0)
{
return false;
}
return true;
}
Connection LinuxSocket::ack()
{
socklen_t addrlen = sizeof(addr);
return accept(socket_id, (struct sockaddr*)&addr, &addrlen);
}
bool LinuxSocket::conn()
{
if (connect(socket_id, (struct sockaddr*)&addr, sizeof(addr)) < 0)
{
return false;
}
return true;
}
void LinuxSocket::emit(std::vector<char> packet)
{
write(socket_id, packet.data(), packet.size());
}
void LinuxSocket::emit(Connection conn, std::vector<char> packet)
{
write(conn, packet.data(), packet.size());
}
std::vector<char> LinuxSocket::obtain(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> LinuxSocket::obtain(Connection conn, int size)
{
std::vector<char> buffer;
buffer.resize(size);
int read_size = read(conn, buffer.data(), buffer.size() - 1);
buffer.resize(read_size);
return buffer;
}
std::unique_ptr<Socket> Socket::Create(IpAddress ip, int port, IpProtocol proto)
{
return std::unique_ptr(new LinuxSocket(ip, port, proto));
}
}

@ -0,0 +1,27 @@
#pragma once
#include <bakanet/tcp_ip/socket.h>
namespace Bk::Net {
class LinuxSocket : public Socket
{
public:
LinuxSocket(IpAddress ip, int port, IpProtocol proto);
virtual ~LinuxSocket();
bool init() override;
bool start(int cpt_conn) override;
Connection ack() override;
bool conn() override;
void emit(std::vector<char> packet) override;
void emit(Connection socket, std::vector<char> packet) override;
std::vector<char> obtain(int size) override;
std::vector<char> obtain(Connection socket, int size) override;
private:
Connection socket_id;
struct sockaddr_in addr;
IpAddress ip_addr;
IpProtocol ip_proto;
};
}

@ -0,0 +1,3 @@
clear
premake5 gmake2
make

@ -0,0 +1,71 @@
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 "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"
}
Loading…
Cancel
Save