Add server sent events, change vfs structure, dark mode error pages and dark mode anonydrop
Some checks failed
Build and Deploy on Tag / build-arch (push) Failing after 8s
Build and Deploy on Tag / update-tap (push) Failing after 4s

This commit is contained in:
2026-04-23 02:23:22 -05:00
parent 3807bc5f36
commit 4cdfbc9542
12 changed files with 392 additions and 85 deletions

View File

@@ -6,7 +6,8 @@ on:
env: env:
PACKAGE_AND_BREW: ${{ secrets.PACKAGE_AND_BREW }} PACKAGE_AND_BREW: ${{ secrets.PACKAGE_AND_BREW }}
VERSION: ${{ gitea.ref_name }}
jobs: jobs:
build-arch: build-arch:
runs-on: arch-builder runs-on: arch-builder
@@ -20,3 +21,22 @@ jobs:
- run: chown build:build /home/build/PKGBUILD - run: chown build:build /home/build/PKGBUILD
- run: chown build:build /home/build/build-arch.sh - run: chown build:build /home/build/build-arch.sh
- run: su build -c /home/build/build-arch.sh - run: su build -c /home/build/build-arch.sh
update-tap:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v4
with:
ref: "master"
path: "tapdir"
repository: "tesses50/tesses-tap.git"
token: ${{ env.PACKAGE_AND_BREW }}
- run: |
cd tapdir
bash ../Packaging/edit-formula.sh
git config user.name "Tesses Gitea Bot"
git config user.email "noreply@tesses.net"
git add .
git commit -m "Push tesses-framework=${{ env.VERSION }}"
git push

19
Packaging/edit-formula.sh Normal file
View File

@@ -0,0 +1,19 @@
export HASH=`curl https://git.tesses.org/tesses50/tessesframework/archive/$VERSION.tar.gz 2> /dev/null | shasum -a 256 | awk '{print $1}'`
echo "class Tessesframework < Formula" > "Formula/tessesframework.rb"
echo " desc \"\"" >> "Formula/tessesframework.rb"
echo " homepage \"\"" >> "Formula/tessesframework.rb"
echo " url \"https://git.tesses.org/tesses50/tessesframework/archive/$VERSION.tar.gz\"" >> "Formula/tessesframework.rb"
echo " sha256 \"$HASH\"" >> "Formula/tessesframework.rb"
echo " license \"MIT\"" >> "Formula/tessesframework.rb"
echo " depends_on \"cmake\" => :build" >> "Formula/tessesframework.rb"
echo " depends_on \"mbedtls@3\"" >> "Formula/tessesframework.rb"
echo " def install" >> "Formula/tessesframework.rb"
echo " system \"cmake\", \"-S\", \".\", \"-B\", \"build\", \"-DTESSESFRAMEWORK_FETCHCONTENT=OFF\", *std_cmake_args" >> "Formula/tessesframework.rb"
echo " system \"cmake\", \"--build\", \"build\"" >> "Formula/tessesframework.rb"
echo " system \"cmake\", \"--install\", \"build\"" >> "Formula/tessesframework.rb"
echo " end" >> "Formula/tessesframework.rb"
echo " test do" >> "Formula/tessesframework.rb"
echo " system \"true\"" >> "Formula/tessesframework.rb"
echo " end" >> "Formula/tessesframework.rb"
echo "end" >> "Formula/tessesframework.rb"

View File

@@ -1,5 +1,8 @@
# Changelog # Changelog
## 0.0.3
Add server sent events, change vfs structure, dark mode error pages and dark mode anonydrop
## 0.0.2 ## 0.0.2
Add UUIDs Add UUIDs

View File

@@ -8,6 +8,9 @@ using namespace Tesses::Framework::Http;
using namespace Tesses::Framework::Streams; using namespace Tesses::Framework::Streams;
using namespace Tesses::Framework::TextStreams; using namespace Tesses::Framework::TextStreams;
using namespace Tesses::Framework::Threading; using namespace Tesses::Framework::Threading;
std::shared_ptr<ServerSentEvents> sse = std::make_shared<ServerSentEvents>();
class Johnny : public ServerContextData class Johnny : public ServerContextData
{ {
public: public:
@@ -65,7 +68,7 @@ class MyWebServer : public IHttpServer {
for(size_t i=0;i<10000; i++) for(size_t i=0;i<10000; i++)
{ {
writer.WriteLine("<li>" + std::to_string(i) + "</li>"); writer.WriteLine("<li>" + std::to_string(i) + "</li>");
TF_Sleep(10);
} }
writer.WriteLine("</ul>"); writer.WriteLine("</ul>");
@@ -74,6 +77,15 @@ class MyWebServer : public IHttpServer {
writer.WriteLine("</html>"); writer.WriteLine("</html>");
return true; return true;
} }
else if(ctx.path == "/ssetest.html")
{
}
else if(ctx.path == "/sse")
{
ctx.SendServerSentEvents(sse);
return true;
}
else if(ctx.path == "/main.js") else if(ctx.path == "/main.js")
{ {
@@ -162,6 +174,13 @@ class MyOtherWebServer : public IHttpServer
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
TF_InitWithConsole(); TF_InitWithConsole();
int64_t timer = 0;
auto timerHDL= TF_Timer([&timer]()->void{
timer++;
sse->SendData("Timer has ticked " + std::to_string(timer) + " times now");
});
std::shared_ptr<RouteServer> routeSvr = std::make_shared<RouteServer>(); std::shared_ptr<RouteServer> routeSvr = std::make_shared<RouteServer>();
routeSvr->Get("/name/{name}/greeting",[](ServerContext& ctx)->bool{ routeSvr->Get("/name/{name}/greeting",[](ServerContext& ctx)->bool{
std::string name; std::string name;

View File

@@ -67,7 +67,7 @@ namespace Tesses::Framework
std::shared_ptr<TF_Timer_Handle> TF_Timer(); std::shared_ptr<TF_Timer_Handle> TF_Timer();
std::shared_ptr<TF_Timer_Handle> TF_Timer(std::function<void()> cb, int64_t interval=1000, bool enabled=true); std::shared_ptr<TF_Timer_Handle> TF_Timer(std::function<void()> cb, int64_t interval=1000, bool enabled=true);
std::shared_ptr<TF_Timer_Handle> TF_Timer(std::function<void()> cb, std::chrono::milliseconds interval, bool enabled=true); std::shared_ptr<TF_Timer_Handle> TF_Timer(std::function<void()> cb, std::chrono::milliseconds interval, bool enabled=true);
void TF_Init(); void TF_Init();
void TF_InitWithConsole(); void TF_InitWithConsole();
void TF_AllowPortable(std::string argv0); void TF_AllowPortable(std::string argv0);
@@ -76,6 +76,7 @@ namespace Tesses::Framework
void TF_RunEventLoop(); void TF_RunEventLoop();
void TF_RunEventLoopItteration(); void TF_RunEventLoopItteration();
bool TF_IsRunning(); bool TF_IsRunning();
void TF_Sleep(uint32_t sleepMS);
void TF_SetIsRunning(bool _isRunning); void TF_SetIsRunning(bool _isRunning);
void TF_Quit(); void TF_Quit();
bool TF_GetConsoleEventsEnabled(); bool TF_GetConsoleEventsEnabled();

View File

@@ -13,12 +13,30 @@ namespace Tesses::Framework::Http
public: public:
virtual ~ServerContextData(); virtual ~ServerContextData();
}; };
class ServerContext;
class ServerSentEvents {
std::vector<std::shared_ptr<Tesses::Framework::Streams::Stream>> strms;
Tesses::Framework::Threading::Mutex mtx;
private:
void SendEventRaw(const std::string& evt);
public:
void SendRetry(uint32_t ms);
void SendRetry(std::chrono::milliseconds ms);
void SendRetry(Tesses::Framework::Date::TimeSpan ts);
void SendData(const std::string& message);
void SendData(const std::string& message, const std::string& dataType);
void SendId(const std::string& idVal);
void SendCustomEvent(const std::string& type, const std::string& value);
void SendComment(const std::string& comment);
friend class ServerContext;
};
class ServerContext { class ServerContext {
bool sent; bool sent;
bool debug; bool debug;
std::vector<std::shared_ptr<ServerSentEvents>> sse;
std::shared_ptr<Tesses::Framework::Streams::Stream> strm; std::shared_ptr<Tesses::Framework::Streams::Stream> strm;
std::map<std::string,ServerContextData*> data; std::map<std::string,ServerContextData*> data;
std::queue<std::function<bool(ServerContext& ctx)>> headerhandlers; std::queue<std::function<bool(ServerContext& ctx)>> headerhandlers;
@@ -54,6 +72,7 @@ namespace Tesses::Framework::Http
void SendNotFound(); void SendNotFound();
void SendBadRequest(); void SendBadRequest();
void SendException(std::exception& ex); void SendException(std::exception& ex);
void SendServerSentEvents(std::shared_ptr<ServerSentEvents> sse);
std::shared_ptr<Tesses::Framework::Streams::Stream> OpenResponseStream(); std::shared_ptr<Tesses::Framework::Streams::Stream> OpenResponseStream();
std::shared_ptr<Tesses::Framework::Streams::Stream> OpenRequestStream(); std::shared_ptr<Tesses::Framework::Streams::Stream> OpenRequestStream();
ServerContext& WithStatusCode(StatusCode code); ServerContext& WithStatusCode(StatusCode code);
@@ -87,6 +106,9 @@ namespace Tesses::Framework::Http
data[name] = item; data[name] = item;
return item; return item;
} }
friend class ServerSentEvents;
}; };
class IHttpServer { class IHttpServer {

View File

@@ -4,7 +4,7 @@
namespace Tesses::Framework::Streams namespace Tesses::Framework::Streams
{ {
class NetworkStream; class NetworkStream;
class TcpServer { class TcpServer {
int32_t sock; int32_t sock;
bool owns; bool owns;
@@ -20,7 +20,7 @@ namespace Tesses::Framework::Streams
~TcpServer(); ~TcpServer();
bool IsValid(); bool IsValid();
void Close(); void Close();
}; };
enum class SocketType { enum class SocketType {
ST_IPv4_TCP, ST_IPv4_TCP,
ST_IPv4_UDP, ST_IPv4_UDP,
@@ -46,14 +46,19 @@ namespace Tesses::Framework::Streams
void Listen(int32_t backlog); void Listen(int32_t backlog);
void Bind(std::string ip, uint16_t port); void Bind(std::string ip, uint16_t port);
void SetBroadcast(bool bC); void SetBroadcast(bool bC);
void SetReuseAddress(bool reuse);
void SetReusePort(bool reuse);
void SetMulticastTTL(uint8_t ttl);
void SetMulticastMembership(std::string multicastAddress, std::string ifaceIP="0.0.0.0");
std::shared_ptr<NetworkStream> Accept(std::string& ip, uint16_t& port); std::shared_ptr<NetworkStream> Accept(std::string& ip, uint16_t& port);
size_t Read(uint8_t* buff, size_t sz); size_t Read(uint8_t* buff, size_t sz);
size_t Write(const uint8_t* buff, size_t sz); size_t Write(const uint8_t* buff, size_t sz);
size_t ReadFrom(uint8_t* buff, size_t sz, std::string& ip, uint16_t& port); size_t ReadFrom(uint8_t* buff, size_t sz, std::string& ip, uint16_t& port);
size_t WriteTo(const uint8_t* buff, size_t sz, std::string ip, uint16_t port); size_t WriteTo(const uint8_t* buff, size_t sz, std::string ip, uint16_t port);
static std::vector<std::pair<std::string,std::string>> GetIPs(bool ipV6=false); static std::vector<std::pair<std::string,std::string>> GetIPs(bool ipV6=false);
~NetworkStream(); ~NetworkStream();
void SetNoDelay(bool noDelay); void SetNoDelay(bool noDelay);
void Close(); void Close();
}; };
} }

View File

@@ -27,6 +27,79 @@ using namespace Tesses::Framework::TextStreams;
namespace Tesses::Framework::Http namespace Tesses::Framework::Http
{ {
void ServerSentEvents::SendEventRaw(const std::string& evt)
{
this->mtx.Lock();
for(auto& item : this->strms)
{
try {
StreamWriter writer(item);
writer.newline = "\r\n";
writer.WriteLine(evt);
}catch(...) {
}
}
this->mtx.Unlock();
}
void ServerSentEvents::SendId(const std::string& id)
{
SendCustomEvent("id",id);
}
void ServerSentEvents::SendData(const std::string& message)
{
SendCustomEvent("data", message);
}
void ServerSentEvents::SendComment(const std::string& comment)
{
SendCustomEvent("", comment);
}
void ServerSentEvents::SendCustomEvent(const std::string& etype, const std::string& message)
{
std::string text = etype + ": ";
for(auto item : message)
{
if(item == '\r') continue;
if(item == '\n') {
text += "\r\n" + etype + ": ";
}
else text += item;
}
SendEventRaw(text);
}
void ServerSentEvents::SendData(const std::string& message, const std::string& mtype)
{
std::string text = "event: " + mtype + "\r\ndata: ";
for(auto item : message)
{
if(item == '\r') continue;
if(item == '\n') {
text += "\r\ndata: ";
}
else text += item;
}
SendEventRaw(text);
}
void ServerSentEvents::SendRetry(uint32_t ms)
{
SendCustomEvent("retry", std::to_string(ms));
}
void ServerSentEvents::SendRetry(std::chrono::milliseconds ms)
{
SendCustomEvent("retry", std::to_string(ms.count()));
}
void ServerSentEvents::SendRetry(Tesses::Framework::Date::TimeSpan ts)
{
SendRetry((uint32_t)ts.TotalSeconds() * 1000);
}
class WSServer class WSServer
{ {
public: public:
@@ -282,6 +355,7 @@ namespace Tesses::Framework::Http
this->conn->OnClose(false); this->conn->OnClose(false);
} }
}; };
/* /*
static int _header_field(multipart_parser* p, const char *at, size_t length) static int _header_field(multipart_parser* p, const char *at, size_t length)
{ {
@@ -344,6 +418,7 @@ namespace Tesses::Framework::Http
data->currentHeaders.Clear(); data->currentHeaders.Clear();
return 0; return 0;
}*/ }*/
std::string ServerContext::GetUrlWithQuery() std::string ServerContext::GetUrlWithQuery()
{ {
if(this->queryParams.kvp.empty()) return this->path; if(this->queryParams.kvp.empty()) return this->path;
@@ -364,6 +439,34 @@ namespace Tesses::Framework::Http
} }
} }
void ServerContext::SendServerSentEvents(std::shared_ptr<ServerSentEvents> sse)
{
this->responseHeaders.SetValue("X-Accel-Buffering","no");
this->responseHeaders.SetValue("Content-Type","text/event-stream");
this->responseHeaders.SetValue("Cache-Control","no-cache");
auto strm = this->OpenResponseStream();
if(strm == nullptr || this->method == "HEAD") return;
sse->mtx.Lock();
sse->strms.push_back(strm);
sse->mtx.Unlock();
while(!this->strm->EndOfStream())
{
TF_Sleep(10);
}
sse->mtx.Lock();
for(auto index = sse->strms.begin(); index != sse->strms.end(); index++)
{
if(*index == strm)
{
sse->strms.erase(index);
break;
}
}
sse->mtx.Unlock();
}
std::string ServerContext::ReadString() std::string ServerContext::ReadString()
{ {
if(strm == nullptr) return {}; if(strm == nullptr) return {};

View File

@@ -160,20 +160,30 @@ namespace Tesses::Framework::Http
if(this->length == -1 && this->http1_1 && !done && !this->recv) if(this->length == -1 && this->http1_1 && !done && !this->recv)
{ {
this->done=true; this->done=true;
StreamWriter writer(this->strm); try {
writer.newline = "\r\n";
writer.WriteLine("0"); StreamWriter writer(this->strm);
writer.WriteLine(); writer.newline = "\r\n";
writer.WriteLine("0");
writer.WriteLine();
}catch(...){
}
} }
} }
HttpStream::~HttpStream() HttpStream::~HttpStream()
{ {
if(this->length == -1 && this->http1_1 && !done && !this->recv) if(this->length == -1 && this->http1_1 && !done && !this->recv)
{ {
try {
StreamWriter writer(this->strm); StreamWriter writer(this->strm);
writer.newline = "\r\n"; writer.newline = "\r\n";
writer.WriteLine("0"); writer.WriteLine("0");
writer.WriteLine(); writer.WriteLine();
}catch(...) {
}
} }
} }
} }

View File

@@ -1,8 +1,10 @@
#include "TessesFramework/Streams/NetworkStream.hpp" #include "TessesFramework/Streams/NetworkStream.hpp"
#include "TessesFramework/Http/HttpUtils.hpp" #include "TessesFramework/Http/HttpUtils.hpp"
#include <TessesFramework/Streams/NetworkStream.hpp>
#include <iostream> #include <iostream>
#include <cstring> #include <cstring>
using HttpUtils = Tesses::Framework::Http::HttpUtils; using HttpUtils = Tesses::Framework::Http::HttpUtils;
#if defined(TESSESFRAMEWORK_ENABLE_NETWORKING) #if defined(TESSESFRAMEWORK_ENABLE_NETWORKING)
@@ -11,7 +13,7 @@ using HttpUtils = Tesses::Framework::Http::HttpUtils;
#define ss_family sin_family #define ss_family sin_family
#endif #endif
#if defined(GEKKO) && !(defined(TESSESFRAMEWORK_USE_WII_SOCKET) && defined(HW_RVL)) #if defined(GEKKO) && !(defined(TESSESFRAMEWORK_USE_WII_SOCKET) && defined(HW_RVL))
#include <network.h> #include <network.h>
#define NETWORK_GETSOCKNAME net_getsockname #define NETWORK_GETSOCKNAME net_getsockname
#define NETWORK_RECV net_recv #define NETWORK_RECV net_recv
@@ -34,6 +36,8 @@ using HttpUtils = Tesses::Framework::Http::HttpUtils;
#endif #endif
#undef min #undef min
#pragma comment(lib, "ws2_32.lib") #pragma comment(lib, "ws2_32.lib")
#else #else
extern "C" { extern "C" {
@@ -47,6 +51,7 @@ extern "C" {
#if defined(AF_UNIX) && !defined(GEKKO) && !defined(__SWITCH__) && !defined(__PS2__) #if defined(AF_UNIX) && !defined(GEKKO) && !defined(__SWITCH__) && !defined(__PS2__)
#include <sys/un.h> #include <sys/un.h>
#endif #endif
#include <poll.h> #include <poll.h>
} }
#endif #endif
@@ -88,7 +93,7 @@ namespace Tesses::Framework::Streams {
std::vector<std::pair<std::string,std::string>> NetworkStream::GetIPs(bool ipV6) std::vector<std::pair<std::string,std::string>> NetworkStream::GetIPs(bool ipV6)
{ {
std::vector<std::pair<std::string, std::string>> ipConfig; std::vector<std::pair<std::string, std::string>> ipConfig;
#if defined(GEKKO) #if defined(GEKKO)
//if_config( char *local_ip, char *netmask, char *gateway,bool use_dhcp, int max_retries); //if_config( char *local_ip, char *netmask, char *gateway,bool use_dhcp, int max_retries);
char localIp[16]; char localIp[16];
@@ -103,7 +108,7 @@ namespace Tesses::Framework::Streams {
ULONG size = 15000; ULONG size = 15000;
PIP_ADAPTER_ADDRESSES addresses = NULL; PIP_ADAPTER_ADDRESSES addresses = NULL;
addresses = (PIP_ADAPTER_ADDRESSES)malloc(size); addresses = (PIP_ADAPTER_ADDRESSES)malloc(size);
int retval = GetAdaptersAddresses(family, flags, 0, addresses, &size); int retval = GetAdaptersAddresses(family, flags, 0, addresses, &size);
if(retval != 0) { if(retval != 0) {
free(addresses); free(addresses);
@@ -145,15 +150,15 @@ namespace Tesses::Framework::Streams {
if (ifa->ifa_addr == NULL) if (ifa->ifa_addr == NULL)
continue; continue;
if (ifa->ifa_addr->sa_family == AF_INET) { // IPv4 if (ifa->ifa_addr->sa_family == AF_INET) { // IPv4
ipConfig.push_back(std::pair<std::string,std::string>(ifa->ifa_name, StringifyIP(ifa->ifa_addr))); ipConfig.push_back(std::pair<std::string,std::string>(ifa->ifa_name, StringifyIP(ifa->ifa_addr)));
} }
#if defined(AF_INET6) #if defined(AF_INET6)
if (ifa->ifa_addr->sa_family == AF_INET6 && ipV6) { // IPv6 if (ifa->ifa_addr->sa_family == AF_INET6 && ipV6) { // IPv6
ipConfig.push_back(std::pair<std::string,std::string>(ifa->ifa_name, StringifyIP(ifa->ifa_addr))); ipConfig.push_back(std::pair<std::string,std::string>(ifa->ifa_name, StringifyIP(ifa->ifa_addr)));
} }
#endif #endif
} }
@@ -161,7 +166,7 @@ namespace Tesses::Framework::Streams {
freeifaddrs(ifAddrStruct); freeifaddrs(ifAddrStruct);
#endif #endif
return ipConfig; return ipConfig;
} }
void SetPort(struct sockaddr* addr, uint16_t port) void SetPort(struct sockaddr* addr, uint16_t port)
{ {
@@ -175,10 +180,10 @@ namespace Tesses::Framework::Streams {
{ {
struct sockaddr_in6* a = (struct sockaddr_in6*)addr;\ struct sockaddr_in6* a = (struct sockaddr_in6*)addr;\
a->sin6_port = htons(port); a->sin6_port = htons(port);
} }
#endif #endif
} }
static uint16_t getPort(struct sockaddr* addr) static uint16_t getPort(struct sockaddr* addr)
{ {
@@ -192,13 +197,13 @@ namespace Tesses::Framework::Streams {
{ {
struct sockaddr_in6* a = (struct sockaddr_in6*)addr;\ struct sockaddr_in6* a = (struct sockaddr_in6*)addr;\
return ntohs(a->sin6_port); return ntohs(a->sin6_port);
} }
#endif #endif
return 0; return 0;
} }
bool IPParse(std::string str,struct sockaddr_storage* addr) bool IPParse(std::string str,struct sockaddr_storage* addr)
{ {
memset(addr,0,sizeof(struct sockaddr_storage)); memset(addr,0,sizeof(struct sockaddr_storage));
uint8_t ip[16]; uint8_t ip[16];
@@ -218,7 +223,7 @@ namespace Tesses::Framework::Streams {
{ {
struct sockaddr_in6* inAddr = (struct sockaddr_in6*)addr; struct sockaddr_in6* inAddr = (struct sockaddr_in6*)addr;
inAddr->sin6_family = AF_INET6; inAddr->sin6_family = AF_INET6;
memcpy(&inAddr->sin6_addr,ip,16); memcpy(&inAddr->sin6_addr,ip,16);
return 6; return 6;
@@ -281,9 +286,9 @@ namespace Tesses::Framework::Streams {
HttpUtils::NibbleToHex(ip[15] & 0x0F), HttpUtils::NibbleToHex(ip[15] & 0x0F),
}); });
} }
#endif #endif
return ""; return "";
@@ -293,7 +298,7 @@ namespace Tesses::Framework::Streams {
uint32_t addr; uint32_t addr;
uint8_t addr_parts[4]; uint8_t addr_parts[4];
} my_addr_t; } my_addr_t;
bool NetworkStream::DataAvailable(int timeout) bool NetworkStream::DataAvailable(int timeout)
{ {
pollfd fd; pollfd fd;
@@ -314,7 +319,7 @@ namespace Tesses::Framework::Streams {
} }
return false; return false;
} }
NetworkStream::NetworkStream(std::string unixPath,bool isServer) NetworkStream::NetworkStream(std::string unixPath,bool isServer)
{ {
this->endOfStream=false; this->endOfStream=false;
@@ -328,12 +333,12 @@ namespace Tesses::Framework::Streams {
return; return;
} }
struct sockaddr_un unx; struct sockaddr_un unx;
memset(&unx, 0, sizeof(unx)); memset(&unx, 0, sizeof(unx));
unx.sun_family = AF_UNIX; unx.sun_family = AF_UNIX;
strncpy(unx.sun_path, unixPath.c_str(),sizeof(unx.sun_path)-1); strncpy(unx.sun_path, unixPath.c_str(),sizeof(unx.sun_path)-1);
if(isServer) if(isServer)
{ {
unlink(unixPath.c_str()); unlink(unixPath.c_str());
@@ -344,7 +349,7 @@ namespace Tesses::Framework::Streams {
return; return;
} }
} }
else else
{ {
if(NETWORK_CONNECT(this->sock,(const sockaddr*)&unx, (socklen_t)sizeof(unx)) != 0) if(NETWORK_CONNECT(this->sock,(const sockaddr*)&unx, (socklen_t)sizeof(unx)) != 0)
{ {
@@ -360,7 +365,7 @@ namespace Tesses::Framework::Streams {
TcpServer::TcpServer(std::string unixPath,int32_t backlog) TcpServer::TcpServer(std::string unixPath,int32_t backlog)
{ {
this->owns=true; this->owns=true;
this->valid=false; this->valid=false;
#if defined(AF_UNIX) && !defined(GEKKO) && !defined(__PS2__) && !defined(__SWITCH__) && ((defined(_WIN32) && defined(HAS_AFUNIX) ) || !defined(_WIN32)) #if defined(AF_UNIX) && !defined(GEKKO) && !defined(__PS2__) && !defined(__SWITCH__) && ((defined(_WIN32) && defined(HAS_AFUNIX) ) || !defined(_WIN32))
@@ -372,7 +377,7 @@ namespace Tesses::Framework::Streams {
return; return;
} }
struct sockaddr_un unx; struct sockaddr_un unx;
memset(&unx, 0, sizeof(unx)); memset(&unx, 0, sizeof(unx));
unx.sun_family = AF_UNIX; unx.sun_family = AF_UNIX;
unlink(unixPath.c_str()); unlink(unixPath.c_str());
@@ -384,7 +389,7 @@ namespace Tesses::Framework::Streams {
return; return;
} }
if(NETWORK_LISTEN(this->sock, backlog) != 0) if(NETWORK_LISTEN(this->sock, backlog) != 0)
{ {
std::cout << "FAILED TO LISTEN FOR SOME REASON" << std::endl; std::cout << "FAILED TO LISTEN FOR SOME REASON" << std::endl;
this->valid = false; this->valid = false;
@@ -397,14 +402,14 @@ namespace Tesses::Framework::Streams {
TcpServer::TcpServer(uint16_t port, int32_t backlog) TcpServer::TcpServer(uint16_t port, int32_t backlog)
{ {
this->owns=true; this->owns=true;
this->sock = NETWORK_SOCKET(AF_INET, SOCK_STREAM, 0); this->sock = NETWORK_SOCKET(AF_INET, SOCK_STREAM, 0);
if(this->sock < 0) if(this->sock < 0)
{ {
std::cout << "FAILED TO CREATE SOCKET FOR SOME REASON" << std::endl; std::cout << "FAILED TO CREATE SOCKET FOR SOME REASON" << std::endl;
this->valid=false; this->valid=false;
return; return;
} }
struct sockaddr_in addr; struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
@@ -436,7 +441,7 @@ namespace Tesses::Framework::Streams {
return; return;
} }
if(NETWORK_LISTEN(this->sock, backlog) != 0) if(NETWORK_LISTEN(this->sock, backlog) != 0)
{ {
std::cout << "FAILED TO LISTEN FOR SOME REASON" << std::endl; std::cout << "FAILED TO LISTEN FOR SOME REASON" << std::endl;
this->valid = false; this->valid = false;
@@ -496,24 +501,24 @@ namespace Tesses::Framework::Streams {
uint8_t ipBytes[16]; uint8_t ipBytes[16];
bool success = IPParse(ip, &addr); bool success = IPParse(ip, &addr);
if(!success) if(!success)
{ {
this->valid=false; this->valid=false;
return; return;
} }
SetPort((struct sockaddr*)&addr, port); SetPort((struct sockaddr*)&addr, port);
this->sock = NETWORK_SOCKET((int)addr.ss_family, SOCK_STREAM, 0); this->sock = NETWORK_SOCKET((int)addr.ss_family, SOCK_STREAM, 0);
if(this->sock < 0) if(this->sock < 0)
{ {
this->valid=false; this->valid=false;
return; return;
} }
if(NETWORK_BIND(this->sock, (const sockaddr*)&addr, (socklen_t)sizeof(addr)) != 0) if(NETWORK_BIND(this->sock, (const sockaddr*)&addr, (socklen_t)sizeof(addr)) != 0)
{ {
@@ -522,7 +527,7 @@ namespace Tesses::Framework::Streams {
return; return;
} }
if(NETWORK_LISTEN(this->sock, backlog) != 0) if(NETWORK_LISTEN(this->sock, backlog) != 0)
{ {
this->valid = false; this->valid = false;
return; return;
@@ -554,7 +559,7 @@ namespace Tesses::Framework::Streams {
struct sockaddr_storage storage; struct sockaddr_storage storage;
memset(&storage,0, sizeof(storage)); memset(&storage,0, sizeof(storage));
socklen_t addrlen=(socklen_t)sizeof(storage); socklen_t addrlen=(socklen_t)sizeof(storage);
int s = NETWORK_ACCEPT(this->sock, (struct sockaddr*)&storage, &addrlen); int s = NETWORK_ACCEPT(this->sock, (struct sockaddr*)&storage, &addrlen);
if(s < 0) if(s < 0)
{ {
@@ -563,7 +568,7 @@ namespace Tesses::Framework::Streams {
ip = StringifyIP((struct sockaddr*)&storage); ip = StringifyIP((struct sockaddr*)&storage);
port = getPort((struct sockaddr*)&storage); port = getPort((struct sockaddr*)&storage);
return std::make_shared<NetworkStream>(s,true); return std::make_shared<NetworkStream>(s,true);
} }
bool NetworkStream::CanRead() bool NetworkStream::CanRead()
@@ -584,32 +589,32 @@ namespace Tesses::Framework::Streams {
case SocketType::ST_IPv4_TCP: case SocketType::ST_IPv4_TCP:
#if defined(AF_INET) #if defined(AF_INET)
this->sock = NETWORK_SOCKET(AF_INET,SOCK_STREAM, 0); this->sock = NETWORK_SOCKET(AF_INET,SOCK_STREAM, 0);
#endif #endif
break; break;
case SocketType::ST_IPv4_UDP: case SocketType::ST_IPv4_UDP:
#if defined(AF_INET) #if defined(AF_INET)
this->sock = NETWORK_SOCKET(AF_INET,SOCK_DGRAM, 0); this->sock = NETWORK_SOCKET(AF_INET,SOCK_DGRAM, 0);
#endif #endif
break; break;
case SocketType::ST_IPv6_TCP: case SocketType::ST_IPv6_TCP:
#if defined(AF_INET6) #if defined(AF_INET6)
this->sock = NETWORK_SOCKET(AF_INET6,SOCK_STREAM, 0); this->sock = NETWORK_SOCKET(AF_INET6,SOCK_STREAM, 0);
#endif #endif
break; break;
case SocketType::ST_IPv6_UDP: case SocketType::ST_IPv6_UDP:
#if defined(AF_INET6) #if defined(AF_INET6)
this->sock = NETWORK_SOCKET(AF_INET6,SOCK_DGRAM, 0); this->sock = NETWORK_SOCKET(AF_INET6,SOCK_DGRAM, 0);
#endif #endif
break; break;
case SocketType::ST_UNIX: case SocketType::ST_UNIX:
#if defined(AF_UNIX) && ((defined(_WIN32) && defined(HAS_AFUNIX) ) || !defined(_WIN32)) #if defined(AF_UNIX) && ((defined(_WIN32) && defined(HAS_AFUNIX) ) || !defined(_WIN32))
this->sock = NETWORK_SOCKET(AF_UNIX,SOCK_DGRAM, 0); this->sock = NETWORK_SOCKET(AF_UNIX,SOCK_DGRAM, 0);
#endif #endif
break; break;
} }
@@ -621,7 +626,7 @@ namespace Tesses::Framework::Streams {
this->owns=true; this->owns=true;
this->success=false; this->success=false;
std::string portStr = std::to_string((uint32_t)port); std::string portStr = std::to_string((uint32_t)port);
struct addrinfo hint; struct addrinfo hint;
memset(&hint, 0, sizeof(hint)); memset(&hint, 0, sizeof(hint));
#if defined(AF_INET6) #if defined(AF_INET6)
@@ -631,7 +636,7 @@ namespace Tesses::Framework::Streams {
#endif #endif
hint.ai_socktype = datagram ? SOCK_DGRAM : SOCK_STREAM; hint.ai_socktype = datagram ? SOCK_DGRAM : SOCK_STREAM;
struct addrinfo* result; struct addrinfo* result;
int status = NETWORK_GETADDRINFO(ipOrFqdn.c_str(),portStr.c_str(), &hint, &result); int status = NETWORK_GETADDRINFO(ipOrFqdn.c_str(),portStr.c_str(), &hint, &result);
@@ -680,11 +685,11 @@ namespace Tesses::Framework::Streams {
return this->endOfStream; return this->endOfStream;
} }
void NetworkStream::Listen(int32_t backlog) void NetworkStream::Listen(int32_t backlog)
{ {
if(this->success) if(this->success)
NETWORK_LISTEN(this->sock, backlog); NETWORK_LISTEN(this->sock, backlog);
} }
void NetworkStream::Bind(std::string ip, uint16_t port) void NetworkStream::Bind(std::string ip, uint16_t port)
{ {
if(!this->success) return; if(!this->success) return;
@@ -693,14 +698,14 @@ namespace Tesses::Framework::Streams {
uint8_t ipBytes[16]; uint8_t ipBytes[16];
bool success = IPParse(ip, &addr); bool success = IPParse(ip, &addr);
if(!success) if(!success)
{ {
this->success=false; this->success=false;
if(this->owns) if(this->owns)
NETWORK_CLOSE(this->sock); NETWORK_CLOSE(this->sock);
return; return;
} }
SetPort((struct sockaddr*)&addr, port); SetPort((struct sockaddr*)&addr, port);
int on=1; int on=1;
#if defined(SO_REUSEPORT) #if defined(SO_REUSEPORT)
@@ -720,16 +725,81 @@ namespace Tesses::Framework::Streams {
return; return;
} }
} }
void NetworkStream::SetBroadcast(bool bC) void NetworkStream::SetReuseAddress(bool reuse)
{ {
if(!this->success) return; if(!this->success) return;
int broadcast = 1; int no = reuse ? 1 : 0;
if (NETWORK_SETSOCKOPT(sock, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof(broadcast)) != 0) if (NETWORK_SETSOCKOPT(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&no, sizeof(no)) != 0)
{ {
this->success=false; this->success=false;
if(this->owns) if(this->owns)
NETWORK_CLOSE(this->sock); NETWORK_CLOSE(this->sock);
}
}
void NetworkStream::SetReusePort(bool reuse)
{
if(!this->success) return;
int no = reuse ? 1 : 0;
if (NETWORK_SETSOCKOPT(sock, SOL_SOCKET, SO_REUSEPORT, (const char*)&no, sizeof(no)) != 0)
{
this->success=false;
if(this->owns)
NETWORK_CLOSE(this->sock);
}
}
void NetworkStream::SetMulticastTTL(uint8_t ttl)
{
if(!this->success) return;
#if defined(IPPROTO_IP) && defined(IP_MULTICAST_TTL)
if (NETWORK_SETSOCKOPT(sock, IPPROTO_IP, IP_MULTICAST_TTL, (const char*)&ttl, sizeof(ttl)) != 0)
{
this->success=false;
if(this->owns)
NETWORK_CLOSE(this->sock);
}
#endif
}
void NetworkStream::SetMulticastMembership(std::string multicastAddress, std::string ifaceIP)
{
if(!this->success) return;
#if defined(IPPROTO_IP) && defined(IP_MULTICAST_TTL)
struct sockaddr_storage maddr;
struct sockaddr_storage iaddr;
bool success = IPParse(multicastAddress, &maddr) && IPParse(ifaceIP, &iaddr);
if(success && maddr.ss_family == AF_INET && iaddr.ss_family == AF_INET)
{
struct ip_mreq req;
req.imr_multiaddr = ((struct sockaddr_in*)&maddr)->sin_addr;
req.imr_interface = ((struct sockaddr_in*)&iaddr)->sin_addr;
if(NETWORK_SETSOCKOPT(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*)&req, sizeof(req)) != 0)
{
this->success=false;
if(this->owns)
NETWORK_CLOSE(this->sock);
}
}
#endif
}
void NetworkStream::SetBroadcast(bool bC)
{
if(!this->success) return;
int broadcast = bC ? 1 : 0;
if (NETWORK_SETSOCKOPT(sock, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof(broadcast)) != 0)
{
this->success=false;
if(this->owns)
NETWORK_CLOSE(this->sock);
} }
} }
std::shared_ptr<NetworkStream> NetworkStream::Accept(std::string& ip, uint16_t& port) std::shared_ptr<NetworkStream> NetworkStream::Accept(std::string& ip, uint16_t& port)
@@ -745,12 +815,12 @@ namespace Tesses::Framework::Streams {
ip = StringifyIP((struct sockaddr*)&storage); ip = StringifyIP((struct sockaddr*)&storage);
port = getPort((struct sockaddr*)&storage); port = getPort((struct sockaddr*)&storage);
return std::make_shared<NetworkStream>((int32_t)s,(bool)true); return std::make_shared<NetworkStream>((int32_t)s,(bool)true);
} }
size_t NetworkStream::Read(uint8_t* buff, size_t sz) size_t NetworkStream::Read(uint8_t* buff, size_t sz)
{ {
if(!this->success) return 0; if(!this->success) return 0;
auto r = NETWORK_RECV(this->sock,(char*)buff,sz,0); auto r = NETWORK_RECV(this->sock,(char*)buff,sz,0);
@@ -759,20 +829,20 @@ namespace Tesses::Framework::Streams {
this->endOfStream=true; this->endOfStream=true;
return 0; return 0;
} }
return (size_t)r; return (size_t)r;
} }
size_t NetworkStream::Write(const uint8_t* buff, size_t sz) size_t NetworkStream::Write(const uint8_t* buff, size_t sz)
{ {
if(!this->success) return 0; if(!this->success) return 0;
auto sz2 = NETWORK_SEND(this->sock,(const char*)buff,sz, 0); auto sz2 = NETWORK_SEND(this->sock,(const char*)buff,sz, 0);
if(sz2 <= 0) { if(sz2 <= 0) {
this->endOfStream=true; this->endOfStream=true;
return 0; return 0;
} }
return (size_t)sz; return (size_t)sz;
} }
size_t NetworkStream::ReadFrom(uint8_t* buff, size_t sz, std::string& ip, uint16_t& port) size_t NetworkStream::ReadFrom(uint8_t* buff, size_t sz, std::string& ip, uint16_t& port)
@@ -786,10 +856,10 @@ namespace Tesses::Framework::Streams {
if(r < 0) return 0; if(r < 0) return 0;
return (size_t)r; return (size_t)r;
} }
size_t NetworkStream::WriteTo(const uint8_t* buff, size_t sz, std::string ip, uint16_t port) size_t NetworkStream::WriteTo(const uint8_t* buff, size_t sz, std::string ip, uint16_t port)
{ {
@@ -800,14 +870,14 @@ namespace Tesses::Framework::Streams {
uint8_t ipBytes[16]; uint8_t ipBytes[16];
bool success = IPParse(ip, &addr); bool success = IPParse(ip, &addr);
if(!success) if(!success)
{ {
this->success=false; this->success=false;
if(this->owns) if(this->owns)
NETWORK_CLOSE(this->sock); NETWORK_CLOSE(this->sock);
return 0; return 0;
} }
SetPort((struct sockaddr*)&addr, port); SetPort((struct sockaddr*)&addr, port);
auto sz2 = NETWORK_SENDTO(this->sock,(const char*)buff,sz, 0, (const sockaddr*)&addr, (socklen_t)sizeof(addr)); auto sz2 = NETWORK_SENDTO(this->sock,(const char*)buff,sz, 0, (const sockaddr*)&addr, (socklen_t)sizeof(addr));
if(sz2 < 0) return 0; if(sz2 < 0) return 0;
@@ -827,11 +897,11 @@ namespace Tesses::Framework::Streams {
} }
void NetworkStream::SetNoDelay(bool noDelay) void NetworkStream::SetNoDelay(bool noDelay)
{ {
int noDelay2 = noDelay; int noDelay2 = noDelay;
NETWORK_SETSOCKOPT(this->sock, SOL_SOCKET, TCP_NODELAY, (const char*)&noDelay2,(socklen_t)sizeof(noDelay2)); NETWORK_SETSOCKOPT(this->sock, SOL_SOCKET, TCP_NODELAY, (const char*)&noDelay2,(socklen_t)sizeof(noDelay2));
} }
} }
#else #else
namespace Tesses::Framework::Streams { namespace Tesses::Framework::Streams {
@@ -850,7 +920,7 @@ TcpServer::TcpServer(std::string ip, uint16_t port, int32_t backlog)
} }
TcpServer::TcpServer(std::string unixPath,int32_t backlog) TcpServer::TcpServer(std::string unixPath,int32_t backlog)
{ {
} }
std::shared_ptr<NetworkStream> TcpServer::GetStream(std::string& ip, uint16_t& port) std::shared_ptr<NetworkStream> TcpServer::GetStream(std::string& ip, uint16_t& port)
{ {
@@ -866,7 +936,7 @@ bool TcpServer::IsValid()
} }
void TcpServer::Close() void TcpServer::Close()
{ {
} }
bool NetworkStream::EndOfStream() { bool NetworkStream::EndOfStream() {
return true; return true;
@@ -877,7 +947,7 @@ bool NetworkStream::CanRead() {
bool NetworkStream::CanWrite() { bool NetworkStream::CanWrite() {
return false; return false;
} }
NetworkStream::NetworkStream(SocketType type) NetworkStream::NetworkStream(SocketType type)
{ {
@@ -888,7 +958,7 @@ NetworkStream::NetworkStream(std::string ipOrFqdn, uint16_t port, bool datagram,
} }
NetworkStream::NetworkStream(std::string unixPath, bool isServer) NetworkStream::NetworkStream(std::string unixPath, bool isServer)
{ {
} }
NetworkStream::NetworkStream(int32_t sock, bool owns) NetworkStream::NetworkStream(int32_t sock, bool owns)
{ {
@@ -906,6 +976,23 @@ void NetworkStream::SetBroadcast(bool bC)
{ {
} }
void NetworkStream::SetReuseAddress(bool reuse)
{
}
void NetworkStream::SetReusePort(bool reuse)
{
}
void NetworkStream::SetMulticastTTL(uint8_t ttl)
{
}
void NetworkStream::SetMulticastMembership(std::string multicastAddress, std::string ifaceIP="0.0.0.0")
{
}
std::shared_ptr<NetworkStream> NetworkStream::Accept(std::string& ip, uint16_t& port) std::shared_ptr<NetworkStream> NetworkStream::Accept(std::string& ip, uint16_t& port)
{ {
return nullptr; return nullptr;
@@ -936,7 +1023,7 @@ NetworkStream::~NetworkStream()
} }
void NetworkStream::SetNoDelay(bool noDelay) void NetworkStream::SetNoDelay(bool noDelay)
{ {
} }
void NetworkStream::Close() void NetworkStream::Close()
{ {

View File

@@ -49,7 +49,9 @@ namespace Tesses::Framework::Streams {
read = len; read = len;
if(read > 0) if(read > 0)
{ {
size_t r0=read;
read=this->Write(buffer,read); read=this->Write(buffer,read);
if(read == 0) if(read == 0)
{ {
throw std::out_of_range("Failed to write!"); throw std::out_of_range("Failed to write!");

View File

@@ -53,6 +53,10 @@ static GXRModeObj *rmode = NULL;
#endif #endif
#if !defined(_WIN32)
#include <unistd.h>
#endif
namespace Tesses::Framework namespace Tesses::Framework
{ {
@@ -85,7 +89,19 @@ namespace Tesses::Framework
cb(); cb();
#endif #endif
} }
void TF_Sleep(uint32_t sleepMS)
{
#if defined(_WIN32)
Sleep((DWORD)sleepMS);
#else
struct timespec ts;
ts.tv_sec = (time_t)(sleepMS / 1000);
ts.tv_nsec = (sleepMS % 1000) * 1000000;
nanosleep(&ts,NULL);
#endif
}
void TF_ConnectToSelf(uint16_t port) void TF_ConnectToSelf(uint16_t port)
{ {
Tesses::Framework::Streams::NetworkStream ns("127.0.0.1",port,false,false,false); Tesses::Framework::Streams::NetworkStream ns("127.0.0.1",port,false,false,false);