From 23bf0d94e95f73c6e05682389bbf2e6884f0b096 Mon Sep 17 00:00:00 2001 From: Mike Nolan Date: Wed, 8 Jan 2025 08:41:41 -0600 Subject: [PATCH] Add docker file --- CMakeLists.txt | 7 +- Dockerfile | 5 ++ TessesFrameworkFeatures.h.in | 8 ++ include/TessesFramework/Filesystem/VFS.hpp | 15 +++- include/TessesFramework/Lazy.hpp | 51 ++++++++++++ include/TessesFramework/TessesFramework.hpp | 3 +- include/TessesFramework/Threading/Mutex.hpp | 5 +- include/TessesFramework/Threading/Thread.hpp | 6 +- src/Filesystem/LocalFS.cpp | 2 +- src/Filesystem/VFS.cpp | 83 +++++++++++++++++++- src/Http/HttpServer.cpp | 29 ++++++- src/Streams/NetworkStream.cpp | 11 ++- src/Threading/Mutex.cpp | 19 +++-- src/Threading/Thread.cpp | 26 +++--- 14 files changed, 226 insertions(+), 44 deletions(-) create mode 100644 Dockerfile create mode 100644 TessesFrameworkFeatures.h.in create mode 100644 include/TessesFramework/Lazy.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 35c511b..da8a616 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -134,9 +134,14 @@ install(EXPORT TessesFrameworkTargets include(CMakePackageConfigHelpers) configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/TessesFrameworkConfig.cmake" INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/TessesFramework) +configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/TessesFrameworkFeatures.h.in "${CMAKE_CURRENT_BINARY_DIR}/TessesFrameworkFeatures.h" +INSTALL_DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/TessesFramework/TessesFrameworkFeatures.h) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/TessesFrameworkConfig.cmake" DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/TessesFramework) + +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/TessesFrameworkFeatures.h" +DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/TessesFramework) endif() if(TESSESFRAMEWORK_ENABLE_EXAMPLES) add_executable(copyfile examples/copyfile.cpp) @@ -162,4 +167,4 @@ add_executable(tfileserver apps/tfileserver.cpp) target_link_libraries(tfileserver PUBLIC tessesframework) install(TARGETS tfileserver DESTINATION bin) -endif() \ No newline at end of file +endif() diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..8ef1136 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,5 @@ +FROM ubuntu:noble + +RUN apt update && apt install -y cmake g++ gcc libmbedtls-dev build-essential + +RUN mkdir build && cd build && cmake -S .. -B . && make -j12 && make install \ No newline at end of file diff --git a/TessesFrameworkFeatures.h.in b/TessesFrameworkFeatures.h.in new file mode 100644 index 0000000..7fa1ba1 --- /dev/null +++ b/TessesFrameworkFeatures.h.in @@ -0,0 +1,8 @@ +#pragma once +#define TESSES_FRAMEWORK_FLAG_OFF 0 +#define TESSES_FRAMEWORK_FLAG_ON 1 +#if TESSES_FRAMEWORK_FLAG_@TESSESFRAMEWORK_ENABLE_MBED@ +#define TESSESFRAMEWORK_ENABLE_MBED +#endif +#undef TESSES_FRAMEWORK_FLAG_OFF +#undef TESSES_FRAMEWORK_FLAG_ON \ No newline at end of file diff --git a/include/TessesFramework/Filesystem/VFS.hpp b/include/TessesFramework/Filesystem/VFS.hpp index 632777f..1485156 100644 --- a/include/TessesFramework/Filesystem/VFS.hpp +++ b/include/TessesFramework/Filesystem/VFS.hpp @@ -11,19 +11,23 @@ namespace Tesses::Framework::Filesystem public: static VFSPath RelativeCurrentDirectory(); bool relative; - static std::vector SplitPath(std::string path,bool native=false); + static std::vector SplitPath(std::string path); std::vector path; VFSPath(); VFSPath(std::vector path); VFSPath(std::string path); VFSPath(VFSPath p, std::string subent); VFSPath(VFSPath p, VFSPath p2); - + VFSPath GetParent(); VFSPath CollapseRelativeParents(); std::string GetFileName(); + bool HasExtension(); + std::string GetExtension(); + void ChangeExtension(std::string ext); + void RemoveExtension(); std::string ToString(); }; VFSPath operator/(VFSPath p, VFSPath p2); @@ -32,7 +36,12 @@ namespace Tesses::Framework::Filesystem VFSPath operator+(VFSPath p, VFSPath p2); VFSPath operator+(VFSPath p, std::string p2); VFSPath operator+(std::string p, VFSPath p2); - + bool operator==(VFSPath p,VFSPath p2); + bool operator!=(VFSPath p,VFSPath p2); + bool operator==(std::string p,VFSPath p2); + bool operator!=(std::string p,VFSPath p2); + bool operator==(VFSPath p,std::string p2); + bool operator!=(VFSPath p,std::string p2); class VFSPathEnumeratorData { public: VFSPathEnumeratorData(std::function moveNext, std::function destroy) diff --git a/include/TessesFramework/Lazy.hpp b/include/TessesFramework/Lazy.hpp new file mode 100644 index 0000000..8364d2b --- /dev/null +++ b/include/TessesFramework/Lazy.hpp @@ -0,0 +1,51 @@ +#pragma once +#include "Common.hpp" +#include "Threading/Mutex.hpp" +#include +namespace Tesses::Framework { +template + class Lazy { + Threading::Mutex mtx; + T value; + bool hasInit=false; + std::function init; + std::function free; + public: + Lazy(std::function init, std::function free) + { + this->init = init; + this->free = free; + } + Lazy(std::function init) : Lazy(init, [](T item)->void {}) + { + + } + bool HasInit() + { + mtx.Lock(); + bool hI = this->hasInit; + mtx.Unlock(); + return hI; + } + T& GetValue() + { + mtx.Lock(); + if(hasInit) + { + mtx.Unlock(); + return this->value; + } + else + { + this->value = this->init(); + mtx.Unlock(); + return this->value; + } + mtx.Unlock(); + } + ~Lazy() + { + if(hasInit) this->free(this->value); + } + }; +} \ No newline at end of file diff --git a/include/TessesFramework/TessesFramework.hpp b/include/TessesFramework/TessesFramework.hpp index e90cadb..4b20fcf 100644 --- a/include/TessesFramework/TessesFramework.hpp +++ b/include/TessesFramework/TessesFramework.hpp @@ -17,4 +17,5 @@ #include "Filesystem/NullFilesystem.hpp" #include "Filesystem/MountableFilesystem.hpp" #include "Filesystem/MemoryFilesystem.hpp" -#include "Crypto/ClientTLSStream.hpp" \ No newline at end of file +#include "Crypto/ClientTLSStream.hpp" +#include "Lazy.hpp" \ No newline at end of file diff --git a/include/TessesFramework/Threading/Mutex.hpp b/include/TessesFramework/Threading/Mutex.hpp index 82bc0f8..8d91963 100644 --- a/include/TessesFramework/Threading/Mutex.hpp +++ b/include/TessesFramework/Threading/Mutex.hpp @@ -4,7 +4,7 @@ #elif defined(GEKKO) #include #else -#include +#include #endif namespace Tesses::Framework::Threading { @@ -14,7 +14,8 @@ namespace Tesses::Framework::Threading #elif defined(GEKKO) mutex_t mtx; #else - mtx_t mtx; + pthread_mutex_t mtx; + pthread_mutexattr_t attr; #endif public: Mutex(); diff --git a/include/TessesFramework/Threading/Thread.hpp b/include/TessesFramework/Threading/Thread.hpp index cdefbfd..02fb4d0 100644 --- a/include/TessesFramework/Threading/Thread.hpp +++ b/include/TessesFramework/Threading/Thread.hpp @@ -5,7 +5,7 @@ #elif defined(GEKKO) #include #else -#include +#include #endif #include namespace Tesses::Framework::Threading @@ -22,8 +22,8 @@ namespace Tesses::Framework::Threading lwp_t thrd; static void* cb(void* ptr); #else - thrd_t thrd; - static int cb(void* ptr); + pthread_t thrd; + static void* cb(void* ptr); #endif std::function fn; diff --git a/src/Filesystem/LocalFS.cpp b/src/Filesystem/LocalFS.cpp index 6c21a09..88e6703 100644 --- a/src/Filesystem/LocalFS.cpp +++ b/src/Filesystem/LocalFS.cpp @@ -117,7 +117,7 @@ namespace Tesses::Framework::Filesystem VFSPath LocalFilesystem::SystemToVFSPath(std::string path) { VFSPath p; - p.path = VFSPath::SplitPath(path,true); + p.path = VFSPath::SplitPath(path); p.relative=true; if(!path.empty()) { diff --git a/src/Filesystem/VFS.cpp b/src/Filesystem/VFS.cpp index 5a5cf96..29f7604 100644 --- a/src/Filesystem/VFS.cpp +++ b/src/Filesystem/VFS.cpp @@ -153,6 +153,39 @@ namespace Tesses::Framework::Filesystem { return VFSPath(p) + p2; } + bool operator==(VFSPath p,VFSPath p2) + { + if(p.relative != p2.relative) return false; + if(p.path.size() != p2.path.size()) return false; + for(size_t i = 0; i < p.path.size(); i++) + if(p.path[i] != p2.path[i]) return false; + return true; + } + bool operator!=(VFSPath p,VFSPath p2) + { + if(p.relative != p2.relative) return true; + if(p.path.size() != p2.path.size()) return true; + for(size_t i = 0; i < p.path.size(); i++) + if(p.path[i] != p2.path[i]) return true; + return false; + + } + bool operator==(std::string p,VFSPath p2) + { + return VFSPath(p) == p2; + } + bool operator!=(std::string p,VFSPath p2) + { + return VFSPath(p) != p2; + } + bool operator==(VFSPath p,std::string p2) + { + return p == VFSPath(p2); + } + bool operator!=(VFSPath p,std::string p2) + { + return p != VFSPath(p2); + } VFSPath VFS::ReadLink(VFSPath path) { return VFSPath("/"); @@ -191,7 +224,7 @@ namespace Tesses::Framework::Filesystem return path; } - std::vector VFSPath::SplitPath(std::string path,bool nativePath) + std::vector VFSPath::SplitPath(std::string path) { std::vector parts; std::string curPath = {}; @@ -206,7 +239,7 @@ namespace Tesses::Framework::Filesystem } } #if defined(WIN32) - else if(c == '\\' && nativePath) + else if(c == '\\') { if(!curPath.empty()) { @@ -236,6 +269,47 @@ namespace Tesses::Framework::Filesystem { this->path = p; } + + bool VFSPath::HasExtension() + { + if(this->path.empty()) return false; + auto& str = this->path.back(); + auto index = str.find_last_of('.'); + if(index == std::string::npos) return false; + return true; + } + std::string VFSPath::GetExtension() + { + if(this->path.empty()) return {}; + auto& str = this->path.back(); + auto index = str.find_last_of('.'); + if(index == std::string::npos) return {}; + return str.substr(index); + } + void VFSPath::ChangeExtension(std::string ext) + { + if(this->path.empty()) return; + auto& str = this->path.back(); + auto index = str.find_last_of('.'); + if(index != std::string::npos) + { + str = str.substr(0,index); + } + if(ext.empty()) return; + if(ext[0] != '.') + { + str += '.' + ext; + } + else + { + str += ext; + } + } + void VFSPath::RemoveExtension() + { + ChangeExtension({}); + } + VFSPath::VFSPath(std::string str) { this->path = SplitPath(str); @@ -247,7 +321,7 @@ namespace Tesses::Framework::Filesystem { auto firstPartPath = this->path.front(); - if(!firstPartPath.empty() && firstPartPath.back() == '/') this->relative=false; + if(!firstPartPath.empty() && firstPartPath.back() == ':') this->relative=false; } } } @@ -265,6 +339,8 @@ namespace Tesses::Framework::Filesystem { std::vector paths; if(this->path.empty()) return VFSPath(); + if(!this->relative && this->path.size() == 1 && !this->path[0].empty() && this->path[0].back() == ':') return *this; + paths.insert(paths.begin(), this->path.begin(), this->path.end()-1); auto res= VFSPath(paths); res.relative = this->relative; @@ -280,6 +356,7 @@ namespace Tesses::Framework::Filesystem std::string VFSPath::ToString() { if(this->path.empty() && !this->relative) return "/"; + if(!this->relative && this->path.size() == 1 && !this->path[0].empty() && this->path[0].back() == ':') return this->path[0] + "/"; bool first=true; std::string p = {}; for(auto item : this->path) diff --git a/src/Http/HttpServer.cpp b/src/Http/HttpServer.cpp index a2d2e0b..0681720 100644 --- a/src/Http/HttpServer.cpp +++ b/src/Http/HttpServer.cpp @@ -94,6 +94,31 @@ namespace Tesses::Framework::Http { if(this->queryParams.kvp.empty()) return this->originalPath; return this->originalPath + "?" + HttpUtils::QueryParamsEncode(this->queryParams); + } + void ServerContext::ReadStream(Stream* strm) + { + if(strm == nullptr) return; + auto strm2 = this->OpenRequestStream(); + if(strm2 != nullptr) + { + strm2->CopyTo(strm); + delete strm2; + } + } + void ServerContext::ReadStream(Stream& strm) + { + ReadStream(&strm); + } + std::string ServerContext::ReadString() + { + if(strm == nullptr) return {}; + auto strm2 = this->OpenRequestStream(); + if(strm2 != nullptr) + { + TextStreams::StreamReader reader(strm2,true); + return reader.ReadToEnd(); + } + return {}; } bool ServerContext::NeedToParseFormData() { @@ -628,7 +653,7 @@ namespace Tesses::Framework::Http uint8_t* buffer = new uint8_t[len]; len = bStrm.ReadBlock(buffer,len); std::string query((const char*)buffer,len); - delete buffer; + delete[] buffer; HttpUtils::QueryParamsDecode(ctx.queryParams, query); } @@ -658,4 +683,4 @@ namespace Tesses::Framework::Http if(bStrm.EndOfStream()) return; } } -} \ No newline at end of file +} diff --git a/src/Streams/NetworkStream.cpp b/src/Streams/NetworkStream.cpp index b1a0a94..7bd80f0 100644 --- a/src/Streams/NetworkStream.cpp +++ b/src/Streams/NetworkStream.cpp @@ -32,7 +32,7 @@ extern "C" { #if defined(GEKKO) extern "C" uint32_t if_config( char *local_ip, char *netmask, char *gateway,bool use_dhcp, int max_retries); -#elif !defined(_WIN32) +#elif !defined(_WIN32) && !defined(__ANDROID__) #include #endif @@ -71,7 +71,7 @@ namespace Tesses::Framework::Streams { char gateway[16]; if_config(localIp,netmask, gateway, true, 1); ipConfig.push_back(std::pair("net",localIp)); - #elif defined(_WIN32) + #elif defined(_WIN32) || defined(__ANDROID__) #else struct ifaddrs *ifAddrStruct = NULL; @@ -503,7 +503,10 @@ namespace Tesses::Framework::Streams { if(!this->success) return 0; ssize_t sz2 = NETWORK_SEND(this->sock,(const char*)buff,sz, 0); - if(sz2 < 0) return 0; + if(sz2 <= 0) { + this->endOfStream=true; + return 0; + } return (size_t)sz; } @@ -550,4 +553,4 @@ namespace Tesses::Framework::Streams { if(this->owns && this->success) NETWORK_CLOSE(this->sock); } -} \ No newline at end of file +} diff --git a/src/Threading/Mutex.cpp b/src/Threading/Mutex.cpp index 137bb02..0127cf9 100644 --- a/src/Threading/Mutex.cpp +++ b/src/Threading/Mutex.cpp @@ -1,5 +1,6 @@ #include "TessesFramework/Threading/Mutex.hpp" #include +#include namespace Tesses::Framework::Threading { Mutex::Mutex() @@ -10,9 +11,10 @@ namespace Tesses::Framework::Threading mtx = LWP_MUTEX_NULL; LWP_MutexInit(&mtx, true); #else - memset(&mtx, 0, sizeof(mtx_t)); - mtx_init(&mtx, mtx_recursive); - + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&mtx,&attr); + #endif } void Mutex::Lock() @@ -22,7 +24,7 @@ namespace Tesses::Framework::Threading #elif defined(GEKKO) LWP_MutexLock(mtx); #else - mtx_lock(&mtx); + pthread_mutex_lock(&mtx); #endif } void Mutex::Unlock() @@ -32,7 +34,7 @@ namespace Tesses::Framework::Threading #elif defined(GEKKO) LWP_MutexUnlock(mtx); #else - mtx_unlock(&mtx); + pthread_mutex_unlock(&mtx); #endif } bool Mutex::TryLock() @@ -42,7 +44,7 @@ namespace Tesses::Framework::Threading #elif defined(GEKKO) return LWP_MutexTryLock(mtx) == 0; #else - return mtx_trylock(&mtx) == thrd_success; + return pthread_mutex_trylock(&mtx) == 0; #endif } Mutex::~Mutex() @@ -52,8 +54,9 @@ namespace Tesses::Framework::Threading #elif defined(GEKKO) LWP_MutexDestroy(mtx); #else - mtx_destroy(&mtx); + pthread_mutex_destroy(&mtx); + pthread_mutexattr_destroy(&attr); #endif } -}; \ No newline at end of file +}; diff --git a/src/Threading/Thread.cpp b/src/Threading/Thread.cpp index f6cbf8d..e17eafa 100644 --- a/src/Threading/Thread.cpp +++ b/src/Threading/Thread.cpp @@ -18,22 +18,17 @@ namespace Tesses::Framework::Threading } #else - #if defined(GEKKO) + void* Thread::cb(void* data) - #else - int Thread::cb(void* data) - #endif - { + { + auto thrd = static_cast(data); auto fn = thrd->fn; thrd->hasInvoked=true; fn(); - #if defined(GEKKO) return NULL; - #else - return 0; - #endif + } #endif Thread::Thread(std::function fn) @@ -43,10 +38,10 @@ namespace Tesses::Framework::Threading #if defined(_WIN32) this->thrd = CreateThread(NULL,0,cb,static_cast(this), 0, &this->thrdId); #elif defined(GEKKO) - thrd = LWP_THREAD_NULL; - LWP_CreateThread(&thrd, cb, static_cast(this), NULL, 12000, LWP_PRIO_HIGHEST); + auto res = LWP_CreateThread(&this->thrd, cb, static_cast(this), nullptr,12000, 98); #else - thrd_create(&thrd, cb, static_cast(this)); + pthread_create(&thrd,NULL,cb,static_cast(this)); + //thrd_create(&thrd, cb, static_cast(this)); #endif while(!this->hasInvoked); } @@ -56,7 +51,7 @@ namespace Tesses::Framework::Threading #if defined(_WIN32) CloseHandle(thrd); #else - thrd_detach(thrd); + pthread_detach(thrd); #endif #endif } @@ -69,9 +64,8 @@ namespace Tesses::Framework::Threading void* res; LWP_JoinThread(thrd,&res); #else - int res; - thrd_join(thrd,&res); + pthread_join(thrd,NULL); #endif } -} \ No newline at end of file +}