diff --git a/apps/tfetch.cpp b/apps/tfetch.cpp index 2506a53..9605a8e 100644 --- a/apps/tfetch.cpp +++ b/apps/tfetch.cpp @@ -8,11 +8,20 @@ int main(int argc, char** argv) if(argc < 3) { printf("USAGE: %s \n",argv[0]); + printf("USAGE: %s \n",argv[0]); return 1; } - std::string path = argv[2]; - Tesses::Framework::Http::DownloadToFileSimple(argv[1],path); - + if(argc >= 4) + { + std::string unixSocket = argv[1]; + std::string url = argv[2]; + std::string path = argv[3]; + Tesses::Framework::Http::DownloadUnixSocketToFileSimple(unixSocket,url,path); + } + else { + std::string path = argv[2]; + Tesses::Framework::Http::DownloadToFileSimple(argv[1],path); + } return 0; } \ No newline at end of file diff --git a/include/TessesFramework/Http/HttpClient.hpp b/include/TessesFramework/Http/HttpClient.hpp index 788af19..27d959b 100644 --- a/include/TessesFramework/Http/HttpClient.hpp +++ b/include/TessesFramework/Http/HttpClient.hpp @@ -45,10 +45,12 @@ namespace Tesses::Framework::Http std::string method; std::string url; + std::string unixSocket; HttpDictionary requestHeaders; HttpRequestBody* body; static Tesses::Framework::Streams::Stream* EstablishConnection(Uri uri,bool ignoreSSLErrors,std::string trusted_root_cert_bundle); + static Tesses::Framework::Streams::Stream* EstablishUnixPathConnection(std::string unixPath, Uri uri, bool ignoreSSLErrors, std::string trusted_root_cert_bundle); void SendRequest(Tesses::Framework::Streams::Stream* strm); }; @@ -77,8 +79,22 @@ namespace Tesses::Framework::Http void DownloadToFileSimple(std::string url, Tesses::Framework::Filesystem::VFS& vfs, Tesses::Framework::Filesystem::VFSPath path); void DownloadToFileSimple(std::string url, Tesses::Framework::Filesystem::VFSPath path); std::string DownloadToStringSimple(std::string url); + bool WebSocketClientSuccessDefault(HttpDictionary& dict,bool v); void WebSocketClient(std::string url, HttpDictionary& requestHeaders, WebSocketConnection& wsc, std::function cb=WebSocketClientSuccessDefault); void WebSocketClient(std::string url, HttpDictionary& requestHeaders, WebSocketConnection* wsc, std::function cb=WebSocketClientSuccessDefault); + + void DownloadUnixSocketToStreamSimple(std::string unixSocket,std::string url, Tesses::Framework::Streams::Stream* strm); + void DownloadUnixSocketToStreamSimple(std::string unixSocket,std::string url, Tesses::Framework::Streams::Stream& strm); + + void DownloadUnixSocketToFileSimple(std::string unixSocket,std::string url, Tesses::Framework::Filesystem::VFS* vfs, Tesses::Framework::Filesystem::VFSPath path); + void DownloadUnixSocketToFileSimple(std::string unixSocket,std::string url, Tesses::Framework::Filesystem::VFS& vfs, Tesses::Framework::Filesystem::VFSPath path); + + void DownloadUnixSocketToFileSimple(std::string unixSocket,std::string url, Tesses::Framework::Filesystem::VFSPath path); + std::string DownloadUnixSocketToStringSimple(std::string unixSocket,std::string url); + + + void WebSocketUnixSocketClient(std::string unixSocket,std::string url, HttpDictionary& requestHeaders, WebSocketConnection& wsc, std::function cb=WebSocketClientSuccessDefault); + void WebSocketUnixSocketClient(std::string unixSocket,std::string url,HttpDictionary& requestHeaders, WebSocketConnection* wsc, std::function cb=WebSocketClientSuccessDefault); } \ No newline at end of file diff --git a/include/TessesFramework/Http/HttpServer.hpp b/include/TessesFramework/Http/HttpServer.hpp index e17ab32..c66dfa3 100644 --- a/include/TessesFramework/Http/HttpServer.hpp +++ b/include/TessesFramework/Http/HttpServer.hpp @@ -88,6 +88,7 @@ namespace Tesses::Framework::Http bool ownsTCP; bool ownsHttp; bool showIPs; + bool showARTL; public: HttpServer(Tesses::Framework::Streams::TcpServer& tcpServer, IHttpServer& http, bool showIPs=true); @@ -96,6 +97,8 @@ namespace Tesses::Framework::Http HttpServer(Tesses::Framework::Streams::TcpServer* tcpServer, bool ownsTCP, IHttpServer* http, bool ownsHttpServer, bool showIPs=true); HttpServer(uint16_t port, IHttpServer& http, bool showIPs=true); HttpServer(uint16_t port, IHttpServer* http, bool owns, bool showIPs=true); + HttpServer(std::string unixPath, IHttpServer& http); + HttpServer(std::string unixPath, IHttpServer* http, bool owns); uint16_t GetPort(); void StartAccepting(); static void Process(Tesses::Framework::Streams::Stream& strm, IHttpServer& server, std::string ip, uint16_t port, bool encrypted); diff --git a/include/TessesFramework/Streams/NetworkStream.hpp b/include/TessesFramework/Streams/NetworkStream.hpp index 54ce08b..85ce07c 100644 --- a/include/TessesFramework/Streams/NetworkStream.hpp +++ b/include/TessesFramework/Streams/NetworkStream.hpp @@ -14,6 +14,7 @@ namespace Tesses::Framework::Streams TcpServer(int32_t sock,bool owns); TcpServer(uint16_t port, int32_t backlog); TcpServer(std::string ip, uint16_t port, int32_t backlog); + TcpServer(std::string unixPath,int32_t backlog); NetworkStream* GetStream(std::string& ip, uint16_t& port); uint16_t GetPort(); ~TcpServer(); @@ -30,6 +31,7 @@ namespace Tesses::Framework::Streams bool CanRead(); bool CanWrite(); NetworkStream(bool ipV6,bool datagram); + NetworkStream(std::string unixPath,bool isServer); NetworkStream(std::string ipOrFqdn, uint16_t port, bool datagram,bool broadcast,bool supportIPv6); NetworkStream(int32_t sock, bool owns); uint16_t GetPort(); diff --git a/src/Http/HttpClient.cpp b/src/Http/HttpClient.cpp index d4c28e0..461d7d9 100644 --- a/src/Http/HttpClient.cpp +++ b/src/Http/HttpClient.cpp @@ -117,7 +117,6 @@ namespace Tesses::Framework::Http body->Write(strm); } } - Stream* HttpRequest::EstablishConnection(Uri uri, bool ignoreSSLErrors, std::string trusted_root_cert_bundle) { if(uri.scheme == "http:" || uri.scheme == "ws:") @@ -127,7 +126,22 @@ namespace Tesses::Framework::Http else if(uri.scheme == "https:" || uri.scheme == "wss:") { auto netStrm = new NetworkStream(uri.host,uri.GetPort(),false,false,false); - if(netStrm == nullptr) return netStrm; + if(netStrm == nullptr) return nullptr; + return new ClientTLSStream(netStrm, true, ignoreSSLErrors,uri.host, trusted_root_cert_bundle); + } + + return nullptr; + } + Stream* HttpRequest::EstablishUnixPathConnection(std::string unixPath,Uri uri, bool ignoreSSLErrors, std::string trusted_root_cert_bundle) + { + if(uri.scheme == "http:" || uri.scheme == "ws:") + { + return new NetworkStream(unixPath,false); + } + else if(uri.scheme == "https:" || uri.scheme == "wss:") + { + auto netStrm = new NetworkStream(unixPath,false); + if(netStrm == nullptr) return nullptr; return new ClientTLSStream(netStrm, true, ignoreSSLErrors,uri.host, trusted_root_cert_bundle); } @@ -182,7 +196,7 @@ namespace Tesses::Framework::Http Uri uri; while(Uri::TryParse(url, uri)) { - auto strm = HttpRequest::EstablishConnection(uri, req.ignoreSSLErrors,req.trusted_root_cert_bundle); + auto strm = req.unixSocket.empty() ? HttpRequest::EstablishConnection(uri, req.ignoreSSLErrors,req.trusted_root_cert_bundle) : HttpRequest::EstablishUnixPathConnection(req.unixSocket,uri, req.ignoreSSLErrors,req.trusted_root_cert_bundle); if(strm == nullptr) return; auto reqHeaders = req.requestHeaders; @@ -284,50 +298,84 @@ namespace Tesses::Framework::Http return new HttpStream(this->handleStrm,false,length,true,version=="HTTP/1.1"); } - void DownloadToStreamSimple(std::string url, Tesses::Framework::Streams::Stream* strm) + void DownloadUnixSocketToStreamSimple(std::string unixSocket,std::string url, Tesses::Framework::Streams::Stream* strm) { if(strm == nullptr) throw TextException("strm is null"); HttpRequest request; request.url = url; + request.unixSocket = unixSocket; request.followRedirects=true; request.method = "GET"; HttpResponse response(request); if(response.statusCode < 200 || response.statusCode > 299) throw TextException("Status code does not indicate success: " + std::to_string(response.statusCode) + " " + HttpUtils::StatusCodeString(response.statusCode)); response.CopyToStream(strm); } - void DownloadToStreamSimple(std::string url, Tesses::Framework::Streams::Stream& strm) + void DownloadUnixSocketToStreamSimple(std::string unixSocket,std::string url, Tesses::Framework::Streams::Stream& strm) { - DownloadToStreamSimple(url,&strm); + DownloadUnixSocketToStreamSimple(unixSocket,url,&strm); } - void DownloadToFileSimple(std::string url, Tesses::Framework::Filesystem::VFS* vfs, Tesses::Framework::Filesystem::VFSPath path) + void DownloadUnixSocketToFileSimple(std::string unixSocket,std::string url, Tesses::Framework::Filesystem::VFS* vfs, Tesses::Framework::Filesystem::VFSPath path) { if(vfs == nullptr) throw TextException("vfs is null"); auto strm = vfs->OpenFile(path,"wb"); if(strm == nullptr) throw TextException("strm is null"); - DownloadToStreamSimple(url,strm); + DownloadUnixSocketToStreamSimple(unixSocket,url,strm); delete strm; } - void DownloadToFileSimple(std::string url, Tesses::Framework::Filesystem::VFS& vfs, Tesses::Framework::Filesystem::VFSPath path) + void DownloadUnixSocketToFileSimple(std::string unixSocket,std::string url, Tesses::Framework::Filesystem::VFS& vfs, Tesses::Framework::Filesystem::VFSPath path) { auto strm = vfs.OpenFile(path,"wb"); if(strm == nullptr) throw TextException("strm is null"); - DownloadToStreamSimple(url,strm); + DownloadUnixSocketToStreamSimple(unixSocket,url,strm); delete strm; } + void DownloadUnixSocketToFileSimple(std::string unixSocket,std::string url, Tesses::Framework::Filesystem::VFSPath path) + { + DownloadUnixSocketToFileSimple(unixSocket,url,Tesses::Framework::Filesystem::LocalFS,path); + } + std::string DownloadUnixSocketToStringSimple(std::string unixSocket,std::string url) + { + HttpRequest request; + request.url = url; + request.unixSocket = unixSocket; + request.followRedirects=true; + request.method = "GET"; + HttpResponse response(request); + if(response.statusCode < 200 || response.statusCode > 299) throw TextException("Status code does not indicate success: " + std::to_string(response.statusCode) + " " + HttpUtils::StatusCodeString(response.statusCode)); + return response.ReadAsString(); + } + void DownloadToStreamSimple(std::string url, Tesses::Framework::Streams::Stream* strm) + { + DownloadUnixSocketToStreamSimple("",url,strm); + } + void DownloadToStreamSimple(std::string url, Tesses::Framework::Streams::Stream& strm) + { + DownloadUnixSocketToStreamSimple("",url,strm); + } + + void DownloadToFileSimple(std::string url, Tesses::Framework::Filesystem::VFS* vfs, Tesses::Framework::Filesystem::VFSPath path) + { + DownloadUnixSocketToFileSimple("",url,vfs,path); + } + void DownloadToFileSimple(std::string url, Tesses::Framework::Filesystem::VFS& vfs, Tesses::Framework::Filesystem::VFSPath path) + { + DownloadUnixSocketToFileSimple("",url,vfs,path); + } void DownloadToFileSimple(std::string url, Tesses::Framework::Filesystem::VFSPath path) { - DownloadToFileSimple(url,Tesses::Framework::Filesystem::LocalFS,path); + DownloadUnixSocketToFileSimple("",url,path); } std::string DownloadToStringSimple(std::string url) { - HttpRequest request; + HttpRequest request; request.url = url; request.followRedirects=true; request.method = "GET"; HttpResponse response(request); if(response.statusCode < 200 || response.statusCode > 299) throw TextException("Status code does not indicate success: " + std::to_string(response.statusCode) + " " + HttpUtils::StatusCodeString(response.statusCode)); return response.ReadAsString(); + } bool WebSocketClientSuccessDefault(HttpDictionary& dict,bool v) { @@ -335,7 +383,11 @@ namespace Tesses::Framework::Http } void WebSocketClient(std::string url, HttpDictionary& requestHeaders, WebSocketConnection& wsc, std::function cb) { - WebSocketClient(url,requestHeaders, &wsc,cb); + WebSocketUnixSocketClient("",url,requestHeaders,wsc,cb); + } + void WebSocketUnixSocketClient(std::string unixSocket,std::string url, HttpDictionary& requestHeaders, WebSocketConnection& wsc, std::function cb) + { + WebSocketUnixSocketClient(unixSocket,url,requestHeaders, &wsc,cb); } class WSClient { @@ -574,13 +626,18 @@ namespace Tesses::Framework::Http }; - void WebSocketClient(std::string url, HttpDictionary& requestHeaders, WebSocketConnection* wsc, std::function cb) + { + WebSocketUnixSocketClient("",url,requestHeaders,wsc,cb); + } + + void WebSocketUnixSocketClient(std::string unixSocket,std::string url, HttpDictionary& requestHeaders, WebSocketConnection* wsc, std::function cb) { HttpRequest req; req.url = url; req.requestHeaders = requestHeaders; req.followRedirects=true; + req.unixSocket = unixSocket; std::string hash = ""; diff --git a/src/Http/HttpServer.cpp b/src/Http/HttpServer.cpp index 9543aaf..85ff563 100644 --- a/src/Http/HttpServer.cpp +++ b/src/Http/HttpServer.cpp @@ -550,6 +550,7 @@ namespace Tesses::Framework::Http this->ownsHttp = ownsHttpServer; this->showIPs = showIPs; this->thrd=nullptr; + this->showARTL = showIPs; } @@ -561,6 +562,15 @@ namespace Tesses::Framework::Http { } + HttpServer::HttpServer(std::string unixPath, IHttpServer* http, bool owns) : HttpServer(new TcpServer(unixPath,10),true,http,owns,false) + { + this->showARTL=true; + } + HttpServer::HttpServer(std::string unixPath, IHttpServer& http) : HttpServer(unixPath,&http,false) + { + + } + uint16_t HttpServer::GetPort() { if(server != nullptr) @@ -633,6 +643,11 @@ namespace Tesses::Framework::Http std::cout << "\x1B[35mhttp://"; std::cout << _ip.second << ":" << std::to_string(this->GetPort()) << "/\n"; } + + + } + if(this->showARTL) + { if(!svr->IsValid()) std::cout << "\x1B[31mError, we failed to bind or something\x1B[39m\n" << std::endl; std::cout << "\x1B[31mAlmost Ready to Listen\x1B[39m\n"; } diff --git a/src/Http/HttpUtils.cpp b/src/Http/HttpUtils.cpp index f4f7fab..8a0e3b1 100644 --- a/src/Http/HttpUtils.cpp +++ b/src/Http/HttpUtils.cpp @@ -93,6 +93,7 @@ namespace Tesses::Framework::Http { uri.port=0; auto firstPart = HttpUtils::SplitString(url,"//",2); if(firstPart.size() == 2) + uri.scheme=firstPart[0]; else if(firstPart.empty()) return false; diff --git a/src/Streams/NetworkStream.cpp b/src/Streams/NetworkStream.cpp index f86e1dd..12df1e8 100644 --- a/src/Streams/NetworkStream.cpp +++ b/src/Streams/NetworkStream.cpp @@ -34,6 +34,9 @@ extern "C" { #include #include #include +#if defined(AF_UNIX) +#include +#endif } #endif #if defined(GEKKO) @@ -264,6 +267,81 @@ namespace Tesses::Framework::Streams { uint32_t addr; uint8_t addr_parts[4]; } my_addr_t; + NetworkStream::NetworkStream(std::string unixPath,bool isServer) + { + this->endOfStream=false; + this->owns = true; + this->success=false; + #if defined(AF_UNIX) + this->sock = NETWORK_SOCKET(AF_UNIX,SOCK_STREAM,0); + if(this->sock < 0) + { + this->success=false; + return; + } + struct sockaddr_un unx; + + memset(&unx, 0, sizeof(unx)); + unx.sun_family = AF_UNIX; + + strncpy(unx.sun_path, unixPath.c_str(),sizeof(unx.sun_path)-1); + + if(isServer) + { + unlink(unixPath.c_str()); + if(NETWORK_BIND(this->sock, (const sockaddr*)&unx, (socklen_t)sizeof(unx)) != 0) + { + std::cout << "FAILED TO BIND: " << strerror(errno) << std::endl; + this->success = false; + return; + } + } + else + { + if(NETWORK_CONNECT(this->sock,(const sockaddr*)&unx, (socklen_t)sizeof(unx)) != 0) + { + this->success=false; + return; + } + } + #endif + } + + TcpServer::TcpServer(std::string unixPath,int32_t backlog) + { + + + this->owns=true; + this->valid=false; + #if defined(AF_UNIX) + this->sock = NETWORK_SOCKET(AF_UNIX,SOCK_STREAM,0); + if(this->sock < 0) + { + this->valid=false; + return; + } + struct sockaddr_un unx; + + memset(&unx, 0, sizeof(unx)); + unx.sun_family = AF_UNIX; + unlink(unixPath.c_str()); + strncpy(unx.sun_path, unixPath.c_str(),sizeof(unx.sun_path)-1); + if(NETWORK_BIND(this->sock, (const sockaddr*)&unx, (socklen_t)sizeof(unx)) != 0) + { + std::cout << "FAILED TO BIND: " << strerror(errno) << std::endl; + this->valid = false; + return; + } + + if(NETWORK_LISTEN(this->sock, backlog) != 0) + { + std::cout << "FAILED TO LISTEN FOR SOME REASON" << std::endl; + this->valid = false; + return; + } + this->valid = true; + #endif + } TcpServer::TcpServer(uint16_t port, int32_t backlog) { @@ -302,7 +380,7 @@ namespace Tesses::Framework::Streams { } if(NETWORK_BIND(this->sock, (const sockaddr*)&addr, (socklen_t)sizeof(addr)) != 0) { - std::cout << "FAILED TO BIND FOR SOME REASON" << std::endl; + std::cout << "FAILED TO BIND: " << strerror(errno) << std::endl; this->valid = false; return; } @@ -387,6 +465,8 @@ namespace Tesses::Framework::Streams { if(NETWORK_BIND(this->sock, (const sockaddr*)&addr, (socklen_t)sizeof(addr)) != 0) { + + std::cout << "FAILED TO BIND: " << strerror(errno) << std::endl; this->valid = false; return; } @@ -557,6 +637,8 @@ namespace Tesses::Framework::Streams { int r = NETWORK_BIND(this->sock, (struct sockaddr*)&addr, sizeof(addr)); if(r != 0) { + + std::cout << "FAILED TO BIND: " << strerror(errno) << std::endl; this->success=false; if(this->owns) NETWORK_CLOSE(this->sock); @@ -683,6 +765,10 @@ TcpServer::TcpServer(uint16_t port, int32_t backlog) TcpServer::TcpServer(std::string ip, uint16_t port, int32_t backlog) { +} +TcpServer::TcpServer(std::string unixPath,int32_t backlog) +{ + } NetworkStream* TcpServer::GetStream(std::string& ip, uint16_t& port) { @@ -717,6 +803,10 @@ NetworkStream::NetworkStream(bool ipV6,bool datagram) NetworkStream::NetworkStream(std::string ipOrFqdn, uint16_t port, bool datagram,bool broadcast,bool supportIPv6) { +} +NetworkStream::NetworkStream(std::string unixPath, bool isServer) +{ + } NetworkStream::NetworkStream(int32_t sock, bool owns) {