Compare commits

...

25 Commits

Author SHA1 Message Date
anulax1225 7ccbc81ea4 Fixed http parsing ago%!(EXTRA string=1 year)
anulax1225 8fdd4be2ac Added a to_lower_case function ago%!(EXTRA string=1 year)
anulax1225 750f8002e9 Removed all code from main.cpp ago%!(EXTRA string=1 year)
anulax1225 a47ef015af Reorgenised http code ago%!(EXTRA string=1 year)
anulax1225 705a8875ba Client updated ago%!(EXTRA string=1 year)
anulax1225 ac99458453 Added commun.h to the include dirs ago%!(EXTRA string=1 year)
anulax1225 3e33fd9729 Prepering for basic http ago%!(EXTRA string=1 year)
anulax1225 644fada095 Continuing client/server http ago%!(EXTRA string=1 year)
anulax1225 0884bcaf1c Cleaned File ago%!(EXTRA string=1 year)
anulax1225 71c558d7bf Created a simple http client/server ago%!(EXTRA string=1 year)
anulax1225 0ad9bedec5 Added more features needed for more complexe portocols ago%!(EXTRA string=1 year)
anulax1225 7a0ef3aca8 Created a new exemple with a server client interface ago%!(EXTRA string=1 year)
anulax1225 8195ab166b Changed Premake config ago%!(EXTRA string=1 year)
anulax1225 f384c3fbb3 Cleaned ip_address file ago%!(EXTRA string=1 year)
anulax1225 05855a2d50 Removed dns lookup function from file ago%!(EXTRA string=1 year)
anulax1225 9534946adf Added new files to the headers file ago%!(EXTRA string=1 year)
anulax1225 5656e1ddd7 Created a file for the dns lookup function ago%!(EXTRA string=1 year)
anulax1225 0196d77f1e Created a container for packet management ago%!(EXTRA string=1 year)
anulax1225 9c0f3563a5 Changed premake config by adding two new projects for the client and the server. and making bakanet a staticlib ago%!(EXTRA string=1 year)
anulax1225 0f69d3d862 Created a client server test program ago%!(EXTRA string=1 year)
anulax1225 7958c9eace Refactored project folder ago%!(EXTRA string=1 year)
anulax1225 da0d4cc766 Added an exemple with the simple web server ago%!(EXTRA string=1 year)
anulax1225 afdcfdc9a8 Created simple abstraction for socket usage ago%!(EXTRA string=1 year)
anulax1225 652ee8138c Added build script for linux ago%!(EXTRA string=1 year)
anulax1225 b5fae8b6e9 Basic hello world web serveur ago%!(EXTRA string=1 year)
  1. 10
      .gitignore
  2. 9
      README.md
  3. 6
      bakanet/src/bakanet.h
  4. 43
      bakanet/src/bakanet/dns_lookup.cpp
  5. 15
      bakanet/src/bakanet/dns_lookup.h
  6. 10
      bakanet/src/bakanet/ip_address.cpp
  7. 23
      bakanet/src/bakanet/ip_address.h
  8. 11
      bakanet/src/bakanet/ip_protocol.h
  9. 12
      bakanet/src/bakanet/ip_version.h
  10. 62
      bakanet/src/bakanet/packet.h
  11. 87
      bakanet/src/bakanet/socket.cpp
  12. 45
      bakanet/src/bakanet/socket.h
  13. 9
      build
  14. 92
      premake5.lua
  15. 32
      sandbox/client/client.cpp
  16. 12
      sandbox/commun.h
  17. 91
      sandbox/server/http/http_packet.cpp
  18. 44
      sandbox/server/http/http_packet.h
  19. 38
      sandbox/server/http/http_server.cpp
  20. 8
      sandbox/server/http/http_server.h
  21. 43
      sandbox/server/http/http_tools.cpp
  22. 9
      sandbox/server/http/http_tools.h
  23. 11
      sandbox/server/main.cpp

10
.gitignore vendored

@ -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…
Cancel
Save