Compare commits
8 Commits
5435280209
...
developmen
| Author | SHA1 | Date | |
|---|---|---|---|
| 266ef5f830 | |||
| 86b062771a | |||
| c55f0c0f4f | |||
| e2c7a5f5bd | |||
| 4cdfbc9542 | |||
| 3807bc5f36 | |||
| 38bb29ecc0 | |||
| c5cf13e1b7 |
@@ -2,17 +2,18 @@ name: Build and Deploy on Tag
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- 'v*'
|
- "v*"
|
||||||
|
|
||||||
env:
|
env:
|
||||||
GITEA_AUTH: ${{ secrets.MY_GITEA_AUTH }}
|
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
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- run: pacman --noconfirm -Sy mbedtls curl
|
- run: pacman --noconfirm -Sy mbedtls curl zip zig ninja
|
||||||
- run: pacman --config /opt/cross/ppc/pacman.conf --noconfirm -Sy mbedtls
|
- run: pacman --config /opt/cross/ppc/pacman.conf --noconfirm -Sy mbedtls
|
||||||
- run: cp Packaging/Linux/PKGBUILD /home/build/PKGBUILD
|
- run: cp Packaging/Linux/PKGBUILD /home/build/PKGBUILD
|
||||||
- run: cp Packaging/Linux/build-arch.sh /home/build/build-arch.sh
|
- run: cp Packaging/Linux/build-arch.sh /home/build/build-arch.sh
|
||||||
@@ -20,24 +21,30 @@ 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
|
||||||
build-jammy:
|
- run: env -C Packaging/Tools bash build.sh
|
||||||
runs-on: deb-builder-jammy
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Build for jammy, noble
|
|
||||||
run: |
|
|
||||||
bash build-ubuntu-jammy.sh
|
|
||||||
bash push-ubuntu-jammy.sh
|
|
||||||
working-directory: ./Packaging/Linux
|
|
||||||
build-plucky:
|
|
||||||
runs-on: deb-builder-plucky
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Build for plucky, resolute
|
|
||||||
run: |
|
|
||||||
bash build-ubuntu-plucky.sh
|
|
||||||
bash push-ubuntu-plucky.sh
|
|
||||||
working-directory: ./Packaging/Linux
|
|
||||||
- uses: akkuman/gitea-release-action@v1
|
- uses: akkuman/gitea-release-action@v1
|
||||||
env:
|
env:
|
||||||
NODE_OPTIONS: '--experimental-fetch' # if nodejs < 18
|
NODE_OPTIONS: '--experimental-fetch' # if nodejs < 18
|
||||||
|
with:
|
||||||
|
prerelease: true
|
||||||
|
files: |-
|
||||||
|
artifacts/**
|
||||||
|
|
||||||
|
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
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,3 +3,4 @@ builds
|
|||||||
.vscode
|
.vscode
|
||||||
out
|
out
|
||||||
/.vs
|
/.vs
|
||||||
|
artifacts
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
version: 43
|
|
||||||
jobs:
|
|
||||||
- name: Build for x86_64
|
|
||||||
steps:
|
|
||||||
- type: CheckoutStep
|
|
||||||
name: Checkout
|
|
||||||
cloneCredential:
|
|
||||||
type: DefaultCredential
|
|
||||||
withLfs: true
|
|
||||||
withSubmodules: false
|
|
||||||
condition: SUCCESSFUL
|
|
||||||
optional: false
|
|
||||||
- type: CommandStep
|
|
||||||
name: Execute build
|
|
||||||
runInContainer: true
|
|
||||||
image: onedev.site.tesses.net/dependencies/dependencies:latest
|
|
||||||
interpreter:
|
|
||||||
type: DefaultInterpreter
|
|
||||||
commands: |
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake -S .. -B . -DTESSESFRAMEWORK_FETCHCONTENT=OFF
|
|
||||||
make -j12
|
|
||||||
make install DESTDIR=out
|
|
||||||
useTTY: true
|
|
||||||
condition: SUCCESSFUL
|
|
||||||
optional: false
|
|
||||||
- type: BuildImageStep
|
|
||||||
name: Build Docker Image
|
|
||||||
dockerfile: Dockerfile.run
|
|
||||||
output:
|
|
||||||
type: RegistryOutput
|
|
||||||
tags: onedev.site.tesses.net/tesses-framework/tesses-framework:latest onedev.site.tesses.net/tesses-framework/tesses-framework:@commit_hash@ git.tesseslanguage.com/tesses50/tesses-framework:latest git.tesseslanguage.com/tesses50/tesses-framework:@commit_hash@
|
|
||||||
registryLogins:
|
|
||||||
- registryUrl: '@server_url@'
|
|
||||||
userName: '@job_token@'
|
|
||||||
passwordSecret: dockersecret
|
|
||||||
- registryUrl: git.tesseslanguage.com
|
|
||||||
userName: tesses50
|
|
||||||
passwordSecret: GITEA_AUTH
|
|
||||||
platforms: linux/amd64
|
|
||||||
condition: SUCCESSFUL
|
|
||||||
optional: false
|
|
||||||
triggers:
|
|
||||||
- type: BranchUpdateTrigger
|
|
||||||
branches: master
|
|
||||||
userMatch: anyone
|
|
||||||
projects: tesses-framework
|
|
||||||
retryCondition: never
|
|
||||||
maxRetries: 3
|
|
||||||
retryDelay: 30
|
|
||||||
timeout: 14400
|
|
||||||
@@ -7,68 +7,7 @@ set(TESSESFRAMEWORK_PATCH_VERSION 2)
|
|||||||
project(TessesFramework VERSION ${TESSESFRAMEWORK_MAJOR_VERSION}.${TESSESFRAMEWORK_MINOR_VERSION}.${TESSESFRAMEWORK_PATCH_VERSION})
|
project(TessesFramework VERSION ${TESSESFRAMEWORK_MAJOR_VERSION}.${TESSESFRAMEWORK_MINOR_VERSION}.${TESSESFRAMEWORK_PATCH_VERSION})
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
include(cmake/sources.cmake)
|
||||||
list(APPEND TESSESFRAMEWORK_SOURCE
|
|
||||||
src/Random.cpp
|
|
||||||
src/Date/Date.cpp
|
|
||||||
src/Http/FileServer.cpp
|
|
||||||
src/Http/MountableServer.cpp
|
|
||||||
src/Http/RouteServer.cpp
|
|
||||||
src/Http/CallbackServer.cpp
|
|
||||||
src/Http/HttpServer.cpp
|
|
||||||
src/Http/HttpUtils.cpp
|
|
||||||
src/Http/HttpClient.cpp
|
|
||||||
src/Http/HttpStream.cpp
|
|
||||||
src/Http/ContentDisposition.cpp
|
|
||||||
src/Http/WebSocket.cpp
|
|
||||||
src/Http/ChangeableServer.cpp
|
|
||||||
src/Http/BasicAuthServer.cpp
|
|
||||||
src/Http/CGIServer.cpp
|
|
||||||
src/Mail/Smtp.cpp
|
|
||||||
src/Serialization/Json.cpp
|
|
||||||
src/Serialization/SQLite.cpp
|
|
||||||
src/Serialization/BitConverter.cpp
|
|
||||||
src/Serialization/Bencode.cpp
|
|
||||||
src/Platform/Environment.cpp
|
|
||||||
src/Platform/Process.cpp
|
|
||||||
src/Streams/FileStream.cpp
|
|
||||||
src/Streams/MemoryStream.cpp
|
|
||||||
src/Streams/NetworkStream.cpp
|
|
||||||
src/Streams/Stream.cpp
|
|
||||||
src/Streams/BufferedStream.cpp
|
|
||||||
src/Streams/ByteReader.cpp
|
|
||||||
src/Streams/ByteWriter.cpp
|
|
||||||
src/Streams/PtyStream.cpp
|
|
||||||
src/Text/StringConverter.cpp
|
|
||||||
src/Text/HeaderGenerator.cpp
|
|
||||||
src/TextStreams/StreamReader.cpp
|
|
||||||
src/TextStreams/StreamWriter.cpp
|
|
||||||
src/TextStreams/TextReader.cpp
|
|
||||||
src/TextStreams/TextWriter.cpp
|
|
||||||
src/TextStreams/StdIOReader.cpp
|
|
||||||
src/TextStreams/StdIOWriter.cpp
|
|
||||||
src/TextStreams/StringReader.cpp
|
|
||||||
src/TextStreams/StringWriter.cpp
|
|
||||||
src/Threading/Thread.cpp
|
|
||||||
src/Threading/Mutex.cpp
|
|
||||||
src/Threading/ThreadPool.cpp
|
|
||||||
src/Filesystem/VFS.cpp
|
|
||||||
src/Filesystem/LocalFS.cpp
|
|
||||||
src/Filesystem/MemoryFilesystem.cpp
|
|
||||||
src/Filesystem/SubdirFilesystem.cpp
|
|
||||||
src/Filesystem/NullFilesystem.cpp
|
|
||||||
src/Filesystem/MountableFilesystem.cpp
|
|
||||||
src/Filesystem/FSHelpers.cpp
|
|
||||||
src/Filesystem/TempFS.cpp
|
|
||||||
src/Crypto/MbedTLS/ClientTLSStream.cpp
|
|
||||||
src/Crypto/MbedTLS/Crypto.cpp
|
|
||||||
src/Args.cpp
|
|
||||||
src/TF_Init.cpp
|
|
||||||
src/HiddenField.cpp
|
|
||||||
src/Uuid.cpp
|
|
||||||
src/BitTorrent/TorrentFile.cpp
|
|
||||||
src/BitTorrent/TorrentStream.cpp
|
|
||||||
)
|
|
||||||
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
||||||
|
|
||||||
|
|
||||||
@@ -82,7 +21,7 @@ option(TESSESFRAMEWORK_ENABLE_PROCESS "Enable process api" ON)
|
|||||||
option(TESSESFRAMEWORK_ENABLE_RPATH "Enable RPATH" ON)
|
option(TESSESFRAMEWORK_ENABLE_RPATH "Enable RPATH" ON)
|
||||||
|
|
||||||
if(TESSESFRAMEWORK_ENABLE_SQLITE)
|
if(TESSESFRAMEWORK_ENABLE_SQLITE)
|
||||||
list(APPEND TESSESFRAMEWORK_SOURCE
|
list(APPEND TESSESFRAMEWORK_SOURCE
|
||||||
src/Serialization/sqlite/sqlite3-mod.c
|
src/Serialization/sqlite/sqlite3-mod.c
|
||||||
src/Serialization/sqlite/vfs.c
|
src/Serialization/sqlite/vfs.c
|
||||||
)
|
)
|
||||||
@@ -145,12 +84,12 @@ endif()
|
|||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
mbedtls
|
mbedtls
|
||||||
URL https://downloads.tesses.net/cache/libraries/source/mbedtls-3.6.4.tar.bz2
|
URL https://downloads.tesses.net/cache/libraries/source/mbedtls-3.6.4.tar.bz2
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
FetchContent_MakeAvailable(mbedtls)
|
FetchContent_MakeAvailable(mbedtls)
|
||||||
else()
|
else()
|
||||||
set(MBEDTLS_DIR "" CACHE PATH "Mbed tls directory")
|
find_package(MbedTLS REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
@@ -198,11 +137,6 @@ else()
|
|||||||
target_compile_definitions(TessesFramework PUBLIC TESSESFRAMEWORK_CERT_BUNDLE_FILE=${TESSESFRAMEWORK_CERT_BUNDLE_FILE})
|
target_compile_definitions(TessesFramework PUBLIC TESSESFRAMEWORK_CERT_BUNDLE_FILE=${TESSESFRAMEWORK_CERT_BUNDLE_FILE})
|
||||||
endif()
|
endif()
|
||||||
if(NOT TESSESFRAMEWORK_FETCHCONTENT)
|
if(NOT TESSESFRAMEWORK_FETCHCONTENT)
|
||||||
if(MBEDTLS_DIR STREQUAL "")
|
|
||||||
else()
|
|
||||||
target_include_directories(${TessesFramework_TARGET} PUBLIC ${MBEDTLS_DIR}/include)
|
|
||||||
target_link_directories(${TessesFramework_TARGET} PUBLIC ${MBEDTLS_DIR}/lib)
|
|
||||||
endif()
|
|
||||||
target_link_libraries(${TessesFramework_TARGET} PUBLIC mbedtls mbedx509 mbedcrypto)
|
target_link_libraries(${TessesFramework_TARGET} PUBLIC mbedtls mbedx509 mbedcrypto)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
@@ -300,7 +234,7 @@ endif()
|
|||||||
|
|
||||||
|
|
||||||
if(TESSESFRAMEWORK_INSTALL_DEVELOPMENT)
|
if(TESSESFRAMEWORK_INSTALL_DEVELOPMENT)
|
||||||
install(TARGETS ${TessesFrameworkLibs}
|
install(TARGETS ${TessesFrameworkLibs}
|
||||||
EXPORT TessesFrameworkTargets
|
EXPORT TessesFrameworkTargets
|
||||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
@@ -329,6 +263,8 @@ DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/TessesFramework)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(TESSESFRAMEWORK_ENABLE_EXAMPLES)
|
if(TESSESFRAMEWORK_ENABLE_EXAMPLES)
|
||||||
|
add_executable(timer examples/timer.cpp)
|
||||||
|
target_link_libraries(timer PUBLIC tessesframework)
|
||||||
|
|
||||||
add_executable(copyfile examples/copyfile.cpp)
|
add_executable(copyfile examples/copyfile.cpp)
|
||||||
target_link_libraries(copyfile PUBLIC tessesframework)
|
target_link_libraries(copyfile PUBLIC tessesframework)
|
||||||
@@ -351,8 +287,6 @@ if(TESSESFRAMEWORK_ENABLE_EXAMPLES)
|
|||||||
add_executable(wsecho examples/wsecho.cpp)
|
add_executable(wsecho examples/wsecho.cpp)
|
||||||
target_link_libraries(wsecho PUBLIC tessesframework)
|
target_link_libraries(wsecho PUBLIC tessesframework)
|
||||||
|
|
||||||
add_executable(runevent examples/runevent.cpp)
|
|
||||||
target_link_libraries(runevent PUBLIC tessesframework)
|
|
||||||
|
|
||||||
add_executable(tests examples/tests.cpp)
|
add_executable(tests examples/tests.cpp)
|
||||||
target_link_libraries(tests PUBLIC tessesframework)
|
target_link_libraries(tests PUBLIC tessesframework)
|
||||||
@@ -434,4 +368,6 @@ set(CPACK_PACKAGE_VERSION_MINOR "${TessesFramework_VERSION_MINOR}")
|
|||||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libmbedtls-dev (>= 2.28.8)")
|
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libmbedtls-dev (>= 2.28.8)")
|
||||||
|
|
||||||
include(CPack)
|
include(CPack)
|
||||||
add_subdirectory(pkgconfig)
|
if(TESSESFRAMEWORK_INSTALL_DEVELOPMENT)
|
||||||
|
add_subdirectory(pkgconfig)
|
||||||
|
endif()
|
||||||
|
|||||||
@@ -1,90 +0,0 @@
|
|||||||
{
|
|
||||||
"version": 3,
|
|
||||||
"configurePresets": [
|
|
||||||
{
|
|
||||||
"name": "linux-debug",
|
|
||||||
"displayName": "Linux Debug",
|
|
||||||
"description": "Target the Windows Subsystem for Linux (WSL) or a remote Linux system.",
|
|
||||||
"generator": "Ninja",
|
|
||||||
"binaryDir": "${sourceDir}/out/build/${presetName}",
|
|
||||||
"installDir": "${sourceDir}/out/install/${presetName}",
|
|
||||||
"cacheVariables": { "CMAKE_BUILD_TYPE": "Debug" },
|
|
||||||
"condition": {
|
|
||||||
"type": "equals",
|
|
||||||
"lhs": "${hostSystemName}",
|
|
||||||
"rhs": "Linux"
|
|
||||||
},
|
|
||||||
"vendor": { "microsoft.com/VisualStudioRemoteSettings/CMake/2.0": { "remoteSourceRootDir": "$env{HOME}/.vs/$ms{projectDirName}" } }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "macos-debug",
|
|
||||||
"displayName": "macOS Debug",
|
|
||||||
"description": "Target a remote macOS system.",
|
|
||||||
"generator": "Ninja",
|
|
||||||
"binaryDir": "${sourceDir}/out/build/${presetName}",
|
|
||||||
"installDir": "${sourceDir}/out/install/${presetName}",
|
|
||||||
"cacheVariables": { "CMAKE_BUILD_TYPE": "Debug" },
|
|
||||||
"condition": {
|
|
||||||
"type": "equals",
|
|
||||||
"lhs": "${hostSystemName}",
|
|
||||||
"rhs": "Darwin"
|
|
||||||
},
|
|
||||||
"vendor": { "microsoft.com/VisualStudioRemoteSettings/CMake/1.0": { "sourceDir": "$env{HOME}/.vs/$ms{projectDirName}" } }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "windows-base",
|
|
||||||
"description": "Target Windows with the Visual Studio development environment.",
|
|
||||||
"hidden": true,
|
|
||||||
"generator": "Ninja",
|
|
||||||
"binaryDir": "${sourceDir}/out/build/${presetName}",
|
|
||||||
"installDir": "${sourceDir}/out/install/${presetName}",
|
|
||||||
"cacheVariables": {
|
|
||||||
"CMAKE_C_COMPILER": "cl.exe",
|
|
||||||
"CMAKE_CXX_COMPILER": "cl.exe",
|
|
||||||
"TESSESFRAMEWORK_ENABLE_MBED": false,
|
|
||||||
"TESSESFRAMEWORK_FETCHCONTENT": false
|
|
||||||
},
|
|
||||||
"condition": {
|
|
||||||
"type": "equals",
|
|
||||||
"lhs": "${hostSystemName}",
|
|
||||||
"rhs": "Windows"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "x64-debug",
|
|
||||||
"displayName": "x64 Debug",
|
|
||||||
"description": "Target Windows (64-bit) with the Visual Studio development environment. (Debug)",
|
|
||||||
"inherits": "windows-base",
|
|
||||||
"architecture": {
|
|
||||||
"value": "x64",
|
|
||||||
"strategy": "external"
|
|
||||||
},
|
|
||||||
"cacheVariables": { "CMAKE_BUILD_TYPE": "Debug" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "x64-release",
|
|
||||||
"displayName": "x64 Release",
|
|
||||||
"description": "Target Windows (64-bit) with the Visual Studio development environment. (RelWithDebInfo)",
|
|
||||||
"inherits": "x64-debug",
|
|
||||||
"cacheVariables": { "CMAKE_BUILD_TYPE": "Release" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "x86-debug",
|
|
||||||
"displayName": "x86 Debug",
|
|
||||||
"description": "Target Windows (32-bit) with the Visual Studio development environment. (Debug)",
|
|
||||||
"inherits": "windows-base",
|
|
||||||
"architecture": {
|
|
||||||
"value": "x86",
|
|
||||||
"strategy": "external"
|
|
||||||
},
|
|
||||||
"cacheVariables": { "CMAKE_BUILD_TYPE": "Debug" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "x86-release",
|
|
||||||
"displayName": "x86 Release",
|
|
||||||
"description": "Target Windows (32-bit) with the Visual Studio development environment. (RelWithDebInfo)",
|
|
||||||
"inherits": "x86-debug",
|
|
||||||
"cacheVariables": { "CMAKE_BUILD_TYPE": "Release" }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
FROM ubuntu:noble
|
|
||||||
|
|
||||||
RUN apt update && apt install -y cmake g++ gcc libmbedtls-dev build-essential git ca-certificates
|
|
||||||
|
|
||||||
RUN mkdir /src && cd /src && git clone https://onedev.site.tesses.net/tesses-framework . && mkdir build && cd build && cmake -S .. -B . && make -j12 && make install && cd / && rm -r /src
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
FROM onedev.site.tesses.net/dependencies/dependencies:latest
|
|
||||||
COPY build/out /
|
|
||||||
|
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
# Maintainer: Mike Nolan <tesses@tesses.net>
|
# Maintainer: Mike Nolan <tesses@tesses.net>
|
||||||
pkgname=tesses-framework # '-bzr', '-git', '-hg' or '-svn'
|
pkgname=tessesframework # '-bzr', '-git', '-hg' or '-svn'
|
||||||
pkgver=0.0.2
|
pkgver=0.0.3
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
pkgdesc=""
|
pkgdesc=""
|
||||||
arch=('x86_64' 'powerpc')
|
arch=('x86_64' 'powerpc')
|
||||||
url="https://onedev.site.tesses.net/tesses-framework"
|
url="https://git.tesses.org/tesses50/tessesframework"
|
||||||
license=('MIT')
|
license=('MIT')
|
||||||
groups=()
|
groups=()
|
||||||
depends=('mbedtls')
|
depends=('mbedtls')
|
||||||
makedepends=('git' 'cmake' 'make' 'base-devel' 'wget') # 'bzr', 'git', 'mercurial' or 'subversion'
|
makedepends=('git' 'cmake' 'make' 'base-devel' 'wget') # 'bzr', 'git', 'mercurial' or 'subversion'
|
||||||
install=
|
install=
|
||||||
source=('tesses-framework::git+https://onedev.site.tesses.net/tesses-framework')
|
source=('tessesframework::git+https://git.tesses.org/tesses50/tessesframework')
|
||||||
noextract=()
|
noextract=()
|
||||||
sha256sums=('SKIP')
|
sha256sums=('SKIP')
|
||||||
if [[ -z "$CMAKE_TOOLCHAIN" ]]; then
|
if [[ -z "$CMAKE_TOOLCHAIN" ]]; then
|
||||||
@@ -22,22 +22,21 @@ fi
|
|||||||
|
|
||||||
prepare() {
|
prepare() {
|
||||||
cd "$srcdir/${pkgname}"
|
cd "$srcdir/${pkgname}"
|
||||||
wget https://downloads.tesses.net/ShellPackage.crvm
|
|
||||||
}
|
}
|
||||||
|
|
||||||
build() {
|
build() {
|
||||||
cd "$srcdir/${pkgname}"
|
cd "$srcdir/${pkgname}"
|
||||||
mkdir build
|
mkdir build
|
||||||
|
|
||||||
if [[ -z "$CMAKE_TOOLCHAIN" ]]; then
|
if [[ -z "$CMAKE_TOOLCHAIN" ]]; then
|
||||||
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_BUILD_TYPE=Release
|
||||||
else
|
else
|
||||||
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_TOOLCHAIN_FILE="$CMAKE_TOOLCHAIN"
|
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE="$CMAKE_TOOLCHAIN"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd build
|
cd build
|
||||||
make -j`nproc`
|
make -j`nproc`
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -47,4 +46,3 @@ package() {
|
|||||||
cd "$srcdir/${pkgname}/build"
|
cd "$srcdir/${pkgname}/build"
|
||||||
make install DESTDIR="$pkgdir/"
|
make install DESTDIR="$pkgdir/"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,14 +4,14 @@ mkdir x86_64
|
|||||||
cd x86_64
|
cd x86_64
|
||||||
cp ../PKGBUILD .
|
cp ../PKGBUILD .
|
||||||
makepkg
|
makepkg
|
||||||
curl --user tesses50:$GITEA_AUTH \
|
curl --user tesses50:$PACKAGE_AND_BREW \
|
||||||
--upload-file *.pkg.tar.zst \
|
--upload-file *.pkg.tar.zst \
|
||||||
https://git.tesseslanguage.com/api/packages/tesses50/arch/core
|
https://git.tesses.org/api/packages/tesses50/arch/core
|
||||||
cd ..
|
cd ..
|
||||||
mkdir powerpc
|
mkdir powerpc
|
||||||
cd powerpc
|
cd powerpc
|
||||||
cp ../PKGBUILD .
|
cp ../PKGBUILD .
|
||||||
CARCH=powerpc CMAKE_TOOLCHAIN=/opt/cross/ppc/toolchain.cmake makepkg
|
CARCH=powerpc CMAKE_TOOLCHAIN=/opt/cross/ppc/toolchain.cmake makepkg
|
||||||
curl --user tesses50:$GITEA_AUTH \
|
curl --user tesses50:$PACKAGE_AND_BREW \
|
||||||
--upload-file *.pkg.tar.zst \
|
--upload-file *.pkg.tar.zst \
|
||||||
https://git.tesseslanguage.com/api/packages/tesses50/arch/core
|
https://git.tesses.org/api/packages/tesses50/arch/core
|
||||||
|
|||||||
@@ -1,46 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
source ./version.sh
|
|
||||||
mkdir -p build/jammy
|
|
||||||
cd build/jammy
|
|
||||||
mkdir build-amd64
|
|
||||||
cmake -S ../../../../ -B build-amd64 -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF
|
|
||||||
cd build-amd64
|
|
||||||
make -j`nproc`
|
|
||||||
make install DESTDIR=../tessesframework_$DEB_VERSION\_amd64
|
|
||||||
mkdir -p ../tessesframework_$DEB_VERSION\_amd64/DEBIAN
|
|
||||||
bash ../../../make-control.sh ../tessesframework_$DEB_VERSION\_amd64/DEBIAN/control amd64
|
|
||||||
cd ../
|
|
||||||
dpkg-deb --build tessesframework_$DEB_VERSION\_amd64
|
|
||||||
|
|
||||||
# ARM64
|
|
||||||
mkdir build-arm64
|
|
||||||
cmake -S ../../../../ -B build-arm64 -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_TOOLCHAIN_FILE=/opt/toolchains/arm64.cmake
|
|
||||||
cd build-arm64
|
|
||||||
make -j`nproc`
|
|
||||||
make install DESTDIR=../tessesframework_$DEB_VERSION\_arm64
|
|
||||||
mkdir -p ../tessesframework_$DEB_VERSION\_arm64/DEBIAN
|
|
||||||
bash ../../../make-control.sh ../tessesframework_$DEB_VERSION\_arm64/DEBIAN/control arm64
|
|
||||||
cd ../
|
|
||||||
dpkg-deb --build tessesframework_$DEB_VERSION\_arm64
|
|
||||||
|
|
||||||
# RISCV64
|
|
||||||
mkdir build-riscv64
|
|
||||||
cmake -S ../../../../ -B build-riscv64 -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_TOOLCHAIN_FILE=/opt/toolchains/riscv64.cmake
|
|
||||||
cd build-riscv64
|
|
||||||
make -j`nproc`
|
|
||||||
make install DESTDIR=../tessesframework_$DEB_VERSION\_riscv64
|
|
||||||
mkdir -p ../tessesframework_$DEB_VERSION\_riscv64/DEBIAN
|
|
||||||
bash ../../../make-control.sh ../tessesframework_$DEB_VERSION\_riscv64/DEBIAN/control riscv64
|
|
||||||
cd ../
|
|
||||||
dpkg-deb --build tessesframework_$DEB_VERSION\_riscv64
|
|
||||||
|
|
||||||
# ARMHF
|
|
||||||
mkdir build-armhf
|
|
||||||
cmake -S ../../../../ -B build-armhf -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_TOOLCHAIN_FILE=/opt/toolchains/armhf.cmake
|
|
||||||
cd build-armhf
|
|
||||||
make -j`nproc`
|
|
||||||
make install DESTDIR=../tessesframework_$DEB_VERSION\_armhf
|
|
||||||
mkdir -p ../tessesframework_$DEB_VERSION\_armhf/DEBIAN
|
|
||||||
bash ../../../make-control.sh ../tessesframework_$DEB_VERSION\_armhf/DEBIAN/control armhf
|
|
||||||
cd ../
|
|
||||||
dpkg-deb --build tessesframework_$DEB_VERSION\_armhf
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
source ./version.sh
|
|
||||||
mkdir -p build/plucky
|
|
||||||
cd build/plucky
|
|
||||||
mkdir build-amd64
|
|
||||||
cmake -S ../../../../ -B build-amd64 -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF
|
|
||||||
cd build-amd64
|
|
||||||
make -j`nproc`
|
|
||||||
make install DESTDIR=../tessesframework_$DEB_VERSION\_amd64
|
|
||||||
mkdir -p ../tessesframework_$DEB_VERSION\_amd64/DEBIAN
|
|
||||||
bash ../../../make-control.sh ../tessesframework_$DEB_VERSION\_amd64/DEBIAN/control amd64
|
|
||||||
cd ../
|
|
||||||
dpkg-deb --build tessesframework_$DEB_VERSION\_amd64
|
|
||||||
|
|
||||||
# ARM64
|
|
||||||
mkdir build-arm64
|
|
||||||
cmake -S ../../../../ -B build-arm64 -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_TOOLCHAIN_FILE=/opt/toolchains/arm64.cmake
|
|
||||||
cd build-arm64
|
|
||||||
make -j`nproc`
|
|
||||||
make install DESTDIR=../tessesframework_$DEB_VERSION\_arm64
|
|
||||||
mkdir -p ../tessesframework_$DEB_VERSION\_arm64/DEBIAN
|
|
||||||
bash ../../../make-control.sh ../tessesframework_$DEB_VERSION\_arm64/DEBIAN/control arm64
|
|
||||||
cd ../
|
|
||||||
dpkg-deb --build tessesframework_$DEB_VERSION\_arm64
|
|
||||||
|
|
||||||
# RISCV64
|
|
||||||
mkdir build-riscv64
|
|
||||||
cmake -S ../../../../ -B build-riscv64 -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_TOOLCHAIN_FILE=/opt/toolchains/riscv64.cmake
|
|
||||||
cd build-riscv64
|
|
||||||
make -j`nproc`
|
|
||||||
make install DESTDIR=../tessesframework_$DEB_VERSION\_riscv64
|
|
||||||
mkdir -p ../tessesframework_$DEB_VERSION\_riscv64/DEBIAN
|
|
||||||
bash ../../../make-control.sh ../tessesframework_$DEB_VERSION\_riscv64/DEBIAN/control riscv64
|
|
||||||
cd ../
|
|
||||||
dpkg-deb --build tessesframework_$DEB_VERSION\_riscv64
|
|
||||||
|
|
||||||
# ARMHF
|
|
||||||
mkdir build-armhf
|
|
||||||
cmake -S ../../../../ -B build-armhf -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_TOOLCHAIN_FILE=/opt/toolchains/armhf.cmake
|
|
||||||
cd build-armhf
|
|
||||||
make -j`nproc`
|
|
||||||
make install DESTDIR=../tessesframework_$DEB_VERSION\_armhf
|
|
||||||
mkdir -p ../tessesframework_$DEB_VERSION\_armhf/DEBIAN
|
|
||||||
bash ../../../make-control.sh ../tessesframework_$DEB_VERSION\_armhf/DEBIAN/control armhf
|
|
||||||
cd ../
|
|
||||||
dpkg-deb --build tessesframework_$DEB_VERSION\_armhf
|
|
||||||
|
|
||||||
# I386
|
|
||||||
mkdir build-i386
|
|
||||||
cmake -S ../../../../ -B build-i386 -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_TOOLCHAIN_FILE=/opt/toolchains/i386.cmake
|
|
||||||
cd build-i386
|
|
||||||
make -j`nproc`
|
|
||||||
make install DESTDIR=../tessesframework_$DEB_VERSION\_i386
|
|
||||||
mkdir -p ../tessesframework_$DEB_VERSION\_i386/DEBIAN
|
|
||||||
bash ../../../make-control.sh ../tessesframework_$DEB_VERSION\_i386/DEBIAN/control i386
|
|
||||||
cd ../
|
|
||||||
dpkg-deb --build tessesframework_$DEB_VERSION\_i386
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
echo "Package: tessesframework" > "$1"
|
|
||||||
echo "Version: $DEB_VERSION" >> "$1"
|
|
||||||
echo "Architecture: $2" >> "$1"
|
|
||||||
echo "Essential: no" >> "$1"
|
|
||||||
echo "Priority: optional" >> "$1"
|
|
||||||
echo "Depends: libmbedtls-dev" >> "$1"
|
|
||||||
echo "Maintainer: Mike Nolan" >> "$1"
|
|
||||||
echo "Description: A cross platform wrapper library" >> "$1"
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
source ./version.sh
|
|
||||||
curl --user tesses50:$GITEA_AUTH -X DELETE \
|
|
||||||
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/jammy/main/tessesframework/$DEB_VERSION/amd64
|
|
||||||
curl --user tesses50:$GITEA_AUTH -X DELETE \
|
|
||||||
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/jammy/main/tessesframework/$DEB_VERSION/arm64
|
|
||||||
curl --user tesses50:$GITEA_AUTH -X DELETE \
|
|
||||||
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/jammy/main/tessesframework/$DEB_VERSION/riscv64
|
|
||||||
curl --user tesses50:$GITEA_AUTH -X DELETE \
|
|
||||||
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/jammy/main/tessesframework/$DEB_VERSION/armhf
|
|
||||||
curl --user tesses50:$GITEA_AUTH \
|
|
||||||
--upload-file build/jammy/tessesframework_$DEB_VERSION\_amd64.deb \
|
|
||||||
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/jammy/main/upload
|
|
||||||
curl --user tesses50:$GITEA_AUTH \
|
|
||||||
--upload-file build/jammy/tessesframework_$DEB_VERSION\_arm64.deb \
|
|
||||||
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/jammy/main/upload
|
|
||||||
curl --user tesses50:$GITEA_AUTH \
|
|
||||||
--upload-file build/jammy/tessesframework_$DEB_VERSION\_riscv64.deb \
|
|
||||||
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/jammy/main/upload
|
|
||||||
curl --user tesses50:$GITEA_AUTH \
|
|
||||||
--upload-file build/jammy/tessesframework_$DEB_VERSION\_armhf.deb \
|
|
||||||
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/jammy/main/upload
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
source ./version.sh
|
|
||||||
curl --user tesses50:$GITEA_AUTH -X DELETE \
|
|
||||||
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/tessesframework/$DEB_VERSION/amd64
|
|
||||||
curl --user tesses50:$GITEA_AUTH -X DELETE \
|
|
||||||
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/tessesframework/$DEB_VERSION/arm64
|
|
||||||
curl --user tesses50:$GITEA_AUTH -X DELETE \
|
|
||||||
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/tessesframework/$DEB_VERSION/i386
|
|
||||||
curl --user tesses50:$GITEA_AUTH -X DELETE \
|
|
||||||
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/tessesframework/$DEB_VERSION/riscv64
|
|
||||||
curl --user tesses50:$GITEA_AUTH -X DELETE \
|
|
||||||
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/tessesframework/$DEB_VERSION/armhf
|
|
||||||
curl --user tesses50:$GITEA_AUTH \
|
|
||||||
--upload-file build/plucky/tessesframework_$DEB_VERSION\_amd64.deb \
|
|
||||||
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/upload
|
|
||||||
curl --user tesses50:$GITEA_AUTH \
|
|
||||||
--upload-file build/plucky/tessesframework_$DEB_VERSION\_arm64.deb \
|
|
||||||
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/upload
|
|
||||||
curl --user tesses50:$GITEA_AUTH \
|
|
||||||
--upload-file build/plucky/tessesframework_$DEB_VERSION\_i386.deb \
|
|
||||||
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/upload
|
|
||||||
curl --user tesses50:$GITEA_AUTH \
|
|
||||||
--upload-file build/plucky/tessesframework_$DEB_VERSION\_riscv64.deb \
|
|
||||||
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/upload
|
|
||||||
curl --user tesses50:$GITEA_AUTH \
|
|
||||||
--upload-file build/plucky/tessesframework_$DEB_VERSION\_armhf.deb \
|
|
||||||
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/upload
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export DEB_VERSION=0.0.2
|
|
||||||
35
Packaging/Tools/build.sh
Normal file
35
Packaging/Tools/build.sh
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
mkdir -p ../../artifacts
|
||||||
|
mkdir -p builds
|
||||||
|
git clone --depth 1 https://git.tesses.org/tesses50/zig-cross builds/zig-cross
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for tripple in x86_64-linux-musl x86-linux-musl aarch64-linux-musl arm-linux-musleabi riscv64-linux-musl powerpc-linux-musleabihf; do
|
||||||
|
export BUILDDIR=builds/$tripple
|
||||||
|
mkdir -p $BUILDDIR
|
||||||
|
cmake -S ../.. -B $BUILDDIR --toolchain $PWD/builds/zig-cross/$tripple\.cmake -DCMAKE_BUILD_TYPE=Release -DTESSESFRAMEWORK_INSTALL_DEVELOPMENT=OFF -DTESSESFRAMEWORK_ENABLE_EXAMPLES=OFF -DTESSESFRAMEWORK_ENABLE_SHARED=OFF -DTESSESFRAMEWORK_ENABLE_STATIC=ON -DCMAKE_EXE_LINKER_FLAGS="-static-libgcc -static-libstdc++ -static -Wl,--strip-all" -DCMAKE_POSITION_INDEPENDENT_CODE=ON -GNinja
|
||||||
|
cmake --build $BUILDDIR || exit 1
|
||||||
|
cmake --install $BUILDDIR --prefix $BUILDDIR/out
|
||||||
|
tar cvzf ../../artifacts/tessesframework-tools-$tripple\.tar.gz -C $BUILDDIR/out/ bin
|
||||||
|
|
||||||
|
done
|
||||||
|
|
||||||
|
for tripple in x86_64-windows-gnu x86-windows-gnu aarch64-windows-gnu; do
|
||||||
|
export BUILDDIR=builds/$tripple
|
||||||
|
mkdir -p $BUILDDIR
|
||||||
|
cmake -S ../.. -B $BUILDDIR --toolchain $PWD/builds/zig-cross/$tripple\.cmake -DCMAKE_BUILD_TYPE=Release -DTESSESFRAMEWORK_INSTALL_DEVELOPMENT=OFF -DTESSESFRAMEWORK_ENABLE_EXAMPLES=OFF -DTESSESFRAMEWORK_ENABLE_SHARED=OFF -DTESSESFRAMEWORK_ENABLE_STATIC=ON -DCMAKE_EXE_LINKER_FLAGS="-static-libgcc -static-libstdc++ -static -Wl,--strip-all" -DCMAKE_POSITION_INDEPENDENT_CODE=ON -GNinja
|
||||||
|
cmake --build $BUILDDIR || exit 1
|
||||||
|
cmake --install $BUILDDIR --prefix $BUILDDIR/out
|
||||||
|
|
||||||
|
env -C $BUILDDIR/out zip -r ../../../../../artifacts/tessesframework-tools-$tripple\.zip bin
|
||||||
|
done
|
||||||
|
|
||||||
|
for tripple in x86_64-macos-none aarch64-macos-none; do
|
||||||
|
export BUILDDIR=builds/$tripple
|
||||||
|
mkdir -p $BUILDDIR
|
||||||
|
cmake -S ../.. -B $BUILDDIR --toolchain $PWD/builds/zig-cross/$tripple\.cmake -DCMAKE_BUILD_TYPE=Release -DTESSESFRAMEWORK_INSTALL_DEVELOPMENT=OFF -DTESSESFRAMEWORK_ENABLE_EXAMPLES=OFF -DTESSESFRAMEWORK_ENABLE_SHARED=OFF -DTESSESFRAMEWORK_ENABLE_STATIC=ON -DCMAKE_POSITION_INDEPENDENT_CODE=ON -GNinja -DCMAKE_EXE_LINKER_FLAGS="-Wl,--strip-all"
|
||||||
|
cmake --build $BUILDDIR || exit 1
|
||||||
|
cmake --install $BUILDDIR --prefix $BUILDDIR/out
|
||||||
|
tar cvzf ../../artifacts/tessesframework-tools-$tripple\.tar.gz -C $BUILDDIR/out/ bin
|
||||||
|
|
||||||
|
done
|
||||||
19
Packaging/edit-formula.sh
Normal file
19
Packaging/edit-formula.sh
Normal 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"
|
||||||
@@ -21,9 +21,9 @@ int main(int argc, char** argv)
|
|||||||
.SendText(
|
.SendText(
|
||||||
"<!DOCTYPE html>"
|
"<!DOCTYPE html>"
|
||||||
"<html>"
|
"<html>"
|
||||||
"<head><meta charset=\"UTF-8\"><title>AnonyDump</title></head>"
|
"<head><meta charset=\"UTF-8\"><title>AnonyDrop</title><meta name=\"color-scheme\" content=\"dark light\"></head>"
|
||||||
"<body>"
|
"<body>"
|
||||||
"<h1>AnonyDump</h1>"
|
"<h1>AnonyDrop</h1>"
|
||||||
"<a href=\"./files/\">Files</a>"
|
"<a href=\"./files/\">Files</a>"
|
||||||
"<form action=\"./upload\" method=\"post\" enctype=\"multipart/form-data\" accept-charset=\"UTF-8\">"
|
"<form action=\"./upload\" method=\"post\" enctype=\"multipart/form-data\" accept-charset=\"UTF-8\">"
|
||||||
"<input type=\"file\" name=\"file\" multiple>"
|
"<input type=\"file\" name=\"file\" multiple>"
|
||||||
@@ -43,19 +43,18 @@ int main(int argc, char** argv)
|
|||||||
if(name != "file") return nullptr;
|
if(name != "file") return nullptr;
|
||||||
VFSPath path("/"+filename);
|
VFSPath path("/"+filename);
|
||||||
auto strm = vfs->OpenFile(path,"wb");
|
auto strm = vfs->OpenFile(path,"wb");
|
||||||
|
|
||||||
return strm;
|
return strm;
|
||||||
});
|
});
|
||||||
ctx.WithMimeType("text/html")
|
ctx.WithMimeType("text/html")
|
||||||
.SendText(
|
.SendText(
|
||||||
"<!DOCTYPE html>"
|
"<!DOCTYPE html>"
|
||||||
"<html>"
|
"<html>"
|
||||||
"<head><title>AnonyDump - Uploaded successfully</title>"
|
"<head><meta name=\"color-scheme\" content=\"dark light\"><title>AnonyDrop - Uploaded successfully</title></head>"
|
||||||
"<body>"
|
"<body>"
|
||||||
"<h1>Uploaded successfully</h1>"
|
"<h1>Uploaded successfully</h1>"
|
||||||
"<a href=\"./\">Back</a>"
|
"<a href=\"./\">Back</a>"
|
||||||
|
|
||||||
"</form>"
|
|
||||||
"</body>"
|
"</body>"
|
||||||
"</html>"
|
"</html>"
|
||||||
);
|
);
|
||||||
@@ -71,7 +70,7 @@ int main(int argc, char** argv)
|
|||||||
"<body>"
|
"<body>"
|
||||||
"<h1>Error: Must contain multipart and POST</h1>"
|
"<h1>Error: Must contain multipart and POST</h1>"
|
||||||
"<a href=\"./\">Back</a>"
|
"<a href=\"./\">Back</a>"
|
||||||
|
|
||||||
"</form>"
|
"</form>"
|
||||||
"</body>"
|
"</body>"
|
||||||
"</html>"
|
"</html>"
|
||||||
@@ -91,4 +90,4 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
TF_Quit();
|
TF_Quit();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
# 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
|
||||||
|
|
||||||
|
|
||||||
## 0.0.1
|
## 0.0.1
|
||||||
Start versioning
|
Start versioning
|
||||||
61
cmake/sources.cmake
Normal file
61
cmake/sources.cmake
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
list(APPEND TESSESFRAMEWORK_SOURCE
|
||||||
|
src/Random.cpp
|
||||||
|
src/Date/Date.cpp
|
||||||
|
src/Http/FileServer.cpp
|
||||||
|
src/Http/MountableServer.cpp
|
||||||
|
src/Http/RouteServer.cpp
|
||||||
|
src/Http/CallbackServer.cpp
|
||||||
|
src/Http/HttpServer.cpp
|
||||||
|
src/Http/HttpUtils.cpp
|
||||||
|
src/Http/HttpClient.cpp
|
||||||
|
src/Http/HttpStream.cpp
|
||||||
|
src/Http/ContentDisposition.cpp
|
||||||
|
src/Http/WebSocket.cpp
|
||||||
|
src/Http/ChangeableServer.cpp
|
||||||
|
src/Http/BasicAuthServer.cpp
|
||||||
|
src/Http/CGIServer.cpp
|
||||||
|
src/Mail/Smtp.cpp
|
||||||
|
src/Serialization/Json.cpp
|
||||||
|
src/Serialization/SQLite.cpp
|
||||||
|
src/Serialization/BitConverter.cpp
|
||||||
|
src/Serialization/Bencode.cpp
|
||||||
|
src/Platform/Environment.cpp
|
||||||
|
src/Platform/Process.cpp
|
||||||
|
src/Streams/FileStream.cpp
|
||||||
|
src/Streams/MemoryStream.cpp
|
||||||
|
src/Streams/NetworkStream.cpp
|
||||||
|
src/Streams/Stream.cpp
|
||||||
|
src/Streams/BufferedStream.cpp
|
||||||
|
src/Streams/ByteReader.cpp
|
||||||
|
src/Streams/ByteWriter.cpp
|
||||||
|
src/Streams/PtyStream.cpp
|
||||||
|
src/Text/StringConverter.cpp
|
||||||
|
src/Text/HeaderGenerator.cpp
|
||||||
|
src/TextStreams/StreamReader.cpp
|
||||||
|
src/TextStreams/StreamWriter.cpp
|
||||||
|
src/TextStreams/TextReader.cpp
|
||||||
|
src/TextStreams/TextWriter.cpp
|
||||||
|
src/TextStreams/StdIOReader.cpp
|
||||||
|
src/TextStreams/StdIOWriter.cpp
|
||||||
|
src/TextStreams/StringReader.cpp
|
||||||
|
src/TextStreams/StringWriter.cpp
|
||||||
|
src/Threading/Thread.cpp
|
||||||
|
src/Threading/Mutex.cpp
|
||||||
|
src/Threading/ThreadPool.cpp
|
||||||
|
src/Filesystem/VFS.cpp
|
||||||
|
src/Filesystem/LocalFS.cpp
|
||||||
|
src/Filesystem/SubdirFilesystem.cpp
|
||||||
|
src/Filesystem/NullFilesystem.cpp
|
||||||
|
src/Filesystem/MountableFilesystem.cpp
|
||||||
|
src/Filesystem/RelativeFilesystem.cpp
|
||||||
|
src/Filesystem/FSHelpers.cpp
|
||||||
|
src/Filesystem/TempFS.cpp
|
||||||
|
src/Crypto/MbedTLS/ClientTLSStream.cpp
|
||||||
|
src/Crypto/MbedTLS/Crypto.cpp
|
||||||
|
src/Args.cpp
|
||||||
|
src/TF_Init.cpp
|
||||||
|
src/HiddenField.cpp
|
||||||
|
src/Uuid.cpp
|
||||||
|
src/BitTorrent/TorrentFile.cpp
|
||||||
|
src/BitTorrent/TorrentStream.cpp
|
||||||
|
)
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
services:
|
services:
|
||||||
portable-json:
|
portable-json:
|
||||||
image: onedev.site.tesses.net/tesses-framework/portable-json-creator:latest
|
image: git.tesses.org/tesses50/portable-json-creator:latest
|
||||||
ports:
|
ports:
|
||||||
- "4999:4999"
|
- "4999:4999"
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
#include "TessesFramework/TessesFramework.hpp"
|
|
||||||
using namespace Tesses::Framework;
|
|
||||||
int main(int argc, char** argv)
|
|
||||||
{
|
|
||||||
TF_Init();
|
|
||||||
auto event = std::make_shared<FunctionalEvent<uint64_t>>([](uint64_t n)->void {
|
|
||||||
std::cout << n << std::endl;
|
|
||||||
});
|
|
||||||
OnItteraton += event;
|
|
||||||
|
|
||||||
|
|
||||||
auto event2 = std::make_shared<FunctionalEvent<uint64_t>>([&event](uint64_t n)->void{
|
|
||||||
if(n == 10000) OnItteraton -= event;
|
|
||||||
});
|
|
||||||
OnItteraton += event2;
|
|
||||||
|
|
||||||
|
|
||||||
TF_RunEventLoop();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
17
examples/timer.cpp
Normal file
17
examples/timer.cpp
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#include "TessesFramework/Common.hpp"
|
||||||
|
#include "TessesFramework/TessesFramework.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
using namespace Tesses::Framework;
|
||||||
|
TF_Init();
|
||||||
|
|
||||||
|
auto timer = TF_Timer([]()->void {
|
||||||
|
std::cout << "Hi, I am a timer" << std::endl;
|
||||||
|
});
|
||||||
|
|
||||||
|
TF_RunEventLoop();
|
||||||
|
|
||||||
|
TF_Quit();
|
||||||
|
}
|
||||||
@@ -1,10 +1,16 @@
|
|||||||
#include "TessesFramework/TessesFramework.hpp"
|
#include "TessesFramework/TessesFramework.hpp"
|
||||||
|
#include <TessesFramework/Platform/Environment.hpp>
|
||||||
|
#include <exception>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <stdexcept>
|
||||||
using namespace Tesses::Framework;
|
using namespace Tesses::Framework;
|
||||||
using namespace Tesses::Framework::Http;
|
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:
|
||||||
@@ -26,7 +32,7 @@ class MyWebServer : public IHttpServer {
|
|||||||
if(ctx.path == "/")
|
if(ctx.path == "/")
|
||||||
{
|
{
|
||||||
std::shared_ptr<FileStream> fs = std::make_shared<FileStream>("index.html","rb");
|
std::shared_ptr<FileStream> fs = std::make_shared<FileStream>("index.html","rb");
|
||||||
|
|
||||||
ctx
|
ctx
|
||||||
.WithMimeType("text/html")
|
.WithMimeType("text/html")
|
||||||
.SendStream(fs);
|
.SendStream(fs);
|
||||||
@@ -62,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>");
|
||||||
@@ -71,11 +77,20 @@ 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")
|
||||||
{
|
{
|
||||||
|
|
||||||
std::shared_ptr<FileStream> fs = std::make_shared<FileStream>("main.js","rb");
|
std::shared_ptr<FileStream> fs = std::make_shared<FileStream>("main.js","rb");
|
||||||
|
|
||||||
ctx
|
ctx
|
||||||
.WithMimeType("text/js")
|
.WithMimeType("text/js")
|
||||||
.SendStream(fs);
|
.SendStream(fs);
|
||||||
@@ -92,10 +107,10 @@ class MyWebServer : public IHttpServer {
|
|||||||
Johnny* data = ctx.GetServerContentData<Johnny>("mytag");
|
Johnny* data = ctx.GetServerContentData<Johnny>("mytag");
|
||||||
data->text = "Demi Lovato";
|
data->text = "Demi Lovato";
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
class MyOtherWebServer : public IHttpServer
|
class MyOtherWebServer : public IHttpServer
|
||||||
{
|
{
|
||||||
@@ -115,10 +130,30 @@ class MyOtherWebServer : public IHttpServer
|
|||||||
.WithContentDisposition(HttpUtils::Sanitise(name) + ".txt",false)
|
.WithContentDisposition(HttpUtils::Sanitise(name) + ".txt",false)
|
||||||
.SendText(name + " is cool.");
|
.SendText(name + " is cool.");
|
||||||
//do something with q
|
//do something with q
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(ctx.path == "/status")
|
||||||
|
{
|
||||||
|
int64_t num;
|
||||||
|
if(ctx.queryParams.TryGetFirstInt("code", num))
|
||||||
|
{
|
||||||
|
ctx.statusCode = (StatusCode)num;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.SendErrorPage(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if(ctx.path == "/error")
|
||||||
|
{
|
||||||
|
throw std::runtime_error("This is a error");
|
||||||
|
}
|
||||||
|
else if(ctx.path == "/error-debug")
|
||||||
|
{
|
||||||
|
ctx.WithDebug(true);
|
||||||
|
throw std::runtime_error("Platform is " + Tesses::Framework::Platform::Environment::GetPlatform());
|
||||||
|
}
|
||||||
else if(ctx.path == "/mymount/steve")
|
else if(ctx.path == "/mymount/steve")
|
||||||
{
|
{
|
||||||
Johnny* data = ctx.GetServerContentData<Johnny>("mytag");
|
Johnny* data = ctx.GetServerContentData<Johnny>("mytag");
|
||||||
@@ -131,7 +166,7 @@ class MyOtherWebServer : public IHttpServer
|
|||||||
ctx.WithMimeType("text/html").SendText(txt);
|
ctx.WithMimeType("text/html").SendText(txt);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -139,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;
|
||||||
@@ -172,4 +214,4 @@ int main(int argc, char** argv)
|
|||||||
server.StartAccepting();
|
server.StartAccepting();
|
||||||
TF_RunEventLoop();
|
TF_RunEventLoop();
|
||||||
std::cout << "Closing server" << std::endl;
|
std::cout << "Closing server" << std::endl;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <memory>
|
||||||
|
#include <ratio>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <map>
|
#include <map>
|
||||||
@@ -15,84 +18,56 @@
|
|||||||
namespace Tesses::Framework
|
namespace Tesses::Framework
|
||||||
{
|
{
|
||||||
|
|
||||||
template<typename...TArgs>
|
|
||||||
class Event {
|
|
||||||
public:
|
|
||||||
virtual void Invoke(TArgs... args)=0;
|
|
||||||
virtual ~Event()
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
template<typename...TArgs>
|
|
||||||
class FunctionalEvent : public Event<TArgs...> {
|
|
||||||
std::function<void(TArgs...)> cb;
|
|
||||||
public:
|
|
||||||
FunctionalEvent(std::function<void(TArgs...)> cb)
|
|
||||||
{
|
|
||||||
this->cb = cb;
|
|
||||||
}
|
|
||||||
void Invoke(TArgs... args)
|
|
||||||
{
|
|
||||||
this->cb(args...);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename...TArgs>
|
|
||||||
class EventList : public Event<TArgs...> {
|
|
||||||
Threading::Mutex mtx;
|
|
||||||
std::vector<std::shared_ptr<Event<TArgs...>>> items;
|
|
||||||
public:
|
|
||||||
void operator+=(std::shared_ptr<Event<TArgs...>> event)
|
|
||||||
{
|
|
||||||
mtx.Lock();
|
|
||||||
for(std::shared_ptr<Event<TArgs...>>& item : this->items)
|
|
||||||
{
|
|
||||||
if(item.get() == event.get()) {
|
|
||||||
mtx.Unlock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this->items.push_back(event);
|
|
||||||
mtx.Unlock();
|
|
||||||
}
|
|
||||||
void operator-=(std::shared_ptr<Event<TArgs...>> event)
|
|
||||||
{
|
|
||||||
mtx.Lock();
|
|
||||||
for(auto i = this->items.begin(); i != this->items.end(); i++)
|
|
||||||
{
|
|
||||||
if(i->get() == event.get())
|
|
||||||
{
|
|
||||||
this->items.erase(i);
|
|
||||||
mtx.Unlock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mtx.Unlock();
|
|
||||||
}
|
|
||||||
void Invoke(TArgs... args)
|
|
||||||
{
|
|
||||||
mtx.Lock();
|
|
||||||
for(auto& item : this->items)
|
|
||||||
{
|
|
||||||
item->Invoke(args...);
|
|
||||||
}
|
|
||||||
mtx.Unlock();
|
|
||||||
}
|
|
||||||
void Remove(std::function<bool(std::shared_ptr<Event<TArgs...>>)> cb)
|
|
||||||
{
|
|
||||||
for(auto index = this->items.begin(); index != this->items.end(); index++)
|
|
||||||
{
|
|
||||||
if(cb(*index))
|
|
||||||
{
|
|
||||||
this->items.erase(index);
|
|
||||||
index--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
extern EventList<uint64_t> OnItteraton;
|
|
||||||
std::optional<std::string> TF_GetCommandName();
|
std::optional<std::string> TF_GetCommandName();
|
||||||
|
class TF_Timer_Handle;
|
||||||
|
//Used for internal purposes, don't use unless you want to run timer events on another thread
|
||||||
|
|
||||||
|
class TF_Timer_Handler {
|
||||||
|
private:
|
||||||
|
std::vector<std::weak_ptr<TF_Timer_Handle>> handles;
|
||||||
|
public:
|
||||||
|
void Update();
|
||||||
|
|
||||||
|
|
||||||
|
static std::shared_ptr<TF_Timer_Handle> Make(std::shared_ptr<TF_Timer_Handler> handler);
|
||||||
|
friend class TF_Timer_Handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TF_Timer_Handle {
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<TF_Timer_Handler> timerHandler;
|
||||||
|
std::function<void()> cb;
|
||||||
|
std::chrono::milliseconds interval;
|
||||||
|
std::chrono::time_point<std::chrono::steady_clock, std::chrono::milliseconds> last;
|
||||||
|
bool enabled;
|
||||||
|
TF_Timer_Handle() = delete;
|
||||||
|
|
||||||
|
TF_Timer_Handle(std::shared_ptr<TF_Timer_Handler> timerHandler);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void SetCallback(std::function<void()> cb);
|
||||||
|
|
||||||
|
int64_t GetIntervalMilliseconds();
|
||||||
|
std::chrono::duration<int64_t,std::milli> GetIntervalDuration();
|
||||||
|
|
||||||
|
void SetIntervalFromMilliseconds(int64_t ms);
|
||||||
|
|
||||||
|
void SetIntervalFromDuration(std::chrono::milliseconds dur);
|
||||||
|
|
||||||
|
|
||||||
|
void SetEnabled(bool enabled);
|
||||||
|
bool GetEnabled();
|
||||||
|
friend class TF_Timer_Handler;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
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, 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);
|
||||||
@@ -101,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();
|
||||||
|
|||||||
@@ -1,50 +1,46 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "VFS.hpp"
|
#include "VFS.hpp"
|
||||||
#include "VFSFix.hpp"
|
#include "VFSFix.hpp"
|
||||||
|
|
||||||
namespace Tesses::Framework::Filesystem
|
namespace Tesses::Framework::Filesystem
|
||||||
{
|
{
|
||||||
class LocalFilesystem : public VFS
|
class LocalFilesystem : public VFS
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
std::shared_ptr<Tesses::Framework::Streams::Stream> OpenFile(VFSPath path, std::string mode);
|
std::shared_ptr<Tesses::Framework::Streams::Stream> OpenFile(VFSPath path, std::string mode);
|
||||||
|
|
||||||
void CreateDirectory(VFSPath path);
|
void CreateDirectory(VFSPath path);
|
||||||
void DeleteDirectory(VFSPath path);
|
void DeleteDirectory(VFSPath path);
|
||||||
bool RegularFileExists(VFSPath path);
|
|
||||||
bool SymlinkExists(VFSPath path);
|
|
||||||
bool CharacterDeviceExists(VFSPath path);
|
|
||||||
bool BlockDeviceExists(VFSPath path);
|
|
||||||
bool SocketFileExists(VFSPath path);
|
|
||||||
bool FIFOFileExists(VFSPath path);
|
|
||||||
bool DirectoryExists(VFSPath path);
|
|
||||||
|
|
||||||
void DeleteFile(VFSPath path);
|
void DeleteFile(VFSPath path);
|
||||||
void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile);
|
void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile);
|
||||||
VFSPathEnumerator EnumeratePaths(VFSPath path);
|
VFSPathEnumerator EnumeratePaths(VFSPath path);
|
||||||
void CreateHardlink(VFSPath existingFile, VFSPath newName);
|
void CreateHardlink(VFSPath existingFile, VFSPath newName);
|
||||||
|
|
||||||
void MoveFile(VFSPath src, VFSPath dest);
|
void MoveFile(VFSPath src, VFSPath dest);
|
||||||
|
|
||||||
void MoveDirectory(VFSPath src, VFSPath dest);
|
void MoveDirectory(VFSPath src, VFSPath dest);
|
||||||
VFSPath ReadLink(VFSPath path);
|
VFSPath ReadLink(VFSPath path);
|
||||||
std::string VFSPathToSystem(VFSPath path);
|
std::string VFSPathToSystem(VFSPath path);
|
||||||
VFSPath SystemToVFSPath(std::string path);
|
VFSPath SystemToVFSPath(std::string path);
|
||||||
|
|
||||||
void GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess);
|
|
||||||
void SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess);
|
|
||||||
|
|
||||||
|
void SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess);
|
||||||
|
bool Stat(VFSPath path, StatData& stat);
|
||||||
bool StatVFS(VFSPath path, StatVFSData& vfsData);
|
bool StatVFS(VFSPath path, StatVFSData& vfsData);
|
||||||
|
|
||||||
void Chmod(VFSPath path, uint32_t mode);
|
void Chmod(VFSPath path, uint32_t mode);
|
||||||
|
void Chown(VFSPath path, uint32_t uid, uint32_t gid);
|
||||||
|
|
||||||
void Lock(VFSPath path);
|
void Lock(VFSPath path);
|
||||||
void Unlock(VFSPath path);
|
void Unlock(VFSPath path);
|
||||||
|
|
||||||
|
FIFOCreationResult CreateFIFO(VFSPath path, uint32_t mod);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::shared_ptr<FSWatcher> CreateWatcher(std::shared_ptr<VFS> vfs, VFSPath path);
|
std::shared_ptr<FSWatcher> CreateWatcher(std::shared_ptr<VFS> vfs, VFSPath path);
|
||||||
|
|
||||||
};
|
};
|
||||||
extern std::shared_ptr<LocalFilesystem> LocalFS;
|
extern std::shared_ptr<LocalFilesystem> LocalFS;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,100 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "VFS.hpp"
|
|
||||||
#include "VFSFix.hpp"
|
|
||||||
#include "../Threading/Mutex.hpp"
|
|
||||||
#include <atomic>
|
|
||||||
namespace Tesses::Framework::Filesystem
|
|
||||||
{
|
|
||||||
class MemoryEntry {
|
|
||||||
public:
|
|
||||||
std::string name;
|
|
||||||
virtual ~MemoryEntry();
|
|
||||||
};
|
|
||||||
class MemoryFileData {
|
|
||||||
public:
|
|
||||||
MemoryFileData();
|
|
||||||
Date::DateTime lastWrite;
|
|
||||||
|
|
||||||
bool canAccess;
|
|
||||||
size_t readers;
|
|
||||||
std::vector<uint8_t> file;
|
|
||||||
};
|
|
||||||
|
|
||||||
class MemoryFile : public MemoryEntry
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
std::shared_ptr<MemoryFileData> data;
|
|
||||||
~MemoryFile();
|
|
||||||
};
|
|
||||||
|
|
||||||
class MemoryDirectory : public MemoryEntry
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MemoryDirectory();
|
|
||||||
Date::DateTime lastWrite;
|
|
||||||
std::vector<MemoryEntry*> entries;
|
|
||||||
~MemoryDirectory();
|
|
||||||
};
|
|
||||||
|
|
||||||
class MemorySymlink : public MemoryEntry
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Date::DateTime lastWrite;
|
|
||||||
VFSPath linkedTo;
|
|
||||||
};
|
|
||||||
|
|
||||||
class MemoryFilesystemStream : public Streams::Stream
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
std::shared_ptr<Tesses::Framework::Threading::Mutex> mtx;
|
|
||||||
std::shared_ptr<MemoryFileData> data;
|
|
||||||
bool canRead;
|
|
||||||
bool canWrite;
|
|
||||||
bool canSeek;
|
|
||||||
int64_t pos;
|
|
||||||
MemoryFilesystemStream(std::shared_ptr<Tesses::Framework::Threading::Mutex> mtx, std::shared_ptr<MemoryFileData> data,bool canRead, bool canWrite, bool canSeek);
|
|
||||||
size_t Read(uint8_t* buff, size_t sz);
|
|
||||||
size_t Write(const uint8_t* buff, size_t sz);
|
|
||||||
bool CanRead();
|
|
||||||
bool CanWrite();
|
|
||||||
bool CanSeek();
|
|
||||||
int64_t GetPosition();
|
|
||||||
void Flush();
|
|
||||||
void Seek(int64_t pos, Streams::SeekOrigin whence);
|
|
||||||
~MemoryFilesystemStream();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class MemoryFilesystem : public VFS
|
|
||||||
{
|
|
||||||
std::shared_ptr<Tesses::Framework::Threading::Mutex> mtx;
|
|
||||||
MemoryDirectory root;
|
|
||||||
|
|
||||||
MemoryEntry* GetEntry(VFSPath path,bool followSymlink);
|
|
||||||
public:
|
|
||||||
MemoryFilesystem();
|
|
||||||
std::shared_ptr<Tesses::Framework::Streams::Stream> OpenFile(VFSPath path, std::string mode);
|
|
||||||
|
|
||||||
void CreateDirectory(VFSPath path);
|
|
||||||
void DeleteDirectory(VFSPath path);
|
|
||||||
bool RegularFileExists(VFSPath path);
|
|
||||||
bool SymlinkExists(VFSPath path);
|
|
||||||
bool DirectoryExists(VFSPath path);
|
|
||||||
|
|
||||||
void DeleteFile(VFSPath path);
|
|
||||||
void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile);
|
|
||||||
VFSPathEnumerator EnumeratePaths(VFSPath path);
|
|
||||||
void CreateHardlink(VFSPath existingFile, VFSPath newName);
|
|
||||||
|
|
||||||
void MoveFile(VFSPath src, VFSPath dest);
|
|
||||||
|
|
||||||
void MoveDirectory(VFSPath src, VFSPath dest);
|
|
||||||
VFSPath ReadLink(VFSPath path);
|
|
||||||
std::string VFSPathToSystem(VFSPath path);
|
|
||||||
VFSPath SystemToVFSPath(std::string path);
|
|
||||||
void GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess);
|
|
||||||
void SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess);
|
|
||||||
|
|
||||||
~MemoryFilesystem();
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "VFS.hpp"
|
#include "VFS.hpp"
|
||||||
#include "VFSFix.hpp"
|
#include "VFSFix.hpp"
|
||||||
|
|
||||||
namespace Tesses::Framework::Filesystem
|
namespace Tesses::Framework::Filesystem
|
||||||
{
|
{
|
||||||
class MountableDirectory {
|
class MountableDirectory {
|
||||||
@@ -19,10 +19,10 @@ namespace Tesses::Framework::Filesystem
|
|||||||
std::shared_ptr<VFS> root;
|
std::shared_ptr<VFS> root;
|
||||||
|
|
||||||
std::vector<MountableDirectory*> directories;
|
std::vector<MountableDirectory*> directories;
|
||||||
|
|
||||||
void GetFS(VFSPath srcPath, VFSPath& destRoot, VFSPath& destPath, std::shared_ptr<VFS>& vfs);
|
void GetFS(VFSPath srcPath, VFSPath& destRoot, VFSPath& destPath, std::shared_ptr<VFS>& vfs);
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MountableFilesystem();
|
MountableFilesystem();
|
||||||
MountableFilesystem(std::shared_ptr<VFS> root);
|
MountableFilesystem(std::shared_ptr<VFS> root);
|
||||||
@@ -31,15 +31,7 @@ namespace Tesses::Framework::Filesystem
|
|||||||
std::shared_ptr<Tesses::Framework::Streams::Stream> OpenFile(VFSPath path, std::string mode);
|
std::shared_ptr<Tesses::Framework::Streams::Stream> OpenFile(VFSPath path, std::string mode);
|
||||||
void CreateDirectory(VFSPath path);
|
void CreateDirectory(VFSPath path);
|
||||||
void DeleteDirectory(VFSPath path);
|
void DeleteDirectory(VFSPath path);
|
||||||
bool SpecialFileExists(VFSPath path);
|
bool Stat(VFSPath path, StatData& data);
|
||||||
bool FileExists(VFSPath path);
|
|
||||||
bool RegularFileExists(VFSPath path);
|
|
||||||
bool SymlinkExists(VFSPath path);
|
|
||||||
bool CharacterDeviceExists(VFSPath path);
|
|
||||||
bool BlockDeviceExists(VFSPath path);
|
|
||||||
bool SocketFileExists(VFSPath path);
|
|
||||||
bool FIFOFileExists(VFSPath path);
|
|
||||||
bool DirectoryExists(VFSPath path);
|
|
||||||
void DeleteFile(VFSPath path);
|
void DeleteFile(VFSPath path);
|
||||||
void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile);
|
void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile);
|
||||||
VFSPathEnumerator EnumeratePaths(VFSPath path);
|
VFSPathEnumerator EnumeratePaths(VFSPath path);
|
||||||
@@ -50,14 +42,18 @@ namespace Tesses::Framework::Filesystem
|
|||||||
std::string VFSPathToSystem(VFSPath path);
|
std::string VFSPathToSystem(VFSPath path);
|
||||||
VFSPath SystemToVFSPath(std::string path);
|
VFSPath SystemToVFSPath(std::string path);
|
||||||
~MountableFilesystem();
|
~MountableFilesystem();
|
||||||
void GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess);
|
|
||||||
void SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess);
|
void SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess);
|
||||||
|
|
||||||
bool StatVFS(VFSPath path, StatVFSData& vfsData);
|
bool StatVFS(VFSPath path, StatVFSData& vfsData);
|
||||||
|
|
||||||
void Chmod(VFSPath path, uint32_t mode);
|
void Chmod(VFSPath path, uint32_t mode);
|
||||||
|
void Chown(VFSPath path, uint32_t uid, uint32_t gid);
|
||||||
|
FIFOCreationResult CreateFIFO(VFSPath path, uint32_t mode);
|
||||||
|
|
||||||
|
|
||||||
void Lock(VFSPath path);
|
void Lock(VFSPath path);
|
||||||
void Unlock(VFSPath path);
|
void Unlock(VFSPath path);
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,16 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "VFS.hpp"
|
#include "VFS.hpp"
|
||||||
#include "VFSFix.hpp"
|
#include "VFSFix.hpp"
|
||||||
|
|
||||||
namespace Tesses::Framework::Filesystem
|
namespace Tesses::Framework::Filesystem
|
||||||
{
|
{
|
||||||
class NullFilesystem : public VFS
|
class NullFilesystem : public VFS
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::shared_ptr<Tesses::Framework::Streams::Stream> OpenFile(VFSPath path, std::string mode);
|
std::shared_ptr<Tesses::Framework::Streams::Stream> OpenFile(VFSPath path, std::string mode);
|
||||||
void CreateDirectory(VFSPath path);
|
|
||||||
void DeleteDirectory(VFSPath path);
|
|
||||||
bool RegularFileExists(VFSPath path);
|
|
||||||
bool DirectoryExists(VFSPath path);
|
|
||||||
void DeleteFile(VFSPath path);
|
|
||||||
VFSPathEnumerator EnumeratePaths(VFSPath path);
|
VFSPathEnumerator EnumeratePaths(VFSPath path);
|
||||||
void MoveFile(VFSPath src, VFSPath dest);
|
bool Stat(VFSPath path, StatData& data);
|
||||||
std::string VFSPathToSystem(VFSPath path);
|
std::string VFSPathToSystem(VFSPath path);
|
||||||
VFSPath SystemToVFSPath(std::string path);
|
VFSPath SystemToVFSPath(std::string path);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
54
include/TessesFramework/Filesystem/RelativeFilesystem.hpp
Normal file
54
include/TessesFramework/Filesystem/RelativeFilesystem.hpp
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "VFS.hpp"
|
||||||
|
#include "VFSFix.hpp"
|
||||||
|
|
||||||
|
namespace Tesses::Framework::Filesystem
|
||||||
|
{
|
||||||
|
class RelativeFilesystem : public VFS {
|
||||||
|
Tesses::Framework::Threading::Mutex mtx;
|
||||||
|
VFSPath working;
|
||||||
|
std::shared_ptr<VFS> vfs;
|
||||||
|
private:
|
||||||
|
VFSPath ToParent(VFSPath path);
|
||||||
|
public:
|
||||||
|
RelativeFilesystem(std::shared_ptr<VFS> vfs, VFSPath working);
|
||||||
|
VFSPath GetWorking();
|
||||||
|
void SetWorking(VFSPath path);
|
||||||
|
std::shared_ptr<VFS> GetVFS();
|
||||||
|
|
||||||
|
std::shared_ptr<Tesses::Framework::Streams::Stream> OpenFile(VFSPath path, std::string mode);
|
||||||
|
void CreateDirectory(VFSPath path);
|
||||||
|
void DeleteDirectory(VFSPath path);
|
||||||
|
void DeleteFile(VFSPath path);
|
||||||
|
void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile);
|
||||||
|
VFSPathEnumerator EnumeratePaths(VFSPath path);
|
||||||
|
void CreateHardlink(VFSPath existingFile, VFSPath newName);
|
||||||
|
void MoveFile(VFSPath src, VFSPath dest);
|
||||||
|
void MoveDirectory(VFSPath src, VFSPath dest);
|
||||||
|
void DeleteDirectoryRecurse(VFSPath path);
|
||||||
|
VFSPath ReadLink(VFSPath path);
|
||||||
|
std::string VFSPathToSystem(VFSPath path);
|
||||||
|
VFSPath SystemToVFSPath(std::string path);
|
||||||
|
void SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess);
|
||||||
|
bool StatVFS(VFSPath path, StatVFSData& vfsData);
|
||||||
|
bool Stat(VFSPath path, StatData& data);
|
||||||
|
|
||||||
|
void Chown(VFSPath path, uint32_t uid, uint32_t gid);
|
||||||
|
void Chmod(VFSPath path, uint32_t mode);
|
||||||
|
FIFOCreationResult CreateFIFO(VFSPath path, uint32_t mode);
|
||||||
|
void Lock(VFSPath path);
|
||||||
|
void Unlock(VFSPath path);
|
||||||
|
protected:
|
||||||
|
std::shared_ptr<FSWatcher> CreateWatcher(std::shared_ptr<VFS> vfs, VFSPath path);
|
||||||
|
|
||||||
|
|
||||||
|
class Watcher : public FSWatcher {
|
||||||
|
std::shared_ptr<FSWatcher> watcher;
|
||||||
|
protected:
|
||||||
|
void SetEnabledImpl(bool enabled);
|
||||||
|
public:
|
||||||
|
Watcher(std::shared_ptr<RelativeFilesystem> vfs, VFSPath path);
|
||||||
|
~Watcher();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "VFS.hpp"
|
#include "VFS.hpp"
|
||||||
#include "VFSFix.hpp"
|
#include "VFSFix.hpp"
|
||||||
|
|
||||||
namespace Tesses::Framework::Filesystem
|
namespace Tesses::Framework::Filesystem
|
||||||
{
|
{
|
||||||
class SubdirFilesystem : public VFS
|
class SubdirFilesystem : public VFS
|
||||||
@@ -15,15 +15,6 @@ namespace Tesses::Framework::Filesystem
|
|||||||
std::shared_ptr<Tesses::Framework::Streams::Stream> OpenFile(VFSPath path, std::string mode);
|
std::shared_ptr<Tesses::Framework::Streams::Stream> OpenFile(VFSPath path, std::string mode);
|
||||||
void CreateDirectory(VFSPath path);
|
void CreateDirectory(VFSPath path);
|
||||||
void DeleteDirectory(VFSPath path);
|
void DeleteDirectory(VFSPath path);
|
||||||
bool SpecialFileExists(VFSPath path);
|
|
||||||
bool FileExists(VFSPath path);
|
|
||||||
bool RegularFileExists(VFSPath path);
|
|
||||||
bool SymlinkExists(VFSPath path);
|
|
||||||
bool CharacterDeviceExists(VFSPath path);
|
|
||||||
bool BlockDeviceExists(VFSPath path);
|
|
||||||
bool SocketFileExists(VFSPath path);
|
|
||||||
bool FIFOFileExists(VFSPath path);
|
|
||||||
bool DirectoryExists(VFSPath path);
|
|
||||||
void DeleteFile(VFSPath path);
|
void DeleteFile(VFSPath path);
|
||||||
void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile);
|
void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile);
|
||||||
VFSPathEnumerator EnumeratePaths(VFSPath path);
|
VFSPathEnumerator EnumeratePaths(VFSPath path);
|
||||||
@@ -35,13 +26,28 @@ namespace Tesses::Framework::Filesystem
|
|||||||
std::string VFSPathToSystem(VFSPath path);
|
std::string VFSPathToSystem(VFSPath path);
|
||||||
VFSPath SystemToVFSPath(std::string path);
|
VFSPath SystemToVFSPath(std::string path);
|
||||||
~SubdirFilesystem();
|
~SubdirFilesystem();
|
||||||
void GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess);
|
|
||||||
void SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess);
|
void SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess);
|
||||||
bool StatVFS(VFSPath path, StatVFSData& vfsData);
|
bool StatVFS(VFSPath path, StatVFSData& vfsData);
|
||||||
|
bool Stat(VFSPath path, StatData& data);
|
||||||
|
|
||||||
|
void Chown(VFSPath path, uint32_t uid, uint32_t gid);
|
||||||
void Chmod(VFSPath path, uint32_t mode);
|
void Chmod(VFSPath path, uint32_t mode);
|
||||||
|
FIFOCreationResult CreateFIFO(VFSPath path, uint32_t mode);
|
||||||
void Lock(VFSPath path);
|
void Lock(VFSPath path);
|
||||||
void Unlock(VFSPath path);
|
void Unlock(VFSPath path);
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::shared_ptr<FSWatcher> CreateWatcher(std::shared_ptr<VFS> vfs, VFSPath path);
|
||||||
|
|
||||||
|
|
||||||
|
class Watcher : public FSWatcher {
|
||||||
|
std::shared_ptr<FSWatcher> watcher;
|
||||||
|
protected:
|
||||||
|
void SetEnabledImpl(bool enabled);
|
||||||
|
public:
|
||||||
|
Watcher(std::shared_ptr<SubdirFilesystem> vfs, VFSPath path);
|
||||||
|
~Watcher();
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
#include "../Common.hpp"
|
#include "../Common.hpp"
|
||||||
#include "VFS.hpp"
|
#include "VFS.hpp"
|
||||||
#include "VFSFix.hpp"
|
#include "VFSFix.hpp"
|
||||||
namespace Tesses::Framework::Filesystem
|
namespace Tesses::Framework::Filesystem
|
||||||
{
|
{
|
||||||
void UniqueString(std::string& text);
|
void UniqueString(std::string& text);
|
||||||
|
|
||||||
@@ -20,15 +20,6 @@ namespace Tesses::Framework::Filesystem
|
|||||||
std::shared_ptr<Tesses::Framework::Streams::Stream> OpenFile(VFSPath path, std::string mode);
|
std::shared_ptr<Tesses::Framework::Streams::Stream> OpenFile(VFSPath path, std::string mode);
|
||||||
void CreateDirectory(VFSPath path);
|
void CreateDirectory(VFSPath path);
|
||||||
void DeleteDirectory(VFSPath path);
|
void DeleteDirectory(VFSPath path);
|
||||||
bool SpecialFileExists(VFSPath path);
|
|
||||||
bool FileExists(VFSPath path);
|
|
||||||
bool RegularFileExists(VFSPath path);
|
|
||||||
bool SymlinkExists(VFSPath path);
|
|
||||||
bool CharacterDeviceExists(VFSPath path);
|
|
||||||
bool BlockDeviceExists(VFSPath path);
|
|
||||||
bool SocketFileExists(VFSPath path);
|
|
||||||
bool FIFOFileExists(VFSPath path);
|
|
||||||
bool DirectoryExists(VFSPath path);
|
|
||||||
void DeleteFile(VFSPath path);
|
void DeleteFile(VFSPath path);
|
||||||
void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile);
|
void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile);
|
||||||
VFSPathEnumerator EnumeratePaths(VFSPath path);
|
VFSPathEnumerator EnumeratePaths(VFSPath path);
|
||||||
@@ -39,16 +30,23 @@ namespace Tesses::Framework::Filesystem
|
|||||||
VFSPath ReadLink(VFSPath path);
|
VFSPath ReadLink(VFSPath path);
|
||||||
std::string VFSPathToSystem(VFSPath path);
|
std::string VFSPathToSystem(VFSPath path);
|
||||||
VFSPath SystemToVFSPath(std::string path);
|
VFSPath SystemToVFSPath(std::string path);
|
||||||
|
|
||||||
void GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess);
|
|
||||||
void SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess);
|
void SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess);
|
||||||
bool StatVFS(VFSPath path, StatVFSData& vfsData);
|
bool StatVFS(VFSPath path, StatVFSData& vfsData);
|
||||||
|
bool Stat(VFSPath path, StatData& data);
|
||||||
|
|
||||||
void Chmod(VFSPath path, uint32_t mode);
|
void Chmod(VFSPath path, uint32_t mode);
|
||||||
|
|
||||||
|
void Chown(VFSPath path, uint32_t uid, uint32_t gid);
|
||||||
|
FIFOCreationResult CreateFIFO(VFSPath path, uint32_t mode);
|
||||||
void Close();
|
void Close();
|
||||||
|
|
||||||
void Lock(VFSPath path);
|
void Lock(VFSPath path);
|
||||||
void Unlock(VFSPath path);
|
void Unlock(VFSPath path);
|
||||||
~TempFS();
|
~TempFS();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::shared_ptr<FSWatcher> CreateWatcher(std::shared_ptr<VFS> vfs, VFSPath path);
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "../Common.hpp"
|
#include "../Common.hpp"
|
||||||
#include "../Streams/Stream.hpp"
|
#include "../Streams/Stream.hpp"
|
||||||
|
#include <TessesFramework/Common.hpp>
|
||||||
|
#include <TessesFramework/Date/Date.hpp>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "../Date/Date.hpp"
|
#include "../Date/Date.hpp"
|
||||||
#include "VFSFix.hpp"
|
#include "VFSFix.hpp"
|
||||||
|
|
||||||
namespace Tesses::Framework::Filesystem
|
namespace Tesses::Framework::Filesystem
|
||||||
{
|
{
|
||||||
|
|
||||||
class StatVFSData {
|
struct StatVFSData {
|
||||||
public:
|
|
||||||
uint64_t BlockSize;
|
uint64_t BlockSize;
|
||||||
uint64_t FragmentSize;
|
uint64_t FragmentSize;
|
||||||
uint64_t Blocks;
|
uint64_t Blocks;
|
||||||
@@ -23,12 +25,94 @@ namespace Tesses::Framework::Filesystem
|
|||||||
uint64_t Flags;
|
uint64_t Flags;
|
||||||
uint64_t MaxNameLength;
|
uint64_t MaxNameLength;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr uint32_t MODE_USER_READ = 0400;
|
||||||
|
constexpr uint32_t MODE_USER_WRITE = 0200;
|
||||||
|
constexpr uint32_t MODE_USER_EXEC = 0100;
|
||||||
|
|
||||||
|
constexpr uint32_t MODE_GROUP_READ = (MODE_USER_READ >> 3);
|
||||||
|
constexpr uint32_t MODE_GROUP_WRITE = (MODE_USER_WRITE >> 3);
|
||||||
|
constexpr uint32_t MODE_GROUP_EXEC = (MODE_USER_EXEC >> 3);
|
||||||
|
|
||||||
|
constexpr uint32_t MODE_OTHER_READ = (MODE_GROUP_READ >> 3);
|
||||||
|
constexpr uint32_t MODE_OTHER_WRITE = (MODE_GROUP_WRITE >> 3);
|
||||||
|
constexpr uint32_t MODE_OTHER_EXEC = (MODE_GROUP_EXEC >> 3);
|
||||||
|
|
||||||
|
constexpr uint32_t MODE_REGULAR = 0100000;
|
||||||
|
constexpr uint32_t MODE_DIRECTORY = 0040000;
|
||||||
|
constexpr uint32_t MODE_CHAR_DEVICE = 0020000;
|
||||||
|
constexpr uint32_t MODE_BLOCK_DEVICE = 0060000;
|
||||||
|
constexpr uint32_t MODE_SOCKET = 0140000;
|
||||||
|
constexpr uint32_t MODE_FIFO = 0010000;
|
||||||
|
constexpr uint32_t MODE_SYMLINK = 0120000;
|
||||||
|
|
||||||
|
|
||||||
|
struct StatData {
|
||||||
|
uint64_t Device;
|
||||||
|
uint64_t Inode;
|
||||||
|
uint32_t Mode;
|
||||||
|
uint64_t HardLinks;
|
||||||
|
uint32_t UserId;
|
||||||
|
uint32_t GroupId;
|
||||||
|
uint64_t DeviceId;
|
||||||
|
uint64_t Size;
|
||||||
|
uint64_t BlockSize;
|
||||||
|
uint64_t BlockCount;
|
||||||
|
Date::DateTime LastAccess;
|
||||||
|
Date::DateTime LastModified;
|
||||||
|
Date::DateTime LastStatus;
|
||||||
|
|
||||||
|
bool IsRegularFile()
|
||||||
|
{
|
||||||
|
return (Mode & MODE_REGULAR) > 0;
|
||||||
|
}
|
||||||
|
bool IsDirectory()
|
||||||
|
{
|
||||||
|
return (Mode & MODE_DIRECTORY) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsCharDevice()
|
||||||
|
{
|
||||||
|
return (Mode & MODE_CHAR_DEVICE) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsBlockDevice()
|
||||||
|
{
|
||||||
|
return (Mode & MODE_BLOCK_DEVICE) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsSocket()
|
||||||
|
{
|
||||||
|
return (Mode & MODE_SOCKET) > 0;
|
||||||
|
}
|
||||||
|
bool IsFIFO()
|
||||||
|
{
|
||||||
|
return (Mode & MODE_FIFO) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsSymlink()
|
||||||
|
{
|
||||||
|
return (Mode & MODE_SYMLINK) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsSpecial()
|
||||||
|
{
|
||||||
|
if(IsRegularFile()) return false;
|
||||||
|
if(IsDirectory()) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ToSizeString(bool usesBin=true)
|
||||||
|
{
|
||||||
|
return TF_FileSize(this->Size, usesBin);
|
||||||
|
}
|
||||||
|
};
|
||||||
class VFSPath {
|
class VFSPath {
|
||||||
public:
|
public:
|
||||||
static VFSPath CurrentDirectoryAsRelative();
|
static VFSPath CurrentDirectoryAsRelative();
|
||||||
bool relative;
|
bool relative;
|
||||||
static std::vector<std::string> SplitPath(std::string path);
|
static std::vector<std::string> SplitPath(std::string path);
|
||||||
std::vector<std::string> path;
|
std::vector<std::string> path;
|
||||||
VFSPath();
|
VFSPath();
|
||||||
explicit VFSPath(const char* path) : VFSPath(std::string(path))
|
explicit VFSPath(const char* path) : VFSPath(std::string(path))
|
||||||
{}
|
{}
|
||||||
@@ -36,7 +120,7 @@ namespace Tesses::Framework::Filesystem
|
|||||||
VFSPath(std::string path);
|
VFSPath(std::string path);
|
||||||
VFSPath(VFSPath p, std::string subent);
|
VFSPath(VFSPath p, std::string subent);
|
||||||
VFSPath(VFSPath p, VFSPath p2);
|
VFSPath(VFSPath p, VFSPath p2);
|
||||||
|
|
||||||
//does not check for ?
|
//does not check for ?
|
||||||
static VFSPath ParseUriPath(std::string path);
|
static VFSPath ParseUriPath(std::string path);
|
||||||
|
|
||||||
@@ -52,7 +136,7 @@ namespace Tesses::Framework::Filesystem
|
|||||||
static VFSPath GetAbsoluteCurrentDirectory();
|
static VFSPath GetAbsoluteCurrentDirectory();
|
||||||
static void SetAbsoluteCurrentDirectory(VFSPath path);
|
static void SetAbsoluteCurrentDirectory(VFSPath path);
|
||||||
VFSPath MakeAbsolute() const;
|
VFSPath MakeAbsolute() const;
|
||||||
|
|
||||||
VFSPath MakeAbsolute(VFSPath curDir) const;
|
VFSPath MakeAbsolute(VFSPath curDir) const;
|
||||||
VFSPath MakeRelative() const;
|
VFSPath MakeRelative() const;
|
||||||
VFSPath MakeRelative(VFSPath toMakeRelativeTo) const;
|
VFSPath MakeRelative(VFSPath toMakeRelativeTo) const;
|
||||||
@@ -98,10 +182,10 @@ namespace Tesses::Framework::Filesystem
|
|||||||
|
|
||||||
VFSPathEnumeratorItterator& operator++();
|
VFSPathEnumeratorItterator& operator++();
|
||||||
VFSPathEnumeratorItterator& operator++(int);
|
VFSPathEnumeratorItterator& operator++(int);
|
||||||
|
|
||||||
VFSPath& operator*();
|
VFSPath& operator*();
|
||||||
VFSPath* operator->();
|
VFSPath* operator->();
|
||||||
|
|
||||||
bool operator!=(VFSPathEnumeratorItterator right);
|
bool operator!=(VFSPathEnumeratorItterator right);
|
||||||
bool operator==(VFSPathEnumeratorItterator right);
|
bool operator==(VFSPathEnumeratorItterator right);
|
||||||
};
|
};
|
||||||
@@ -185,48 +269,60 @@ namespace Tesses::Framework::Filesystem
|
|||||||
std::shared_ptr<VFS> GetFilesystem();
|
std::shared_ptr<VFS> GetFilesystem();
|
||||||
const VFSPath& GetPath();
|
const VFSPath& GetPath();
|
||||||
virtual ~FSWatcher() = default;
|
virtual ~FSWatcher() = default;
|
||||||
|
|
||||||
static std::shared_ptr<FSWatcher> Create(std::shared_ptr<VFS> vfs, VFSPath path);
|
static std::shared_ptr<FSWatcher> Create(std::shared_ptr<VFS> vfs, VFSPath path);
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class FIFOCreationResult {
|
||||||
|
Success=0,
|
||||||
|
Exists = 1,
|
||||||
|
ReadOnlyFS = 2,
|
||||||
|
Denied = 3,
|
||||||
|
OutOfInodes = 4,
|
||||||
|
UnknownError = 5,
|
||||||
|
Unsupported = 255
|
||||||
};
|
};
|
||||||
|
|
||||||
class VFS {
|
class VFS {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual std::shared_ptr<Tesses::Framework::Streams::Stream> OpenFile(VFSPath path, std::string mode)=0;
|
virtual std::shared_ptr<Tesses::Framework::Streams::Stream> OpenFile(VFSPath path, std::string mode)=0;
|
||||||
virtual void CreateDirectory(VFSPath path)=0;
|
virtual void CreateDirectory(VFSPath path);
|
||||||
virtual void DeleteDirectory(VFSPath path)=0;
|
virtual void DeleteDirectory(VFSPath path);
|
||||||
virtual bool RegularFileExists(VFSPath path)=0;
|
bool DirectoryExists(VFSPath path);
|
||||||
virtual bool SymlinkExists(VFSPath path);
|
bool RegularFileExists(VFSPath path);
|
||||||
virtual bool CharacterDeviceExists(VFSPath path);
|
bool SymlinkExists(VFSPath path);
|
||||||
virtual bool BlockDeviceExists(VFSPath path);
|
bool CharacterDeviceExists(VFSPath path);
|
||||||
virtual bool SocketFileExists(VFSPath path);
|
bool BlockDeviceExists(VFSPath path);
|
||||||
virtual bool FIFOFileExists(VFSPath path);
|
bool SocketFileExists(VFSPath path);
|
||||||
virtual bool FileExists(VFSPath path);
|
bool FIFOFileExists(VFSPath path);
|
||||||
virtual bool SpecialFileExists(VFSPath path);
|
bool FileExists(VFSPath path);
|
||||||
|
bool SpecialFileExists(VFSPath path);
|
||||||
virtual void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile);
|
virtual void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile);
|
||||||
virtual void CreateHardlink(VFSPath existingFile, VFSPath newName);
|
virtual void CreateHardlink(VFSPath existingFile, VFSPath newName);
|
||||||
virtual bool DirectoryExists(VFSPath path)=0;
|
virtual void DeleteFile(VFSPath path);
|
||||||
virtual void DeleteFile(VFSPath path)=0;
|
|
||||||
virtual void DeleteDirectoryRecurse(VFSPath path);
|
virtual void DeleteDirectoryRecurse(VFSPath path);
|
||||||
virtual VFSPathEnumerator EnumeratePaths(VFSPath path) = 0;
|
virtual VFSPathEnumerator EnumeratePaths(VFSPath path) = 0;
|
||||||
virtual void MoveFile(VFSPath src, VFSPath dest)=0;
|
virtual void MoveFile(VFSPath src, VFSPath dest);
|
||||||
virtual void MoveDirectory(VFSPath src, VFSPath dest);
|
virtual void MoveDirectory(VFSPath src, VFSPath dest);
|
||||||
virtual VFSPath ReadLink(VFSPath path);
|
virtual VFSPath ReadLink(VFSPath path);
|
||||||
virtual std::string VFSPathToSystem(VFSPath path)=0;
|
virtual std::string VFSPathToSystem(VFSPath path)=0;
|
||||||
virtual VFSPath SystemToVFSPath(std::string path)=0;
|
virtual VFSPath SystemToVFSPath(std::string path)=0;
|
||||||
|
|
||||||
|
|
||||||
virtual void GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess);
|
void GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess);
|
||||||
virtual void SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess);
|
virtual void SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess);
|
||||||
|
|
||||||
|
virtual bool Stat(VFSPath path, StatData& data) = 0;
|
||||||
virtual bool StatVFS(VFSPath path, StatVFSData& data);
|
virtual bool StatVFS(VFSPath path, StatVFSData& data);
|
||||||
|
|
||||||
virtual void Chmod(VFSPath path, uint32_t mode);
|
virtual void Chmod(VFSPath path, uint32_t mode);
|
||||||
|
virtual void Chown(VFSPath path, uint32_t userId, uint32_t groupId);
|
||||||
|
|
||||||
virtual void Lock(VFSPath path);
|
virtual void Lock(VFSPath path);
|
||||||
virtual void Unlock(VFSPath path);
|
virtual void Unlock(VFSPath path);
|
||||||
|
virtual FIFOCreationResult CreateFIFO(VFSPath path, uint32_t mode);
|
||||||
|
|
||||||
virtual ~VFS();
|
virtual ~VFS();
|
||||||
|
|
||||||
virtual void Close();
|
virtual void Close();
|
||||||
@@ -236,7 +332,6 @@ namespace Tesses::Framework::Filesystem
|
|||||||
friend class FSWatcher;
|
friend class FSWatcher;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace Literals
|
namespace Literals
|
||||||
{
|
{
|
||||||
@@ -246,4 +341,3 @@ namespace Tesses::Framework::Filesystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,19 +6,40 @@
|
|||||||
#include "../Date/Date.hpp"
|
#include "../Date/Date.hpp"
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include "WebSocket.hpp"
|
#include "WebSocket.hpp"
|
||||||
|
#include <queue>
|
||||||
namespace Tesses::Framework::Http
|
namespace Tesses::Framework::Http
|
||||||
{
|
{
|
||||||
class ServerContextData {
|
class ServerContextData {
|
||||||
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;
|
||||||
|
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;
|
||||||
public:
|
public:
|
||||||
HttpDictionary requestHeaders;
|
HttpDictionary requestHeaders;
|
||||||
HttpDictionary responseHeaders;
|
HttpDictionary responseHeaders;
|
||||||
@@ -34,7 +55,7 @@ namespace Tesses::Framework::Http
|
|||||||
uint16_t serverPort;
|
uint16_t serverPort;
|
||||||
std::string version;
|
std::string version;
|
||||||
bool encrypted;
|
bool encrypted;
|
||||||
ServerContext(std::shared_ptr<Tesses::Framework::Streams::Stream> strm);
|
ServerContext(std::shared_ptr<Tesses::Framework::Streams::Stream> strm, bool debug=false);
|
||||||
~ServerContext();
|
~ServerContext();
|
||||||
std::shared_ptr<Tesses::Framework::Streams::Stream> GetStream();
|
std::shared_ptr<Tesses::Framework::Streams::Stream> GetStream();
|
||||||
std::string GetOriginalPathWithQuery();
|
std::string GetOriginalPathWithQuery();
|
||||||
@@ -51,8 +72,10 @@ 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& WithLastModified(Date::DateTime time);
|
ServerContext& WithLastModified(Date::DateTime time);
|
||||||
ServerContext& WithHeader(std::string key, std::string value);
|
ServerContext& WithHeader(std::string key, std::string value);
|
||||||
ServerContext& WithSingleHeader(std::string key, std::string value);
|
ServerContext& WithSingleHeader(std::string key, std::string value);
|
||||||
@@ -61,6 +84,9 @@ namespace Tesses::Framework::Http
|
|||||||
ServerContext& WriteHeaders();
|
ServerContext& WriteHeaders();
|
||||||
ServerContext& WithLocationHeader(std::string url);
|
ServerContext& WithLocationHeader(std::string url);
|
||||||
ServerContext& WithLocationHeader(std::string url,StatusCode sc);
|
ServerContext& WithLocationHeader(std::string url,StatusCode sc);
|
||||||
|
ServerContext& WithHeaderIntercepter(std::function<bool(ServerContext&)> cb);
|
||||||
|
ServerContext& WithDebug(bool debug=true);
|
||||||
|
bool Debug();
|
||||||
void StartWebSocketSession(std::function<void(std::function<void(WebSocketMessage&)>,std::function<void()>,std::function<void()>)> onOpen, std::function<void(WebSocketMessage&)> onReceive, std::function<void(bool)> onClose);
|
void StartWebSocketSession(std::function<void(std::function<void(WebSocketMessage&)>,std::function<void()>,std::function<void()>)> onOpen, std::function<void(WebSocketMessage&)> onReceive, std::function<void(bool)> onClose);
|
||||||
void StartWebSocketSession(std::shared_ptr<WebSocketConnection> connection);
|
void StartWebSocketSession(std::shared_ptr<WebSocketConnection> connection);
|
||||||
std::string GetServerRoot();
|
std::string GetServerRoot();
|
||||||
@@ -68,7 +94,7 @@ namespace Tesses::Framework::Http
|
|||||||
void SendRedirect(std::string url);
|
void SendRedirect(std::string url);
|
||||||
void SendRedirect(std::string url, StatusCode sc);
|
void SendRedirect(std::string url, StatusCode sc);
|
||||||
|
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
T* GetServerContentData(std::string tag)
|
T* GetServerContentData(std::string tag)
|
||||||
{
|
{
|
||||||
@@ -80,6 +106,9 @@ namespace Tesses::Framework::Http
|
|||||||
data[name] = item;
|
data[name] = item;
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
friend class ServerSentEvents;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class IHttpServer {
|
class IHttpServer {
|
||||||
@@ -95,14 +124,15 @@ namespace Tesses::Framework::Http
|
|||||||
|
|
||||||
bool showIPs;
|
bool showIPs;
|
||||||
bool showARTL;
|
bool showARTL;
|
||||||
|
bool debug;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HttpServer(std::shared_ptr<Tesses::Framework::Streams::TcpServer> tcpServer, std::shared_ptr<IHttpServer> http, bool showIPs=true);
|
HttpServer(std::shared_ptr<Tesses::Framework::Streams::TcpServer> tcpServer, std::shared_ptr<IHttpServer> http, bool showIPs=true, bool debug=false);
|
||||||
HttpServer(uint16_t port, std::shared_ptr<IHttpServer> http, bool showIPs=true);
|
HttpServer(uint16_t port, std::shared_ptr<IHttpServer> http, bool showIPs=true, bool debug=false);
|
||||||
HttpServer(std::string unixPath, std::shared_ptr<IHttpServer> http);
|
HttpServer(std::string unixPath, std::shared_ptr<IHttpServer> http, bool debug=false);
|
||||||
uint16_t GetPort();
|
uint16_t GetPort();
|
||||||
void StartAccepting();
|
void StartAccepting();
|
||||||
static void Process(std::shared_ptr<Tesses::Framework::Streams::Stream> strm, std::shared_ptr<IHttpServer> server, std::string ip, uint16_t port,uint16_t serverPort, bool encrypted);
|
static void Process(std::shared_ptr<Tesses::Framework::Streams::Stream> strm, std::shared_ptr<IHttpServer> server, std::string ip, uint16_t port,uint16_t serverPort, bool encrypted, bool debug=false);
|
||||||
~HttpServer();
|
~HttpServer();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
#include "Filesystem/SubdirFilesystem.hpp"
|
#include "Filesystem/SubdirFilesystem.hpp"
|
||||||
#include "Filesystem/NullFilesystem.hpp"
|
#include "Filesystem/NullFilesystem.hpp"
|
||||||
#include "Filesystem/MountableFilesystem.hpp"
|
#include "Filesystem/MountableFilesystem.hpp"
|
||||||
#include "Filesystem/MemoryFilesystem.hpp"
|
#include "Filesystem/RelativeFilesystem.hpp"
|
||||||
#include "Filesystem/FSHelpers.hpp"
|
#include "Filesystem/FSHelpers.hpp"
|
||||||
#include "Crypto/ClientTLSStream.hpp"
|
#include "Crypto/ClientTLSStream.hpp"
|
||||||
#include "Crypto/Crypto.hpp"
|
#include "Crypto/Crypto.hpp"
|
||||||
@@ -46,4 +46,4 @@
|
|||||||
#include "Serialization/BitConverter.hpp"
|
#include "Serialization/BitConverter.hpp"
|
||||||
#include "Args.hpp"
|
#include "Args.hpp"
|
||||||
#include "BitTorrent/TorrentFile.hpp"
|
#include "BitTorrent/TorrentFile.hpp"
|
||||||
#include "Random.hpp"
|
#include "Random.hpp"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ set(PKGCONFIG_INCLUDEDIR "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}")
|
|||||||
set(PKGCONFIG_LIBDIR "\${prefix}/${CMAKE_INSTALL_LIBDIR}")
|
set(PKGCONFIG_LIBDIR "\${prefix}/${CMAKE_INSTALL_LIBDIR}")
|
||||||
|
|
||||||
set(PKGCONFIG_PROJECT_DESCRIPTION "A cross platform wrapper library")
|
set(PKGCONFIG_PROJECT_DESCRIPTION "A cross platform wrapper library")
|
||||||
set(PKGCONFIG_PROJECT_HOMEPAGE_URL "https://onedev.site.tesses.net/tesses-framework")
|
set(PKGCONFIG_PROJECT_HOMEPAGE_URL "https://git.tesses.org/tessesframework")
|
||||||
|
|
||||||
if(TESSESFRAMEWORK_ENABLE_MBED)
|
if(TESSESFRAMEWORK_ENABLE_MBED)
|
||||||
set(PKGCONFIG_DEPS "Requires: mbedtls")
|
set(PKGCONFIG_DEPS "Requires: mbedtls")
|
||||||
@@ -22,4 +22,4 @@ configure_file(tessesframework.pc.in tessesframework.pc @ONLY)
|
|||||||
install(FILES
|
install(FILES
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/tessesframework.pc
|
${CMAKE_CURRENT_BINARY_DIR}/tessesframework.pc
|
||||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
#include "TessesFramework/Filesystem/LocalFS.hpp"
|
#include "TessesFramework/Filesystem/LocalFS.hpp"
|
||||||
#include "TessesFramework/Streams/FileStream.hpp"
|
#include "TessesFramework/Streams/FileStream.hpp"
|
||||||
|
#include <cerrno>
|
||||||
|
#include <filesystem>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include "TessesFramework/Filesystem/VFSFix.hpp"
|
#include "TessesFramework/Filesystem/VFSFix.hpp"
|
||||||
@@ -9,6 +12,7 @@
|
|||||||
#else
|
#else
|
||||||
#include <utime.h>
|
#include <utime.h>
|
||||||
#include <sys/statvfs.h>
|
#include <sys/statvfs.h>
|
||||||
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "TessesFramework/Threading/Thread.hpp"
|
#include "TessesFramework/Threading/Thread.hpp"
|
||||||
@@ -27,16 +31,44 @@ namespace Tesses::Framework::Filesystem
|
|||||||
pft->dwHighDateTime = time_value.HighPart;
|
pft->dwHighDateTime = time_value.HighPart;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
void LocalFilesystem::GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess)
|
bool LocalFilesystem::Stat(VFSPath path, StatData& sfs)
|
||||||
{
|
{
|
||||||
|
|
||||||
std::string s = VFSPathToSystem(path);
|
std::string s = VFSPathToSystem(path);
|
||||||
|
#if defined(_WIN32)
|
||||||
|
|
||||||
|
struct __stat64 st;
|
||||||
|
if(_stat64(s.c_str(),&st) == 0)
|
||||||
|
#else
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if(stat(s.c_str(),&st) == 0)
|
if(stat(s.c_str(),&st) == 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
{
|
{
|
||||||
lastAccess = Date::DateTime((int64_t)st.st_atime);
|
|
||||||
lastWrite = Date::DateTime((int64_t)st.st_mtime);
|
sfs.Device = (uint64_t)st.st_dev;
|
||||||
|
sfs.Inode = (uint64_t)st.st_ino;
|
||||||
|
sfs.Mode = (uint32_t)st.st_mode;
|
||||||
|
sfs.HardLinks = (uint64_t)st.st_nlink;
|
||||||
|
sfs.UserId = (uint32_t)st.st_uid;
|
||||||
|
sfs.GroupId = (uint32_t)st.st_gid;
|
||||||
|
sfs.DeviceId = (uint64_t)st.st_rdev;
|
||||||
|
sfs.Size = (uint64_t)st.st_size;
|
||||||
|
#if defined(_WIN32)
|
||||||
|
sfs.BlockSize = 512;
|
||||||
|
sfs.BlockCount = sfs.Size / sfs.BlockSize;
|
||||||
|
#else
|
||||||
|
sfs.BlockSize = (uint64_t)st.st_blksize;
|
||||||
|
sfs.BlockCount = (uint64_t)st.st_blocks;
|
||||||
|
#endif
|
||||||
|
sfs.LastAccess = Date::DateTime((int64_t)st.st_atime);
|
||||||
|
sfs.LastModified = Date::DateTime((int64_t)st.st_mtime);
|
||||||
|
sfs.LastStatus = Date::DateTime((int64_t)st.st_ctime);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalFilesystem::SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess)
|
void LocalFilesystem::SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess)
|
||||||
{
|
{
|
||||||
std::string s = VFSPathToSystem(path);
|
std::string s = VFSPathToSystem(path);
|
||||||
@@ -44,7 +76,7 @@ namespace Tesses::Framework::Filesystem
|
|||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
FILETIME lastWriteF;
|
FILETIME lastWriteF;
|
||||||
FILETIME lastAccessF;
|
FILETIME lastAccessF;
|
||||||
|
|
||||||
TimetToFileTime((time_t)lastWrite.ToEpoch(),&lastWriteF);
|
TimetToFileTime((time_t)lastWrite.ToEpoch(),&lastWriteF);
|
||||||
TimetToFileTime((time_t)lastAccess.ToEpoch(),&lastAccessF);
|
TimetToFileTime((time_t)lastAccess.ToEpoch(),&lastAccessF);
|
||||||
HANDLE hFile = CreateFileA(
|
HANDLE hFile = CreateFileA(
|
||||||
@@ -96,34 +128,6 @@ namespace Tesses::Framework::Filesystem
|
|||||||
{
|
{
|
||||||
std::filesystem::create_directories(VFSPathToSystem(path));
|
std::filesystem::create_directories(VFSPathToSystem(path));
|
||||||
}
|
}
|
||||||
bool LocalFilesystem::DirectoryExists(VFSPath path)
|
|
||||||
{
|
|
||||||
return std::filesystem::is_directory(VFSPathToSystem(path));
|
|
||||||
}
|
|
||||||
bool LocalFilesystem::RegularFileExists(VFSPath path)
|
|
||||||
{
|
|
||||||
return std::filesystem::is_regular_file(VFSPathToSystem(path));
|
|
||||||
}
|
|
||||||
bool LocalFilesystem::SymlinkExists(VFSPath path)
|
|
||||||
{
|
|
||||||
return std::filesystem::is_symlink(VFSPathToSystem(path));
|
|
||||||
}
|
|
||||||
bool LocalFilesystem::BlockDeviceExists(VFSPath path)
|
|
||||||
{
|
|
||||||
return std::filesystem::is_block_file(VFSPathToSystem(path));
|
|
||||||
}
|
|
||||||
bool LocalFilesystem::CharacterDeviceExists(VFSPath path)
|
|
||||||
{
|
|
||||||
return std::filesystem::is_character_file(VFSPathToSystem(path));
|
|
||||||
}
|
|
||||||
bool LocalFilesystem::SocketFileExists(VFSPath path)
|
|
||||||
{
|
|
||||||
return std::filesystem::is_socket(VFSPathToSystem(path));
|
|
||||||
}
|
|
||||||
bool LocalFilesystem::FIFOFileExists(VFSPath path)
|
|
||||||
{
|
|
||||||
return std::filesystem::is_fifo(VFSPathToSystem(path));
|
|
||||||
}
|
|
||||||
void LocalFilesystem::CreateSymlink(VFSPath existingFile, VFSPath symlinkFile)
|
void LocalFilesystem::CreateSymlink(VFSPath existingFile, VFSPath symlinkFile)
|
||||||
{
|
{
|
||||||
if(std::filesystem::is_directory(VFSPathToSystem(existingFile)))
|
if(std::filesystem::is_directory(VFSPathToSystem(existingFile)))
|
||||||
@@ -182,10 +186,13 @@ namespace Tesses::Framework::Filesystem
|
|||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
VFSPathEnumerator LocalFilesystem::EnumeratePaths(VFSPath path)
|
VFSPathEnumerator LocalFilesystem::EnumeratePaths(VFSPath path)
|
||||||
{
|
{
|
||||||
auto dir = new std::filesystem::directory_iterator(VFSPathToSystem(path));
|
std::filesystem::path sysPath = VFSPathToSystem(path);
|
||||||
|
if(!std::filesystem::is_directory(sysPath)) return VFSPathEnumerator();
|
||||||
|
|
||||||
|
auto dir = new std::filesystem::directory_iterator(sysPath);
|
||||||
return VFSPathEnumerator([dir,path](VFSPath& path0)->bool {
|
return VFSPathEnumerator([dir,path](VFSPath& path0)->bool {
|
||||||
std::filesystem::directory_iterator& ittr = *dir;
|
std::filesystem::directory_iterator& ittr = *dir;
|
||||||
if(ittr != std::filesystem::directory_iterator())
|
if(ittr != std::filesystem::directory_iterator())
|
||||||
@@ -236,8 +243,47 @@ namespace Tesses::Framework::Filesystem
|
|||||||
chmod(pathStr.c_str(), (mode_t)mode);
|
chmod(pathStr.c_str(), (mode_t)mode);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
void LocalFilesystem::Chown(VFSPath path, uint32_t uid, uint32_t gid)
|
||||||
|
{
|
||||||
|
auto pathStr = this->VFSPathToSystem(path);
|
||||||
|
#if defined(_WIN32)
|
||||||
|
|
||||||
|
#else
|
||||||
|
chown(pathStr.c_str(), (uid_t)uid, (gid_t)gid);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FIFOCreationResult LocalFilesystem::CreateFIFO(VFSPath path, uint32_t mod)
|
||||||
|
{
|
||||||
|
auto pathStr = this->VFSPathToSystem(path);
|
||||||
|
#if defined(_WIN32)
|
||||||
|
return FIFOCreationResult::Unsupported;
|
||||||
|
#else
|
||||||
|
int res = mkfifo(pathStr.c_str(), (mode_t)mod);
|
||||||
|
if(res == 0) return FIFOCreationResult::Success;
|
||||||
|
else if(res == -1)
|
||||||
|
{
|
||||||
|
switch(res)
|
||||||
|
{
|
||||||
|
case EEXIST:
|
||||||
|
return FIFOCreationResult::Exists;
|
||||||
|
case ENOTSUP:
|
||||||
|
return FIFOCreationResult::Unsupported;
|
||||||
|
case EACCES:
|
||||||
|
return FIFOCreationResult::Denied;
|
||||||
|
case ENOSPC:
|
||||||
|
return FIFOCreationResult::OutOfInodes;
|
||||||
|
case EROFS:
|
||||||
|
return FIFOCreationResult::ReadOnlyFS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FIFOCreationResult::UnknownError;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void LocalFilesystem::Lock(VFSPath path)
|
void LocalFilesystem::Lock(VFSPath path)
|
||||||
{
|
{
|
||||||
auto p2 = VFSPathToSystem(path);
|
auto p2 = VFSPathToSystem(path);
|
||||||
@@ -275,7 +321,7 @@ namespace Tesses::Framework::Filesystem
|
|||||||
lflags |= (((uint32_t)flags & (uint32_t)FSWatcherEventType::MoveOld) != 0) ? IN_MOVED_FROM : 0;
|
lflags |= (((uint32_t)flags & (uint32_t)FSWatcherEventType::MoveOld) != 0) ? IN_MOVED_FROM : 0;
|
||||||
lflags |= (((uint32_t)flags & (uint32_t)FSWatcherEventType::MoveNew) != 0) ? IN_MOVED_TO : 0;
|
lflags |= (((uint32_t)flags & (uint32_t)FSWatcherEventType::MoveNew) != 0) ? IN_MOVED_TO : 0;
|
||||||
lflags |= (((uint32_t)flags & (uint32_t)FSWatcherEventType::Opened) != 0) ? IN_OPEN : 0;
|
lflags |= (((uint32_t)flags & (uint32_t)FSWatcherEventType::Opened) != 0) ? IN_OPEN : 0;
|
||||||
|
|
||||||
return lflags;
|
return lflags;
|
||||||
}
|
}
|
||||||
static FSWatcherEventType from_linux_mask(uint32_t lflags)
|
static FSWatcherEventType from_linux_mask(uint32_t lflags)
|
||||||
@@ -293,7 +339,7 @@ namespace Tesses::Framework::Filesystem
|
|||||||
flags |= ((lflags & IN_MOVED_FROM) != 0) ? (uint32_t)FSWatcherEventType::MoveOld : 0;
|
flags |= ((lflags & IN_MOVED_FROM) != 0) ? (uint32_t)FSWatcherEventType::MoveOld : 0;
|
||||||
flags |= ((lflags & IN_MOVED_TO) != 0) ? (uint32_t)FSWatcherEventType::MoveNew : 0;
|
flags |= ((lflags & IN_MOVED_TO) != 0) ? (uint32_t)FSWatcherEventType::MoveNew : 0;
|
||||||
flags |= ((lflags & IN_OPEN) != 0) ? (uint32_t)FSWatcherEventType::Opened : 0;
|
flags |= ((lflags & IN_OPEN) != 0) ? (uint32_t)FSWatcherEventType::Opened : 0;
|
||||||
|
|
||||||
return (FSWatcherEventType)flags;
|
return (FSWatcherEventType)flags;
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
@@ -303,7 +349,7 @@ namespace Tesses::Framework::Filesystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void SetEnabledImpl(bool enabled)
|
void SetEnabledImpl(bool enabled)
|
||||||
{
|
{
|
||||||
if(enabled)
|
if(enabled)
|
||||||
@@ -325,7 +371,7 @@ namespace Tesses::Framework::Filesystem
|
|||||||
__attribute__ ((aligned(__alignof__(struct inotify_event))));
|
__attribute__ ((aligned(__alignof__(struct inotify_event))));
|
||||||
const struct inotify_event *event;
|
const struct inotify_event *event;
|
||||||
ssize_t size;
|
ssize_t size;
|
||||||
|
|
||||||
bool fail=false;
|
bool fail=false;
|
||||||
|
|
||||||
FSWatcherEvent evt;
|
FSWatcherEvent evt;
|
||||||
@@ -397,12 +443,12 @@ namespace Tesses::Framework::Filesystem
|
|||||||
close(fd);
|
close(fd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -420,8 +466,8 @@ namespace Tesses::Framework::Filesystem
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
std::shared_ptr<FSWatcher> LocalFilesystem::CreateWatcher(std::shared_ptr<VFS> vfs, VFSPath path)
|
std::shared_ptr<FSWatcher> LocalFilesystem::CreateWatcher(std::shared_ptr<VFS> vfs, VFSPath path)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,669 +0,0 @@
|
|||||||
#include "TessesFramework/Filesystem/MemoryFilesystem.hpp"
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
namespace Tesses::Framework::Filesystem
|
|
||||||
{
|
|
||||||
|
|
||||||
MemoryFilesystemStream::MemoryFilesystemStream(std::shared_ptr<Tesses::Framework::Threading::Mutex> mtx, std::shared_ptr<MemoryFileData> data,bool canRead, bool canWrite, bool canSeek)
|
|
||||||
{
|
|
||||||
this->mtx = mtx;
|
|
||||||
this->data = data;
|
|
||||||
this->canRead = canRead;
|
|
||||||
this->canWrite = canWrite;
|
|
||||||
this->canSeek = canSeek;
|
|
||||||
this->pos=0;
|
|
||||||
}
|
|
||||||
size_t MemoryFilesystemStream::Read(uint8_t* buff, size_t sz)
|
|
||||||
{
|
|
||||||
if(!this->canRead) return 0;
|
|
||||||
if(this->pos >= this->data->file.size()) return 0;
|
|
||||||
|
|
||||||
size_t toRead = std::min(sz, (size_t)(this->data->file.size()-this->pos));
|
|
||||||
|
|
||||||
memcpy(buff, this->data->file.data() + this->pos, toRead);
|
|
||||||
|
|
||||||
this->pos += toRead;
|
|
||||||
return toRead;
|
|
||||||
}
|
|
||||||
size_t MemoryFilesystemStream::Write(const uint8_t* buff, size_t sz)
|
|
||||||
{
|
|
||||||
if(!this->canWrite) return 0;
|
|
||||||
if(this->canSeek)
|
|
||||||
{
|
|
||||||
|
|
||||||
if(this->pos > this->data->file.size())
|
|
||||||
{
|
|
||||||
this->data->file.resize(this->pos+sz);
|
|
||||||
}
|
|
||||||
this->data->file.insert(this->data->file.begin()+this->pos, buff, buff+sz);
|
|
||||||
this->pos+=sz;
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->data->file.insert(this->data->file.end(), buff, buff+sz);
|
|
||||||
}
|
|
||||||
return sz;
|
|
||||||
}
|
|
||||||
bool MemoryFilesystemStream::CanRead()
|
|
||||||
{
|
|
||||||
return canRead;
|
|
||||||
}
|
|
||||||
bool MemoryFilesystemStream::CanWrite()
|
|
||||||
{
|
|
||||||
return canWrite;
|
|
||||||
}
|
|
||||||
bool MemoryFilesystemStream::CanSeek()
|
|
||||||
{
|
|
||||||
return canSeek;
|
|
||||||
}
|
|
||||||
int64_t MemoryFilesystemStream::GetPosition()
|
|
||||||
{
|
|
||||||
if(!this->canSeek) return (int64_t)this->data->file.size();
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
void MemoryFilesystemStream::Flush()
|
|
||||||
{
|
|
||||||
//its already flushed
|
|
||||||
}
|
|
||||||
void MemoryFilesystemStream::Seek(int64_t pos, Streams::SeekOrigin whence)
|
|
||||||
{
|
|
||||||
if(canSeek) return;
|
|
||||||
switch(whence)
|
|
||||||
{
|
|
||||||
case Streams::SeekOrigin::Begin:
|
|
||||||
this->pos = (size_t)pos;
|
|
||||||
break;
|
|
||||||
case Streams::SeekOrigin::Current:
|
|
||||||
this->pos += (size_t)pos;
|
|
||||||
break;
|
|
||||||
case Streams::SeekOrigin::End:
|
|
||||||
this->pos = (size_t)(this->data->file.size() + pos);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MemoryFilesystemStream::~MemoryFilesystemStream()
|
|
||||||
{
|
|
||||||
mtx->Lock();
|
|
||||||
if(this->canWrite) this->data->canAccess=true;
|
|
||||||
this->data->readers--;
|
|
||||||
mtx->Unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryEntry* MemoryFilesystem::GetEntry(VFSPath path,bool followSymlink)
|
|
||||||
{
|
|
||||||
if(path.relative) return nullptr;
|
|
||||||
if(path.path.empty()) return &this->root;
|
|
||||||
|
|
||||||
auto entry = GetEntry(path.GetParent(),true);
|
|
||||||
if(entry == nullptr) return nullptr;
|
|
||||||
|
|
||||||
auto dir = dynamic_cast<MemoryDirectory*>(entry);
|
|
||||||
if(dir != nullptr)
|
|
||||||
{
|
|
||||||
for(auto item : dir->entries)
|
|
||||||
{
|
|
||||||
if(item->name == path.GetFileName())
|
|
||||||
{
|
|
||||||
auto link = dynamic_cast<MemorySymlink*>(item);
|
|
||||||
if(followSymlink && link != nullptr)
|
|
||||||
{
|
|
||||||
item = GetEntry(link->linkedTo,true);
|
|
||||||
}
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<Streams::Stream> MemoryFilesystem::OpenFile(VFSPath path, std::string mode)
|
|
||||||
{
|
|
||||||
bool canRead=false;
|
|
||||||
bool canWrite=false;
|
|
||||||
bool canSeek=true;
|
|
||||||
bool mustExist=false;
|
|
||||||
bool truncate=false;
|
|
||||||
|
|
||||||
|
|
||||||
if(mode.size() >= 1)
|
|
||||||
{
|
|
||||||
if(mode[0] == 'r')
|
|
||||||
{
|
|
||||||
canRead = true;
|
|
||||||
mustExist=true;
|
|
||||||
}
|
|
||||||
else if(mode[0] == 'w')
|
|
||||||
{
|
|
||||||
canWrite = true;
|
|
||||||
truncate=true;
|
|
||||||
}
|
|
||||||
else if(mode[0] == 'a')
|
|
||||||
{
|
|
||||||
canSeek = false;
|
|
||||||
canWrite = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(((mode.size() >= 2 && mode[1] == '+') || (mode.size() >= 2 && mode[1] == 'b' && mode[2] == '+')))
|
|
||||||
{
|
|
||||||
canRead = true;
|
|
||||||
canWrite = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
mtx->Lock();
|
|
||||||
if(mustExist)
|
|
||||||
{
|
|
||||||
auto file = GetEntry(path,true);
|
|
||||||
|
|
||||||
if(file == nullptr)
|
|
||||||
{
|
|
||||||
mtx->Unlock();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto f = dynamic_cast<MemoryFile*>(file);
|
|
||||||
if(f == nullptr)
|
|
||||||
{
|
|
||||||
mtx->Unlock();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
if(!f->data->canAccess)
|
|
||||||
{
|
|
||||||
mtx->Unlock();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
if(canWrite && f->data->readers > 0)
|
|
||||||
{
|
|
||||||
mtx->Unlock();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
f->data->readers++;
|
|
||||||
if(canWrite) f->data->canAccess=false;
|
|
||||||
|
|
||||||
mtx->Unlock();
|
|
||||||
return std::make_shared<MemoryFilesystemStream>(mtx,f->data,canRead,canWrite,canSeek);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto file = dynamic_cast<MemoryFile*>(GetEntry(path,true));
|
|
||||||
|
|
||||||
|
|
||||||
if(file != nullptr)
|
|
||||||
{
|
|
||||||
if(!file->data->canAccess)
|
|
||||||
{
|
|
||||||
mtx->Unlock();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
if(file->data->readers > 0)
|
|
||||||
{
|
|
||||||
mtx->Unlock();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
file->data->canAccess=false;
|
|
||||||
file->data->readers++;
|
|
||||||
if(truncate) {file->data->file.clear(); file->data->lastWrite=Date::DateTime::NowUTC();}
|
|
||||||
mtx->Unlock();
|
|
||||||
return std::make_shared<MemoryFilesystemStream>(mtx,file->data,canRead,canWrite,canSeek);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
auto dir = GetEntry(path.GetParent(),true);
|
|
||||||
|
|
||||||
if(dir == nullptr)
|
|
||||||
{
|
|
||||||
mtx->Unlock();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto myDir = dynamic_cast<MemoryDirectory*>(dir);
|
|
||||||
|
|
||||||
|
|
||||||
if(myDir == nullptr)
|
|
||||||
{
|
|
||||||
mtx->Unlock();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryFile* thefile=nullptr;
|
|
||||||
|
|
||||||
for(auto f : myDir->entries)
|
|
||||||
{
|
|
||||||
if(f->name == path.GetFileName())
|
|
||||||
{
|
|
||||||
auto symlink = dynamic_cast<MemorySymlink*>(f);
|
|
||||||
while(symlink != nullptr)
|
|
||||||
{
|
|
||||||
auto ent = GetEntry(symlink->name,false);
|
|
||||||
auto sym = dynamic_cast<MemorySymlink*>(f);
|
|
||||||
if(sym != nullptr)
|
|
||||||
symlink = sym;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto myDir0 = dynamic_cast<MemoryDirectory*>(GetEntry(symlink->linkedTo.GetParent(),true));
|
|
||||||
if(myDir0 != nullptr)
|
|
||||||
{
|
|
||||||
for(auto f2 : myDir0->entries)
|
|
||||||
{
|
|
||||||
if(f2->name == symlink->linkedTo.GetFileName())
|
|
||||||
{
|
|
||||||
auto myFile = dynamic_cast<MemoryFile*>(f2);
|
|
||||||
if(myFile != nullptr)
|
|
||||||
{
|
|
||||||
thefile = myFile;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mtx->Unlock();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
myDir = myDir0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mtx->Unlock();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(thefile == nullptr)
|
|
||||||
{
|
|
||||||
|
|
||||||
MemoryFile* f = new MemoryFile();
|
|
||||||
f->name = path.GetFileName();
|
|
||||||
f->data = std::make_shared<MemoryFileData>();
|
|
||||||
f->data->canAccess=false;
|
|
||||||
f->data->readers++;
|
|
||||||
|
|
||||||
myDir->entries.push_back(f);
|
|
||||||
|
|
||||||
mtx->Unlock();
|
|
||||||
return std::make_shared<MemoryFilesystemStream>(mtx,f->data,canRead,canWrite,canSeek);
|
|
||||||
}
|
|
||||||
if(thefile != nullptr)
|
|
||||||
{
|
|
||||||
if(!thefile->data->canAccess)
|
|
||||||
{
|
|
||||||
mtx->Unlock();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
if(thefile->data->readers > 0)
|
|
||||||
{
|
|
||||||
mtx->Unlock();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
thefile->data->canAccess=false;
|
|
||||||
thefile->data->readers++;
|
|
||||||
if(truncate) {thefile->data->file.clear(); thefile->data->lastWrite=Date::DateTime::NowUTC();}
|
|
||||||
mtx->Unlock();
|
|
||||||
return std::make_shared<MemoryFilesystemStream>(mtx,thefile->data,canRead,canWrite,canSeek);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mtx->Unlock();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MemoryFilesystem::CreateDirectory(VFSPath path)
|
|
||||||
{
|
|
||||||
if(path.relative) return;
|
|
||||||
if(path.path.empty()) return;
|
|
||||||
mtx->Lock();
|
|
||||||
MemoryDirectory* dir=&root;
|
|
||||||
for(auto part : path.path)
|
|
||||||
{
|
|
||||||
bool have=false;
|
|
||||||
for(auto dirent : dir->entries)
|
|
||||||
{
|
|
||||||
if(dirent->name == part)
|
|
||||||
{
|
|
||||||
auto symlink = dynamic_cast<MemorySymlink*>(dirent);
|
|
||||||
if(symlink != nullptr)
|
|
||||||
{
|
|
||||||
dirent = GetEntry(symlink->linkedTo,true);
|
|
||||||
}
|
|
||||||
auto dirdirent = dynamic_cast<MemoryDirectory*>(dirent);
|
|
||||||
if(dirdirent != nullptr)
|
|
||||||
{
|
|
||||||
dir = dirdirent;
|
|
||||||
have=true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mtx->Unlock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!have)
|
|
||||||
{
|
|
||||||
MemoryDirectory* dir2 = new MemoryDirectory();
|
|
||||||
dir2->name = part;
|
|
||||||
|
|
||||||
dir2->lastWrite=Date::DateTime::NowUTC();
|
|
||||||
|
|
||||||
dir->entries.push_back(dir2);
|
|
||||||
dir->lastWrite=Date::DateTime::NowUTC();
|
|
||||||
|
|
||||||
dir=dir2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mtx->Unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MemoryFilesystem::DeleteFile(VFSPath path)
|
|
||||||
{
|
|
||||||
if(path.relative || path.path.empty()) return;
|
|
||||||
mtx->Lock();
|
|
||||||
MemoryDirectory* dir=&root;
|
|
||||||
if(path.path.size() > 1)
|
|
||||||
{
|
|
||||||
dir = dynamic_cast<MemoryDirectory*>(GetEntry(path.GetParent(),true));
|
|
||||||
}
|
|
||||||
if(dir == nullptr)
|
|
||||||
{
|
|
||||||
mtx->Unlock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
std::string fname = path.GetFileName();
|
|
||||||
for(auto index = dir->entries.begin(); index < dir->entries.end(); index++)
|
|
||||||
{
|
|
||||||
auto item = *index;
|
|
||||||
if(item->name == fname)
|
|
||||||
{
|
|
||||||
auto p = dynamic_cast<MemoryDirectory*>(item);
|
|
||||||
if(p == nullptr)
|
|
||||||
{
|
|
||||||
delete item;
|
|
||||||
dir->entries.erase(index);
|
|
||||||
|
|
||||||
dir->lastWrite=Date::DateTime::NowUTC();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mtx->Unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MemoryFilesystem::RegularFileExists(VFSPath path)
|
|
||||||
{
|
|
||||||
|
|
||||||
if(path.relative) return false;
|
|
||||||
if(path.path.empty()) return false;
|
|
||||||
mtx->Lock();
|
|
||||||
auto f = GetEntry(path,false);
|
|
||||||
mtx->Unlock();
|
|
||||||
return dynamic_cast<MemoryFile*>(f) != nullptr;
|
|
||||||
}
|
|
||||||
bool MemoryFilesystem::SymlinkExists(VFSPath path)
|
|
||||||
{
|
|
||||||
|
|
||||||
if(path.relative) return false;
|
|
||||||
if(path.path.empty()) return false;
|
|
||||||
mtx->Lock();
|
|
||||||
auto f = GetEntry(path,false);
|
|
||||||
mtx->Unlock();
|
|
||||||
return dynamic_cast<MemorySymlink*>(f) != nullptr;
|
|
||||||
}
|
|
||||||
bool MemoryFilesystem::DirectoryExists(VFSPath path)
|
|
||||||
{
|
|
||||||
if(path.relative) return false;
|
|
||||||
if(path.path.empty()) return true;
|
|
||||||
mtx->Lock();
|
|
||||||
auto f = GetEntry(path,false);
|
|
||||||
mtx->Unlock();
|
|
||||||
return dynamic_cast<MemoryDirectory*>(f) != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MemoryFilesystem::DeleteDirectory(VFSPath path)
|
|
||||||
{
|
|
||||||
if(path.relative || path.path.empty()) return;
|
|
||||||
mtx->Lock();
|
|
||||||
MemoryDirectory* dir=&root;
|
|
||||||
if(path.path.size() > 1)
|
|
||||||
{
|
|
||||||
dir = dynamic_cast<MemoryDirectory*>(GetEntry(path.GetParent(),true));
|
|
||||||
}
|
|
||||||
if(dir == nullptr)
|
|
||||||
{
|
|
||||||
mtx->Unlock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
std::string fname = path.GetFileName();
|
|
||||||
for(auto index = dir->entries.begin(); index < dir->entries.end(); index++)
|
|
||||||
{
|
|
||||||
auto item = *index;
|
|
||||||
if(item->name == fname)
|
|
||||||
{
|
|
||||||
auto p = dynamic_cast<MemoryDirectory*>(item);
|
|
||||||
if(p != nullptr)
|
|
||||||
{
|
|
||||||
delete item;
|
|
||||||
dir->entries.erase(index);
|
|
||||||
dir->lastWrite=Date::DateTime::NowUTC();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mtx->Unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MemoryFilesystem::CreateSymlink(VFSPath existingFile, VFSPath symlinkFile)
|
|
||||||
{
|
|
||||||
if(existingFile.relative || symlinkFile.relative || symlinkFile.path.empty()) return;
|
|
||||||
mtx->Lock();
|
|
||||||
MemoryDirectory* dir=&root;
|
|
||||||
if(symlinkFile.path.size() > 1)
|
|
||||||
{
|
|
||||||
dir = dynamic_cast<MemoryDirectory*>(GetEntry(symlinkFile.GetParent(),true));
|
|
||||||
}
|
|
||||||
if(dir == nullptr)
|
|
||||||
{
|
|
||||||
mtx->Unlock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
std::string fname = symlinkFile.GetFileName();
|
|
||||||
for(auto index = dir->entries.begin(); index < dir->entries.end(); index++)
|
|
||||||
{
|
|
||||||
auto item = *index;
|
|
||||||
if(item->name == fname)
|
|
||||||
{
|
|
||||||
auto p = dynamic_cast<MemorySymlink*>(item);
|
|
||||||
if(p != nullptr)
|
|
||||||
{
|
|
||||||
p->linkedTo = existingFile;
|
|
||||||
p->lastWrite = Date::DateTime::NowUTC();
|
|
||||||
}
|
|
||||||
mtx->Unlock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MemorySymlink* symlink = new MemorySymlink();
|
|
||||||
symlink->name = fname;
|
|
||||||
symlink->linkedTo = existingFile;
|
|
||||||
symlink->lastWrite = Date::DateTime::NowUTC();
|
|
||||||
dir->entries.push_back(symlink);
|
|
||||||
dir->lastWrite = Date::DateTime::NowUTC();
|
|
||||||
|
|
||||||
mtx->Unlock();
|
|
||||||
}
|
|
||||||
VFSPathEnumerator MemoryFilesystem::EnumeratePaths(VFSPath path)
|
|
||||||
{
|
|
||||||
std::pair<size_t,std::vector<std::string>>* paths=new std::pair<size_t,std::vector<std::string>>();
|
|
||||||
paths->first=0;
|
|
||||||
mtx->Lock();
|
|
||||||
auto dir = dynamic_cast<MemoryDirectory*>(GetEntry(path,true));
|
|
||||||
if(dir != nullptr)
|
|
||||||
{
|
|
||||||
for(auto item : dir->entries) paths->second.push_back(item->name);
|
|
||||||
}
|
|
||||||
mtx->Unlock();
|
|
||||||
|
|
||||||
return VFSPathEnumerator([paths,path](VFSPath& _path)->bool{
|
|
||||||
if(paths->first < paths->second.size())
|
|
||||||
{
|
|
||||||
_path = path / paths->second[paths->first++];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},[paths]()->void{
|
|
||||||
delete paths;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void MemoryFilesystem::CreateHardlink(VFSPath existingFile, VFSPath newName)
|
|
||||||
{
|
|
||||||
mtx->Lock();
|
|
||||||
auto existing = dynamic_cast<MemoryFile*>(GetEntry(existingFile,true));
|
|
||||||
if(existing == nullptr)
|
|
||||||
{
|
|
||||||
mtx->Unlock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
MemoryDirectory* dir=&root;
|
|
||||||
if(newName.path.size() > 1)
|
|
||||||
{
|
|
||||||
dir = dynamic_cast<MemoryDirectory*>(GetEntry(newName.GetParent(),true));
|
|
||||||
}
|
|
||||||
if(dir == nullptr)
|
|
||||||
{
|
|
||||||
mtx->Unlock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string fname = newName.GetFileName();
|
|
||||||
for(auto index = dir->entries.begin(); index < dir->entries.end(); index++)
|
|
||||||
{
|
|
||||||
auto item = *index;
|
|
||||||
if(item->name == fname)
|
|
||||||
{
|
|
||||||
|
|
||||||
mtx->Unlock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryFile* memFile = new MemoryFile();
|
|
||||||
memFile->name = fname;
|
|
||||||
memFile->data = existing->data;
|
|
||||||
dir->entries.push_back(memFile);
|
|
||||||
dir->lastWrite=Date::DateTime::NowUTC();
|
|
||||||
|
|
||||||
mtx->Unlock();
|
|
||||||
}
|
|
||||||
void MemoryFilesystem::MoveFile(VFSPath src, VFSPath dest)
|
|
||||||
{
|
|
||||||
DeleteFile(dest);
|
|
||||||
CreateHardlink(src,dest);
|
|
||||||
DeleteFile(src);
|
|
||||||
}
|
|
||||||
void MemoryFilesystem::MoveDirectory(VFSPath src, VFSPath dest)
|
|
||||||
{
|
|
||||||
CreateDirectory(dest);
|
|
||||||
for(auto ent : EnumeratePaths(src))
|
|
||||||
{
|
|
||||||
VFSPath destPath = dest / ent.GetFileName();
|
|
||||||
if(FileExists(ent)) MoveFile(ent,destPath);
|
|
||||||
if(DirectoryExists(ent)) MoveDirectory(ent,destPath);
|
|
||||||
|
|
||||||
}
|
|
||||||
DeleteDirectory(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
VFSPath MemoryFilesystem::ReadLink(VFSPath p)
|
|
||||||
{
|
|
||||||
mtx->Lock();
|
|
||||||
VFSPath p2;
|
|
||||||
auto symlink = dynamic_cast<MemorySymlink*>(GetEntry(p,false));
|
|
||||||
if(symlink != nullptr)
|
|
||||||
{
|
|
||||||
p2 = symlink->linkedTo;
|
|
||||||
}
|
|
||||||
mtx->Unlock();
|
|
||||||
return p2;
|
|
||||||
}
|
|
||||||
std::string MemoryFilesystem::VFSPathToSystem(VFSPath path)
|
|
||||||
{
|
|
||||||
return path.ToString();
|
|
||||||
}
|
|
||||||
VFSPath MemoryFilesystem::SystemToVFSPath(std::string path)
|
|
||||||
{
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
void MemoryFilesystem::GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess)
|
|
||||||
{
|
|
||||||
|
|
||||||
mtx->Lock();
|
|
||||||
auto node = GetEntry(path,false);
|
|
||||||
auto dir = dynamic_cast<MemoryDirectory*>(node);
|
|
||||||
|
|
||||||
auto file = dynamic_cast<MemoryFile*>(node);
|
|
||||||
|
|
||||||
auto sym = dynamic_cast<MemorySymlink*>(node);
|
|
||||||
|
|
||||||
if(dir != nullptr) lastWrite = dir->lastWrite;
|
|
||||||
if(file != nullptr) lastWrite = file->data->lastWrite;
|
|
||||||
if(sym != nullptr) lastWrite = sym->lastWrite;
|
|
||||||
mtx->Unlock();
|
|
||||||
lastAccess = lastWrite;
|
|
||||||
}
|
|
||||||
void MemoryFilesystem::SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess)
|
|
||||||
{
|
|
||||||
mtx->Lock();
|
|
||||||
auto node = GetEntry(path,false);
|
|
||||||
auto dir = dynamic_cast<MemoryDirectory*>(node);
|
|
||||||
|
|
||||||
auto file = dynamic_cast<MemoryFile*>(node);
|
|
||||||
|
|
||||||
auto sym = dynamic_cast<MemorySymlink*>(node);
|
|
||||||
|
|
||||||
if(dir != nullptr) dir->lastWrite = lastWrite;
|
|
||||||
if(file != nullptr) file->data->lastWrite = lastWrite;
|
|
||||||
if(sym != nullptr) sym->lastWrite = lastWrite;
|
|
||||||
mtx->Unlock();
|
|
||||||
}
|
|
||||||
MemoryFilesystem::~MemoryFilesystem()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
MemoryFilesystem::MemoryFilesystem()
|
|
||||||
{
|
|
||||||
mtx = std::make_shared<Threading::Mutex>();
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryEntry::~MemoryEntry()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
MemoryFile::~MemoryFile()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
MemoryDirectory::MemoryDirectory()
|
|
||||||
{
|
|
||||||
this->lastWrite = Date::DateTime::NowUTC();
|
|
||||||
}
|
|
||||||
MemoryDirectory::~MemoryDirectory()
|
|
||||||
{
|
|
||||||
for(auto item : this->entries) delete item;
|
|
||||||
}
|
|
||||||
MemoryFileData::MemoryFileData()
|
|
||||||
{
|
|
||||||
this->lastWrite = Date::DateTime::NowUTC();
|
|
||||||
this->canAccess=true;
|
|
||||||
this->readers=0;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -24,7 +24,7 @@ namespace Tesses::Framework::Filesystem
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void MountableFilesystem::GetFS(VFSPath srcPath, VFSPath& destRoot, VFSPath& destPath, std::shared_ptr<VFS>& vfs)
|
void MountableFilesystem::GetFS(VFSPath srcPath, VFSPath& destRoot, VFSPath& destPath, std::shared_ptr<VFS>& vfs)
|
||||||
{
|
{
|
||||||
if(srcPath.path.empty()) return;
|
if(srcPath.path.empty()) return;
|
||||||
for(auto item : this->directories)
|
for(auto item : this->directories)
|
||||||
@@ -38,8 +38,8 @@ namespace Tesses::Framework::Filesystem
|
|||||||
srcPath1.relative=false;
|
srcPath1.relative=false;
|
||||||
destPath = srcPath1;
|
destPath = srcPath1;
|
||||||
destRoot = VFSPath(VFSPath(),item->name);
|
destRoot = VFSPath(VFSPath(),item->name);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
VFSPath srcPath2(std::vector(srcPath.path.begin()+1,srcPath.path.end()));
|
VFSPath srcPath2(std::vector(srcPath.path.begin()+1,srcPath.path.end()));
|
||||||
srcPath2.relative=false;
|
srcPath2.relative=false;
|
||||||
@@ -49,9 +49,9 @@ namespace Tesses::Framework::Filesystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void MountableDirectory::GetFS(VFSPath srcPath, VFSPath curDir, VFSPath& destRoot, VFSPath& destPath, std::shared_ptr<VFS>& vfs)
|
void MountableDirectory::GetFS(VFSPath srcPath, VFSPath curDir, VFSPath& destRoot, VFSPath& destPath, std::shared_ptr<VFS>& vfs)
|
||||||
{
|
{
|
||||||
if(srcPath.path.empty()) return;
|
if(srcPath.path.empty()) return;
|
||||||
for(auto item : this->dirs)
|
for(auto item : this->dirs)
|
||||||
@@ -61,13 +61,13 @@ namespace Tesses::Framework::Filesystem
|
|||||||
if(item->vfs != nullptr)
|
if(item->vfs != nullptr)
|
||||||
{
|
{
|
||||||
vfs = item->vfs;
|
vfs = item->vfs;
|
||||||
|
|
||||||
VFSPath srcPath1(std::vector(srcPath.path.begin()+1,srcPath.path.end()));
|
VFSPath srcPath1(std::vector(srcPath.path.begin()+1,srcPath.path.end()));
|
||||||
|
|
||||||
srcPath1.relative=false;
|
srcPath1.relative=false;
|
||||||
destPath = srcPath1;
|
destPath = srcPath1;
|
||||||
destRoot = curDir;
|
destRoot = curDir;
|
||||||
|
|
||||||
}
|
}
|
||||||
VFSPath srcPath2(std::vector(srcPath.path.begin()+1,srcPath.path.end()));
|
VFSPath srcPath2(std::vector(srcPath.path.begin()+1,srcPath.path.end()));
|
||||||
srcPath2.relative=false;
|
srcPath2.relative=false;
|
||||||
@@ -83,7 +83,7 @@ namespace Tesses::Framework::Filesystem
|
|||||||
VFSPath destRoot;
|
VFSPath destRoot;
|
||||||
VFSPath destPath = path;
|
VFSPath destPath = path;
|
||||||
std::shared_ptr<VFS> vfs = root;
|
std::shared_ptr<VFS> vfs = root;
|
||||||
|
|
||||||
GetFS(path, destRoot, destPath, vfs);
|
GetFS(path, destRoot, destPath, vfs);
|
||||||
if(vfs != nullptr)
|
if(vfs != nullptr)
|
||||||
return VFSPath(destRoot,vfs->ReadLink(destPath));
|
return VFSPath(destRoot,vfs->ReadLink(destPath));
|
||||||
@@ -96,24 +96,65 @@ namespace Tesses::Framework::Filesystem
|
|||||||
VFSPath destRoot;
|
VFSPath destRoot;
|
||||||
VFSPath destPath = path;
|
VFSPath destPath = path;
|
||||||
std::shared_ptr<VFS> vfs = root;
|
std::shared_ptr<VFS> vfs = root;
|
||||||
|
|
||||||
GetFS(path, destRoot, destPath, vfs);
|
GetFS(path, destRoot, destPath, vfs);
|
||||||
if(vfs != nullptr)
|
if(vfs != nullptr)
|
||||||
return vfs->StatVFS(destPath,data);
|
return vfs->StatVFS(destPath,data);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MountableFilesystem::Stat(VFSPath path, StatData& data)
|
||||||
|
{
|
||||||
|
path = path.CollapseRelativeParents();
|
||||||
|
VFSPath destRoot;
|
||||||
|
VFSPath destPath = path;
|
||||||
|
std::shared_ptr<VFS> vfs = root;
|
||||||
|
|
||||||
|
GetFS(path, destRoot, destPath, vfs);
|
||||||
|
if(vfs != nullptr)
|
||||||
|
return vfs->Stat(destPath,data);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void MountableFilesystem::Chmod(VFSPath path, uint32_t mode)
|
void MountableFilesystem::Chmod(VFSPath path, uint32_t mode)
|
||||||
{
|
{
|
||||||
path = path.CollapseRelativeParents();
|
path = path.CollapseRelativeParents();
|
||||||
VFSPath destRoot;
|
VFSPath destRoot;
|
||||||
VFSPath destPath = path;
|
VFSPath destPath = path;
|
||||||
std::shared_ptr<VFS> vfs = root;
|
std::shared_ptr<VFS> vfs = root;
|
||||||
|
|
||||||
GetFS(path, destRoot, destPath, vfs);
|
GetFS(path, destRoot, destPath, vfs);
|
||||||
if(vfs != nullptr)
|
if(vfs != nullptr)
|
||||||
vfs->Chmod(destPath,mode);
|
vfs->Chmod(destPath,mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MountableFilesystem::Chown(VFSPath path, uint32_t uid, uint32_t gid)
|
||||||
|
{
|
||||||
|
path = path.CollapseRelativeParents();
|
||||||
|
VFSPath destRoot;
|
||||||
|
VFSPath destPath = path;
|
||||||
|
std::shared_ptr<VFS> vfs = root;
|
||||||
|
|
||||||
|
GetFS(path, destRoot, destPath, vfs);
|
||||||
|
if(vfs != nullptr)
|
||||||
|
vfs->Chown(destPath,uid, gid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FIFOCreationResult MountableFilesystem::CreateFIFO(VFSPath path, uint32_t mod)
|
||||||
|
{
|
||||||
|
path = path.CollapseRelativeParents();
|
||||||
|
VFSPath destRoot;
|
||||||
|
VFSPath destPath = path;
|
||||||
|
std::shared_ptr<VFS> vfs = root;
|
||||||
|
|
||||||
|
GetFS(path, destRoot, destPath, vfs);
|
||||||
|
if(vfs != nullptr)
|
||||||
|
return vfs->CreateFIFO(destPath,mod);
|
||||||
|
return FIFOCreationResult::UnknownError;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
std::shared_ptr<Tesses::Framework::Streams::Stream> MountableFilesystem::OpenFile(VFSPath path, std::string mode)
|
std::shared_ptr<Tesses::Framework::Streams::Stream> MountableFilesystem::OpenFile(VFSPath path, std::string mode)
|
||||||
{
|
{
|
||||||
@@ -121,7 +162,7 @@ namespace Tesses::Framework::Filesystem
|
|||||||
VFSPath destRoot;
|
VFSPath destRoot;
|
||||||
VFSPath destPath = path;
|
VFSPath destPath = path;
|
||||||
std::shared_ptr<VFS> vfs = root;
|
std::shared_ptr<VFS> vfs = root;
|
||||||
|
|
||||||
GetFS(path, destRoot, destPath, vfs);
|
GetFS(path, destRoot, destPath, vfs);
|
||||||
|
|
||||||
if(vfs != nullptr)
|
if(vfs != nullptr)
|
||||||
@@ -131,238 +172,92 @@ namespace Tesses::Framework::Filesystem
|
|||||||
void MountableFilesystem::CreateDirectory(VFSPath path)
|
void MountableFilesystem::CreateDirectory(VFSPath path)
|
||||||
{
|
{
|
||||||
path = path.CollapseRelativeParents();
|
path = path.CollapseRelativeParents();
|
||||||
|
|
||||||
VFSPath destRoot;
|
VFSPath destRoot;
|
||||||
VFSPath destPath = path;
|
VFSPath destPath = path;
|
||||||
std::shared_ptr<VFS> vfs = root;
|
std::shared_ptr<VFS> vfs = root;
|
||||||
|
|
||||||
GetFS(path, destRoot, destPath, vfs);
|
GetFS(path, destRoot, destPath, vfs);
|
||||||
|
|
||||||
if(destPath.path.empty()) return;
|
if(destPath.path.empty()) return;
|
||||||
|
|
||||||
if(vfs != nullptr)
|
if(vfs != nullptr)
|
||||||
vfs->CreateDirectory(destPath);
|
vfs->CreateDirectory(destPath);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MountableFilesystem::DeleteDirectory(VFSPath path)
|
void MountableFilesystem::DeleteDirectory(VFSPath path)
|
||||||
{
|
{
|
||||||
path = path.CollapseRelativeParents();
|
path = path.CollapseRelativeParents();
|
||||||
|
|
||||||
VFSPath destRoot;
|
VFSPath destRoot;
|
||||||
VFSPath destPath = path;
|
VFSPath destPath = path;
|
||||||
std::shared_ptr<VFS> vfs = root;
|
std::shared_ptr<VFS> vfs = root;
|
||||||
|
|
||||||
GetFS(path, destRoot, destPath, vfs);
|
GetFS(path, destRoot, destPath, vfs);
|
||||||
|
|
||||||
if(destPath.path.empty()) return;
|
if(destPath.path.empty()) return;
|
||||||
|
|
||||||
if(vfs != nullptr)
|
if(vfs != nullptr)
|
||||||
vfs->DeleteDirectory(destPath);
|
vfs->DeleteDirectory(destPath);
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MountableFilesystem::SpecialFileExists(VFSPath path)
|
|
||||||
{
|
|
||||||
path = path.CollapseRelativeParents();
|
|
||||||
|
|
||||||
VFSPath destRoot;
|
|
||||||
VFSPath destPath = path;
|
|
||||||
std::shared_ptr<VFS> vfs = root;
|
|
||||||
|
|
||||||
GetFS(path, destRoot, destPath, vfs);
|
|
||||||
|
|
||||||
if(vfs != nullptr)
|
|
||||||
return vfs->SpecialFileExists(destPath);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MountableFilesystem::FileExists(VFSPath path)
|
|
||||||
{
|
|
||||||
path = path.CollapseRelativeParents();
|
|
||||||
|
|
||||||
VFSPath destRoot;
|
|
||||||
VFSPath destPath = path;
|
|
||||||
std::shared_ptr<VFS> vfs = root;
|
|
||||||
|
|
||||||
GetFS(path, destRoot, destPath, vfs);
|
|
||||||
|
|
||||||
if(vfs != nullptr)
|
|
||||||
return vfs->FileExists(destPath);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool MountableFilesystem::RegularFileExists(VFSPath path)
|
|
||||||
{
|
|
||||||
path = path.CollapseRelativeParents();
|
|
||||||
|
|
||||||
VFSPath destRoot;
|
|
||||||
VFSPath destPath = path;
|
|
||||||
std::shared_ptr<VFS> vfs = root;
|
|
||||||
|
|
||||||
GetFS(path, destRoot, destPath, vfs);
|
|
||||||
|
|
||||||
if(vfs != nullptr)
|
|
||||||
return vfs->RegularFileExists(destPath);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MountableFilesystem::SymlinkExists(VFSPath path)
|
|
||||||
{
|
|
||||||
path = path.CollapseRelativeParents();
|
|
||||||
|
|
||||||
VFSPath destRoot;
|
|
||||||
VFSPath destPath = path;
|
|
||||||
std::shared_ptr<VFS> vfs = root;
|
|
||||||
|
|
||||||
GetFS(path, destRoot, destPath, vfs);
|
|
||||||
|
|
||||||
if(vfs != nullptr)
|
|
||||||
return vfs->SymlinkExists(destPath);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool MountableFilesystem::CharacterDeviceExists(VFSPath path)
|
|
||||||
{
|
|
||||||
path = path.CollapseRelativeParents();
|
|
||||||
|
|
||||||
VFSPath destRoot;
|
|
||||||
VFSPath destPath = path;
|
|
||||||
std::shared_ptr<VFS> vfs = root;
|
|
||||||
|
|
||||||
GetFS(path, destRoot, destPath, vfs);
|
|
||||||
|
|
||||||
if(vfs != nullptr)
|
|
||||||
return vfs->CharacterDeviceExists(destPath);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool MountableFilesystem::BlockDeviceExists(VFSPath path)
|
|
||||||
{
|
|
||||||
path = path.CollapseRelativeParents();
|
|
||||||
|
|
||||||
VFSPath destRoot;
|
|
||||||
VFSPath destPath = path;
|
|
||||||
std::shared_ptr<VFS> vfs = root;
|
|
||||||
|
|
||||||
GetFS(path, destRoot, destPath, vfs);
|
|
||||||
|
|
||||||
if(vfs != nullptr)
|
|
||||||
return vfs->BlockDeviceExists(destPath);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MountableFilesystem::SocketFileExists(VFSPath path)
|
|
||||||
{
|
|
||||||
path = path.CollapseRelativeParents();
|
|
||||||
|
|
||||||
VFSPath destRoot;
|
|
||||||
VFSPath destPath = path;
|
|
||||||
std::shared_ptr<VFS> vfs = root;
|
|
||||||
|
|
||||||
GetFS(path, destRoot, destPath, vfs);
|
|
||||||
|
|
||||||
if(vfs != nullptr)
|
|
||||||
return vfs->SocketFileExists(destPath);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool MountableFilesystem::FIFOFileExists(VFSPath path)
|
|
||||||
{
|
|
||||||
path = path.CollapseRelativeParents();
|
|
||||||
|
|
||||||
VFSPath destRoot;
|
|
||||||
VFSPath destPath = path;
|
|
||||||
std::shared_ptr<VFS> vfs = root;
|
|
||||||
|
|
||||||
GetFS(path, destRoot, destPath, vfs);
|
|
||||||
|
|
||||||
if(vfs != nullptr)
|
|
||||||
return vfs->FIFOFileExists(destPath);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool MountableFilesystem::DirectoryExists(VFSPath path)
|
|
||||||
{
|
|
||||||
path = path.CollapseRelativeParents();
|
|
||||||
|
|
||||||
VFSPath destRoot;
|
|
||||||
VFSPath destPath = path;
|
|
||||||
std::shared_ptr<VFS> vfs = root;
|
|
||||||
|
|
||||||
GetFS(path, destRoot, destPath, vfs);
|
|
||||||
if(destPath.path.empty()) return true;
|
|
||||||
|
|
||||||
if(vfs != nullptr)
|
|
||||||
return vfs->DirectoryExists(destPath);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
void MountableFilesystem::DeleteFile(VFSPath path)
|
void MountableFilesystem::DeleteFile(VFSPath path)
|
||||||
{
|
{
|
||||||
path = path.CollapseRelativeParents();
|
path = path.CollapseRelativeParents();
|
||||||
|
|
||||||
VFSPath destRoot;
|
VFSPath destRoot;
|
||||||
VFSPath destPath = path;
|
VFSPath destPath = path;
|
||||||
std::shared_ptr<VFS> vfs = root;
|
std::shared_ptr<VFS> vfs = root;
|
||||||
|
|
||||||
GetFS(path, destRoot, destPath, vfs);
|
GetFS(path, destRoot, destPath, vfs);
|
||||||
|
|
||||||
if(vfs != nullptr)
|
if(vfs != nullptr)
|
||||||
vfs->DeleteFile(destPath);
|
vfs->DeleteFile(destPath);
|
||||||
|
|
||||||
}
|
}
|
||||||
void MountableFilesystem::Lock(VFSPath path)
|
void MountableFilesystem::Lock(VFSPath path)
|
||||||
{
|
{
|
||||||
path = path.CollapseRelativeParents();
|
path = path.CollapseRelativeParents();
|
||||||
|
|
||||||
VFSPath destRoot;
|
VFSPath destRoot;
|
||||||
VFSPath destPath = path;
|
VFSPath destPath = path;
|
||||||
std::shared_ptr<VFS> vfs = root;
|
std::shared_ptr<VFS> vfs = root;
|
||||||
|
|
||||||
GetFS(path, destRoot, destPath, vfs);
|
GetFS(path, destRoot, destPath, vfs);
|
||||||
|
|
||||||
if(vfs != nullptr)
|
if(vfs != nullptr)
|
||||||
vfs->Lock(destPath);
|
vfs->Lock(destPath);
|
||||||
|
|
||||||
}
|
}
|
||||||
void MountableFilesystem::Unlock(VFSPath path)
|
void MountableFilesystem::Unlock(VFSPath path)
|
||||||
{
|
{
|
||||||
path = path.CollapseRelativeParents();
|
path = path.CollapseRelativeParents();
|
||||||
|
|
||||||
VFSPath destRoot;
|
VFSPath destRoot;
|
||||||
VFSPath destPath = path;
|
VFSPath destPath = path;
|
||||||
std::shared_ptr<VFS> vfs = root;
|
std::shared_ptr<VFS> vfs = root;
|
||||||
|
|
||||||
GetFS(path, destRoot, destPath, vfs);
|
GetFS(path, destRoot, destPath, vfs);
|
||||||
|
|
||||||
if(vfs != nullptr)
|
if(vfs != nullptr)
|
||||||
vfs->Unlock(destPath);
|
vfs->Unlock(destPath);
|
||||||
|
|
||||||
}
|
|
||||||
void MountableFilesystem::GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess)
|
|
||||||
{
|
|
||||||
|
|
||||||
path = path.CollapseRelativeParents();
|
|
||||||
|
|
||||||
VFSPath destRoot;
|
|
||||||
VFSPath destPath = path;
|
|
||||||
std::shared_ptr<VFS> vfs = root;
|
|
||||||
|
|
||||||
GetFS(path, destRoot, destPath, vfs);
|
|
||||||
|
|
||||||
if(vfs != nullptr)
|
|
||||||
vfs->GetDate(destPath,lastWrite,lastAccess);
|
|
||||||
}
|
}
|
||||||
void MountableFilesystem::SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess)
|
void MountableFilesystem::SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess)
|
||||||
{
|
{
|
||||||
|
|
||||||
path = path.CollapseRelativeParents();
|
path = path.CollapseRelativeParents();
|
||||||
|
|
||||||
VFSPath destRoot;
|
VFSPath destRoot;
|
||||||
VFSPath destPath = path;
|
VFSPath destPath = path;
|
||||||
std::shared_ptr<VFS> vfs = root;
|
std::shared_ptr<VFS> vfs = root;
|
||||||
|
|
||||||
GetFS(path, destRoot, destPath, vfs);
|
GetFS(path, destRoot, destPath, vfs);
|
||||||
|
|
||||||
if(vfs != nullptr)
|
if(vfs != nullptr)
|
||||||
@@ -372,17 +267,17 @@ namespace Tesses::Framework::Filesystem
|
|||||||
{
|
{
|
||||||
existingFile = existingFile.CollapseRelativeParents();
|
existingFile = existingFile.CollapseRelativeParents();
|
||||||
symlinkFile = existingFile.CollapseRelativeParents();
|
symlinkFile = existingFile.CollapseRelativeParents();
|
||||||
|
|
||||||
VFSPath existingDestRoot;
|
VFSPath existingDestRoot;
|
||||||
VFSPath existingDestPath = existingFile;
|
VFSPath existingDestPath = existingFile;
|
||||||
std::shared_ptr<VFS> existingVFS = root;
|
std::shared_ptr<VFS> existingVFS = root;
|
||||||
VFSPath symlinkDestRoot;
|
VFSPath symlinkDestRoot;
|
||||||
VFSPath symlinkDestPath = symlinkFile;
|
VFSPath symlinkDestPath = symlinkFile;
|
||||||
std::shared_ptr<VFS> symlinkVFS = root;
|
std::shared_ptr<VFS> symlinkVFS = root;
|
||||||
|
|
||||||
GetFS(existingFile, existingDestRoot, existingDestPath, existingVFS);
|
GetFS(existingFile, existingDestRoot, existingDestPath, existingVFS);
|
||||||
GetFS(symlinkFile, symlinkDestRoot, symlinkDestPath, symlinkVFS);
|
GetFS(symlinkFile, symlinkDestRoot, symlinkDestPath, symlinkVFS);
|
||||||
|
|
||||||
if(existingVFS != nullptr && existingVFS == symlinkVFS)
|
if(existingVFS != nullptr && existingVFS == symlinkVFS)
|
||||||
existingVFS->CreateSymlink(existingDestPath, symlinkDestPath);
|
existingVFS->CreateSymlink(existingDestPath, symlinkDestPath);
|
||||||
}
|
}
|
||||||
@@ -391,17 +286,17 @@ namespace Tesses::Framework::Filesystem
|
|||||||
{
|
{
|
||||||
src = src.CollapseRelativeParents();
|
src = src.CollapseRelativeParents();
|
||||||
dest = dest.CollapseRelativeParents();
|
dest = dest.CollapseRelativeParents();
|
||||||
|
|
||||||
VFSPath srcDestRoot;
|
VFSPath srcDestRoot;
|
||||||
VFSPath srcDestPath = src;
|
VFSPath srcDestPath = src;
|
||||||
std::shared_ptr<VFS> srcVFS = root;
|
std::shared_ptr<VFS> srcVFS = root;
|
||||||
VFSPath destDestRoot;
|
VFSPath destDestRoot;
|
||||||
VFSPath destDestPath = dest;
|
VFSPath destDestPath = dest;
|
||||||
std::shared_ptr<VFS> destVFS = root;
|
std::shared_ptr<VFS> destVFS = root;
|
||||||
|
|
||||||
GetFS(src, srcDestRoot, srcDestPath, srcVFS);
|
GetFS(src, srcDestRoot, srcDestPath, srcVFS);
|
||||||
GetFS(dest, destDestRoot, destDestPath, destVFS);
|
GetFS(dest, destDestRoot, destDestPath, destVFS);
|
||||||
|
|
||||||
if(srcVFS != nullptr && srcVFS == destVFS)
|
if(srcVFS != nullptr && srcVFS == destVFS)
|
||||||
srcVFS->MoveDirectory(srcDestPath, destDestPath);
|
srcVFS->MoveDirectory(srcDestPath, destDestPath);
|
||||||
}
|
}
|
||||||
@@ -409,17 +304,17 @@ namespace Tesses::Framework::Filesystem
|
|||||||
{
|
{
|
||||||
src = src.CollapseRelativeParents();
|
src = src.CollapseRelativeParents();
|
||||||
dest = dest.CollapseRelativeParents();
|
dest = dest.CollapseRelativeParents();
|
||||||
|
|
||||||
VFSPath srcDestRoot;
|
VFSPath srcDestRoot;
|
||||||
VFSPath srcDestPath = src;
|
VFSPath srcDestPath = src;
|
||||||
std::shared_ptr<VFS> srcVFS = root;
|
std::shared_ptr<VFS> srcVFS = root;
|
||||||
VFSPath destDestRoot;
|
VFSPath destDestRoot;
|
||||||
VFSPath destDestPath = dest;
|
VFSPath destDestPath = dest;
|
||||||
std::shared_ptr<VFS> destVFS = root;
|
std::shared_ptr<VFS> destVFS = root;
|
||||||
|
|
||||||
GetFS(src, srcDestRoot, srcDestPath, srcVFS);
|
GetFS(src, srcDestRoot, srcDestPath, srcVFS);
|
||||||
GetFS(dest, destDestRoot, destDestPath, destVFS);
|
GetFS(dest, destDestRoot, destDestPath, destVFS);
|
||||||
|
|
||||||
if(srcVFS != nullptr && srcVFS == destVFS)
|
if(srcVFS != nullptr && srcVFS == destVFS)
|
||||||
srcVFS->MoveFile(srcDestPath, destDestPath);
|
srcVFS->MoveFile(srcDestPath, destDestPath);
|
||||||
}
|
}
|
||||||
@@ -427,17 +322,17 @@ namespace Tesses::Framework::Filesystem
|
|||||||
{
|
{
|
||||||
existingFile = existingFile.CollapseRelativeParents();
|
existingFile = existingFile.CollapseRelativeParents();
|
||||||
newName = existingFile.CollapseRelativeParents();
|
newName = existingFile.CollapseRelativeParents();
|
||||||
|
|
||||||
VFSPath existingDestRoot;
|
VFSPath existingDestRoot;
|
||||||
VFSPath existingDestPath = existingFile;
|
VFSPath existingDestPath = existingFile;
|
||||||
std::shared_ptr<VFS> existingVFS = root;
|
std::shared_ptr<VFS> existingVFS = root;
|
||||||
VFSPath newNameRoot;
|
VFSPath newNameRoot;
|
||||||
VFSPath newNamePath = newName;
|
VFSPath newNamePath = newName;
|
||||||
std::shared_ptr<VFS> newNameVFS = root;
|
std::shared_ptr<VFS> newNameVFS = root;
|
||||||
|
|
||||||
GetFS(existingFile, existingDestRoot, existingDestPath, existingVFS);
|
GetFS(existingFile, existingDestRoot, existingDestPath, existingVFS);
|
||||||
GetFS(newName, newNameRoot, newNamePath, newNameVFS);
|
GetFS(newName, newNameRoot, newNamePath, newNameVFS);
|
||||||
|
|
||||||
if(existingVFS != nullptr && existingVFS == newNameVFS)
|
if(existingVFS != nullptr && existingVFS == newNameVFS)
|
||||||
existingVFS->CreateHardlink(existingDestPath, newNamePath);
|
existingVFS->CreateHardlink(existingDestPath, newNamePath);
|
||||||
}
|
}
|
||||||
@@ -449,17 +344,17 @@ namespace Tesses::Framework::Filesystem
|
|||||||
};
|
};
|
||||||
VFSPathEnumerator MountableFilesystem::EnumeratePaths(VFSPath path)
|
VFSPathEnumerator MountableFilesystem::EnumeratePaths(VFSPath path)
|
||||||
{
|
{
|
||||||
|
|
||||||
path = path.CollapseRelativeParents();
|
path = path.CollapseRelativeParents();
|
||||||
bool mydirs = path.path.empty();
|
bool mydirs = path.path.empty();
|
||||||
std::vector<MountableDirectory*>* dirs = &this->directories;
|
std::vector<MountableDirectory*>* dirs = &this->directories;
|
||||||
|
|
||||||
if(!path.path.empty())
|
if(!path.path.empty())
|
||||||
for(auto p : path.path)
|
for(auto p : path.path)
|
||||||
{
|
{
|
||||||
mydirs=true;
|
mydirs=true;
|
||||||
bool hasSet=false;
|
bool hasSet=false;
|
||||||
|
|
||||||
for(auto itm : *dirs)
|
for(auto itm : *dirs)
|
||||||
{
|
{
|
||||||
if(itm->name == p)
|
if(itm->name == p)
|
||||||
@@ -476,13 +371,13 @@ namespace Tesses::Framework::Filesystem
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VFSPath destRoot;
|
VFSPath destRoot;
|
||||||
VFSPath destPath = path;
|
VFSPath destPath = path;
|
||||||
std::shared_ptr<VFS> vfs = root;
|
std::shared_ptr<VFS> vfs = root;
|
||||||
|
|
||||||
GetFS(path, destRoot, destPath, vfs);
|
GetFS(path, destRoot, destPath, vfs);
|
||||||
|
|
||||||
|
|
||||||
MountableEnumerationState* state = new MountableEnumerationState();
|
MountableEnumerationState* state = new MountableEnumerationState();
|
||||||
state->dirs = *dirs;
|
state->dirs = *dirs;
|
||||||
@@ -493,11 +388,11 @@ namespace Tesses::Framework::Filesystem
|
|||||||
state->enumerator = nullptr;
|
state->enumerator = nullptr;
|
||||||
|
|
||||||
return VFSPathEnumerator([state,path](VFSPath& path0)->bool{
|
return VFSPathEnumerator([state,path](VFSPath& path0)->bool{
|
||||||
|
|
||||||
while(state->enumerator != nullptr && state->enumerator->MoveNext())
|
while(state->enumerator != nullptr && state->enumerator->MoveNext())
|
||||||
{
|
{
|
||||||
auto fname = state->enumerator->Current.GetFileName();
|
auto fname = state->enumerator->Current.GetFileName();
|
||||||
|
|
||||||
bool mustContinue=false;
|
bool mustContinue=false;
|
||||||
for(auto item : state->dirs)
|
for(auto item : state->dirs)
|
||||||
{
|
{
|
||||||
@@ -527,11 +422,11 @@ namespace Tesses::Framework::Filesystem
|
|||||||
delete state;
|
delete state;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void MountableFilesystem::Mount(VFSPath path, std::shared_ptr<VFS> fs)
|
void MountableFilesystem::Mount(VFSPath path, std::shared_ptr<VFS> fs)
|
||||||
{
|
{
|
||||||
path = path.CollapseRelativeParents();
|
path = path.CollapseRelativeParents();
|
||||||
|
|
||||||
if(path.path.empty())
|
if(path.path.empty())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -557,12 +452,12 @@ namespace Tesses::Framework::Filesystem
|
|||||||
dir->name = *index;
|
dir->name = *index;
|
||||||
dir->owns=false;
|
dir->owns=false;
|
||||||
dir->vfs=NULL;
|
dir->vfs=NULL;
|
||||||
|
|
||||||
fsLs->push_back(dir);
|
fsLs->push_back(dir);
|
||||||
fsLs = &(dir->dirs);
|
fsLs = &(dir->dirs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
needToCreate=true;
|
needToCreate=true;
|
||||||
std::string lastDir = path.GetFileName();
|
std::string lastDir = path.GetFileName();
|
||||||
|
|
||||||
@@ -571,7 +466,7 @@ namespace Tesses::Framework::Filesystem
|
|||||||
if(item->name == lastDir)
|
if(item->name == lastDir)
|
||||||
{
|
{
|
||||||
needToCreate=false;
|
needToCreate=false;
|
||||||
|
|
||||||
item->vfs = fs;
|
item->vfs = fs;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -581,7 +476,7 @@ namespace Tesses::Framework::Filesystem
|
|||||||
{
|
{
|
||||||
MountableDirectory* dir = new MountableDirectory();
|
MountableDirectory* dir = new MountableDirectory();
|
||||||
dir->name = lastDir;
|
dir->name = lastDir;
|
||||||
|
|
||||||
dir->vfs=fs;
|
dir->vfs=fs;
|
||||||
fsLs->push_back(dir);
|
fsLs->push_back(dir);
|
||||||
}
|
}
|
||||||
@@ -590,11 +485,11 @@ namespace Tesses::Framework::Filesystem
|
|||||||
|
|
||||||
static bool myumount(MountableDirectory* dir,VFSPath path)
|
static bool myumount(MountableDirectory* dir,VFSPath path)
|
||||||
{
|
{
|
||||||
if(path.path.empty())
|
if(path.path.empty())
|
||||||
{
|
{
|
||||||
dir->vfs = nullptr;
|
dir->vfs = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dir->dirs.empty())
|
if(dir->dirs.empty())
|
||||||
{
|
{
|
||||||
delete dir;
|
delete dir;
|
||||||
@@ -608,8 +503,8 @@ namespace Tesses::Framework::Filesystem
|
|||||||
{
|
{
|
||||||
VFSPath srcPath2(std::vector(path.path.begin()+1,path.path.end()));
|
VFSPath srcPath2(std::vector(path.path.begin()+1,path.path.end()));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if(myumount(item,srcPath2))
|
if(myumount(item,srcPath2))
|
||||||
{
|
{
|
||||||
dir->dirs.erase(index);
|
dir->dirs.erase(index);
|
||||||
@@ -629,14 +524,14 @@ namespace Tesses::Framework::Filesystem
|
|||||||
void MountableFilesystem::Unmount(VFSPath path)
|
void MountableFilesystem::Unmount(VFSPath path)
|
||||||
{
|
{
|
||||||
path = path.CollapseRelativeParents();
|
path = path.CollapseRelativeParents();
|
||||||
|
|
||||||
for(auto index = this->directories.begin(); index < this->directories.end(); index++)
|
for(auto index = this->directories.begin(); index < this->directories.end(); index++)
|
||||||
{
|
{
|
||||||
auto item = *index;
|
auto item = *index;
|
||||||
if(!path.path.empty() && path.path.front() == item->name)
|
if(!path.path.empty() && path.path.front() == item->name)
|
||||||
{
|
{
|
||||||
VFSPath srcPath2(std::vector(path.path.begin()+1,path.path.end()));
|
VFSPath srcPath2(std::vector(path.path.begin()+1,path.path.end()));
|
||||||
|
|
||||||
if(myumount(item,srcPath2))
|
if(myumount(item,srcPath2))
|
||||||
{
|
{
|
||||||
this->directories.erase(index);
|
this->directories.erase(index);
|
||||||
@@ -654,4 +549,4 @@ namespace Tesses::Framework::Filesystem
|
|||||||
{
|
{
|
||||||
return VFSPath(path);
|
return VFSPath(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,33 +6,11 @@ namespace Tesses::Framework::Filesystem
|
|||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
void NullFilesystem::CreateDirectory(VFSPath path)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
void NullFilesystem::DeleteDirectory(VFSPath path)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
bool NullFilesystem::RegularFileExists(VFSPath path)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool NullFilesystem::DirectoryExists(VFSPath path)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
void NullFilesystem::DeleteFile(VFSPath path)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
VFSPathEnumerator NullFilesystem::EnumeratePaths(VFSPath path)
|
VFSPathEnumerator NullFilesystem::EnumeratePaths(VFSPath path)
|
||||||
{
|
{
|
||||||
return VFSPathEnumerator();
|
return VFSPathEnumerator();
|
||||||
}
|
|
||||||
void NullFilesystem::MoveFile(VFSPath src, VFSPath dest)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
}
|
||||||
std::string NullFilesystem::VFSPathToSystem(VFSPath path)
|
std::string NullFilesystem::VFSPathToSystem(VFSPath path)
|
||||||
{
|
{
|
||||||
@@ -42,4 +20,9 @@ namespace Tesses::Framework::Filesystem
|
|||||||
{
|
{
|
||||||
return VFSPath(path);
|
return VFSPath(path);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
bool NullFilesystem::Stat(VFSPath path, StatData& data)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
206
src/Filesystem/RelativeFilesystem.cpp
Normal file
206
src/Filesystem/RelativeFilesystem.cpp
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
#include "TessesFramework/Filesystem/RelativeFilesystem.hpp"
|
||||||
|
|
||||||
|
namespace Tesses::Framework::Filesystem
|
||||||
|
{
|
||||||
|
VFSPath RelativeFilesystem::ToParent(VFSPath path)
|
||||||
|
{
|
||||||
|
if(path.relative)
|
||||||
|
{
|
||||||
|
return path.MakeAbsolute(GetWorking());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RelativeFilesystem::RelativeFilesystem(std::shared_ptr<VFS> vfs, VFSPath working) : vfs(vfs), working(working)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
VFSPath RelativeFilesystem::GetWorking()
|
||||||
|
{
|
||||||
|
mtx.Lock();
|
||||||
|
auto p = this->working;
|
||||||
|
mtx.Unlock();
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
void RelativeFilesystem::SetWorking(VFSPath path)
|
||||||
|
{
|
||||||
|
mtx.Lock();
|
||||||
|
this->working=path;
|
||||||
|
mtx.Unlock();
|
||||||
|
}
|
||||||
|
std::shared_ptr<VFS> RelativeFilesystem::GetVFS()
|
||||||
|
{
|
||||||
|
return vfs;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Tesses::Framework::Streams::Stream> RelativeFilesystem::OpenFile(VFSPath path, std::string mode)
|
||||||
|
{
|
||||||
|
return this->vfs->OpenFile(ToParent(path),mode);
|
||||||
|
}
|
||||||
|
void RelativeFilesystem::CreateDirectory(VFSPath path)
|
||||||
|
{
|
||||||
|
this->vfs->CreateDirectory(ToParent(path));
|
||||||
|
}
|
||||||
|
void RelativeFilesystem::DeleteDirectory(VFSPath path)
|
||||||
|
{
|
||||||
|
this->vfs->DeleteDirectory(ToParent(path));
|
||||||
|
}
|
||||||
|
void RelativeFilesystem::DeleteFile(VFSPath path)
|
||||||
|
{
|
||||||
|
this->vfs->DeleteFile(ToParent(path));
|
||||||
|
}
|
||||||
|
void RelativeFilesystem::CreateSymlink(VFSPath existingFile, VFSPath symlinkFile)
|
||||||
|
{
|
||||||
|
this->vfs->CreateSymlink(existingFile, ToParent(symlinkFile));
|
||||||
|
}
|
||||||
|
VFSPathEnumerator RelativeFilesystem::EnumeratePaths(VFSPath path)
|
||||||
|
{
|
||||||
|
VFSPathEnumerator* enumerator = this->vfs->EnumeratePaths(ToParent(path)).MakePointer();
|
||||||
|
|
||||||
|
return VFSPathEnumerator([enumerator,path,this](VFSPath& path0)->bool{
|
||||||
|
if(enumerator->MoveNext())
|
||||||
|
{
|
||||||
|
path0 = path / enumerator->Current.GetFileName();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},[enumerator]()->void{
|
||||||
|
delete enumerator;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
void RelativeFilesystem::CreateHardlink(VFSPath existingFile, VFSPath newName)
|
||||||
|
{
|
||||||
|
if(existingFile.relative || newName.relative)
|
||||||
|
{
|
||||||
|
auto working = GetWorking();
|
||||||
|
if(existingFile.relative)
|
||||||
|
existingFile = existingFile.MakeAbsolute(working);
|
||||||
|
|
||||||
|
if(newName.relative)
|
||||||
|
newName = newName.MakeAbsolute(working);
|
||||||
|
}
|
||||||
|
vfs->CreateHardlink(existingFile, newName);
|
||||||
|
}
|
||||||
|
void RelativeFilesystem::MoveFile(VFSPath src, VFSPath dest)
|
||||||
|
{
|
||||||
|
if(src.relative || dest.relative)
|
||||||
|
{
|
||||||
|
auto working = GetWorking();
|
||||||
|
if(src.relative)
|
||||||
|
src = src.MakeAbsolute(working);
|
||||||
|
|
||||||
|
if(dest.relative)
|
||||||
|
dest = dest.MakeAbsolute(working);
|
||||||
|
}
|
||||||
|
vfs->MoveFile(src, dest);
|
||||||
|
}
|
||||||
|
void RelativeFilesystem::MoveDirectory(VFSPath src, VFSPath dest)
|
||||||
|
{
|
||||||
|
if(src.relative || dest.relative)
|
||||||
|
{
|
||||||
|
auto working = GetWorking();
|
||||||
|
if(src.relative)
|
||||||
|
src = src.MakeAbsolute(working);
|
||||||
|
|
||||||
|
if(dest.relative)
|
||||||
|
dest = dest.MakeAbsolute(working);
|
||||||
|
}
|
||||||
|
vfs->MoveDirectory(src, dest);
|
||||||
|
}
|
||||||
|
void RelativeFilesystem::DeleteDirectoryRecurse(VFSPath path)
|
||||||
|
{
|
||||||
|
vfs->DeleteDirectoryRecurse(ToParent(path));
|
||||||
|
}
|
||||||
|
VFSPath RelativeFilesystem::ReadLink(VFSPath path)
|
||||||
|
{
|
||||||
|
return vfs->ReadLink(ToParent(path));
|
||||||
|
}
|
||||||
|
std::string RelativeFilesystem::VFSPathToSystem(VFSPath path)
|
||||||
|
{
|
||||||
|
return vfs->VFSPathToSystem(path);
|
||||||
|
}
|
||||||
|
VFSPath RelativeFilesystem::SystemToVFSPath(std::string path)
|
||||||
|
{
|
||||||
|
return vfs->SystemToVFSPath(path);
|
||||||
|
}
|
||||||
|
void RelativeFilesystem::SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess)
|
||||||
|
{
|
||||||
|
vfs->SetDate(ToParent(path),lastWrite,lastAccess);
|
||||||
|
}
|
||||||
|
bool RelativeFilesystem::StatVFS(VFSPath path, StatVFSData& vfsData)
|
||||||
|
{
|
||||||
|
return vfs->StatVFS(ToParent(path), vfsData);
|
||||||
|
}
|
||||||
|
bool RelativeFilesystem::Stat(VFSPath path, StatData& data)
|
||||||
|
{
|
||||||
|
return vfs->Stat(ToParent(path),data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RelativeFilesystem::Chown(VFSPath path, uint32_t uid, uint32_t gid)
|
||||||
|
{
|
||||||
|
vfs->Chown(ToParent(path),uid,gid);
|
||||||
|
}
|
||||||
|
void RelativeFilesystem::Chmod(VFSPath path, uint32_t mode)
|
||||||
|
{
|
||||||
|
vfs->Chmod(ToParent(path), mode);
|
||||||
|
}
|
||||||
|
FIFOCreationResult RelativeFilesystem::CreateFIFO(VFSPath path, uint32_t mode)
|
||||||
|
{
|
||||||
|
return vfs->CreateFIFO(ToParent(path),mode);
|
||||||
|
}
|
||||||
|
void RelativeFilesystem::Lock(VFSPath path)
|
||||||
|
{
|
||||||
|
vfs->Lock(ToParent(path));
|
||||||
|
}
|
||||||
|
void RelativeFilesystem::Unlock(VFSPath path)
|
||||||
|
{
|
||||||
|
vfs->Unlock(ToParent(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RelativeFilesystem::Watcher::Watcher(std::shared_ptr<RelativeFilesystem> vfs, VFSPath path) : FSWatcher(vfs, path)
|
||||||
|
{
|
||||||
|
this->watcher = FSWatcher::Create(vfs->vfs, vfs->ToParent(path));
|
||||||
|
this->watcher->event = [vfs,this,path](FSWatcherEvent & evt)-> void{
|
||||||
|
if(path.relative)
|
||||||
|
{
|
||||||
|
auto working = vfs->GetWorking();
|
||||||
|
FSWatcherEvent e2=evt;
|
||||||
|
if(evt.IsEvent(FSWatcherEventType::Moved))
|
||||||
|
{
|
||||||
|
e2.dest = e2.dest.MakeRelative(working);
|
||||||
|
}
|
||||||
|
e2.src = e2.src.MakeRelative(working);
|
||||||
|
|
||||||
|
if(this->event) this->event(e2);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(this->event)
|
||||||
|
this->event(evt);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void RelativeFilesystem::Watcher::SetEnabledImpl(bool enabled)
|
||||||
|
{
|
||||||
|
this->enabled = enabled;
|
||||||
|
this->watcher->events = this->events;
|
||||||
|
this->watcher->SetEnabled(enabled);
|
||||||
|
}
|
||||||
|
RelativeFilesystem::Watcher::~Watcher()
|
||||||
|
{
|
||||||
|
this->watcher->SetEnabled(false);
|
||||||
|
}
|
||||||
|
std::shared_ptr<FSWatcher> RelativeFilesystem::CreateWatcher(std::shared_ptr<VFS> vfs, VFSPath path)
|
||||||
|
{
|
||||||
|
auto sdfs = std::dynamic_pointer_cast<RelativeFilesystem>(vfs);
|
||||||
|
if(sdfs)
|
||||||
|
{
|
||||||
|
return std::make_shared<Watcher>(sdfs,path);
|
||||||
|
}
|
||||||
|
return VFS::CreateWatcher(vfs,path);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,7 +13,7 @@ namespace Tesses::Framework::Filesystem
|
|||||||
// /a/b/c
|
// /a/b/c
|
||||||
VFSPath newPath;
|
VFSPath newPath;
|
||||||
newPath.relative=false;
|
newPath.relative=false;
|
||||||
|
|
||||||
if(path.path.size() >= this->path.path.size())
|
if(path.path.size() >= this->path.path.size())
|
||||||
{
|
{
|
||||||
newPath.path.reserve(path.path.size()-this->path.path.size());
|
newPath.path.reserve(path.path.size()-this->path.path.size());
|
||||||
@@ -41,7 +41,7 @@ namespace Tesses::Framework::Filesystem
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
this->path = path;
|
this->path = path;
|
||||||
|
|
||||||
}
|
}
|
||||||
std::shared_ptr<Tesses::Framework::Streams::Stream> SubdirFilesystem::OpenFile(VFSPath path, std::string mode)
|
std::shared_ptr<Tesses::Framework::Streams::Stream> SubdirFilesystem::OpenFile(VFSPath path, std::string mode)
|
||||||
{
|
{
|
||||||
@@ -55,34 +55,6 @@ namespace Tesses::Framework::Filesystem
|
|||||||
{
|
{
|
||||||
this->parent->DeleteDirectory(ToParent(path));
|
this->parent->DeleteDirectory(ToParent(path));
|
||||||
}
|
}
|
||||||
bool SubdirFilesystem::RegularFileExists(VFSPath path)
|
|
||||||
{
|
|
||||||
return this->parent->RegularFileExists(ToParent(path));
|
|
||||||
}
|
|
||||||
bool SubdirFilesystem::SymlinkExists(VFSPath path)
|
|
||||||
{
|
|
||||||
return this->parent->SymlinkExists(ToParent(path));
|
|
||||||
}
|
|
||||||
bool SubdirFilesystem::CharacterDeviceExists(VFSPath path)
|
|
||||||
{
|
|
||||||
return this->parent->CharacterDeviceExists(ToParent(path));
|
|
||||||
}
|
|
||||||
bool SubdirFilesystem::BlockDeviceExists(VFSPath path)
|
|
||||||
{
|
|
||||||
return this->parent->BlockDeviceExists(ToParent(path));
|
|
||||||
}
|
|
||||||
bool SubdirFilesystem::SocketFileExists(VFSPath path)
|
|
||||||
{
|
|
||||||
return this->parent->SocketFileExists(ToParent(path));
|
|
||||||
}
|
|
||||||
bool SubdirFilesystem::FIFOFileExists(VFSPath path)
|
|
||||||
{
|
|
||||||
return this->parent->FIFOFileExists(ToParent(path));
|
|
||||||
}
|
|
||||||
bool SubdirFilesystem::DirectoryExists(VFSPath path)
|
|
||||||
{
|
|
||||||
return this->parent->DirectoryExists(ToParent(path));
|
|
||||||
}
|
|
||||||
void SubdirFilesystem::DeleteFile(VFSPath path)
|
void SubdirFilesystem::DeleteFile(VFSPath path)
|
||||||
{
|
{
|
||||||
this->parent->DeleteFile(ToParent(path));
|
this->parent->DeleteFile(ToParent(path));
|
||||||
@@ -105,7 +77,7 @@ namespace Tesses::Framework::Filesystem
|
|||||||
{
|
{
|
||||||
VFSPathEnumerator* enumerator = this->parent->EnumeratePaths(ToParent(path)).MakePointer();
|
VFSPathEnumerator* enumerator = this->parent->EnumeratePaths(ToParent(path)).MakePointer();
|
||||||
|
|
||||||
return VFSPathEnumerator([enumerator,path,this](VFSPath& path0)->bool{
|
return VFSPathEnumerator([enumerator,this](VFSPath& path0)->bool{
|
||||||
if(enumerator->MoveNext())
|
if(enumerator->MoveNext())
|
||||||
{
|
{
|
||||||
path0 = FromParent(enumerator->Current);
|
path0 = FromParent(enumerator->Current);
|
||||||
@@ -116,15 +88,12 @@ namespace Tesses::Framework::Filesystem
|
|||||||
delete enumerator;
|
delete enumerator;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
void SubdirFilesystem::GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess)
|
|
||||||
{
|
|
||||||
this->parent->GetDate(ToParent(path),lastWrite,lastAccess);
|
|
||||||
}
|
|
||||||
void SubdirFilesystem::SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess)
|
void SubdirFilesystem::SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess)
|
||||||
{
|
{
|
||||||
this->parent->SetDate(ToParent(path),lastWrite,lastAccess);
|
this->parent->SetDate(ToParent(path),lastWrite,lastAccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubdirFilesystem::CreateHardlink(VFSPath existingFile, VFSPath newName)
|
void SubdirFilesystem::CreateHardlink(VFSPath existingFile, VFSPath newName)
|
||||||
{
|
{
|
||||||
this->parent->CreateHardlink(ToParent(existingFile),ToParent(newName));
|
this->parent->CreateHardlink(ToParent(existingFile),ToParent(newName));
|
||||||
@@ -142,34 +111,75 @@ namespace Tesses::Framework::Filesystem
|
|||||||
return this->parent->VFSPathToSystem(ToParent(path));
|
return this->parent->VFSPathToSystem(ToParent(path));
|
||||||
}
|
}
|
||||||
VFSPath SubdirFilesystem::SystemToVFSPath(std::string path)
|
VFSPath SubdirFilesystem::SystemToVFSPath(std::string path)
|
||||||
{
|
{
|
||||||
return FromParent(this->parent->SystemToVFSPath(path));
|
return FromParent(this->parent->SystemToVFSPath(path));
|
||||||
}
|
}
|
||||||
void SubdirFilesystem::DeleteDirectoryRecurse(VFSPath path)
|
void SubdirFilesystem::DeleteDirectoryRecurse(VFSPath path)
|
||||||
{
|
{
|
||||||
this->parent->DeleteDirectoryRecurse(ToParent(path));
|
this->parent->DeleteDirectoryRecurse(ToParent(path));
|
||||||
}
|
}
|
||||||
bool SubdirFilesystem::SpecialFileExists(VFSPath path)
|
|
||||||
{
|
|
||||||
return this->parent->SpecialFileExists(ToParent(path));
|
|
||||||
}
|
|
||||||
bool SubdirFilesystem::FileExists(VFSPath path)
|
|
||||||
{
|
|
||||||
return this->parent->FileExists(ToParent(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
SubdirFilesystem::~SubdirFilesystem()
|
SubdirFilesystem::~SubdirFilesystem()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
bool SubdirFilesystem::StatVFS(VFSPath path, StatVFSData& vfsData)
|
bool SubdirFilesystem::StatVFS(VFSPath path, StatVFSData& vfsData)
|
||||||
{
|
{
|
||||||
return this->parent->StatVFS(ToParent(path), vfsData);
|
return this->parent->StatVFS(ToParent(path), vfsData);
|
||||||
}
|
}
|
||||||
|
bool SubdirFilesystem::Stat(VFSPath path, StatData& data)
|
||||||
|
{
|
||||||
|
return this->parent->Stat(ToParent(path), data);
|
||||||
|
}
|
||||||
void SubdirFilesystem::Chmod(VFSPath path, uint32_t mode)
|
void SubdirFilesystem::Chmod(VFSPath path, uint32_t mode)
|
||||||
{
|
{
|
||||||
return this->parent->Chmod(ToParent(path), mode);
|
return this->parent->Chmod(ToParent(path), mode);
|
||||||
}
|
}
|
||||||
|
void SubdirFilesystem::Chown(VFSPath path, uint32_t uid, uint32_t gid)
|
||||||
|
{
|
||||||
|
return this->parent->Chown(ToParent(path), uid, gid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FIFOCreationResult SubdirFilesystem::CreateFIFO(VFSPath path, uint32_t mod)
|
||||||
|
{
|
||||||
|
return this->parent->CreateFIFO(path, mod);
|
||||||
|
}
|
||||||
|
|
||||||
|
SubdirFilesystem::Watcher::Watcher(std::shared_ptr<SubdirFilesystem> vfs, VFSPath path) : FSWatcher(vfs, path)
|
||||||
|
{
|
||||||
|
this->watcher = FSWatcher::Create(vfs->parent, vfs->ToParent(path));
|
||||||
|
this->watcher->event = [vfs,this](FSWatcherEvent & evt)-> void{
|
||||||
|
FSWatcherEvent e2=evt;
|
||||||
|
if(evt.IsEvent(FSWatcherEventType::Moved))
|
||||||
|
{
|
||||||
|
e2.dest = vfs->FromParent(e2.dest);
|
||||||
|
}
|
||||||
|
e2.src = vfs->FromParent(e2.src);
|
||||||
|
|
||||||
|
if(this->event) this->event(e2);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void SubdirFilesystem::Watcher::SetEnabledImpl(bool enabled)
|
||||||
|
{
|
||||||
|
this->enabled = enabled;
|
||||||
|
this->watcher->events = this->events;
|
||||||
|
this->watcher->SetEnabled(enabled);
|
||||||
|
}
|
||||||
|
SubdirFilesystem::Watcher::~Watcher()
|
||||||
|
{
|
||||||
|
this->watcher->SetEnabled(false);
|
||||||
|
}
|
||||||
|
std::shared_ptr<FSWatcher> SubdirFilesystem::CreateWatcher(std::shared_ptr<VFS> vfs, VFSPath path)
|
||||||
|
{
|
||||||
|
auto sdfs = std::dynamic_pointer_cast<SubdirFilesystem>(vfs);
|
||||||
|
if(sdfs)
|
||||||
|
{
|
||||||
|
return std::make_shared<Watcher>(sdfs,path);
|
||||||
|
}
|
||||||
|
return VFS::CreateWatcher(vfs,path);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ namespace Tesses::Framework::Filesystem {
|
|||||||
Tesses::Framework::Threading::Mutex umtx;
|
Tesses::Framework::Threading::Mutex umtx;
|
||||||
int64_t uidx=0;
|
int64_t uidx=0;
|
||||||
void UniqueString(std::string& text)
|
void UniqueString(std::string& text)
|
||||||
{
|
{
|
||||||
umtx.Lock();
|
umtx.Lock();
|
||||||
text += std::to_string((int64_t)time(NULL));
|
text += std::to_string((int64_t)time(NULL));
|
||||||
text += "_";
|
text += "_";
|
||||||
text += std::to_string(uidx);
|
text += std::to_string(uidx);
|
||||||
|
|
||||||
uidx++;
|
uidx++;
|
||||||
|
|
||||||
umtx.Unlock();
|
umtx.Unlock();
|
||||||
@@ -54,56 +54,7 @@ namespace Tesses::Framework::Filesystem {
|
|||||||
if(this->vfs == nullptr) return;
|
if(this->vfs == nullptr) return;
|
||||||
this->vfs->DeleteDirectory(path);
|
this->vfs->DeleteDirectory(path);
|
||||||
}
|
}
|
||||||
bool TempFS::SpecialFileExists(VFSPath path)
|
|
||||||
{
|
|
||||||
|
|
||||||
if(this->vfs == nullptr) return false;
|
|
||||||
return this->vfs->SpecialFileExists(path);
|
|
||||||
}
|
|
||||||
bool TempFS::FileExists(VFSPath path)
|
|
||||||
{
|
|
||||||
|
|
||||||
if(this->vfs == nullptr) return false;
|
|
||||||
return this->vfs->FileExists(path);
|
|
||||||
}
|
|
||||||
bool TempFS::RegularFileExists(VFSPath path)
|
|
||||||
{
|
|
||||||
|
|
||||||
if(this->vfs == nullptr) return false;
|
|
||||||
return this->vfs->RegularFileExists(path);
|
|
||||||
}
|
|
||||||
bool TempFS::SymlinkExists(VFSPath path)
|
|
||||||
{
|
|
||||||
|
|
||||||
if(this->vfs == nullptr) return false;
|
|
||||||
return this->vfs->SymlinkExists(path);
|
|
||||||
}
|
|
||||||
bool TempFS::CharacterDeviceExists(VFSPath path)
|
|
||||||
{
|
|
||||||
|
|
||||||
if(this->vfs == nullptr) return false;
|
|
||||||
return this->vfs->CharacterDeviceExists(path);
|
|
||||||
}
|
|
||||||
bool TempFS::BlockDeviceExists(VFSPath path)
|
|
||||||
{
|
|
||||||
if(this->vfs == nullptr) return false;
|
|
||||||
return this->vfs->BlockDeviceExists(path);
|
|
||||||
}
|
|
||||||
bool TempFS::SocketFileExists(VFSPath path)
|
|
||||||
{
|
|
||||||
if(this->vfs == nullptr) return false;
|
|
||||||
return this->vfs->SocketFileExists(path);
|
|
||||||
}
|
|
||||||
bool TempFS::FIFOFileExists(VFSPath path)
|
|
||||||
{
|
|
||||||
if(this->vfs == nullptr) return false;
|
|
||||||
return this->vfs->FIFOFileExists(path);
|
|
||||||
}
|
|
||||||
bool TempFS::DirectoryExists(VFSPath path)
|
|
||||||
{
|
|
||||||
if(this->vfs == nullptr) return false;
|
|
||||||
return this->vfs->DirectoryExists(path);
|
|
||||||
}
|
|
||||||
void TempFS::DeleteFile(VFSPath path)
|
void TempFS::DeleteFile(VFSPath path)
|
||||||
{
|
{
|
||||||
if(this->vfs == nullptr) return;
|
if(this->vfs == nullptr) return;
|
||||||
@@ -126,7 +77,7 @@ namespace Tesses::Framework::Filesystem {
|
|||||||
}
|
}
|
||||||
VFSPathEnumerator TempFS::EnumeratePaths(VFSPath path)
|
VFSPathEnumerator TempFS::EnumeratePaths(VFSPath path)
|
||||||
{
|
{
|
||||||
|
|
||||||
if(this->vfs == nullptr) return VFSPathEnumerator();
|
if(this->vfs == nullptr) return VFSPathEnumerator();
|
||||||
|
|
||||||
return this->vfs->EnumeratePaths(path);
|
return this->vfs->EnumeratePaths(path);
|
||||||
@@ -172,13 +123,7 @@ namespace Tesses::Framework::Filesystem {
|
|||||||
if(this->vfs == nullptr) return VFSPath();
|
if(this->vfs == nullptr) return VFSPath();
|
||||||
return this->vfs->SystemToVFSPath(path);
|
return this->vfs->SystemToVFSPath(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TempFS::GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess)
|
|
||||||
{
|
|
||||||
|
|
||||||
if(this->vfs == nullptr) return;
|
|
||||||
this->vfs->GetDate(path,lastWrite,lastAccess);
|
|
||||||
}
|
|
||||||
void TempFS::SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess)
|
void TempFS::SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -187,10 +132,16 @@ namespace Tesses::Framework::Filesystem {
|
|||||||
}
|
}
|
||||||
bool TempFS::StatVFS(VFSPath path, StatVFSData& vfsData)
|
bool TempFS::StatVFS(VFSPath path, StatVFSData& vfsData)
|
||||||
{
|
{
|
||||||
|
|
||||||
if(this->vfs == nullptr) return false;
|
if(this->vfs == nullptr) return false;
|
||||||
return this->vfs->StatVFS(path, vfsData);
|
return this->vfs->StatVFS(path, vfsData);
|
||||||
}
|
}
|
||||||
|
bool TempFS::Stat(VFSPath path, StatData& data)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(this->vfs == nullptr) return false;
|
||||||
|
return this->vfs->Stat(path, data);
|
||||||
|
}
|
||||||
|
|
||||||
void TempFS::Chmod(VFSPath path, uint32_t mode)
|
void TempFS::Chmod(VFSPath path, uint32_t mode)
|
||||||
{
|
{
|
||||||
@@ -198,6 +149,17 @@ namespace Tesses::Framework::Filesystem {
|
|||||||
if(this->vfs == nullptr) return;
|
if(this->vfs == nullptr) return;
|
||||||
this->vfs->Chmod(path,mode);
|
this->vfs->Chmod(path,mode);
|
||||||
}
|
}
|
||||||
|
void TempFS::Chown(VFSPath path, uint32_t uid, uint32_t gid)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(this->vfs == nullptr) return;
|
||||||
|
this->vfs->Chown(path,uid, gid);
|
||||||
|
}
|
||||||
|
FIFOCreationResult TempFS::CreateFIFO(VFSPath path, uint32_t mod)
|
||||||
|
{
|
||||||
|
if(this->vfs == nullptr) return FIFOCreationResult::UnknownError;
|
||||||
|
return this->vfs->CreateFIFO(path, mod);
|
||||||
|
}
|
||||||
void TempFS::Close()
|
void TempFS::Close()
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -208,6 +170,11 @@ namespace Tesses::Framework::Filesystem {
|
|||||||
if(this->deleteOnDestroy && this->parent->DirectoryExists(p))
|
if(this->deleteOnDestroy && this->parent->DirectoryExists(p))
|
||||||
this->parent->DeleteDirectoryRecurse(p);
|
this->parent->DeleteDirectoryRecurse(p);
|
||||||
}
|
}
|
||||||
|
std::shared_ptr<FSWatcher> TempFS::CreateWatcher(std::shared_ptr<VFS> vfs, VFSPath path)
|
||||||
|
{
|
||||||
|
return FSWatcher::Create(vfs,path);
|
||||||
|
}
|
||||||
|
|
||||||
TempFS::~TempFS()
|
TempFS::~TempFS()
|
||||||
{
|
{
|
||||||
VFSPath p;
|
VFSPath p;
|
||||||
@@ -218,5 +185,5 @@ namespace Tesses::Framework::Filesystem {
|
|||||||
this->parent->DeleteDirectoryRecurse(p);
|
this->parent->DeleteDirectoryRecurse(p);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "TessesFramework/Filesystem/VFS.hpp"
|
#include "TessesFramework/Filesystem/VFS.hpp"
|
||||||
#include "TessesFramework/Http/HttpUtils.hpp"
|
#include "TessesFramework/Http/HttpUtils.hpp"
|
||||||
#include "TessesFramework/Filesystem/LocalFS.hpp"
|
#include "TessesFramework/Filesystem/LocalFS.hpp"
|
||||||
|
#include <TessesFramework/Filesystem/FSHelpers.hpp>
|
||||||
namespace Tesses::Framework::Filesystem
|
namespace Tesses::Framework::Filesystem
|
||||||
{
|
{
|
||||||
VFSPathEnumeratorItterator::VFSPathEnumeratorItterator()
|
VFSPathEnumeratorItterator::VFSPathEnumeratorItterator()
|
||||||
@@ -21,12 +22,12 @@ namespace Tesses::Framework::Filesystem
|
|||||||
enumerator->MoveNext();
|
enumerator->MoveNext();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VFSPath& VFSPathEnumeratorItterator::operator*()
|
VFSPath& VFSPathEnumeratorItterator::operator*()
|
||||||
{
|
{
|
||||||
std::filesystem::directory_iterator i;
|
std::filesystem::directory_iterator i;
|
||||||
|
|
||||||
if(enumerator != nullptr)
|
if(enumerator != nullptr)
|
||||||
return enumerator->Current;
|
return enumerator->Current;
|
||||||
return this->e;
|
return this->e;
|
||||||
@@ -46,7 +47,7 @@ namespace Tesses::Framework::Filesystem
|
|||||||
if(right.enumerator == nullptr)
|
if(right.enumerator == nullptr)
|
||||||
{
|
{
|
||||||
auto r = !enumerator->IsDone();
|
auto r = !enumerator->IsDone();
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -88,7 +89,7 @@ namespace Tesses::Framework::Filesystem
|
|||||||
}
|
}
|
||||||
bool VFSPathEnumerator::IsDone()
|
bool VFSPathEnumerator::IsDone()
|
||||||
{
|
{
|
||||||
|
|
||||||
if(this->data)
|
if(this->data)
|
||||||
{
|
{
|
||||||
return data->eof;
|
return data->eof;
|
||||||
@@ -132,7 +133,7 @@ namespace Tesses::Framework::Filesystem
|
|||||||
{
|
{
|
||||||
mid.append(p.path.back());
|
mid.append(p.path.back());
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!p2.path.empty())
|
if(!p2.path.empty())
|
||||||
{
|
{
|
||||||
mid.append(p2.path.front());
|
mid.append(p2.path.front());
|
||||||
@@ -169,7 +170,7 @@ namespace Tesses::Framework::Filesystem
|
|||||||
for(size_t i = 0; i < p.path.size(); i++)
|
for(size_t i = 0; i < p.path.size(); i++)
|
||||||
if(p.path[i] != p2.path[i]) return true;
|
if(p.path[i] != p2.path[i]) return true;
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
bool operator==(std::string p,VFSPath p2)
|
bool operator==(std::string p,VFSPath p2)
|
||||||
{
|
{
|
||||||
@@ -216,13 +217,98 @@ namespace Tesses::Framework::Filesystem
|
|||||||
{
|
{
|
||||||
return MakeRelative(GetAbsoluteCurrentDirectory());
|
return MakeRelative(GetAbsoluteCurrentDirectory());
|
||||||
}
|
}
|
||||||
|
FIFOCreationResult VFS::CreateFIFO(VFSPath path, uint32_t mode)
|
||||||
|
{
|
||||||
|
return FIFOCreationResult::Unsupported;
|
||||||
|
}
|
||||||
|
bool VFS::DirectoryExists(VFSPath path)
|
||||||
|
{
|
||||||
|
StatData data;
|
||||||
|
if(this->Stat(path, data))
|
||||||
|
{
|
||||||
|
return data.IsDirectory();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool VFS::RegularFileExists(VFSPath path)
|
||||||
|
{
|
||||||
|
StatData data;
|
||||||
|
if(this->Stat(path, data))
|
||||||
|
{
|
||||||
|
return data.IsRegularFile();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool VFS::SymlinkExists(VFSPath path)
|
||||||
|
{
|
||||||
|
StatData data;
|
||||||
|
if(this->Stat(path, data))
|
||||||
|
{
|
||||||
|
return data.IsSymlink();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool VFS::CharacterDeviceExists(VFSPath path)
|
||||||
|
{
|
||||||
|
StatData data;
|
||||||
|
if(this->Stat(path, data))
|
||||||
|
{
|
||||||
|
return data.IsCharDevice();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool VFS::BlockDeviceExists(VFSPath path)
|
||||||
|
{
|
||||||
|
StatData data;
|
||||||
|
if(this->Stat(path, data))
|
||||||
|
{
|
||||||
|
return data.IsBlockDevice();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool VFS::SocketFileExists(VFSPath path)
|
||||||
|
{
|
||||||
|
StatData data;
|
||||||
|
if(this->Stat(path, data))
|
||||||
|
{
|
||||||
|
return data.IsSocket();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool VFS::FIFOFileExists(VFSPath path)
|
||||||
|
{
|
||||||
|
StatData data;
|
||||||
|
if(this->Stat(path, data))
|
||||||
|
{
|
||||||
|
return data.IsFIFO();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool VFS::FileExists(VFSPath path)
|
||||||
|
{
|
||||||
|
StatData data;
|
||||||
|
if(this->Stat(path, data))
|
||||||
|
{
|
||||||
|
return !data.IsDirectory();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool VFS::SpecialFileExists(VFSPath path)
|
||||||
|
{
|
||||||
|
StatData data;
|
||||||
|
if(this->Stat(path, data))
|
||||||
|
{
|
||||||
|
return data.IsSpecial();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
VFSPath VFSPath::MakeRelative(VFSPath toMakeRelativeTo) const
|
VFSPath VFSPath::MakeRelative(VFSPath toMakeRelativeTo) const
|
||||||
{
|
{
|
||||||
|
|
||||||
if(this->relative) return *this;
|
if(this->relative) return *this;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
size_t i;
|
size_t i;
|
||||||
size_t len = std::min(toMakeRelativeTo.path.size(),this->path.size());
|
size_t len = std::min(toMakeRelativeTo.path.size(),this->path.size());
|
||||||
for(i = 0; i < len; i++)
|
for(i = 0; i < len; i++)
|
||||||
@@ -239,7 +325,7 @@ namespace Tesses::Framework::Filesystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> parts(this->path.begin()+i, this->path.end());
|
std::vector<std::string> parts(this->path.begin()+i, this->path.end());
|
||||||
|
|
||||||
if(i < toMakeRelativeTo.path.size())
|
if(i < toMakeRelativeTo.path.size())
|
||||||
{
|
{
|
||||||
for(; i < toMakeRelativeTo.path.size();i++)
|
for(; i < toMakeRelativeTo.path.size();i++)
|
||||||
@@ -264,7 +350,7 @@ namespace Tesses::Framework::Filesystem
|
|||||||
parts.erase(parts.end()-1);
|
parts.erase(parts.end()-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(item == ".")
|
else if(item == ".")
|
||||||
{
|
{
|
||||||
//do nothing but don't emit this
|
//do nothing but don't emit this
|
||||||
}
|
}
|
||||||
@@ -284,7 +370,7 @@ namespace Tesses::Framework::Filesystem
|
|||||||
path.relative=true;
|
path.relative=true;
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> VFSPath::SplitPath(std::string path)
|
std::vector<std::string> VFSPath::SplitPath(std::string path)
|
||||||
{
|
{
|
||||||
std::vector<std::string> parts;
|
std::vector<std::string> parts;
|
||||||
@@ -386,7 +472,7 @@ namespace Tesses::Framework::Filesystem
|
|||||||
str = str.substr(0,index);
|
str = str.substr(0,index);
|
||||||
}
|
}
|
||||||
if(ext.empty()) return;
|
if(ext.empty()) return;
|
||||||
if(ext[0] != '.')
|
if(ext[0] != '.')
|
||||||
{
|
{
|
||||||
str += '.';
|
str += '.';
|
||||||
str += ext;
|
str += ext;
|
||||||
@@ -400,7 +486,7 @@ namespace Tesses::Framework::Filesystem
|
|||||||
{
|
{
|
||||||
ChangeExtension({});
|
ChangeExtension({});
|
||||||
}
|
}
|
||||||
|
|
||||||
VFSPath::VFSPath(std::string str)
|
VFSPath::VFSPath(std::string str)
|
||||||
{
|
{
|
||||||
this->path = SplitPath(str);
|
this->path = SplitPath(str);
|
||||||
@@ -418,13 +504,21 @@ namespace Tesses::Framework::Filesystem
|
|||||||
if(!firstPartPath.empty() && firstPartPath.back() == ':') this->relative=false;
|
if(!firstPartPath.empty() && firstPartPath.back() == ':') this->relative=false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
void VFS::CreateDirectory(VFSPath path)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
void VFS::DeleteDirectory(VFSPath path)
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
VFSPath::VFSPath(VFSPath p1, VFSPath p2)
|
VFSPath::VFSPath(VFSPath p1, VFSPath p2)
|
||||||
{
|
{
|
||||||
this->relative = p1.relative;
|
this->relative = p1.relative;
|
||||||
this->path.insert(this->path.end(),p1.path.begin(),p1.path.end());
|
this->path.insert(this->path.end(),p1.path.begin(),p1.path.end());
|
||||||
this->path.insert(this->path.end(),p2.path.begin(),p2.path.end());
|
this->path.insert(this->path.end(),p2.path.begin(),p2.path.end());
|
||||||
}
|
}
|
||||||
VFSPath::VFSPath(VFSPath p1, std::string subpath) : VFSPath(p1, VFSPath(subpath))
|
VFSPath::VFSPath(VFSPath p1, std::string subpath) : VFSPath(p1, VFSPath(subpath))
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -462,20 +556,30 @@ namespace Tesses::Framework::Filesystem
|
|||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
void VFS::DeleteFile(VFSPath path)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
void VFS::MoveFile(VFSPath src, VFSPath dest)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
auto srcStrm = this->OpenFile(src, "rb");
|
||||||
|
if(!srcStrm->CanRead()) return;
|
||||||
|
auto destStrm = this->OpenFile(dest, "wb");
|
||||||
|
if(!destStrm->CanWrite()) return;
|
||||||
|
srcStrm->CopyTo(destStrm);
|
||||||
|
}
|
||||||
|
|
||||||
|
VFS::DeleteFile(src);
|
||||||
|
}
|
||||||
VFS::~VFS()
|
VFS::~VFS()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VFS::FIFOFileExists(VFSPath path) {return false;}
|
|
||||||
bool VFS::SocketFileExists(VFSPath path) {return false;}
|
|
||||||
bool VFS::CharacterDeviceExists(VFSPath path) {return false;}
|
|
||||||
bool VFS::BlockDeviceExists(VFSPath path) {return false;}
|
|
||||||
bool VFS::SymlinkExists(VFSPath path) {return false;}
|
|
||||||
void VFS::MoveDirectory(VFSPath src, VFSPath dest)
|
void VFS::MoveDirectory(VFSPath src, VFSPath dest)
|
||||||
{
|
{
|
||||||
|
|
||||||
for(auto item : EnumeratePaths(src))
|
for(auto item : EnumeratePaths(src))
|
||||||
{
|
{
|
||||||
if(DirectoryExists(item))
|
if(DirectoryExists(item))
|
||||||
@@ -488,7 +592,7 @@ namespace Tesses::Framework::Filesystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DeleteDirectory(src);
|
DeleteDirectory(src);
|
||||||
}
|
}
|
||||||
void VFS::CreateSymlink(VFSPath existingFile, VFSPath symlinkFile)
|
void VFS::CreateSymlink(VFSPath existingFile, VFSPath symlinkFile)
|
||||||
{
|
{
|
||||||
@@ -496,22 +600,14 @@ namespace Tesses::Framework::Filesystem
|
|||||||
}
|
}
|
||||||
void VFS::CreateHardlink(VFSPath existingFile, VFSPath newName)
|
void VFS::CreateHardlink(VFSPath existingFile, VFSPath newName)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VFS::SpecialFileExists(VFSPath path)
|
|
||||||
{
|
|
||||||
return SymlinkExists(path) || BlockDeviceExists(path) || CharacterDeviceExists(path) || SocketFileExists(path) || FIFOFileExists(path);
|
|
||||||
}
|
|
||||||
bool VFS::FileExists(VFSPath path)
|
|
||||||
{
|
|
||||||
return RegularFileExists(path) || SpecialFileExists(path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void VFS::DeleteDirectoryRecurse(VFSPath path)
|
void VFS::DeleteDirectoryRecurse(VFSPath path)
|
||||||
{
|
{
|
||||||
if(!DirectoryExists(path)) return;
|
if(!DirectoryExists(path)) return;
|
||||||
|
|
||||||
for(auto item : EnumeratePaths(path))
|
for(auto item : EnumeratePaths(path))
|
||||||
{
|
{
|
||||||
if(DirectoryExists(item))
|
if(DirectoryExists(item))
|
||||||
@@ -527,7 +623,12 @@ namespace Tesses::Framework::Filesystem
|
|||||||
}
|
}
|
||||||
void VFS::GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess)
|
void VFS::GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess)
|
||||||
{
|
{
|
||||||
|
StatData data;
|
||||||
|
if(Stat(path, data))
|
||||||
|
{
|
||||||
|
lastWrite = data.LastModified;
|
||||||
|
lastAccess = data.LastAccess;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void VFS::SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess)
|
void VFS::SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess)
|
||||||
{
|
{
|
||||||
@@ -550,9 +651,12 @@ namespace Tesses::Framework::Filesystem
|
|||||||
}
|
}
|
||||||
void VFS::Chmod(VFSPath path, uint32_t mode) {
|
void VFS::Chmod(VFSPath path, uint32_t mode) {
|
||||||
|
|
||||||
|
}
|
||||||
|
void VFS::Chown(VFSPath path, uint32_t uid, uint32_t gid) {
|
||||||
|
|
||||||
}
|
}
|
||||||
void VFS::Close() {
|
void VFS::Close() {
|
||||||
|
|
||||||
}
|
}
|
||||||
void VFS::Lock(VFSPath path)
|
void VFS::Lock(VFSPath path)
|
||||||
{
|
{
|
||||||
@@ -560,7 +664,7 @@ namespace Tesses::Framework::Filesystem
|
|||||||
}
|
}
|
||||||
void VFS::Unlock(VFSPath path)
|
void VFS::Unlock(VFSPath path)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -599,7 +703,7 @@ namespace Tesses::Framework::Filesystem
|
|||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<FSWatcher> FSWatcher::Create(std::shared_ptr<VFS> vfs, VFSPath path)
|
std::shared_ptr<FSWatcher> FSWatcher::Create(std::shared_ptr<VFS> vfs, VFSPath path)
|
||||||
{
|
{
|
||||||
return vfs->CreateWatcher(vfs,path);
|
return vfs->CreateWatcher(vfs,path);
|
||||||
@@ -671,4 +775,4 @@ namespace Tesses::Framework::Filesystem
|
|||||||
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace Tesses::Framework::Http
|
|||||||
}
|
}
|
||||||
FileServer::FileServer(std::shared_ptr<Tesses::Framework::Filesystem::VFS> fs, bool allowListing,bool spa) : FileServer(fs,allowListing,spa,{"index.html","default.html","index.htm","default.htm"})
|
FileServer::FileServer(std::shared_ptr<Tesses::Framework::Filesystem::VFS> fs, bool allowListing,bool spa) : FileServer(fs,allowListing,spa,{"index.html","default.html","index.htm","default.htm"})
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
FileServer::FileServer(std::shared_ptr<Tesses::Framework::Filesystem::VFS> fs, bool allowListing, bool spa, std::vector<std::string> defaultNames)
|
FileServer::FileServer(std::shared_ptr<Tesses::Framework::Filesystem::VFS> fs, bool allowListing, bool spa, std::vector<std::string> defaultNames)
|
||||||
{
|
{
|
||||||
@@ -44,7 +44,7 @@ namespace Tesses::Framework::Http
|
|||||||
this->vfs->GetDate(path,lw,la);
|
this->vfs->GetDate(path,lw,la);
|
||||||
ctx.WithLastModified(lw).WithMimeType(HttpUtils::MimeType(path.GetFileName())).SendStream(strm);
|
ctx.WithLastModified(lw).WithMimeType(HttpUtils::MimeType(path.GetFileName())).SendStream(strm);
|
||||||
retVal = true;
|
retVal = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
@@ -52,8 +52,8 @@ namespace Tesses::Framework::Http
|
|||||||
bool FileServer::Handle(ServerContext& ctx)
|
bool FileServer::Handle(ServerContext& ctx)
|
||||||
{
|
{
|
||||||
auto path = ((VFSPath)HttpUtils::UrlPathDecode(ctx.path)).CollapseRelativeParents();
|
auto path = ((VFSPath)HttpUtils::UrlPathDecode(ctx.path)).CollapseRelativeParents();
|
||||||
|
|
||||||
|
|
||||||
if(this->vfs->DirectoryExists(path))
|
if(this->vfs->DirectoryExists(path))
|
||||||
{
|
{
|
||||||
TF_LOG("Directory exists");
|
TF_LOG("Directory exists");
|
||||||
@@ -73,10 +73,10 @@ namespace Tesses::Framework::Http
|
|||||||
std::string p = HttpUtils::HtmlEncode(ctx.originalPath);
|
std::string p = HttpUtils::HtmlEncode(ctx.originalPath);
|
||||||
std::string html = "<!DOCTYPE html><html><head><meta charset=\"UTF-8\"><title>Index of ";
|
std::string html = "<!DOCTYPE html><html><head><meta charset=\"UTF-8\"><title>Index of ";
|
||||||
html.append(p);
|
html.append(p);
|
||||||
html.append("</title></head><body><h1>Index of ");
|
html.append("</title><meta name=\"color-scheme\" content=\"dark light\"></head><body><h1>Index of ");
|
||||||
html.append(p);
|
html.append(p);
|
||||||
html.append("</h1><hr><pre><a href=\"../\">../</a>\r\n");
|
html.append("</h1><hr><pre><a href=\"../\">../</a>\r\n");
|
||||||
|
|
||||||
|
|
||||||
for(auto item : vfs->EnumeratePaths(path))
|
for(auto item : vfs->EnumeratePaths(path))
|
||||||
{
|
{
|
||||||
@@ -103,7 +103,7 @@ namespace Tesses::Framework::Http
|
|||||||
}
|
}
|
||||||
|
|
||||||
html.append("</pre><hr></body></html>");
|
html.append("</pre><hr></body></html>");
|
||||||
|
|
||||||
ctx.WithMimeType("text/html").SendText(html);
|
ctx.WithMimeType("text/html").SendText(html);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -126,6 +126,6 @@ namespace Tesses::Framework::Http
|
|||||||
}
|
}
|
||||||
FileServer::~FileServer()
|
FileServer::~FileServer()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "TessesFramework/Filesystem/VFSFix.hpp"
|
#include "TessesFramework/Filesystem/VFSFix.hpp"
|
||||||
#include "TessesFramework/Filesystem/VFS.hpp"
|
#include "TessesFramework/Filesystem/VFS.hpp"
|
||||||
|
|
||||||
|
#include <TessesFramework/Http/HttpUtils.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
using FileStream = Tesses::Framework::Streams::FileStream;
|
using FileStream = Tesses::Framework::Streams::FileStream;
|
||||||
using Stream = Tesses::Framework::Streams::Stream;
|
using Stream = Tesses::Framework::Streams::Stream;
|
||||||
@@ -26,7 +27,80 @@ using namespace Tesses::Framework::TextStreams;
|
|||||||
|
|
||||||
namespace Tesses::Framework::Http
|
namespace Tesses::Framework::Http
|
||||||
{
|
{
|
||||||
class WSServer
|
|
||||||
|
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
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Threading::Mutex mtx;
|
Threading::Mutex mtx;
|
||||||
@@ -43,9 +117,9 @@ namespace Tesses::Framework::Http
|
|||||||
uint8_t firstByte= finField | 0x8;
|
uint8_t firstByte= finField | 0x8;
|
||||||
strm->WriteByte(firstByte);
|
strm->WriteByte(firstByte);
|
||||||
strm->WriteByte(0);
|
strm->WriteByte(0);
|
||||||
|
|
||||||
this->strm = nullptr;
|
this->strm = nullptr;
|
||||||
mtx.Unlock();
|
mtx.Unlock();
|
||||||
this->conn->OnClose(true);
|
this->conn->OnClose(true);
|
||||||
}
|
}
|
||||||
void write_len_bytes(uint64_t len)
|
void write_len_bytes(uint64_t len)
|
||||||
@@ -84,7 +158,7 @@ namespace Tesses::Framework::Http
|
|||||||
{
|
{
|
||||||
uint8_t buff[8];
|
uint8_t buff[8];
|
||||||
if(strm->ReadBlock(buff,sizeof(buff)) != sizeof(buff)) return 0;
|
if(strm->ReadBlock(buff,sizeof(buff)) != sizeof(buff)) return 0;
|
||||||
|
|
||||||
uint64_t v = 0;
|
uint64_t v = 0;
|
||||||
v |= (uint64_t)buff[0] << 56;
|
v |= (uint64_t)buff[0] << 56;
|
||||||
v |= (uint64_t)buff[1] << 48;
|
v |= (uint64_t)buff[1] << 48;
|
||||||
@@ -100,7 +174,7 @@ namespace Tesses::Framework::Http
|
|||||||
{
|
{
|
||||||
uint8_t buff[2];
|
uint8_t buff[2];
|
||||||
if(strm->ReadBlock(buff,sizeof(buff)) != sizeof(buff)) return 0;
|
if(strm->ReadBlock(buff,sizeof(buff)) != sizeof(buff)) return 0;
|
||||||
|
|
||||||
uint16_t v = 0;
|
uint16_t v = 0;
|
||||||
v |= (uint16_t)buff[0] << 8;
|
v |= (uint16_t)buff[0] << 8;
|
||||||
v |= (uint16_t)buff[1];
|
v |= (uint16_t)buff[1];
|
||||||
@@ -110,7 +184,7 @@ namespace Tesses::Framework::Http
|
|||||||
{
|
{
|
||||||
while(!hasInit);
|
while(!hasInit);
|
||||||
mtx.Lock();
|
mtx.Lock();
|
||||||
|
|
||||||
uint8_t opcode = msg->isBinary ? 0x2 : 0x1;
|
uint8_t opcode = msg->isBinary ? 0x2 : 0x1;
|
||||||
|
|
||||||
size_t lengthLastByte = msg->data.size() % 4096;
|
size_t lengthLastByte = msg->data.size() % 4096;
|
||||||
@@ -123,21 +197,21 @@ namespace Tesses::Framework::Http
|
|||||||
uint8_t finField = fin ? 0b10000000 : 0;
|
uint8_t finField = fin ? 0b10000000 : 0;
|
||||||
uint8_t opcode2 = i == 0 ? opcode : 0;
|
uint8_t opcode2 = i == 0 ? opcode : 0;
|
||||||
uint8_t firstByte = finField | (opcode2 & 0xF);
|
uint8_t firstByte = finField | (opcode2 & 0xF);
|
||||||
|
|
||||||
size_t len = std::min((size_t)4096,msg->data.size()- offset);
|
size_t len = std::min((size_t)4096,msg->data.size()- offset);
|
||||||
|
|
||||||
strm->WriteByte(firstByte);
|
strm->WriteByte(firstByte);
|
||||||
write_len_bytes((uint64_t)len);
|
write_len_bytes((uint64_t)len);
|
||||||
strm->WriteBlock(msg->data.data() + offset,len);
|
strm->WriteBlock(msg->data.data() + offset,len);
|
||||||
offset += len;
|
offset += len;
|
||||||
}
|
}
|
||||||
mtx.Unlock();
|
mtx.Unlock();
|
||||||
}
|
}
|
||||||
void ping_send(std::vector<uint8_t>& pData)
|
void ping_send(std::vector<uint8_t>& pData)
|
||||||
{
|
{
|
||||||
|
|
||||||
mtx.Lock();
|
mtx.Lock();
|
||||||
|
|
||||||
uint8_t finField = 0b10000000 ;
|
uint8_t finField = 0b10000000 ;
|
||||||
uint8_t firstByte= finField | 0x9;
|
uint8_t firstByte= finField | 0x9;
|
||||||
strm->WriteByte(firstByte);
|
strm->WriteByte(firstByte);
|
||||||
@@ -148,7 +222,7 @@ namespace Tesses::Framework::Http
|
|||||||
void pong_send(std::vector<uint8_t>& pData)
|
void pong_send(std::vector<uint8_t>& pData)
|
||||||
{
|
{
|
||||||
mtx.Lock();
|
mtx.Lock();
|
||||||
|
|
||||||
uint8_t finField = 0b10000000 ;
|
uint8_t finField = 0b10000000 ;
|
||||||
uint8_t firstByte= finField | 0xA;
|
uint8_t firstByte= finField | 0xA;
|
||||||
strm->WriteByte(firstByte);
|
strm->WriteByte(firstByte);
|
||||||
@@ -158,7 +232,7 @@ namespace Tesses::Framework::Http
|
|||||||
}
|
}
|
||||||
bool read_packet(uint8_t len,std::vector<uint8_t>& data)
|
bool read_packet(uint8_t len,std::vector<uint8_t>& data)
|
||||||
{
|
{
|
||||||
|
|
||||||
uint8_t realLen=len & 127;
|
uint8_t realLen=len & 127;
|
||||||
bool masked=(len & 0b10000000) > 0;
|
bool masked=(len & 0b10000000) > 0;
|
||||||
uint64_t reallen2 = realLen >= 126 ? realLen > 126 ? get_long() : get_short() : realLen;
|
uint64_t reallen2 = realLen >= 126 ? realLen > 126 ? get_long() : get_short() : realLen;
|
||||||
@@ -180,7 +254,7 @@ namespace Tesses::Framework::Http
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
WSServer(ServerContext* ctx,std::shared_ptr<WebSocketConnection> conn)
|
WSServer(ServerContext* ctx,std::shared_ptr<WebSocketConnection> conn)
|
||||||
{
|
{
|
||||||
this->ctx = ctx;
|
this->ctx = ctx;
|
||||||
@@ -188,7 +262,7 @@ namespace Tesses::Framework::Http
|
|||||||
this->strm = this->ctx->GetStream();
|
this->strm = this->ctx->GetStream();
|
||||||
this->hasInit=false;
|
this->hasInit=false;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
void Start()
|
void Start()
|
||||||
{
|
{
|
||||||
@@ -198,7 +272,7 @@ namespace Tesses::Framework::Http
|
|||||||
{
|
{
|
||||||
key.append("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
|
key.append("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
|
||||||
auto res = Crypto::Sha1::ComputeHash((const uint8_t*)key.c_str(),key.size());
|
auto res = Crypto::Sha1::ComputeHash((const uint8_t*)key.c_str(),key.size());
|
||||||
|
|
||||||
if(res.empty()) return;
|
if(res.empty()) return;
|
||||||
key = Crypto::Base64_Encode(res);
|
key = Crypto::Base64_Encode(res);
|
||||||
|
|
||||||
@@ -206,7 +280,7 @@ namespace Tesses::Framework::Http
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!ctx->requestHeaders.AnyEquals("Upgrade","websocket"))
|
if(!ctx->requestHeaders.AnyEquals("Upgrade","websocket"))
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -221,7 +295,7 @@ namespace Tesses::Framework::Http
|
|||||||
ctx->responseHeaders.SetValue("Connection","Upgrade");
|
ctx->responseHeaders.SetValue("Connection","Upgrade");
|
||||||
ctx->responseHeaders.SetValue("Upgrade","websocket");
|
ctx->responseHeaders.SetValue("Upgrade","websocket");
|
||||||
ctx->responseHeaders.SetValue("Sec-WebSocket-Accept",key);
|
ctx->responseHeaders.SetValue("Sec-WebSocket-Accept",key);
|
||||||
|
|
||||||
ctx->WriteHeaders();
|
ctx->WriteHeaders();
|
||||||
bool hasMessage =false;
|
bool hasMessage =false;
|
||||||
|
|
||||||
@@ -232,11 +306,11 @@ namespace Tesses::Framework::Http
|
|||||||
|
|
||||||
while( !strm->EndOfStream())
|
while( !strm->EndOfStream())
|
||||||
{
|
{
|
||||||
|
|
||||||
uint8_t frame_start[2];
|
uint8_t frame_start[2];
|
||||||
if( strm->ReadBlock(frame_start,2) != 2) return;
|
if( strm->ReadBlock(frame_start,2) != 2) return;
|
||||||
|
|
||||||
|
|
||||||
uint8_t opcode = frame_start[0] & 0xF;
|
uint8_t opcode = frame_start[0] & 0xF;
|
||||||
bool fin = (frame_start[0] & 0b10000000) > 0;
|
bool fin = (frame_start[0] & 0b10000000) > 0;
|
||||||
switch(opcode)
|
switch(opcode)
|
||||||
@@ -250,7 +324,7 @@ namespace Tesses::Framework::Http
|
|||||||
hasMessage=true;
|
hasMessage=true;
|
||||||
message.data = {};
|
message.data = {};
|
||||||
message.isBinary = opcode == 0x2;
|
message.isBinary = opcode == 0x2;
|
||||||
|
|
||||||
read_packet(frame_start[1], message.data);
|
read_packet(frame_start[1], message.data);
|
||||||
break;
|
break;
|
||||||
case 0x8:
|
case 0x8:
|
||||||
@@ -280,7 +354,8 @@ 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)
|
||||||
{
|
{
|
||||||
@@ -343,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;
|
||||||
@@ -362,7 +438,35 @@ namespace Tesses::Framework::Http
|
|||||||
strm2->CopyTo(strm);
|
strm2->CopyTo(strm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 {};
|
||||||
@@ -389,8 +493,8 @@ namespace Tesses::Framework::Http
|
|||||||
static bool parseUntillBoundaryEnd(std::shared_ptr<Tesses::Framework::Streams::Stream> src, std::shared_ptr<Tesses::Framework::Streams::Stream> dest, std::string boundary)
|
static bool parseUntillBoundaryEnd(std::shared_ptr<Tesses::Framework::Streams::Stream> src, std::shared_ptr<Tesses::Framework::Streams::Stream> dest, std::string boundary)
|
||||||
{
|
{
|
||||||
bool hasMore=true;
|
bool hasMore=true;
|
||||||
uint8_t* checkBuffer = new uint8_t[boundary.size()];
|
std::vector<uint8_t> checkBuffer(boundary.size());
|
||||||
|
|
||||||
int b;
|
int b;
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
size_t i2 = 0;
|
size_t i2 = 0;
|
||||||
@@ -429,21 +533,21 @@ namespace Tesses::Framework::Http
|
|||||||
{
|
{
|
||||||
dest->Write(buffer, sizeof(buffer));
|
dest->Write(buffer, sizeof(buffer));
|
||||||
offsetInMem=0;
|
offsetInMem=0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[offsetInMem++] = checkBuffer[idx];
|
buffer[offsetInMem++] = checkBuffer[idx];
|
||||||
|
|
||||||
idx++;
|
idx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
||||||
if(offsetInMem >= sizeof(buffer))
|
if(offsetInMem >= sizeof(buffer))
|
||||||
{
|
{
|
||||||
dest->Write(buffer, sizeof(buffer));
|
dest->Write(buffer, sizeof(buffer));
|
||||||
offsetInMem=0;
|
offsetInMem=0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[offsetInMem++] = (uint8_t)b;
|
buffer[offsetInMem++] = (uint8_t)b;
|
||||||
@@ -454,8 +558,6 @@ namespace Tesses::Framework::Http
|
|||||||
{
|
{
|
||||||
dest->Write(buffer,offsetInMem);
|
dest->Write(buffer,offsetInMem);
|
||||||
}
|
}
|
||||||
delete[] checkBuffer;
|
|
||||||
|
|
||||||
return hasMore;
|
return hasMore;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -466,7 +568,7 @@ namespace Tesses::Framework::Http
|
|||||||
std::string line;
|
std::string line;
|
||||||
while(reader.ReadLineHttp(line))
|
while(reader.ReadLineHttp(line))
|
||||||
{
|
{
|
||||||
auto v = HttpUtils::SplitString(line,": ", 2);
|
auto v = HttpUtils::SplitString(line,": ", 2);
|
||||||
if(v.size() == 2)
|
if(v.size() == 2)
|
||||||
req.AddValue(v[0],v[1]);
|
req.AddValue(v[0],v[1]);
|
||||||
line.clear();
|
line.clear();
|
||||||
@@ -475,7 +577,7 @@ namespace Tesses::Framework::Http
|
|||||||
std::string cd0;
|
std::string cd0;
|
||||||
ContentDisposition cd1;
|
ContentDisposition cd1;
|
||||||
std::string ct;
|
std::string ct;
|
||||||
|
|
||||||
if(!req.TryGetFirst("Content-Type",ct))
|
if(!req.TryGetFirst("Content-Type",ct))
|
||||||
ct = "application/octet-stream";
|
ct = "application/octet-stream";
|
||||||
if(req.TryGetFirst("Content-Disposition", cd0) && ContentDisposition::TryParse(cd0,cd1))
|
if(req.TryGetFirst("Content-Disposition", cd0) && ContentDisposition::TryParse(cd0,cd1))
|
||||||
@@ -494,10 +596,10 @@ namespace Tesses::Framework::Http
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto strm = cb(ct, cd1.filename, cd1.fieldName);
|
auto strm = cb(ct, cd1.filename, cd1.fieldName);
|
||||||
if(strm == nullptr) strm = std::make_shared<Stream>();
|
if(strm == nullptr) strm = std::make_shared<Stream>();
|
||||||
bool retVal = parseUntillBoundaryEnd(ctx->GetStream(),strm,boundary);
|
bool retVal = parseUntillBoundaryEnd(ctx->GetStream(),strm,boundary);
|
||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -521,9 +623,9 @@ namespace Tesses::Framework::Http
|
|||||||
parseUntillBoundaryEnd(this->strm,nullStrm, ct);
|
parseUntillBoundaryEnd(this->strm,nullStrm, ct);
|
||||||
|
|
||||||
while(parseSection(this, ct, cb));
|
while(parseSection(this, ct, cb));
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpServer::HttpServer(std::shared_ptr<Tesses::Framework::Streams::TcpServer> tcpServer, std::shared_ptr<IHttpServer> http, bool showIPs)
|
HttpServer::HttpServer(std::shared_ptr<Tesses::Framework::Streams::TcpServer> tcpServer, std::shared_ptr<IHttpServer> http, bool showIPs, bool debug)
|
||||||
{
|
{
|
||||||
this->server = tcpServer;
|
this->server = tcpServer;
|
||||||
this->http = http;
|
this->http = http;
|
||||||
@@ -531,19 +633,20 @@ namespace Tesses::Framework::Http
|
|||||||
this->showIPs = showIPs;
|
this->showIPs = showIPs;
|
||||||
this->thrd=nullptr;
|
this->thrd=nullptr;
|
||||||
this->showARTL = showIPs;
|
this->showARTL = showIPs;
|
||||||
|
this->debug = debug;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
HttpServer::HttpServer(uint16_t port, std::shared_ptr<IHttpServer> http, bool showIPs) : HttpServer(std::make_shared<TcpServer>(port,10),http,showIPs)
|
HttpServer::HttpServer(uint16_t port, std::shared_ptr<IHttpServer> http, bool showIPs, bool debug) : HttpServer(std::make_shared<TcpServer>(port,10),http,showIPs, debug)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpServer::HttpServer(std::string unixPath, std::shared_ptr<IHttpServer> http) : HttpServer(std::make_shared<TcpServer>(unixPath,10),http,false)
|
HttpServer::HttpServer(std::string unixPath, std::shared_ptr<IHttpServer> http, bool debug) : HttpServer(std::make_shared<TcpServer>(unixPath,10),http,false, debug)
|
||||||
{
|
{
|
||||||
this->showARTL=true;
|
this->showARTL=true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint16_t HttpServer::GetPort()
|
uint16_t HttpServer::GetPort()
|
||||||
{
|
{
|
||||||
@@ -557,7 +660,7 @@ namespace Tesses::Framework::Http
|
|||||||
int64_t length = -1;
|
int64_t length = -1;
|
||||||
if(!this->responseHeaders.TryGetFirstInt("Content-Length",length))
|
if(!this->responseHeaders.TryGetFirstInt("Content-Length",length))
|
||||||
length = -1;
|
length = -1;
|
||||||
|
|
||||||
if(this->version == "HTTP/1.1" && length == -1)
|
if(this->version == "HTTP/1.1" && length == -1)
|
||||||
this->responseHeaders.SetValue("Transfer-Encoding","chunked");
|
this->responseHeaders.SetValue("Transfer-Encoding","chunked");
|
||||||
|
|
||||||
@@ -584,27 +687,29 @@ namespace Tesses::Framework::Http
|
|||||||
auto serverPort = this->server->GetPort();
|
auto serverPort = this->server->GetPort();
|
||||||
auto http = this->http;
|
auto http = this->http;
|
||||||
TF_LOG("Before Creating Thread");
|
TF_LOG("Before Creating Thread");
|
||||||
thrd = new Threading::Thread([svr,http,serverPort]()->void {
|
bool debug = this->debug;
|
||||||
|
thrd = new Threading::Thread([svr,http,serverPort,debug]()->void {
|
||||||
while(TF_IsRunning())
|
while(TF_IsRunning())
|
||||||
{
|
{
|
||||||
TF_LOG("after TF_IsRunning");
|
TF_LOG("after TF_IsRunning");
|
||||||
std::string ip;
|
std::string ip;
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
auto sock =svr->GetStream(ip,port);
|
auto sock =svr->GetStream(ip,port);
|
||||||
|
|
||||||
TF_LOG("New Host IP: " + ip + ":" + std::to_string(port));
|
TF_LOG("New Host IP: " + ip + ":" + std::to_string(port));
|
||||||
|
|
||||||
if(sock == nullptr)
|
if(sock == nullptr)
|
||||||
{
|
{
|
||||||
std::cout << "STREAM ERROR" << std::endl;
|
std::cout << "STREAM ERROR" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
TF_LOG("Before entering socket thread");
|
TF_LOG("Before entering socket thread");
|
||||||
Threading::Thread thrd2([sock,http,ip,port,serverPort]()->void {
|
|
||||||
|
Threading::Thread thrd2([sock,http,ip,port,serverPort,debug]()->void {
|
||||||
TF_LOG("In thread to process");
|
TF_LOG("In thread to process");
|
||||||
HttpServer::Process(sock,http,ip,port,serverPort,false);
|
HttpServer::Process(sock,http,ip,port,serverPort,false, debug);
|
||||||
TF_LOG("In thread after process");
|
TF_LOG("In thread after process");
|
||||||
|
|
||||||
});
|
});
|
||||||
TF_LOG("Before attach");
|
TF_LOG("Before attach");
|
||||||
thrd2.Detach();
|
thrd2.Detach();
|
||||||
@@ -614,7 +719,7 @@ namespace Tesses::Framework::Http
|
|||||||
if(this->showIPs)
|
if(this->showIPs)
|
||||||
{
|
{
|
||||||
TF_LOG("Before printing interfaces");
|
TF_LOG("Before printing interfaces");
|
||||||
|
|
||||||
StdOut() << "\x1B[34mInterfaces:" << NewLine();
|
StdOut() << "\x1B[34mInterfaces:" << NewLine();
|
||||||
for(auto _ip : NetworkStream::GetIPs())
|
for(auto _ip : NetworkStream::GetIPs())
|
||||||
{
|
{
|
||||||
@@ -623,15 +728,15 @@ namespace Tesses::Framework::Http
|
|||||||
<< "\x1B[35mhttp://"
|
<< "\x1B[35mhttp://"
|
||||||
<< _ip.second << ":" << (uint64_t)this->GetPort() << "/" << NewLine();
|
<< _ip.second << ":" << (uint64_t)this->GetPort() << "/" << NewLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
if(this->showARTL)
|
if(this->showARTL)
|
||||||
{
|
{
|
||||||
if(!svr->IsValid()) std::cout << "\x1B[31mError, we failed to bind or something\x1B[39m\n" << std::endl;
|
if(!svr->IsValid()) std::cout << "\x1B[31mError, we failed to bind or something\x1B[39m\n" << std::endl;
|
||||||
StdOut() << "\x1B[31mAlmost Ready to Listen\x1B[39m" << NewLine();
|
StdOut() << "\x1B[31mAlmost Ready to Listen\x1B[39m" << NewLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
TF_LOG("After printing interfaces");
|
TF_LOG("After printing interfaces");
|
||||||
}
|
}
|
||||||
HttpServer::~HttpServer()
|
HttpServer::~HttpServer()
|
||||||
@@ -644,18 +749,20 @@ namespace Tesses::Framework::Http
|
|||||||
this->thrd->Join();
|
this->thrd->Join();
|
||||||
delete this->thrd;
|
delete this->thrd;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
IHttpServer::~IHttpServer()
|
IHttpServer::~IHttpServer()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
ServerContext::ServerContext(std::shared_ptr<Stream> strm)
|
ServerContext::ServerContext(std::shared_ptr<Stream> strm, bool debug)
|
||||||
{
|
{
|
||||||
this->statusCode = OK;
|
this->statusCode = OK;
|
||||||
this->strm = strm;
|
this->strm = strm;
|
||||||
|
this->debug = debug;
|
||||||
this->sent = false;
|
this->sent = false;
|
||||||
this->queryParams.SetCaseSensitive(true);
|
this->queryParams.SetCaseSensitive(true);
|
||||||
|
this->pathArguments.SetCaseSensitive(true);
|
||||||
this->responseHeaders.AddValue("Server","TessesFrameworkWebServer");
|
this->responseHeaders.AddValue("Server","TessesFrameworkWebServer");
|
||||||
}
|
}
|
||||||
std::shared_ptr<Stream> ServerContext::GetStream()
|
std::shared_ptr<Stream> ServerContext::GetStream()
|
||||||
@@ -677,7 +784,7 @@ namespace Tesses::Framework::Http
|
|||||||
void ServerContext::SendText(std::string text)
|
void ServerContext::SendText(std::string text)
|
||||||
{
|
{
|
||||||
std::shared_ptr<MemoryStream> strm=std::make_shared<MemoryStream>(false);
|
std::shared_ptr<MemoryStream> strm=std::make_shared<MemoryStream>(false);
|
||||||
|
|
||||||
auto& buff= strm->GetBuffer();
|
auto& buff= strm->GetBuffer();
|
||||||
buff.insert(buff.end(),text.begin(),text.end());
|
buff.insert(buff.end(),text.begin(),text.end());
|
||||||
SendStream(strm);
|
SendStream(strm);
|
||||||
@@ -685,11 +792,13 @@ namespace Tesses::Framework::Http
|
|||||||
void ServerContext::SendErrorPage(bool showPath)
|
void ServerContext::SendErrorPage(bool showPath)
|
||||||
{
|
{
|
||||||
if(sent) return;
|
if(sent) return;
|
||||||
std::string errorHtml = showPath ? ("<html><head><title>File " + HttpUtils::HtmlEncode(this->originalPath) + " " + HttpUtils::StatusCodeString(this->statusCode) + "</title></head><body><h1>" + std::to_string((int)this->statusCode) + " " + HttpUtils::StatusCodeString(this->statusCode) + "</h1><h4>" + HttpUtils::HtmlEncode(this->originalPath) + "</h4></body></html>") : "";
|
std::string errorHtml = showPath ? ("<html><head><title>File " + HttpUtils::HtmlEncode(this->originalPath) + " " + HttpUtils::StatusCodeString(this->statusCode) + "</title><meta name=\"color-scheme\" content=\"dark light\"></head><body><h1>" + std::to_string((int)this->statusCode) + " " + HttpUtils::StatusCodeString(this->statusCode) + "</h1><h4>" + HttpUtils::HtmlEncode(this->originalPath) + "</h4></body></html>") : (
|
||||||
|
"<html><head><title>" + std::to_string(this->statusCode) + " " + HttpUtils::StatusCodeString(this->statusCode) + "</title><meta name=\"color-scheme\" content=\"dark light\"></head><body><h1>" + std::to_string((int)this->statusCode) + " " + HttpUtils::StatusCodeString(this->statusCode) + "</h1></body></html>"
|
||||||
|
);
|
||||||
|
|
||||||
WithMimeType("text/html").SendText(errorHtml);
|
WithMimeType("text/html").SendText(errorHtml);
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerContext::~ServerContext()
|
ServerContext::~ServerContext()
|
||||||
{
|
{
|
||||||
for(auto item : this->data)
|
for(auto item : this->data)
|
||||||
@@ -699,7 +808,7 @@ namespace Tesses::Framework::Http
|
|||||||
}
|
}
|
||||||
ServerContextData::~ServerContextData()
|
ServerContextData::~ServerContextData()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
void ServerContext::SendStream(std::shared_ptr<Stream> strm)
|
void ServerContext::SendStream(std::shared_ptr<Stream> strm)
|
||||||
{
|
{
|
||||||
@@ -722,7 +831,7 @@ namespace Tesses::Framework::Http
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
res = HttpUtils::SplitString(res[1],", ",2);
|
res = HttpUtils::SplitString(res[1],", ",2);
|
||||||
if(res.size() != 1)
|
if(res.size() != 1)
|
||||||
{
|
{
|
||||||
this->statusCode = BadRequest;
|
this->statusCode = BadRequest;
|
||||||
this->WriteHeaders();
|
this->WriteHeaders();
|
||||||
@@ -764,7 +873,7 @@ namespace Tesses::Framework::Http
|
|||||||
|
|
||||||
if(end == -1)
|
if(end == -1)
|
||||||
{
|
{
|
||||||
end = len-1;
|
end = len-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(end > len-1)
|
if(end > len-1)
|
||||||
@@ -796,7 +905,7 @@ namespace Tesses::Framework::Http
|
|||||||
uint8_t buffer[1024];
|
uint8_t buffer[1024];
|
||||||
|
|
||||||
size_t read=0;
|
size_t read=0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
read = sizeof(buffer);
|
read = sizeof(buffer);
|
||||||
myLen = (end - begin)+1;
|
myLen = (end - begin)+1;
|
||||||
@@ -809,7 +918,7 @@ namespace Tesses::Framework::Http
|
|||||||
begin += read;
|
begin += read;
|
||||||
} while(read > 0 && !this->strm->EndOfStream());
|
} while(read > 0 && !this->strm->EndOfStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -833,19 +942,19 @@ namespace Tesses::Framework::Http
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
auto chunkedStream = this->OpenResponseStream();
|
auto chunkedStream = this->OpenResponseStream();
|
||||||
|
|
||||||
if(method != "HEAD")
|
if(method != "HEAD")
|
||||||
strm->CopyTo(chunkedStream);
|
strm->CopyTo(chunkedStream);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ServerContext& ServerContext::WithHeader(std::string key, std::string value)
|
ServerContext& ServerContext::WithHeader(std::string key, std::string value)
|
||||||
{
|
{
|
||||||
this->responseHeaders.AddValue(key, value);
|
this->responseHeaders.AddValue(key, value);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
ServerContext& ServerContext::WithSingleHeader(std::string key, std::string value)
|
ServerContext& ServerContext::WithSingleHeader(std::string key, std::string value)
|
||||||
{
|
{
|
||||||
@@ -900,24 +1009,40 @@ namespace Tesses::Framework::Http
|
|||||||
statusCode = StatusCode::BadRequest;
|
statusCode = StatusCode::BadRequest;
|
||||||
SendErrorPage(false);
|
SendErrorPage(false);
|
||||||
}
|
}
|
||||||
|
ServerContext& ServerContext::WithStatusCode(StatusCode code)
|
||||||
|
{
|
||||||
|
this->statusCode = code;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
void ServerContext::SendException(std::exception& ex)
|
void ServerContext::SendException(std::exception& ex)
|
||||||
{
|
{
|
||||||
/*<!DOCTYPE html>
|
if(this->debug)
|
||||||
<html lang="en">
|
{
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
this->WithMimeType("text/html").WithStatusCode(StatusCode::InternalServerError).SendText("<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"UTF-8\"> <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>Internal Server Error at " + HttpUtils::HtmlEncode(this->originalPath) + "</title><meta name=\"color-scheme\" content=\"dark light\"></head><body><h1>Internal Server Error at " + HttpUtils::HtmlEncode(this->originalPath) + "</h1><p>what(): " + HttpUtils::HtmlEncode(ex.what()) + "</p></body></html>");
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
}
|
||||||
<title>Internal Server Error at /</title>
|
else {
|
||||||
</head>
|
this->WithStatusCode(StatusCode::InternalServerError).SendErrorPage(true);
|
||||||
<body>
|
}
|
||||||
<h1>Internal Server Error at /</h1>
|
|
||||||
<p>what(): std::exception</p>
|
|
||||||
</body>
|
|
||||||
</html>*/
|
|
||||||
this->WithMimeType("text/html").SendText("<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"UTF-8\"> <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>Internal Server Error at " + HttpUtils::HtmlEncode(this->originalPath) + "</title></head><body><h1>Internal Server Error at " + HttpUtils::HtmlEncode(this->originalPath) + "</h1><p>what(): " + HttpUtils::HtmlEncode(ex.what()) + "</p></body></html>");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ServerContext& ServerContext::WithHeaderIntercepter(std::function<bool(ServerContext&)> cb)
|
||||||
|
{
|
||||||
|
this->headerhandlers.push(cb);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
ServerContext& ServerContext::WriteHeaders()
|
ServerContext& ServerContext::WriteHeaders()
|
||||||
{
|
{
|
||||||
|
if(this->sent) return *this;
|
||||||
|
while(!this->headerhandlers.empty())
|
||||||
|
{
|
||||||
|
auto header = this->headerhandlers.front();
|
||||||
|
this->headerhandlers.pop();
|
||||||
|
if(header(*this)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
if(this->sent) return *this;
|
if(this->sent) return *this;
|
||||||
this->sent = true;
|
this->sent = true;
|
||||||
|
|
||||||
@@ -933,22 +1058,20 @@ namespace Tesses::Framework::Http
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
writer.WriteLine();
|
writer.WriteLine();
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
void HttpServer::Process(std::shared_ptr<Stream> strm, std::shared_ptr<IHttpServer> server, std::string ip, uint16_t port,uint16_t serverPort, bool encrypted)
|
void HttpServer::Process(std::shared_ptr<Stream> strm, std::shared_ptr<IHttpServer> server, std::string ip, uint16_t port,uint16_t serverPort, bool encrypted, bool debug)
|
||||||
{
|
{
|
||||||
TF_LOG("In process");
|
TF_LOG("In process");
|
||||||
while(true)
|
std::shared_ptr<BufferedStream> bStrm = std::make_shared<BufferedStream>(strm);
|
||||||
{
|
StreamReader reader(bStrm);
|
||||||
std::shared_ptr<BufferedStream> bStrm = std::make_shared<BufferedStream>(strm);
|
ServerContext ctx(bStrm);
|
||||||
StreamReader reader(bStrm);
|
ctx.ip = ip;
|
||||||
ServerContext ctx(bStrm);
|
ctx.port = port;
|
||||||
ctx.ip = ip;
|
ctx.encrypted = encrypted;
|
||||||
ctx.port = port;
|
ctx.serverPort = serverPort;
|
||||||
ctx.encrypted = encrypted;
|
try{
|
||||||
ctx.serverPort = serverPort;
|
|
||||||
try{
|
|
||||||
bool firstLine = true;
|
bool firstLine = true;
|
||||||
std::string line;
|
std::string line;
|
||||||
while(reader.ReadLineHttp(line))
|
while(reader.ReadLineHttp(line))
|
||||||
@@ -987,9 +1110,9 @@ namespace Tesses::Framework::Http
|
|||||||
ctx.WithMimeType("text/plain").SendText("Header line is not 2 elements");
|
ctx.WithMimeType("text/plain").SendText("Header line is not 2 elements");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.requestHeaders.AddValue(v[0],v[1]);
|
ctx.requestHeaders.AddValue(v[0],v[1]);
|
||||||
|
|
||||||
}
|
}
|
||||||
line.clear();
|
line.clear();
|
||||||
firstLine=false;
|
firstLine=false;
|
||||||
@@ -1003,18 +1126,20 @@ namespace Tesses::Framework::Http
|
|||||||
if(ctx.requestHeaders.TryGetFirst("Content-Type",type) && type == "application/x-www-form-urlencoded" && ctx.requestHeaders.TryGetFirstInt("Content-Length",length))
|
if(ctx.requestHeaders.TryGetFirst("Content-Type",type) && type == "application/x-www-form-urlencoded" && ctx.requestHeaders.TryGetFirstInt("Content-Length",length))
|
||||||
{
|
{
|
||||||
size_t len = (size_t)length;
|
size_t len = (size_t)length;
|
||||||
uint8_t* buffer = new uint8_t[len];
|
std::vector<uint8_t> buffer(len);
|
||||||
len = bStrm->ReadBlock(buffer,len);
|
len = bStrm->ReadBlock(buffer.data(),len);
|
||||||
std::string query((const char*)buffer,len);
|
std::string query((const char*)buffer.data(),len);
|
||||||
delete[] buffer;
|
|
||||||
HttpUtils::QueryParamsDecode(ctx.queryParams, query);
|
HttpUtils::QueryParamsDecode(ctx.queryParams, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!server->Handle(ctx))
|
if(!server->Handle(ctx))
|
||||||
{
|
{
|
||||||
ctx.SendNotFound();
|
if((int)ctx.statusCode < 400)
|
||||||
|
ctx.SendNotFound();
|
||||||
|
else
|
||||||
|
ctx.SendErrorPage(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
catch(std::exception& ex)
|
catch(std::exception& ex)
|
||||||
{
|
{
|
||||||
@@ -1033,26 +1158,23 @@ namespace Tesses::Framework::Http
|
|||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
std::runtime_error ex("An unknown error occurred");
|
std::runtime_error ex("An unknown error occurred");
|
||||||
ctx.SendException(ex);
|
ctx.SendException(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ctx.version != "HTTP/1.1" ) return;
|
|
||||||
|
|
||||||
std::string connection;
|
|
||||||
if(ctx.requestHeaders.TryGetFirst("Connection", connection))
|
|
||||||
{
|
|
||||||
if(HttpUtils::ToLower(connection) != "keep-alive") return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ctx.responseHeaders.TryGetFirst("Connection", connection))
|
|
||||||
{
|
|
||||||
if(HttpUtils::ToLower(connection) != "keep-alive") return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(bStrm->EndOfStream()) {
|
}
|
||||||
return;
|
|
||||||
}
|
bool ServerContext::Debug()
|
||||||
}
|
{
|
||||||
|
return this->debug;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerContext& ServerContext::WithDebug(bool debug)
|
||||||
|
{
|
||||||
|
this->debug = debug;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
WebSocketConnection::~WebSocketConnection()
|
WebSocketConnection::~WebSocketConnection()
|
||||||
@@ -1064,7 +1186,7 @@ namespace Tesses::Framework::Http
|
|||||||
std::shared_ptr<CallbackWebSocketConnection> wsc = std::make_shared<CallbackWebSocketConnection>(onOpen,onReceive,onClose);
|
std::shared_ptr<CallbackWebSocketConnection> wsc = std::make_shared<CallbackWebSocketConnection>(onOpen,onReceive,onClose);
|
||||||
StartWebSocketSession(wsc);
|
StartWebSocketSession(wsc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerContext::StartWebSocketSession(std::shared_ptr<WebSocketConnection> connection)
|
void ServerContext::StartWebSocketSession(std::shared_ptr<WebSocketConnection> connection)
|
||||||
{
|
{
|
||||||
WSServer svr(this,connection);
|
WSServer svr(this,connection);
|
||||||
@@ -1080,7 +1202,7 @@ namespace Tesses::Framework::Http
|
|||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
svr.Start();
|
svr.Start();
|
||||||
thrd.Join();
|
thrd.Join();
|
||||||
}
|
}
|
||||||
@@ -1105,4 +1227,3 @@ namespace Tesses::Framework::Http
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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(...) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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,83 @@ 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 !defined(_WIN32)
|
||||||
|
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);
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
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 +817,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 +831,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 +858,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 +872,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 +899,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 +922,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 +938,7 @@ bool TcpServer::IsValid()
|
|||||||
}
|
}
|
||||||
void TcpServer::Close()
|
void TcpServer::Close()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
bool NetworkStream::EndOfStream() {
|
bool NetworkStream::EndOfStream() {
|
||||||
return true;
|
return true;
|
||||||
@@ -877,7 +949,7 @@ bool NetworkStream::CanRead() {
|
|||||||
bool NetworkStream::CanWrite() {
|
bool NetworkStream::CanWrite() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkStream::NetworkStream(SocketType type)
|
NetworkStream::NetworkStream(SocketType type)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -888,7 +960,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 +978,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 +1025,7 @@ NetworkStream::~NetworkStream()
|
|||||||
}
|
}
|
||||||
void NetworkStream::SetNoDelay(bool noDelay)
|
void NetworkStream::SetNoDelay(bool noDelay)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
void NetworkStream::Close()
|
void NetworkStream::Close()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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!");
|
||||||
@@ -106,36 +108,34 @@ namespace Tesses::Framework::Streams {
|
|||||||
void Stream::CopyToLimit(std::shared_ptr<Stream> strm,uint64_t len, size_t buffSize)
|
void Stream::CopyToLimit(std::shared_ptr<Stream> strm,uint64_t len, size_t buffSize)
|
||||||
{
|
{
|
||||||
size_t read;
|
size_t read;
|
||||||
uint8_t* buffer = new uint8_t[buffSize];
|
std::vector<uint8_t> buffer(buffSize);
|
||||||
uint64_t offset = 0;
|
uint64_t offset = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if(offset >= len) break;
|
if(offset >= len) break;
|
||||||
read = (size_t)std::min(len-offset,(uint64_t)buffSize);
|
read = (size_t)std::min(len-offset,(uint64_t)buffer.size());
|
||||||
|
|
||||||
read = this->Read(buffer,read);
|
read = this->Read(buffer.data(),read);
|
||||||
strm->WriteBlock(buffer, read);
|
strm->WriteBlock(buffer.data(), read);
|
||||||
|
|
||||||
offset += read;
|
offset += read;
|
||||||
|
|
||||||
} while(read > 0 && !strm->EndOfStream());
|
} while(read > 0 && !strm->EndOfStream());
|
||||||
strm->Flush();
|
strm->Flush();
|
||||||
|
|
||||||
delete[] buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stream::CopyTo(std::shared_ptr<Stream> strm, size_t buffSize)
|
void Stream::CopyTo(std::shared_ptr<Stream> strm, size_t buffSize)
|
||||||
{
|
{
|
||||||
size_t read;
|
size_t read;
|
||||||
uint8_t* buffer = new uint8_t[buffSize];
|
std::vector<uint8_t> buffer(buffSize);
|
||||||
do {
|
do {
|
||||||
read = this->Read(buffer,buffSize);
|
read = this->Read(buffer.data(),buffer.size());
|
||||||
strm->WriteBlock(buffer, read);
|
strm->WriteBlock(buffer.data(), read);
|
||||||
|
|
||||||
} while(read > 0 && !strm->EndOfStream());
|
} while(read > 0 && !strm->EndOfStream());
|
||||||
strm->Flush();
|
strm->Flush();
|
||||||
|
|
||||||
delete[] buffer;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
Stream::~Stream()
|
Stream::~Stream()
|
||||||
|
|||||||
321
src/TF_Init.cpp
321
src/TF_Init.cpp
@@ -6,11 +6,15 @@
|
|||||||
#include "TessesFramework/Filesystem/FSHelpers.hpp"
|
#include "TessesFramework/Filesystem/FSHelpers.hpp"
|
||||||
#include "TessesFramework/Serialization/Json.hpp"
|
#include "TessesFramework/Serialization/Json.hpp"
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <chrono>
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
|
#include <functional>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
#include <ratio>
|
||||||
|
|
||||||
#if defined(TESSESFRAMEWORK_ENABLE_SQLITE)
|
#if defined(TESSESFRAMEWORK_ENABLE_SQLITE)
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "Serialization/sqlite/sqlite3.h"
|
#include "Serialization/sqlite/sqlite3.h"
|
||||||
}
|
}
|
||||||
@@ -49,11 +53,13 @@ static GXRModeObj *rmode = NULL;
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
namespace Tesses::Framework
|
namespace Tesses::Framework
|
||||||
{
|
{
|
||||||
|
|
||||||
EventList<uint64_t> OnItteraton;
|
|
||||||
#if defined(TESSESFRAMEWORK_ENABLE_THREADING) && (defined(GEKKO) || defined(__SWITCH__))
|
#if defined(TESSESFRAMEWORK_ENABLE_THREADING) && (defined(GEKKO) || defined(__SWITCH__))
|
||||||
namespace Threading
|
namespace Threading
|
||||||
{
|
{
|
||||||
@@ -64,13 +70,14 @@ namespace Tesses::Framework
|
|||||||
volatile static bool isRunningSig=true;
|
volatile static bool isRunningSig=true;
|
||||||
volatile static std::atomic<bool> isRunning;
|
volatile static std::atomic<bool> isRunning;
|
||||||
volatile static std::atomic<bool> gaming_console_events=true;
|
volatile static std::atomic<bool> gaming_console_events=true;
|
||||||
|
|
||||||
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
|
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
|
||||||
|
Threading::Mutex timers_mtx;
|
||||||
Threading::Mutex invokings_mtx;
|
Threading::Mutex invokings_mtx;
|
||||||
|
|
||||||
std::queue<std::function<void()>> invokings;
|
std::queue<std::function<void()>> invokings;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void TF_Invoke(std::function<void()> cb)
|
void TF_Invoke(std::function<void()> cb)
|
||||||
{
|
{
|
||||||
@@ -82,11 +89,23 @@ 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);
|
||||||
|
|
||||||
}
|
}
|
||||||
bool TF_IsRunning()
|
bool TF_IsRunning()
|
||||||
{
|
{
|
||||||
@@ -106,16 +125,142 @@ namespace Tesses::Framework
|
|||||||
}
|
}
|
||||||
#if defined(__SWITCH__)
|
#if defined(__SWITCH__)
|
||||||
bool initedConsole=false;
|
bool initedConsole=false;
|
||||||
PadState default_pad;
|
PadState default_pad;
|
||||||
#endif
|
#endif
|
||||||
uint64_t ittr=0;
|
uint64_t ittr=0;
|
||||||
|
|
||||||
|
|
||||||
|
static std::shared_ptr<TF_Timer_Handler> timer_handler = std::make_shared<TF_Timer_Handler>();
|
||||||
|
|
||||||
|
std::shared_ptr<TF_Timer_Handle> TF_Timer_Handler::Make(std::shared_ptr<TF_Timer_Handler> handler)
|
||||||
|
{
|
||||||
|
auto timer = new TF_Timer_Handle(handler);
|
||||||
|
std::shared_ptr<TF_Timer_Handle> handle(timer);
|
||||||
|
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
|
||||||
|
timers_mtx.Lock();
|
||||||
|
#endif
|
||||||
|
handler->handles.push_back(handle);
|
||||||
|
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
|
||||||
|
timers_mtx.Unlock();
|
||||||
|
#endif
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::shared_ptr<TF_Timer_Handle> TF_Timer()
|
||||||
|
{
|
||||||
|
return TF_Timer_Handler::Make(timer_handler);
|
||||||
|
}
|
||||||
|
std::shared_ptr<TF_Timer_Handle> TF_Timer(std::function<void()> cb, int64_t interval, bool enabled)
|
||||||
|
{
|
||||||
|
auto handle = TF_Timer();
|
||||||
|
handle->SetCallback(cb);
|
||||||
|
handle->SetIntervalFromMilliseconds(interval);
|
||||||
|
|
||||||
|
handle->SetEnabled(enabled);
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
std::shared_ptr<TF_Timer_Handle> TF_Timer(std::function<void()> cb, std::chrono::duration<int64_t,std::milli> interval, bool enabled)
|
||||||
|
{
|
||||||
|
auto handle = TF_Timer();
|
||||||
|
handle->SetCallback(cb);
|
||||||
|
handle->SetIntervalFromDuration(interval);
|
||||||
|
|
||||||
|
handle->SetEnabled(enabled);
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TF_Timer_Handler::Update()
|
||||||
|
{
|
||||||
|
std::chrono::time_point<std::chrono::steady_clock,std::chrono::milliseconds> cur = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now());
|
||||||
|
std::vector<std::function<void()>> cbs;
|
||||||
|
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
|
||||||
|
timers_mtx.Lock();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for(auto index = this->handles.begin(); index != this->handles.end(); index++)
|
||||||
|
{
|
||||||
|
if(index->expired())
|
||||||
|
{
|
||||||
|
this->handles.erase(index);
|
||||||
|
index--;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
auto handle = index->lock();
|
||||||
|
if(handle && handle->enabled && (handle->last + handle->interval) <= cur && handle->cb)
|
||||||
|
{
|
||||||
|
handle->last = cur;
|
||||||
|
cbs.push_back(handle->cb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
|
||||||
|
timers_mtx.Unlock();
|
||||||
|
#endif
|
||||||
|
for(auto item : cbs)
|
||||||
|
{
|
||||||
|
item();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void TF_Timer_Handle::SetCallback(std::function<void()> cb)
|
||||||
|
{
|
||||||
|
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
|
||||||
|
timers_mtx.Lock();
|
||||||
|
#endif
|
||||||
|
this->cb = cb;
|
||||||
|
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
|
||||||
|
timers_mtx.Unlock();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
TF_Timer_Handle::TF_Timer_Handle(std::shared_ptr<TF_Timer_Handler> handler) : timerHandler(handler)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
void TF_Timer_Handle::SetEnabled(bool enabled)
|
||||||
|
{
|
||||||
|
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
|
||||||
|
timers_mtx.Lock();
|
||||||
|
#endif
|
||||||
|
this->enabled = enabled;
|
||||||
|
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
|
||||||
|
timers_mtx.Unlock();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
bool TF_Timer_Handle::GetEnabled()
|
||||||
|
{
|
||||||
|
return this->enabled;
|
||||||
|
}
|
||||||
|
void TF_Timer_Handle::SetIntervalFromDuration(std::chrono::milliseconds ms)
|
||||||
|
{
|
||||||
|
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
|
||||||
|
timers_mtx.Lock();
|
||||||
|
#endif
|
||||||
|
this->interval = ms;
|
||||||
|
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
|
||||||
|
timers_mtx.Unlock();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
void TF_Timer_Handle::SetIntervalFromMilliseconds(int64_t ms)
|
||||||
|
{
|
||||||
|
SetIntervalFromDuration(std::chrono::milliseconds(ms));
|
||||||
|
}
|
||||||
|
std::chrono::duration<int64_t,std::milli> TF_Timer_Handle::GetIntervalDuration()
|
||||||
|
{
|
||||||
|
return this->interval;
|
||||||
|
}
|
||||||
|
int64_t TF_Timer_Handle::GetIntervalMilliseconds()
|
||||||
|
{
|
||||||
|
return this->interval.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void TF_RunEventLoopItteration()
|
void TF_RunEventLoopItteration()
|
||||||
{
|
{
|
||||||
|
|
||||||
OnItteraton.Invoke(ittr++);
|
|
||||||
#if defined(TESSESFRAMEWORK_ENABLE_THREADING) && (defined(GEKKO) || defined(__SWITCH__))
|
#if defined(TESSESFRAMEWORK_ENABLE_THREADING) && (defined(GEKKO) || defined(__SWITCH__))
|
||||||
Tesses::Framework::Threading::LookForFinishedThreads();
|
Tesses::Framework::Threading::LookForFinishedThreads();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
|
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
|
||||||
invokings_mtx.Lock();
|
invokings_mtx.Lock();
|
||||||
@@ -125,10 +270,10 @@ namespace Tesses::Framework
|
|||||||
{
|
{
|
||||||
invokes.front()();
|
invokes.front()();
|
||||||
invokes.pop();
|
invokes.pop();
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(!isRunningSig) isRunning=false;
|
if(!isRunningSig) isRunning=false;
|
||||||
#if defined(GEKKO)
|
#if defined(GEKKO)
|
||||||
if(gaming_console_events)
|
if(gaming_console_events)
|
||||||
@@ -140,7 +285,7 @@ namespace Tesses::Framework
|
|||||||
if(gaming_console_events)
|
if(gaming_console_events)
|
||||||
{
|
{
|
||||||
if(!appletMainLoop()) isRunning=false;
|
if(!appletMainLoop()) isRunning=false;
|
||||||
|
|
||||||
padUpdate(&default_pad);
|
padUpdate(&default_pad);
|
||||||
|
|
||||||
u64 kDown = padGetButtonsDown(&default_pad);
|
u64 kDown = padGetButtonsDown(&default_pad);
|
||||||
@@ -163,7 +308,9 @@ namespace Tesses::Framework
|
|||||||
isRunning = false;
|
isRunning = false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
timer_handler->Update();
|
||||||
|
|
||||||
}
|
}
|
||||||
void TF_SetIsRunning(bool _isRunning)
|
void TF_SetIsRunning(bool _isRunning)
|
||||||
@@ -200,7 +347,7 @@ namespace Tesses::Framework
|
|||||||
signal(SIGINT, _sigInt);
|
signal(SIGINT, _sigInt);
|
||||||
signal(SIGTERM, _sigInt);
|
signal(SIGTERM, _sigInt);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
isRunning=true;
|
isRunning=true;
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
WSADATA wsaData;
|
WSADATA wsaData;
|
||||||
@@ -230,9 +377,9 @@ if (iResult != 0) {
|
|||||||
// Initialize the default gamepad (which reads handheld mode inputs as well as the first connected controller)
|
// Initialize the default gamepad (which reads handheld mode inputs as well as the first connected controller)
|
||||||
#else
|
#else
|
||||||
signal(SIGPIPE,SIG_IGN);
|
signal(SIGPIPE,SIG_IGN);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
bool TF_GetConsoleEventsEnabled()
|
bool TF_GetConsoleEventsEnabled()
|
||||||
{
|
{
|
||||||
@@ -332,7 +479,7 @@ if (iResult != 0) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::string> _argv0=std::nullopt;
|
std::optional<std::string> _argv0=std::nullopt;
|
||||||
|
|
||||||
|
|
||||||
void TF_AllowPortable(std::string argv0)
|
void TF_AllowPortable(std::string argv0)
|
||||||
{
|
{
|
||||||
@@ -346,7 +493,7 @@ if (iResult != 0) {
|
|||||||
auto portable=dir / "portable.json";
|
auto portable=dir / "portable.json";
|
||||||
if(LocalFS->FileExists(portable))
|
if(LocalFS->FileExists(portable))
|
||||||
{
|
{
|
||||||
|
|
||||||
std::string portable_str;
|
std::string portable_str;
|
||||||
Helpers::ReadAllText(LocalFS,portable, portable_str);
|
Helpers::ReadAllText(LocalFS,portable, portable_str);
|
||||||
auto jsonObj=Json::Decode(portable_str);
|
auto jsonObj=Json::Decode(portable_str);
|
||||||
@@ -403,7 +550,7 @@ if (iResult != 0) {
|
|||||||
{
|
{
|
||||||
if(paf_data)
|
if(paf_data)
|
||||||
portable_config.user = LocalFS->SystemToVFSPath(*paf_data) / "TF_User";
|
portable_config.user = LocalFS->SystemToVFSPath(*paf_data) / "TF_User";
|
||||||
}
|
}
|
||||||
else if(portable_str == "documents")
|
else if(portable_str == "documents")
|
||||||
{
|
{
|
||||||
if(paf_documents)
|
if(paf_documents)
|
||||||
@@ -416,7 +563,7 @@ if (iResult != 0) {
|
|||||||
{
|
{
|
||||||
if(portable_config.user)
|
if(portable_config.user)
|
||||||
portable_config.desktop = *(portable_config.user) / "Desktop";
|
portable_config.desktop = *(portable_config.user) / "Desktop";
|
||||||
}
|
}
|
||||||
else if(portable_str == "documents")
|
else if(portable_str == "documents")
|
||||||
{
|
{
|
||||||
if(paf_documents)
|
if(paf_documents)
|
||||||
@@ -429,7 +576,7 @@ if (iResult != 0) {
|
|||||||
{
|
{
|
||||||
if(portable_config.user)
|
if(portable_config.user)
|
||||||
portable_config.downloads = *(portable_config.user) / "Downloads";
|
portable_config.downloads = *(portable_config.user) / "Downloads";
|
||||||
}
|
}
|
||||||
else if(portable_str == "documents")
|
else if(portable_str == "documents")
|
||||||
{
|
{
|
||||||
if(paf_documents)
|
if(paf_documents)
|
||||||
@@ -466,21 +613,21 @@ if (iResult != 0) {
|
|||||||
{
|
{
|
||||||
if(dict2.TryGetValueAsType("user",portable_str))
|
if(dict2.TryGetValueAsType("user",portable_str))
|
||||||
{
|
{
|
||||||
if(portable_str != "system")
|
if(portable_str != "system")
|
||||||
{
|
{
|
||||||
auto userDir = dir / portable_str;
|
auto userDir = dir / portable_str;
|
||||||
portable_config.user = userDir.CollapseRelativeParents();
|
portable_config.user = userDir.CollapseRelativeParents();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dict2.TryGetValueAsType("documents", portable_str))
|
if(dict2.TryGetValueAsType("documents", portable_str))
|
||||||
{
|
{
|
||||||
|
|
||||||
if(portable_str != "system")
|
if(portable_str != "system")
|
||||||
{
|
{
|
||||||
if(portable_str == "default")
|
if(portable_str == "default")
|
||||||
@@ -490,7 +637,7 @@ if (iResult != 0) {
|
|||||||
portable_config.documents = *(portable_config.user) / "Documents";
|
portable_config.documents = *(portable_config.user) / "Documents";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto userDir = dir / portable_str;
|
auto userDir = dir / portable_str;
|
||||||
portable_config.documents = userDir.CollapseRelativeParents();
|
portable_config.documents = userDir.CollapseRelativeParents();
|
||||||
@@ -500,7 +647,7 @@ if (iResult != 0) {
|
|||||||
}
|
}
|
||||||
if(dict2.TryGetValueAsType("downloads", portable_str))
|
if(dict2.TryGetValueAsType("downloads", portable_str))
|
||||||
{
|
{
|
||||||
|
|
||||||
if(portable_str != "system")
|
if(portable_str != "system")
|
||||||
{
|
{
|
||||||
if(portable_str == "default")
|
if(portable_str == "default")
|
||||||
@@ -510,7 +657,7 @@ if (iResult != 0) {
|
|||||||
portable_config.downloads = *(portable_config.user) / "Downloads";
|
portable_config.downloads = *(portable_config.user) / "Downloads";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto userDir = dir / portable_str;
|
auto userDir = dir / portable_str;
|
||||||
portable_config.downloads = userDir.CollapseRelativeParents();
|
portable_config.downloads = userDir.CollapseRelativeParents();
|
||||||
@@ -520,7 +667,7 @@ if (iResult != 0) {
|
|||||||
}
|
}
|
||||||
if(dict2.TryGetValueAsType("desktop", portable_str))
|
if(dict2.TryGetValueAsType("desktop", portable_str))
|
||||||
{
|
{
|
||||||
|
|
||||||
if(portable_str != "system")
|
if(portable_str != "system")
|
||||||
{
|
{
|
||||||
if(portable_str == "default")
|
if(portable_str == "default")
|
||||||
@@ -530,7 +677,7 @@ if (iResult != 0) {
|
|||||||
portable_config.desktop = *(portable_config.user) / "Desktop";
|
portable_config.desktop = *(portable_config.user) / "Desktop";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto userDir = dir / portable_str;
|
auto userDir = dir / portable_str;
|
||||||
portable_config.desktop = userDir.CollapseRelativeParents();
|
portable_config.desktop = userDir.CollapseRelativeParents();
|
||||||
@@ -540,7 +687,7 @@ if (iResult != 0) {
|
|||||||
}
|
}
|
||||||
if(dict2.TryGetValueAsType("pictures", portable_str))
|
if(dict2.TryGetValueAsType("pictures", portable_str))
|
||||||
{
|
{
|
||||||
|
|
||||||
if(portable_str != "system")
|
if(portable_str != "system")
|
||||||
{
|
{
|
||||||
if(portable_str == "default")
|
if(portable_str == "default")
|
||||||
@@ -550,7 +697,7 @@ if (iResult != 0) {
|
|||||||
portable_config.pictures = *(portable_config.user) / "Pictures";
|
portable_config.pictures = *(portable_config.user) / "Pictures";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto userDir = dir / portable_str;
|
auto userDir = dir / portable_str;
|
||||||
portable_config.pictures = userDir.CollapseRelativeParents();
|
portable_config.pictures = userDir.CollapseRelativeParents();
|
||||||
@@ -560,7 +707,7 @@ if (iResult != 0) {
|
|||||||
}
|
}
|
||||||
if(dict2.TryGetValueAsType("videos", portable_str))
|
if(dict2.TryGetValueAsType("videos", portable_str))
|
||||||
{
|
{
|
||||||
|
|
||||||
if(portable_str != "system")
|
if(portable_str != "system")
|
||||||
{
|
{
|
||||||
if(portable_str == "default")
|
if(portable_str == "default")
|
||||||
@@ -570,7 +717,7 @@ if (iResult != 0) {
|
|||||||
portable_config.videos = *(portable_config.user) / "Videos";
|
portable_config.videos = *(portable_config.user) / "Videos";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto userDir = dir / portable_str;
|
auto userDir = dir / portable_str;
|
||||||
portable_config.videos = userDir.CollapseRelativeParents();
|
portable_config.videos = userDir.CollapseRelativeParents();
|
||||||
@@ -580,7 +727,7 @@ if (iResult != 0) {
|
|||||||
}
|
}
|
||||||
if(dict2.TryGetValueAsType("music", portable_str))
|
if(dict2.TryGetValueAsType("music", portable_str))
|
||||||
{
|
{
|
||||||
|
|
||||||
if(portable_str != "system")
|
if(portable_str != "system")
|
||||||
{
|
{
|
||||||
if(portable_str == "default")
|
if(portable_str == "default")
|
||||||
@@ -590,7 +737,7 @@ if (iResult != 0) {
|
|||||||
portable_config.music = *(portable_config.user) / "Music";
|
portable_config.music = *(portable_config.user) / "Music";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto userDir = dir / portable_str;
|
auto userDir = dir / portable_str;
|
||||||
portable_config.music = userDir.CollapseRelativeParents();
|
portable_config.music = userDir.CollapseRelativeParents();
|
||||||
@@ -600,7 +747,7 @@ if (iResult != 0) {
|
|||||||
}
|
}
|
||||||
if(dict2.TryGetValueAsType("config", portable_str))
|
if(dict2.TryGetValueAsType("config", portable_str))
|
||||||
{
|
{
|
||||||
|
|
||||||
if(portable_str != "system")
|
if(portable_str != "system")
|
||||||
{
|
{
|
||||||
if(portable_str == "default")
|
if(portable_str == "default")
|
||||||
@@ -610,7 +757,7 @@ if (iResult != 0) {
|
|||||||
portable_config.config = *(portable_config.user) / "Config";
|
portable_config.config = *(portable_config.user) / "Config";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto userDir = dir / portable_str;
|
auto userDir = dir / portable_str;
|
||||||
portable_config.config = userDir.CollapseRelativeParents();
|
portable_config.config = userDir.CollapseRelativeParents();
|
||||||
@@ -620,7 +767,7 @@ if (iResult != 0) {
|
|||||||
}
|
}
|
||||||
if(dict2.TryGetValueAsType("cache", portable_str))
|
if(dict2.TryGetValueAsType("cache", portable_str))
|
||||||
{
|
{
|
||||||
|
|
||||||
if(portable_str != "system")
|
if(portable_str != "system")
|
||||||
{
|
{
|
||||||
if(portable_str == "default")
|
if(portable_str == "default")
|
||||||
@@ -630,7 +777,7 @@ if (iResult != 0) {
|
|||||||
portable_config.cache = *(portable_config.user) / "Cache";
|
portable_config.cache = *(portable_config.user) / "Cache";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto userDir = dir / portable_str;
|
auto userDir = dir / portable_str;
|
||||||
portable_config.cache = userDir.CollapseRelativeParents();
|
portable_config.cache = userDir.CollapseRelativeParents();
|
||||||
@@ -640,7 +787,7 @@ if (iResult != 0) {
|
|||||||
}
|
}
|
||||||
if(dict2.TryGetValueAsType("data", portable_str))
|
if(dict2.TryGetValueAsType("data", portable_str))
|
||||||
{
|
{
|
||||||
|
|
||||||
if(portable_str != "system")
|
if(portable_str != "system")
|
||||||
{
|
{
|
||||||
if(portable_str == "default")
|
if(portable_str == "default")
|
||||||
@@ -650,7 +797,7 @@ if (iResult != 0) {
|
|||||||
portable_config.data = *(portable_config.user) / "Data";
|
portable_config.data = *(portable_config.user) / "Data";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto userDir = dir / portable_str;
|
auto userDir = dir / portable_str;
|
||||||
portable_config.data = userDir.CollapseRelativeParents();
|
portable_config.data = userDir.CollapseRelativeParents();
|
||||||
@@ -660,7 +807,7 @@ if (iResult != 0) {
|
|||||||
}
|
}
|
||||||
if(dict2.TryGetValueAsType("state", portable_str))
|
if(dict2.TryGetValueAsType("state", portable_str))
|
||||||
{
|
{
|
||||||
|
|
||||||
if(portable_str != "system")
|
if(portable_str != "system")
|
||||||
{
|
{
|
||||||
if(portable_str == "default")
|
if(portable_str == "default")
|
||||||
@@ -670,7 +817,7 @@ if (iResult != 0) {
|
|||||||
portable_config.state = *(portable_config.user) / "State";
|
portable_config.state = *(portable_config.user) / "State";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto userDir = dir / portable_str;
|
auto userDir = dir / portable_str;
|
||||||
portable_config.state = userDir.CollapseRelativeParents();
|
portable_config.state = userDir.CollapseRelativeParents();
|
||||||
@@ -680,7 +827,7 @@ if (iResult != 0) {
|
|||||||
}
|
}
|
||||||
if(dict2.TryGetValueAsType("temp", portable_str))
|
if(dict2.TryGetValueAsType("temp", portable_str))
|
||||||
{
|
{
|
||||||
|
|
||||||
if(portable_str != "system")
|
if(portable_str != "system")
|
||||||
{
|
{
|
||||||
if(portable_str == "default")
|
if(portable_str == "default")
|
||||||
@@ -690,7 +837,7 @@ if (iResult != 0) {
|
|||||||
portable_config.temp = *(portable_config.user) / "Temp";
|
portable_config.temp = *(portable_config.user) / "Temp";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto userDir = dir / portable_str;
|
auto userDir = dir / portable_str;
|
||||||
portable_config.temp = userDir.CollapseRelativeParents();
|
portable_config.temp = userDir.CollapseRelativeParents();
|
||||||
@@ -698,40 +845,40 @@ if (iResult != 0) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else if(portable_str == "absolute")
|
else if(portable_str == "absolute")
|
||||||
{
|
{
|
||||||
if(dict2.TryGetValueAsType("user",portable_str))
|
if(dict2.TryGetValueAsType("user",portable_str))
|
||||||
{
|
{
|
||||||
if(portable_str != "system")
|
if(portable_str != "system")
|
||||||
{
|
{
|
||||||
VFSPath userDir = portable_str;
|
VFSPath userDir = portable_str;
|
||||||
portable_config.user = userDir.CollapseRelativeParents();
|
portable_config.user = userDir.CollapseRelativeParents();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dict2.TryGetValueAsType("documents", portable_str))
|
if(dict2.TryGetValueAsType("documents", portable_str))
|
||||||
{
|
{
|
||||||
|
|
||||||
if(portable_str != "system")
|
if(portable_str != "system")
|
||||||
{
|
{
|
||||||
if(portable_str == "default")
|
if(portable_str == "default")
|
||||||
@@ -741,7 +888,7 @@ if (iResult != 0) {
|
|||||||
portable_config.documents = *(portable_config.user) / "Documents";
|
portable_config.documents = *(portable_config.user) / "Documents";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VFSPath userDir = portable_str;
|
VFSPath userDir = portable_str;
|
||||||
portable_config.documents = userDir.CollapseRelativeParents();
|
portable_config.documents = userDir.CollapseRelativeParents();
|
||||||
@@ -751,7 +898,7 @@ if (iResult != 0) {
|
|||||||
}
|
}
|
||||||
if(dict2.TryGetValueAsType("downloads", portable_str))
|
if(dict2.TryGetValueAsType("downloads", portable_str))
|
||||||
{
|
{
|
||||||
|
|
||||||
if(portable_str != "system")
|
if(portable_str != "system")
|
||||||
{
|
{
|
||||||
if(portable_str == "default")
|
if(portable_str == "default")
|
||||||
@@ -761,7 +908,7 @@ if (iResult != 0) {
|
|||||||
portable_config.downloads = *(portable_config.user) / "Downloads";
|
portable_config.downloads = *(portable_config.user) / "Downloads";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VFSPath userDir = portable_str;
|
VFSPath userDir = portable_str;
|
||||||
portable_config.downloads = userDir.CollapseRelativeParents();
|
portable_config.downloads = userDir.CollapseRelativeParents();
|
||||||
@@ -771,7 +918,7 @@ if (iResult != 0) {
|
|||||||
}
|
}
|
||||||
if(dict2.TryGetValueAsType("desktop", portable_str))
|
if(dict2.TryGetValueAsType("desktop", portable_str))
|
||||||
{
|
{
|
||||||
|
|
||||||
if(portable_str != "system")
|
if(portable_str != "system")
|
||||||
{
|
{
|
||||||
if(portable_str == "default")
|
if(portable_str == "default")
|
||||||
@@ -781,7 +928,7 @@ if (iResult != 0) {
|
|||||||
portable_config.desktop = *(portable_config.user) / "Desktop";
|
portable_config.desktop = *(portable_config.user) / "Desktop";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VFSPath userDir = portable_str;
|
VFSPath userDir = portable_str;
|
||||||
portable_config.desktop = userDir.CollapseRelativeParents();
|
portable_config.desktop = userDir.CollapseRelativeParents();
|
||||||
@@ -791,7 +938,7 @@ if (iResult != 0) {
|
|||||||
}
|
}
|
||||||
if(dict2.TryGetValueAsType("pictures", portable_str))
|
if(dict2.TryGetValueAsType("pictures", portable_str))
|
||||||
{
|
{
|
||||||
|
|
||||||
if(portable_str != "system")
|
if(portable_str != "system")
|
||||||
{
|
{
|
||||||
if(portable_str == "default")
|
if(portable_str == "default")
|
||||||
@@ -801,7 +948,7 @@ if (iResult != 0) {
|
|||||||
portable_config.pictures = *(portable_config.user) / "Pictures";
|
portable_config.pictures = *(portable_config.user) / "Pictures";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VFSPath userDir = portable_str;
|
VFSPath userDir = portable_str;
|
||||||
portable_config.pictures = userDir.CollapseRelativeParents();
|
portable_config.pictures = userDir.CollapseRelativeParents();
|
||||||
@@ -811,7 +958,7 @@ if (iResult != 0) {
|
|||||||
}
|
}
|
||||||
if(dict2.TryGetValueAsType("videos", portable_str))
|
if(dict2.TryGetValueAsType("videos", portable_str))
|
||||||
{
|
{
|
||||||
|
|
||||||
if(portable_str != "system")
|
if(portable_str != "system")
|
||||||
{
|
{
|
||||||
if(portable_str == "default")
|
if(portable_str == "default")
|
||||||
@@ -821,7 +968,7 @@ if (iResult != 0) {
|
|||||||
portable_config.videos = *(portable_config.user) / "Videos";
|
portable_config.videos = *(portable_config.user) / "Videos";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VFSPath userDir = portable_str;
|
VFSPath userDir = portable_str;
|
||||||
portable_config.videos = userDir.CollapseRelativeParents();
|
portable_config.videos = userDir.CollapseRelativeParents();
|
||||||
@@ -831,7 +978,7 @@ if (iResult != 0) {
|
|||||||
}
|
}
|
||||||
if(dict2.TryGetValueAsType("music", portable_str))
|
if(dict2.TryGetValueAsType("music", portable_str))
|
||||||
{
|
{
|
||||||
|
|
||||||
if(portable_str != "system")
|
if(portable_str != "system")
|
||||||
{
|
{
|
||||||
if(portable_str == "default")
|
if(portable_str == "default")
|
||||||
@@ -841,7 +988,7 @@ if (iResult != 0) {
|
|||||||
portable_config.music = *(portable_config.user) / "Music";
|
portable_config.music = *(portable_config.user) / "Music";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VFSPath userDir = portable_str;
|
VFSPath userDir = portable_str;
|
||||||
portable_config.music = userDir.CollapseRelativeParents();
|
portable_config.music = userDir.CollapseRelativeParents();
|
||||||
@@ -851,7 +998,7 @@ if (iResult != 0) {
|
|||||||
}
|
}
|
||||||
if(dict2.TryGetValueAsType("config", portable_str))
|
if(dict2.TryGetValueAsType("config", portable_str))
|
||||||
{
|
{
|
||||||
|
|
||||||
if(portable_str != "system")
|
if(portable_str != "system")
|
||||||
{
|
{
|
||||||
if(portable_str == "default")
|
if(portable_str == "default")
|
||||||
@@ -861,7 +1008,7 @@ if (iResult != 0) {
|
|||||||
portable_config.config = *(portable_config.user) / "Config";
|
portable_config.config = *(portable_config.user) / "Config";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VFSPath userDir = portable_str;
|
VFSPath userDir = portable_str;
|
||||||
portable_config.config = userDir.CollapseRelativeParents();
|
portable_config.config = userDir.CollapseRelativeParents();
|
||||||
@@ -871,7 +1018,7 @@ if (iResult != 0) {
|
|||||||
}
|
}
|
||||||
if(dict2.TryGetValueAsType("cache", portable_str))
|
if(dict2.TryGetValueAsType("cache", portable_str))
|
||||||
{
|
{
|
||||||
|
|
||||||
if(portable_str != "system")
|
if(portable_str != "system")
|
||||||
{
|
{
|
||||||
if(portable_str == "default")
|
if(portable_str == "default")
|
||||||
@@ -881,7 +1028,7 @@ if (iResult != 0) {
|
|||||||
portable_config.cache = *(portable_config.user) / "Cache";
|
portable_config.cache = *(portable_config.user) / "Cache";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VFSPath userDir = portable_str;
|
VFSPath userDir = portable_str;
|
||||||
portable_config.cache = userDir.CollapseRelativeParents();
|
portable_config.cache = userDir.CollapseRelativeParents();
|
||||||
@@ -891,7 +1038,7 @@ if (iResult != 0) {
|
|||||||
}
|
}
|
||||||
if(dict2.TryGetValueAsType("data", portable_str))
|
if(dict2.TryGetValueAsType("data", portable_str))
|
||||||
{
|
{
|
||||||
|
|
||||||
if(portable_str != "system")
|
if(portable_str != "system")
|
||||||
{
|
{
|
||||||
if(portable_str == "default")
|
if(portable_str == "default")
|
||||||
@@ -901,7 +1048,7 @@ if (iResult != 0) {
|
|||||||
portable_config.data = *(portable_config.user) / "Data";
|
portable_config.data = *(portable_config.user) / "Data";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VFSPath userDir = portable_str;
|
VFSPath userDir = portable_str;
|
||||||
portable_config.data = userDir.CollapseRelativeParents();
|
portable_config.data = userDir.CollapseRelativeParents();
|
||||||
@@ -911,7 +1058,7 @@ if (iResult != 0) {
|
|||||||
}
|
}
|
||||||
if(dict2.TryGetValueAsType("state", portable_str))
|
if(dict2.TryGetValueAsType("state", portable_str))
|
||||||
{
|
{
|
||||||
|
|
||||||
if(portable_str != "system")
|
if(portable_str != "system")
|
||||||
{
|
{
|
||||||
if(portable_str == "default")
|
if(portable_str == "default")
|
||||||
@@ -921,7 +1068,7 @@ if (iResult != 0) {
|
|||||||
portable_config.state = *(portable_config.user) / "State";
|
portable_config.state = *(portable_config.user) / "State";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VFSPath userDir = portable_str;
|
VFSPath userDir = portable_str;
|
||||||
portable_config.state = userDir.CollapseRelativeParents();
|
portable_config.state = userDir.CollapseRelativeParents();
|
||||||
@@ -931,7 +1078,7 @@ if (iResult != 0) {
|
|||||||
}
|
}
|
||||||
if(dict2.TryGetValueAsType("temp", portable_str))
|
if(dict2.TryGetValueAsType("temp", portable_str))
|
||||||
{
|
{
|
||||||
|
|
||||||
if(portable_str != "system")
|
if(portable_str != "system")
|
||||||
{
|
{
|
||||||
if(portable_str == "default")
|
if(portable_str == "default")
|
||||||
@@ -941,7 +1088,7 @@ if (iResult != 0) {
|
|||||||
portable_config.temp = *(portable_config.user) / "Temp";
|
portable_config.temp = *(portable_config.user) / "Temp";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VFSPath userDir = portable_str;
|
VFSPath userDir = portable_str;
|
||||||
portable_config.temp = userDir.CollapseRelativeParents();
|
portable_config.temp = userDir.CollapseRelativeParents();
|
||||||
@@ -949,7 +1096,7 @@ if (iResult != 0) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,12 +16,12 @@ namespace Tesses::Framework::Text {
|
|||||||
uint64_t total = 0;
|
uint64_t total = 0;
|
||||||
size_t read;
|
size_t read;
|
||||||
|
|
||||||
uint8_t* data = new uint8_t[BLK_SZ];
|
std::vector<uint8_t> data(BLK_SZ);
|
||||||
bool first=true;
|
bool first=true;
|
||||||
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
read = strm->ReadBlock(data, BLK_SZ);
|
read = strm->ReadBlock(data.data(), data.size());
|
||||||
|
|
||||||
for(size_t i = 0; i < read; i++)
|
for(size_t i = 0; i < read; i++)
|
||||||
{
|
{
|
||||||
@@ -33,7 +33,6 @@ namespace Tesses::Framework::Text {
|
|||||||
} while(read != 0);
|
} while(read != 0);
|
||||||
|
|
||||||
|
|
||||||
delete data;
|
|
||||||
|
|
||||||
writer->WriteLine("};");
|
writer->WriteLine("};");
|
||||||
writer->Write("const size_t ");
|
writer->Write("const size_t ");
|
||||||
|
|||||||
@@ -9,23 +9,18 @@ namespace Tesses::Framework::TextStreams
|
|||||||
}
|
}
|
||||||
bool ConsoleReader::ReadBlock(std::string& str,size_t len)
|
bool ConsoleReader::ReadBlock(std::string& str,size_t len)
|
||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
std::vector<uint8_t> buff(len);
|
||||||
uint8_t* buff = new uint8_t[len];
|
|
||||||
#else
|
|
||||||
uint8_t buff[len];
|
|
||||||
#endif
|
|
||||||
size_t read=0;
|
size_t read=0;
|
||||||
size_t readTotal=0;
|
size_t readTotal=0;
|
||||||
uint8_t* buffOff=buff;
|
uint8_t* buffOff=buff.data();
|
||||||
do {
|
do {
|
||||||
read=fread(buffOff,1,len,stdin);
|
read=fread(buffOff,1,len,stdin);
|
||||||
if(read != 0) {readTotal+= read;len-=read; buffOff+=read;}
|
if(read != 0) {readTotal+= read;len-=read; buffOff+=read;}
|
||||||
} while(read != 0);
|
} while(read != 0);
|
||||||
if(readTotal == 0) return false;
|
if(readTotal == 0) return false;
|
||||||
str.append((const char*)buff, readTotal);
|
str.append((const char*)buff.data(), readTotal);
|
||||||
#if defined(_WIN32)
|
|
||||||
delete buff;
|
|
||||||
#endif
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,13 +30,12 @@ namespace Tesses::Framework::TextStreams {
|
|||||||
|
|
||||||
bool StreamReader::ReadBlock(std::string& str, size_t len)
|
bool StreamReader::ReadBlock(std::string& str, size_t len)
|
||||||
{
|
{
|
||||||
uint8_t* buff = new uint8_t[len];
|
std::vector<uint8_t> buff(len);
|
||||||
|
|
||||||
len = strm->ReadBlock(buff,len);
|
len = strm->ReadBlock(buff.data(),len);
|
||||||
if(len == 0) {delete buff; return false;}
|
if(len == 0) { return false;}
|
||||||
str.append((const char*)buff, len);
|
str.append((const char*)buff.data(), len);
|
||||||
|
|
||||||
delete buff;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user