Compare commits

..

3 Commits

Author SHA1 Message Date
ZimPoPo 861bbd0a4c
Premake5 add clean action ago%!(EXTRA string=1 year)
ZimPoPo 45aab99712
Setup premake5 ago%!(EXTRA string=1 year)
ZimPoPo be52ba2285
Simple client/server message ago%!(EXTRA string=1 year)
  1. 15
      .gitignore
  2. 2
      LICENSE
  3. 1
      README.md
  4. 4
      bakanet/bakanet.vcxproj.user
  5. 13
      bakanet/premake5.lua
  6. 1
      bakanet/src/bakanet.h
  7. 5
      dependencies
  8. 23
      examples/httpserver.cpp
  9. 20
      package.json
  10. 93
      premake5.lua
  11. 15
      sandbox/client/premake5.lua
  12. 68
      sandbox/client/src/main.cpp
  13. 15
      sandbox/server/premake5.lua
  14. 97
      sandbox/server/src/main.cpp
  15. 15
      src/bakanet.h
  16. 9
      src/bakanet/core/dns_lookup.h
  17. 17
      src/bakanet/core/ip_address.h
  18. 11
      src/bakanet/core/ip_protocol.h
  19. 10
      src/bakanet/core/ip_version.h
  20. 37
      src/bakanet/core/socket.h
  21. 30
      src/bakanet/core/socket_options.h
  22. 73
      src/bakanet/http/packet.cpp
  23. 60
      src/bakanet/http/packet.h
  24. 98
      src/bakanet/http/server.cpp
  25. 34
      src/bakanet/http/server.h
  26. 33
      src/bakanetpch.h
  27. 43
      src/platform/linux/linux_dns_lookup.cpp
  28. 13
      src/platform/linux/linux_ip_address.cpp
  29. 104
      src/platform/linux/linux_socket.cpp
  30. 35
      src/platform/linux/linux_socket.h
  31. 40
      src/platform/windows/windows_dns_lookup.cpp
  32. 16
      src/platform/windows/windows_ip_adress.cpp
  33. 107
      src/platform/windows/windows_socket.cpp
  34. 34
      src/platform/windows/windows_socket.h

15
.gitignore vendored

@ -1,10 +1,7 @@
docs/
**.log
bin/
bin-int/
.vscode/
.vs/
**.sln
.vs
**Makefile
**.make
**.vcxproj*
**vcxproj
**.vcxproj.filters
*sln
bin
bin-int

@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [2024] [anulax1225]
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1 +0,0 @@
# Baka net module

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>

@ -0,0 +1,13 @@
project "bakanet"
kind "StaticLib"
language "C++"
cppdialect "C++17"
systemversion "latest"
targetdir ("bin/" .. outputdir .. "/%{prj.name}")
objdir ("bin-int/" .. outputdir .. "/%{prj.name}")
files {
"src/**.h",
"src/**.cpp"
}

@ -0,0 +1 @@
#pragma once

@ -1,5 +0,0 @@
IncludeDirs["bakanet"] = "%{wks.location}/vendor/bakanet/src/"
group "Bakanet"
include "vendor/bakanet"
group ""

@ -1,23 +0,0 @@
#include <bakatools.h>
#include <bakanet.h>
#define PORT 80
using namespace Bk::Net;
int main()
{
Bk::Log::init("Bakanet");
IpAddress ip;
HttpServer server(ip, PORT);
server.get("/", [](HttpRequest& req)
{
HttpReponse res(HTTP_RES_200, req.version);
res.body = "<h1>Bakanet</h1>";
res.body += "<p>Working http server</p>";
res.body += "\n<p>URL /</p>";
return res;
});
server.start();
return 0;
}

@ -1,20 +0,0 @@
{
"name": "Bakanet",
"author": "Anulax",
"git": "https://github.com/anulax1225/bakanet",
"links":
[
"bakanet"
],
"includes":
[
"bakanet"
],
"packages":
[
{
"author": "anulax",
"name": "bakatools"
}
]
}

@ -1,77 +1,32 @@
project "bakanet"
kind "StaticLib"
language "C++"
cppdialect "C++20"
systemversion "latest"
staticruntime "on"
workspace "winsock_test"
architecture "x64"
targetdir("%{wks.location}/bin/" .. outputdir .. "/%{prj.name}")
objdir("%{wks.location}/bin-int/" .. outputdir .. "/%{prj.name}")
includedirs
{
"%{IncludeDirs.spdlog}",
"%{IncludeDirs.bakanet}",
"%{IncludeDirs.bakatools}"
}
files
{
"%{prj.location}/src/bakanet/**.h",
"%{prj.location}/src/bakanet/**.cpp",
"%{prj.location}/src/baknetpch.h",
}
links
{
"bakatools"
}
filter "system:windows"
buildoptions { "/MT", "/utf-8" }
defines
{
"BK_PLATFORM_WINDOWS"
}
files
{
"%{prj.location}/src/platform/windows/**.h",
"%{prj.location}/src/platform/windows/**.cpp",
}
links
configurations
{
"WS2_32.lib"
"Debug",
"Release"
}
filter "system:linux"
defines
{
"BK_PLATFORM_LINUX"
}
-- startproject "winsock_test"
files
{
"%{prj.location}/src/platform/linux/**.h",
"%{prj.location}/src/platform/linux/**.cpp",
}
outputdir = "%{cfg.buildcfg}-%{cfg.system}-%{cfg.architecture}"
filter "configurations:Debug"
defines
{
"BK_DEBUG",
"DEBUG"
}
runtime "Debug"
symbols "on"
-- Include projects
include "bakanet"
include "sandbox/client"
include "sandbox/server"
newaction {
trigger = "clean",
description = "Clean the build",
execute = function()
print("Cleaning...")
os.rmdir("./bin")
os.rmdir("./bin-int")
os.remove("**.sln")
os.remove("**.vcxproj")
os.remove("**.vcxproj.filters")
print("Done.")
end
}
filter "configurations:Release"
defines
{
"BK_RELEASE",
"NDEBUG"
}
runtime "Release"
optimize "on"

@ -0,0 +1,15 @@
project "client"
kind "ConsoleApp"
language "C++"
cppdialect "C++17"
systemversion "latest"
targetdir ("bin/" .. outputdir .. "/%{prj.name}")
objdir ("bin-int/" .. outputdir .. "/%{prj.name}")
files {
"src/**.h",
"src/**.cpp"
}
links { "bakanet"}

@ -0,0 +1,68 @@
#include <iostream>
#include <Ws2tcpip.h>
#include <WinSock2.h>
#include <tchar.h>
#pragma comment(lib,"WS2_32.lib")
int main()
{
WSADATA wsaData;
int err;
err = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (err != 0)
{
std::cout << "Winsock DDL not found!" << std::endl;
WSACleanup();
system("pause");
return 0;
}
//client socket
SOCKET sock;
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET)
{
std::cout << "Invalid client socker: " + WSAGetLastError() << std::endl;
WSACleanup();
system("pause");
return 0;
}
//conf socket
sockaddr_in service;
service.sin_family = AF_INET;
InetPton(AF_INET, _T("127.0.0.1"), &service.sin_addr.s_addr);
service.sin_port = htons(25580);
//connect to serv
if (connect(sock, (SOCKADDR*)&service, sizeof(service)) == SOCKET_ERROR)
{
std::cout << "Failed to connect to the server: " + WSAGetLastError() << std::endl;
closesocket(sock);
WSACleanup();
system("pause");
return 0;
}
//send message to serv
std::string message = "Hello server!";
if (send(sock, message.c_str(), message.length(), 0) == SOCKET_ERROR)
{
std::cout << "Failed to send messaage to the server: " + WSAGetLastError() << std::endl;
closesocket(sock);
WSACleanup();
system("pause");
return 0;
}
std::cout << "All good :)" << std::endl;
closesocket(sock);
WSACleanup();
system("pause");
return 0;
}

@ -0,0 +1,15 @@
project "server"
kind "ConsoleApp"
language "C++"
cppdialect "C++17"
systemversion "latest"
targetdir ("bin/" .. outputdir .. "/%{prj.name}")
objdir ("bin-int/" .. outputdir .. "/%{prj.name}")
files {
"src/**.h",
"src/**.cpp"
}
links { "bakanet"}

@ -0,0 +1,97 @@
#include <iostream>
#include <Ws2tcpip.h>
#include <WinSock2.h>
#include <tchar.h>
#pragma comment(lib, "WS2_32.lib")
int main()
{
WSADATA wsaData;
int err;
err = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (err != 0)
{
std::cout << "Winsock DLL not found!" << std::endl;
WSACleanup();
system("pause");
return 0;
}
//server socket
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET)
{
std::cout << "Invalid server socket: " << WSAGetLastError() << std::endl;
WSACleanup();
system("pause");
return 0;
}
//conf socket
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = INADDR_ANY;
service.sin_port = htons(25580);
//bind
if (bind(sock, (SOCKADDR*)&service, sizeof(service)) == SOCKET_ERROR)
{
std::cout << "Bind failed: " << WSAGetLastError() << std::endl;
closesocket(sock);
WSACleanup();
system("pause");
return 0;
}
//listen
if (listen(sock, SOMAXCONN) == SOCKET_ERROR)
{
std::cout << "Listen failed: " << WSAGetLastError() << std::endl;
closesocket(sock);
WSACleanup();
system("pause");
return 0;
}
std::cout << "Waiting for connection..." << std::endl;
//Accept client socket
SOCKET clientSocket = accept(sock, NULL, NULL);
if (clientSocket == INVALID_SOCKET)
{
std::cout << "Accept failed: " << WSAGetLastError() << std::endl;
closesocket(sock);
WSACleanup();
system("pause");
return 0;
}
std::cout << "Client connected" << std::endl;
char buffer[256];
int bytesRead;
do
{
bytesRead = recv(clientSocket, buffer, sizeof(buffer), 0);
if (bytesRead > 0)
{
buffer[bytesRead] = '\0';
std::cout << buffer << std::endl;
}
} while (bytesRead > 0);
closesocket(clientSocket);
closesocket(sock);
WSACleanup();
system("pause");
return 0;
}

@ -1,15 +0,0 @@
#pragma once
#include <bakanet/core/ip_address.h>
#include <bakanet/core/socket.h>
#if defined(BK_PLATFORM_WINDOWS)
#include <platform/windows/windows_socket.h>
#elif defined(BK_PLATFORM_LINUX)
#include <platform/linux/linux_socket.h>
#else
#error "Plaform not supported"
#endif
#include <bakanet/core/dns_lookup.h>
#include <bakanet/http/server.h>

@ -1,9 +0,0 @@
#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);
}

@ -1,17 +0,0 @@
#pragma once
#include <bakanetpch.h>
#include "ip_version.h"
namespace Bk::Net {
class IpAddress
{
public:
IpAddress(std::string ip = "", IpVersion ipv = IpVersion::IPv4)
: str(ip), version(ipv) { }
struct in_addr get_data();
std::string str;
IpVersion version;
};
}

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

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

@ -1,37 +0,0 @@
#pragma once
#include <bakanetpch.h>
#include "ip_address.h"
#include "ip_protocol.h"
#include "socket_options.h"
namespace Bk::Net {
using Connection = int;
class Socket
{
public:
virtual ~Socket() {}
virtual bool init() = 0;
virtual bool start(int cpt_conn) = 0;
virtual Socket* ack() = 0;
virtual bool conn() = 0;
virtual bool isConnected() = 0;
virtual int get_raw_socket() = 0;
virtual const std::string get_ip() = 0;
virtual void emit(std::vector<char> packet) = 0;
virtual std::vector<char> obtain(int size) = 0;
template<typename T>
static bool set_option(Socket& socket, OptionLayer level, SocketOption option_name, const T* option_value) { return setsockopt(socket.get_raw_socket(), (int)level, (int)option_name, (void*)option_value, sizeof(T)) == 0 ? true : false; }
static Socket* create(IpAddress ip, int port, IpProtocol proto);
protected:
static Socket* create(int id, IpVersion ver, IpProtocol proto);
};
}

@ -1,30 +0,0 @@
#include <bakanetpch.h>
namespace Bk::Net {
enum class OptionLayer
{
IP = IPPROTO_IP,
IPv6 = IPPROTO_IPV6,
RawIP = IPPROTO_ICMP,
TCP = IPPROTO_TCP,
UDP = IPPROTO_UDP,
Socket = SOL_SOCKET,
};
enum class SocketOption
{
Debug = SO_DEBUG,
Broadcast = SO_BROADCAST,
ReuseAddr = SO_REUSEADDR,
KeepAlive = SO_KEEPALIVE,
Linger = SO_LINGER,
OutOfBandInline = SO_OOBINLINE,
SendBuffer = SO_SNDBUF,
ReceiveBuffer = SO_RCVBUF,
DontRoute = SO_DONTROUTE,
ReceiveMin = SO_RCVLOWAT,
ReceiveTimeOut = SO_RCVTIMEO,
SendMin = SO_SNDLOWAT,
SendTimeOut = SO_SNDTIMEO,
};
}

@ -1,73 +0,0 @@
#include "packet.h"
namespace Bk::Net {
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)
{
auto lines = Tools::string_split(data, "\n");
auto req_data = Tools::string_split(lines->at(0), " ");
if(req_data->size() > 0) method = req_data->at(0);
if(req_data->size() > 1) url = req_data->at(1);
if(req_data->size() > 2) version = req_data->at(2);
lines->erase(lines->begin());
for (auto line = lines->begin(); line != lines->end(); line++)
{
if (*line != "\r")
{
auto param = Tools::string_split(*line, ":", 1);
if (param->size() >= 2)
{
Tools::string_trim(param->at(1));
params.insert({param->at(0), param->at(1)});
}
}
else
{
for (auto body_line = ++line; body_line != lines->end(); body_line++)
body += *body_line + "\n";
break;
}
}
}
std::string HttpRequest::to_string()
{
std::string request = "";
request += method + " " + url + " " + version + "\r\n";
if (params.size()) for ( const auto& param : params) request += param.first + ": " + param.second + "\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)
{
//To do
status = "";
version = "";
params = HttpParams(0);
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;
}
}

@ -1,60 +0,0 @@
#pragma once
#include <bakanetpch.h>
#define HTTP_RES_200 "200 OK"
#define HTTP_RES_303 "303 See Other"
#define HTTP_RES_400 "400 Bad Request"
#define HTTP_RES_401 "401 Unauthorized"
#define HTTP_RES_402 "402 Payment Required"
#define HTTP_RES_403 "403 Forbidden"
#define HTTP_RES_404 "404 Not Found"
#define HTTP_RES_405 "405 Method Not Allowed"
#define HTTP_RES_406 "406 Not Acceptable"
#define HTTP_RES_408 "408 Request Timeout"
#define HTTPv1_1 "HTTP/1.1"
namespace Bk::Net {
using HttpParams = std::unordered_map<std::string, std::string>;
class HttpRequest
{
public:
HttpRequest(std::string method,
std::string url,
std::string version,
HttpParams params = HttpParams(0),
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 = HttpParams(0),
std::string body = "");
HttpReponse(std::string data);
std::string to_string();
std::string status;
std::string version;
HttpParams params;
std::string body;
};
}

@ -1,98 +0,0 @@
#include "server.h"
namespace Bk::Net {
HttpServer::HttpServer(IpAddress ip, int port)
{
socket = Socket::create(ip, port, IpProtocol::TCP);
radix = RadixTree();
}
HttpServer::~HttpServer()
{
delete socket;
}
void HttpServer::start()
{
bool running = socket->init() && socket->start(5);
while (running)
{
Socket* conn = socket->ack();
pool.queue([this, conn]()
{
route_request(conn, recv_request(conn));
delete conn;
});
}
pool.stop();
}
void HttpServer::get(std::string url, RequestHandler req_handler)
{
RadixTree* tree;
Tools::string_trim(url, " /");
auto splits = Tools::string_split(url, "/");
if ((tree = radix.get_node(splits->data(), splits->size()))) tree->value["GET"] = req_handler;
else radix.add_nodes(splits->data(), splits->size(), HttpMethodArray({{ "GET", req_handler }}));
}
void HttpServer::post(std::string url, RequestHandler req_handler)
{
RadixTree* tree;
Tools::string_trim(url, " /");
auto splits = Tools::string_split(url, "/");
if ((tree = radix.get_node(splits->data(), splits->size()))) tree->value["POST"] = req_handler;
else radix.add_nodes(splits->data(), splits->size(), HttpMethodArray({{ "POST", req_handler }}));
}
void HttpServer::del(std::string url, RequestHandler req_handler)
{
RadixTree* tree;
Tools::string_trim(url, " /");
auto splits = Tools::string_split(url, "/");
if ((tree = radix.get_node(splits->data(), splits->size()))) tree->value["DELETE"] = req_handler;
else radix.add_nodes(splits->data(), splits->size(), HttpMethodArray({{ "DELETE", req_handler }}));
}
void HttpServer::put(std::string url, RequestHandler req_handler)
{
RadixTree* tree;
Tools::string_trim(url, " /");
auto splits = Tools::string_split(url, "/");
if ((tree = radix.get_node(splits->data(), splits->size()))) tree->value["PUT"] = req_handler;
else radix.add_nodes(splits->data(), splits->size(), HttpMethodArray({{ "PUT", req_handler }}));
}
HttpRequest HttpServer::recv_request(Socket* conn)
{
Type::DataStream req;
std::vector<char> data;
do
{
data = conn->obtain(1024);
req.append_data(data);
} while(data.size() >= 1024);
int req_size = req.size();
if (req_size) return HttpRequest(std::string(req.pull<char>(req_size).release(), req_size));
return HttpRequest("", "", "");
}
void HttpServer::send_reponse(Socket* conn, HttpReponse res)
{
Type::DataStream res_packet;
std::string str_res = res.to_string();
res_packet.push<char>(str_res.c_str(), str_res.length());
conn->emit(res_packet.payload);
}
void HttpServer::route_request(Socket* conn, HttpRequest req)
{
std::string url = std::string(req.url);
Tools::string_trim(url, " /");
Tools::string_to_upper(req.method);
auto urls = Tools::string_split(url, "/");
auto handlers = radix.get_node(urls->data(), urls->size());
if (handlers && (handlers->value.find(req.method) != handlers->value.end())) { send_reponse(conn, handlers->value[req.method](req)); }
else send_reponse(conn, HttpReponse(HTTP_RES_404, "HTTP/1.1"));
}
}

@ -1,34 +0,0 @@
#pragma once
#include <bakanetpch.h>
#include <bakanet/core/ip_address.h>
#include <bakatools/thread/task_pool.h>
#include <bakanet/core/socket.h>
#include "packet.h"
namespace Bk::Net {
using RequestHandler = std::function<HttpReponse(HttpRequest& req)>;
using HttpMethodArray = std::unordered_map<std::string, RequestHandler>;
using RadixTree = Type::Trie<std::string, HttpMethodArray>;
class HttpServer
{
public:
HttpServer(IpAddress ip, int port);
~HttpServer();
void start();
void get(std::string url, RequestHandler req_handler);
void post(std::string url, RequestHandler req_handler);
void del(std::string url, RequestHandler req_handler);
void put(std::string url, RequestHandler req_handler);
private:
Socket* socket;
ThreadPool pool;
RadixTree radix;
HttpRequest recv_request(Socket* conn);
void send_reponse(Socket* conn, HttpReponse res);
void route_request(Socket* conn, HttpRequest req);
};
}

@ -1,33 +0,0 @@
#pragma once
#include <iostream>
#include <cstring>
#include <vector>
#include <string>
#include <exception>
#include <memory>
#include <cstdint>
#include <cctype>
#include <unordered_map>
#include <functional>
#include <thread>
#include <iterator>
#include <bakatools.h>
#if defined(BK_PLATFORM_WINDOWS)
#include <ws2tcpip.h>
#include <winsock2.h>
#include <tchar.h>
#pragma comment(lib,"WS2_32.lib")
#elif defined(BK_PLATFORM_LINUX)
#include <stdio.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/time.h>
#else
#error "Plaform not supported"
#endif

@ -1,43 +0,0 @@
#include <bakanet/core/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;
}
}

@ -1,13 +0,0 @@
#include <bakanet/core/ip_address.h>
namespace Bk::Net {
struct in_addr IpAddress::get_data()
{
struct in_addr addr;
if (!str.length()) {
addr.s_addr = INADDR_ANY;
return addr;
}
else if (inet_pton(AF_INET, str.c_str(), &addr) <= 0) BK_CORE_ERROR("IP processing failed ({0})", str);
return addr;
}
}

@ -1,104 +0,0 @@
#include "linux_socket.h"
#include <cstddef>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
namespace Bk::Net {
LinuxSocket::LinuxSocket(int id, struct sockaddr_in client_addr, IpVersion ver, IpProtocol proto)
: id(id), ip_proto(proto), addr(client_addr)
{
char* myIP = inet_ntoa(addr.sin_addr);
ip_addr = IpAddress(std::string(myIP), ver);
}
LinuxSocket::LinuxSocket(IpAddress ip, int port, IpProtocol proto)
: ip_addr(ip), ip_proto(proto)
{
//LinuxSocket creation step
if ((id = socket((int)ip_addr.version, (int)ip_proto, 0)) < 0)
{
BK_CORE_ERROR("Socket failed");
exit(EXIT_FAILURE);
}
addr.sin_addr = ip_addr.get_data();
addr.sin_family = (int)ip_addr.version;
addr.sin_port = htons(port);
}
LinuxSocket::~LinuxSocket()
{
if(id > 0) close(id);
}
bool LinuxSocket::init()
{
//Binding step
int status;
if ((status = bind(id, (struct sockaddr*)&addr, sizeof(addr)) < 0))
{
BK_CORE_ERROR("Binding failed");
return false;
}
return true;
}
bool LinuxSocket::start(int cpt_conn)
{
//Listening step
if (listen(id, cpt_conn) < 0)
{
BK_CORE_ERROR("Listening failed");
return false;
}
return true;
}
Socket* LinuxSocket::ack()
{
struct sockaddr_in client_addr;
socklen_t addrlen = sizeof(client_addr);
return new LinuxSocket(accept(id, (struct sockaddr*)&client_addr, &addrlen), client_addr, ip_addr.version, ip_proto);
}
bool LinuxSocket::conn()
{
if (connect(id, (struct sockaddr*)&addr, sizeof(addr)) != 0)
{
BK_CORE_ERROR("Connection failed");
return false;
}
return true;
}
bool LinuxSocket::isConnected()
{
char data = 0;
int read_size = recv(id, &data, 1, MSG_PEEK);
return (bool)read_size;
}
void LinuxSocket::emit(std::vector<char> packet)
{
size_t size = send(id, packet.data(), packet.size(), 0);
}
std::vector<char> LinuxSocket::obtain(int size)
{
if(size > this->size)
{
delete [] buffer;
buffer = new char[size];
this->size = size;
}
int read_size = recv(id, buffer, this->size - 1, 0);
if(read_size == -1) return std::vector<char>(0);
std::vector<char> packet(buffer, buffer + read_size);
return packet;
}
Socket* Socket::create(IpAddress ip, int port, IpProtocol proto)
{
return new LinuxSocket(ip, port, proto);
}
}

@ -1,35 +0,0 @@
#pragma once
#include <bakatools.h>
#include <bakanet/core/socket.h>
namespace Bk::Net {
class LinuxSocket : public Socket
{
public:
LinuxSocket(IpAddress ip, int port, IpProtocol proto);
LinuxSocket(int id, struct sockaddr_in client_addr, IpVersion ver, IpProtocol proto);
virtual ~LinuxSocket();
bool init() override;
bool start(int cpt_conn) override;
Socket* ack() override;
bool conn() override;
bool isConnected() override;
int get_raw_socket() override { return id; }
const std::string get_ip() override { return ip_addr.str; }
void emit(std::vector<char> packet) override;
std::vector<char> obtain(int size) override;
private:
Connection id;
int size = 1024;
char* buffer = new char[size];
struct sockaddr_in addr;
IpAddress ip_addr;
IpProtocol ip_proto;
};
}

@ -1,40 +0,0 @@
#include <bakanet/core/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;
char ip_address[INET6_ADDRSTRLEN];
memset(&hints, 0, sizeof hints);
hints.ai_family = (int)ipv;
hints.ai_socktype = SOCK_STREAM;
if (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;
}
}

@ -1,16 +0,0 @@
#include <bakanet/core/ip_address.h>
#include <string.h>
namespace Bk::Net {
struct in_addr IpAddress::get_data()
{
struct in_addr addr;
if (!str.length()) {
addr.s_addr = INADDR_ANY;
return addr;
}
int result = InetPtonW(AF_INET, std::wstring(str.begin(), str.end()).c_str(), &addr);
if (result <= 0) BK_CORE_ERROR("Bad IP {0}", result);
return addr;
}
}

@ -1,107 +0,0 @@
#include "windows_socket.h"
#include <iostream>
namespace Bk::Net {
int WindowsSocket::socket_count = 0;
WindowsSocket::WindowsSocket(int id, IpVersion ver, IpProtocol proto)
: id(id), ip_proto(proto), main(false)
{
char myIP[16] = " ";
socklen_t len = sizeof(addr);
getsockname(id, (struct sockaddr*)&addr, &len);
inet_ntop((int)ver, &addr, myIP, sizeof(myIP));
ip_addr = IpAddress(std::string(myIP, 16), ver);
}
WindowsSocket::WindowsSocket(IpAddress ip, int port, IpProtocol proto)
: ip_addr(ip), ip_proto(proto), main(true)
{
if (socket_count++ < 1)
{
WSADATA wsa_data;
int err;
err = WSAStartup(MAKEWORD(2, 2), &wsa_data);
if (err != 0)
{
BK_CORE_TRACE("WSA failed : {0}", WSAGetLastError());
WSACleanup();
exit(EXIT_FAILURE);
}
}
//WindowsSocket creation step
if ((id = (int)socket((int)ip_addr.version, (int)ip_proto, 0)) < 0)
{
BK_CORE_TRACE("Socket failed : {0}", WSAGetLastError());
exit(EXIT_FAILURE);
}
addr.sin_addr = ip_addr.get_data();
addr.sin_family = (int)ip_addr.version;
addr.sin_port = htons(port);
}
WindowsSocket::~WindowsSocket()
{
if (main && socket_count-- < 1) WSACleanup();
closesocket(id);
}
bool WindowsSocket::init()
{
//Binding step
int status;
if ((status = bind((SOCKET)id, (struct sockaddr*)&addr, sizeof(addr)) < 0))
{
BK_CORE_TRACE("Binding failed : {0}", WSAGetLastError());
return false;
}
return true;
}
bool WindowsSocket::start(int cpt_conn = SOMAXCONN)
{
//Listening step
if (listen(id, cpt_conn) == SOCKET_ERROR) { BK_CORE_TRACE("Listening failed : {0}", WSAGetLastError()); return false; }
return true;
}
Socket* WindowsSocket::ack()
{
socklen_t addrlen = sizeof(addr);
return new WindowsSocket(accept((SOCKET)id, (struct sockaddr*)&addr, &addrlen), ip_addr.version, ip_proto));
}
bool WindowsSocket::conn()
{
if (connect(id, (struct sockaddr*)&addr, sizeof(addr)) < 0) { return false; }
return true;
}
bool WindowsSocket::hasConnection(int seconds, int microseconds) {
struct timeval tv = { seconds, microseconds };
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(id, &rfds);
return select(id + 1, &rfds, (fd_set*)0, (fd_set*)0, &tv) > 0;
};
void WindowsSocket::emit(std::vector<char> packet)
{
send((SOCKET)id, packet.data(), packet.size(), 0);
}
std::vector<char> WindowsSocket::obtain(int size)
{
std::vector<char> buffer;
buffer.resize(size);
int read_size = recv((SOCKET)id, buffer.data(), buffer.size() - 1, 0);
buffer.resize(read_size);
return buffer;
}
Socket* Socket::create(IpAddress ip, int port, IpProtocol proto)
{
return new WindowsSocket(ip, port, proto);
}
}

@ -1,34 +0,0 @@
#pragma once
#include <bakanet/core/socket.h>
namespace Bk::Net {
class WindowsSocket : public Socket
{
public:
static int socket_count;
WindowsSocket(IpAddress ip, int port, IpProtocol proto);
WindowsSocket(int id, IpVersion ver, IpProtocol proto);
virtual ~WindowsSocket();
bool init() override;
bool start(int cpt_conn) override;
Socket* ack() override;
bool conn() override;
bool hasConnection(int seconds = 0, int microseconds = 0) override;
int get_raw_socket() override { return id; }
const std::string get_ip() override { return ip_addr.str; }
void emit(std::vector<char> packet) override;
std::vector<char> obtain(int size) override;
private:
Connection id;
struct sockaddr_in addr;
IpAddress ip_addr;
IpProtocol ip_proto;
bool main;
};
}
Loading…
Cancel
Save