diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index ea56ee5..6149231 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(circuits) +add_subdirectory(math) add_subdirectory(machine_learning) add_subdirectory(physics_simulation) add_subdirectory(quantum_computing) diff --git a/plugins/math/CMakeLists.txt b/plugins/math/CMakeLists.txt new file mode 100644 index 0000000..907ef11 --- /dev/null +++ b/plugins/math/CMakeLists.txt @@ -0,0 +1,12 @@ +set(PLUGIN_NAME ntk_math) + +list(APPEND math_HEADERS ComplexNumber.h) + +list(APPEND math_LIB_INCLUDES ComplexNumber.cpp) + +add_library(${PLUGIN_NAME} SHARED ${math_LIB_INCLUDES} ${math_HEADERS}) + +target_include_directories(${PLUGIN_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(${PLUGIN_NAME} PUBLIC core) +set_property(TARGET ${PLUGIN_NAME} PROPERTY FOLDER plugins) +set_target_properties( ${PLUGIN_NAME} PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON ) \ No newline at end of file diff --git a/plugins/math/ComplexNumber.cpp b/plugins/math/ComplexNumber.cpp new file mode 100644 index 0000000..98c60ab --- /dev/null +++ b/plugins/math/ComplexNumber.cpp @@ -0,0 +1,28 @@ +#include "ComplexNumber.h" + +ComplexNumber::ComplexNumber(double real, double imaginary) + : mReal(real), + mImaginary(imaginary) +{ + +} + +double ComplexNumber::getReal() const +{ + return mReal; +} + +double ComplexNumber::getImaginary() const +{ + return mImaginary; +} + +void ComplexNumber::setReal(double value) +{ + mReal = value; +} + +void ComplexNumber::setImaginary(double value) +{ + mImaginary = value; +} \ No newline at end of file diff --git a/plugins/math/ComplexNumber.h b/plugins/math/ComplexNumber.h new file mode 100644 index 0000000..9b0ee5b --- /dev/null +++ b/plugins/math/ComplexNumber.h @@ -0,0 +1,19 @@ +#pragma once + +class ComplexNumber +{ +public: + ComplexNumber(double real = 0.0, double imaginary = 0.0); + + double getReal() const; + + double getImaginary() const; + + void setReal(double value); + + void setImaginary(double value); + +private: + double mReal{ 0.0 }; + double mImaginary{ 0.0 }; +}; \ No newline at end of file diff --git a/plugins/quantum_computing/CMakeLists.txt b/plugins/quantum_computing/CMakeLists.txt index aaa28c6..47f2510 100644 --- a/plugins/quantum_computing/CMakeLists.txt +++ b/plugins/quantum_computing/CMakeLists.txt @@ -1,15 +1,2 @@ -set(PLUGIN_NAME quantum_computing) - -list(APPEND client_HEADERS - QuantumCircuit.h) - -list(APPEND client_LIB_INCLUDES - QuantumCircuit.cpp) - -add_library(${PLUGIN_NAME} SHARED ${client_LIB_INCLUDES}) - -target_include_directories(${PLUGIN_NAME} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR} - ) -target_link_libraries(${PLUGIN_NAME} PUBLIC core) -set_property(TARGET ${PLUGIN_NAME} PROPERTY FOLDER plugins) \ No newline at end of file +add_subdirectory(src) +add_subdirectory(test) diff --git a/plugins/quantum_computing/src/BlochSphere.cpp b/plugins/quantum_computing/src/BlochSphere.cpp new file mode 100644 index 0000000..ff9d594 --- /dev/null +++ b/plugins/quantum_computing/src/BlochSphere.cpp @@ -0,0 +1,12 @@ +#include "BlochSphere.h" + +BlochSphere::BlochSphere(const Qubit& state) + : mState(state) +{ + +} + +const Qubit& BlochSphere::getState() const +{ + return mState; +} \ No newline at end of file diff --git a/plugins/quantum_computing/src/BlochSphere.h b/plugins/quantum_computing/src/BlochSphere.h new file mode 100644 index 0000000..ae76aa4 --- /dev/null +++ b/plugins/quantum_computing/src/BlochSphere.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Qubit.h" + +class BlochSphere +{ +public: + BlochSphere(const Qubit& state); + + const Qubit& getState() const; +private: + Qubit mState; +}; \ No newline at end of file diff --git a/plugins/quantum_computing/src/CMakeLists.txt b/plugins/quantum_computing/src/CMakeLists.txt new file mode 100644 index 0000000..fcc16cf --- /dev/null +++ b/plugins/quantum_computing/src/CMakeLists.txt @@ -0,0 +1,30 @@ +set(PLUGIN_NAME quantum_computing) + +list(APPEND quantum_computing_HEADERS + QuantumCircuit.h + BlochSphere.h + QuantumState.h + Qubit.h + QuantumGate.h + QuantumOperator.h + visuals/BlochSphereNode.h +) + +list(APPEND quantum_computing_LIB_INCLUDES + QuantumCircuit.cpp + BlochSphere.cpp + QuantumState.cpp + Qubit.cpp + QuantumGate.cpp + QuantumOperator.cpp + visuals/BlochSphereNode.cpp +) + +add_library(${PLUGIN_NAME} SHARED ${quantum_computing_LIB_INCLUDES} ${quantum_computing_HEADERS}) + +target_include_directories(${PLUGIN_NAME} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/visuals + ) +target_link_libraries(${PLUGIN_NAME} PUBLIC core visual_elements ntk_math) +set_property(TARGET ${PLUGIN_NAME} PROPERTY FOLDER plugins) \ No newline at end of file diff --git a/plugins/quantum_computing/QuantumCircuit.cpp b/plugins/quantum_computing/src/QuantumCircuit.cpp similarity index 100% rename from plugins/quantum_computing/QuantumCircuit.cpp rename to plugins/quantum_computing/src/QuantumCircuit.cpp diff --git a/plugins/quantum_computing/QuantumCircuit.h b/plugins/quantum_computing/src/QuantumCircuit.h similarity index 100% rename from plugins/quantum_computing/QuantumCircuit.h rename to plugins/quantum_computing/src/QuantumCircuit.h diff --git a/plugins/quantum_computing/src/QuantumGate.cpp b/plugins/quantum_computing/src/QuantumGate.cpp new file mode 100644 index 0000000..e69de29 diff --git a/plugins/quantum_computing/src/QuantumGate.h b/plugins/quantum_computing/src/QuantumGate.h new file mode 100644 index 0000000..e69de29 diff --git a/plugins/quantum_computing/src/QuantumOperator.cpp b/plugins/quantum_computing/src/QuantumOperator.cpp new file mode 100644 index 0000000..e69de29 diff --git a/plugins/quantum_computing/src/QuantumOperator.h b/plugins/quantum_computing/src/QuantumOperator.h new file mode 100644 index 0000000..e69de29 diff --git a/plugins/quantum_computing/src/QuantumState.cpp b/plugins/quantum_computing/src/QuantumState.cpp new file mode 100644 index 0000000..e69de29 diff --git a/plugins/quantum_computing/src/QuantumState.h b/plugins/quantum_computing/src/QuantumState.h new file mode 100644 index 0000000..e69de29 diff --git a/plugins/quantum_computing/src/Qubit.cpp b/plugins/quantum_computing/src/Qubit.cpp new file mode 100644 index 0000000..3d7ae1f --- /dev/null +++ b/plugins/quantum_computing/src/Qubit.cpp @@ -0,0 +1,18 @@ +#include "Qubit.h" + +Qubit::Qubit(const ComplexNumber& alpha, const ComplexNumber& beta) + : mAlpha(alpha), + mBeta(beta) +{ + +} + +const ComplexNumber& Qubit::getAlpha() const +{ + return mAlpha; +} + +const ComplexNumber& Qubit::getBeta() const +{ + return mBeta; +} \ No newline at end of file diff --git a/plugins/quantum_computing/src/Qubit.h b/plugins/quantum_computing/src/Qubit.h new file mode 100644 index 0000000..4211dda --- /dev/null +++ b/plugins/quantum_computing/src/Qubit.h @@ -0,0 +1,16 @@ +#pragma once + +#include "ComplexNumber.h" + +class Qubit +{ +public: + Qubit(const ComplexNumber& alpha, const ComplexNumber& beta); + + const ComplexNumber& getAlpha() const; + + const ComplexNumber& getBeta() const; +private: + ComplexNumber mAlpha; + ComplexNumber mBeta; +}; \ No newline at end of file diff --git a/plugins/quantum_computing/src/visuals/BlochSphereNode.cpp b/plugins/quantum_computing/src/visuals/BlochSphereNode.cpp new file mode 100644 index 0000000..8b75d1f --- /dev/null +++ b/plugins/quantum_computing/src/visuals/BlochSphereNode.cpp @@ -0,0 +1,40 @@ +#include "BlochSphereNode.h" + +#include "CircleNode.h" + +BlochSphereNode::BlochSphereNode(const DiscretePoint& location) + : AbstractVisualNode(location, "BlochSphereNode") +{ + +} + +void BlochSphereNode::setContent(BlochSphere* content) +{ + mContent = content; + mContentDirty = true; +} + +void BlochSphereNode::setSize(double size) +{ + if (size != mSize) + { + mSize = size; + mContentDirty = true; + } +} + +void BlochSphereNode::update(FontsManager* fontsManager) +{ + if (!mContentDirty) + { + return; + } + + mChildren.clear(); + + auto loc = DiscretePoint(mSize / 2.0, mSize / 2.0); + mOuterCircle = std::make_unique(loc, mSize/2.0); + + addChild(mOuterCircle.get()); + +} \ No newline at end of file diff --git a/plugins/quantum_computing/src/visuals/BlochSphereNode.h b/plugins/quantum_computing/src/visuals/BlochSphereNode.h new file mode 100644 index 0000000..7d3fb02 --- /dev/null +++ b/plugins/quantum_computing/src/visuals/BlochSphereNode.h @@ -0,0 +1,34 @@ +#pragma once + +#include "AbstractVisualNode.h" + +#include + +class BlochSphere; +class CircleNode; +class LineNode; + +class BlochSphereNode : public AbstractVisualNode +{ +public: + BlochSphereNode(const DiscretePoint& location); + + void setContent(BlochSphere* content); + + void update(FontsManager* fontsManager) override; + + void setSize(double size); +private: + double mSize{ 1.0 }; + bool mContentDirty{ true }; + BlochSphere* mContent{ nullptr }; + + std::unique_ptr mOuterCircle; + std::unique_ptr mInnerCircle; + std::unique_ptr mCentreCircle; + std::unique_ptr mStateMarkerCircle; + std::unique_ptr mXAxis; + std::unique_ptr mYAxis; + std::unique_ptr mZAxis; + std::unique_ptr mStateVector; +}; \ No newline at end of file diff --git a/plugins/quantum_computing/test/CMakeLists.txt b/plugins/quantum_computing/test/CMakeLists.txt new file mode 100644 index 0000000..2d117c6 --- /dev/null +++ b/plugins/quantum_computing/test/CMakeLists.txt @@ -0,0 +1,8 @@ + +list(APPEND UNIT_TEST_FILES + TestBlochSphereNode.cpp +) + +add_executable(quantum_computing_unit_tests ${CMAKE_SOURCE_DIR}/test/test_runner.cpp ${UNIT_TEST_FILES}) +target_link_libraries(quantum_computing_unit_tests PUBLIC test_utils quantum_computing) +set_property(TARGET quantum_computing_unit_tests PROPERTY FOLDER plugins) \ No newline at end of file diff --git a/plugins/quantum_computing/test/TestBlochSphereNode.cpp b/plugins/quantum_computing/test/TestBlochSphereNode.cpp new file mode 100644 index 0000000..564fd02 --- /dev/null +++ b/plugins/quantum_computing/test/TestBlochSphereNode.cpp @@ -0,0 +1,35 @@ +#include "TestFramework.h" +#include "TestUtils.h" + +#include "BlochSphereNode.h" +#include "BlochSphere.h" +#include "Scene.h" + +#include "SvgConverter.h" +#include "SvgWriter.h" + +#include "File.h" + +TEST_CASE(TestBlochSphereNode, "quantum_computing") +{ + auto node = std::make_unique(); + + Qubit state({ 1.0, 0.0 }, { 0.0, 0.0 }); + + auto bloch_sphere = std::make_unique(state); + + node->setContent(bloch_sphere.get()); + + auto scene = std::make_unique(); + scene->addNode(node.get()); + scene->update(); + + SvgConverter converter; + auto svg_document = converter.convert(scene.get()); + + SvgWriter writer; + auto svg_content = writer.toString(svg_document.get()); + + File svg_file(TestUtils::getTestOutputDir(__FILE__) / "bloch_sphere.svg"); + svg_file.writeText(svg_content); +} \ No newline at end of file diff --git a/plugins/quantum_computing/test/TestBlochSphereNode.h b/plugins/quantum_computing/test/TestBlochSphereNode.h new file mode 100644 index 0000000..e69de29 diff --git a/src/core/AbstractWebApp.h b/src/core/AbstractWebApp.h new file mode 100644 index 0000000..9e487b5 --- /dev/null +++ b/src/core/AbstractWebApp.h @@ -0,0 +1,12 @@ +#pragma once + +#include "AbstractApp.h" + +class HttpRequest; +class HttpResponse; + +class AbstractWebApp : public AbstractApp +{ +public: + virtual HttpResponse onHttpRequest(const HttpRequest& request) = 0; +}; \ No newline at end of file diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 2d78edb..44b7916 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -2,6 +2,7 @@ set(MODULE_NAME core) list(APPEND core_HEADERS AbstractApp.h + AbstractWebApp.h Dictionary.h Event.h Color.h diff --git a/src/core/http/HttpRequest.cpp b/src/core/http/HttpRequest.cpp index 29d863c..c16d93d 100644 --- a/src/core/http/HttpRequest.cpp +++ b/src/core/http/HttpRequest.cpp @@ -4,6 +4,23 @@ #include +HttpRequest::HttpRequest(Verb verb, const std::string& path) + : mVerb(verb), + mPath(path) +{ + +} + +HttpRequest::Verb HttpRequest::getVerb() const +{ + return mVerb; +} + +std::string HttpRequest::getPath() const +{ + return mPath; +} + void HttpRequest::parseMessage(const std::string& message) { std::stringstream ss(message); diff --git a/src/core/http/HttpRequest.h b/src/core/http/HttpRequest.h index 4630ddf..7acd501 100644 --- a/src/core/http/HttpRequest.h +++ b/src/core/http/HttpRequest.h @@ -7,13 +7,31 @@ class HttpRequest { public: + + enum class Verb + { + GET, + PUT, + POST, + PATCH, + _DELETE, + UNKNOWN + }; + HttpRequest() = default; + HttpRequest(Verb verb, const std::string& path); + + Verb getVerb() const; + + std::string getPath() const; + void parseMessage(const std::string& message); private: void parseFirstLine(const std::string& line); + Verb mVerb = Verb::UNKNOWN; HttpHeader mHeader; std::string mMethod; std::string mPath; diff --git a/src/core/http/HttpResponse.cpp b/src/core/http/HttpResponse.cpp index 8b4dee2..ac904fe 100644 --- a/src/core/http/HttpResponse.cpp +++ b/src/core/http/HttpResponse.cpp @@ -1,10 +1,11 @@ #include "HttpResponse.h" HttpResponse::HttpResponse() - :mHttpVersion("1.1"), - mResponseCode("200 OK"), - mContentType("text/plain"), - mBody() + : mHttpVersion("1.1"), + mStatusCode(200), + mResponseReason("OK"), + mContentType("text/plain"), + mBody() { } @@ -14,25 +15,40 @@ HttpResponse::~HttpResponse() } -void HttpResponse::SetBody(const std::string& body) +unsigned short HttpResponse::getStatusCode() const +{ + return mStatusCode; +} + +const std::string& HttpResponse::getBody() const +{ + return mBody; +} + +void HttpResponse::setBody(const std::string& body) { mBody = body; } -unsigned HttpResponse::GetBodyLength() const +unsigned HttpResponse::getBodyLength() const { return unsigned(mBody.length()); } -std::string HttpResponse::GetHeaderString() const +std::string HttpResponse::getHeaderString() const { - std::string header = "HTTP/" + mHttpVersion + " " + mResponseCode + "\n"; + std::string header = "HTTP/" + mHttpVersion + " " + std::to_string(mStatusCode) + " " + mResponseReason + "\n"; header += "Content-Type: " + mContentType + "\n"; - header += "Content-Length: " + std::to_string(GetBodyLength()) + "\n"; + header += "Content-Length: " + std::to_string(getBodyLength()) + "\n"; return header; } -std::string HttpResponse::ToString() const +std::string HttpResponse::getResponseReason() const { - return GetHeaderString() + "\n\n" + mBody; + return mResponseReason; +} + +std::string HttpResponse::toString() const +{ + return getHeaderString() + "\n\n" + mBody; } diff --git a/src/core/http/HttpResponse.h b/src/core/http/HttpResponse.h index 5b75fad..0dd2675 100644 --- a/src/core/http/HttpResponse.h +++ b/src/core/http/HttpResponse.h @@ -9,17 +9,25 @@ public: ~HttpResponse(); - void SetBody(const std::string& body); + void setBody(const std::string& body); - unsigned GetBodyLength() const; + unsigned getBodyLength() const; - std::string GetHeaderString() const; + const std::string& getBody() const; - std::string ToString() const; + std::string getHeaderString() const; + + std::string toString() const; + + unsigned short getStatusCode() const; + + std::string getResponseReason() const; private: + unsigned short mStatusCode{ 200 }; + std::string mResponseReason{ }; + std::string mHttpVersion; - std::string mResponseCode; std::string mContentType; std::string mBody; }; diff --git a/src/geometry/CMakeLists.txt b/src/geometry/CMakeLists.txt index 09c4664..8b0cbf8 100644 --- a/src/geometry/CMakeLists.txt +++ b/src/geometry/CMakeLists.txt @@ -11,6 +11,8 @@ list(APPEND geometry_LIB_INCLUDES Linalg.cpp Line.cpp LineSegment.cpp + Matrix.h + Matrix.cpp Path.h Path.cpp Point.h @@ -28,8 +30,7 @@ list(APPEND geometry_LIB_INCLUDES # add the library add_library(geometry SHARED ${geometry_LIB_INCLUDES}) -target_include_directories(geometry PUBLIC - "${CMAKE_CURRENT_SOURCE_DIR}") +target_include_directories(geometry PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") set_target_properties( geometry PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON ) set_property(TARGET geometry PROPERTY FOLDER src) diff --git a/src/geometry/Matrix.cpp b/src/geometry/Matrix.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/geometry/Matrix.h b/src/geometry/Matrix.h new file mode 100644 index 0000000..e69de29 diff --git a/src/network/CMakeLists.txt b/src/network/CMakeLists.txt index 7705d3d..60bdfe6 100644 --- a/src/network/CMakeLists.txt +++ b/src/network/CMakeLists.txt @@ -7,7 +7,16 @@ list(APPEND platform_INCLUDES else() list(APPEND platform_INCLUDES server/win32/Win32WebServer.h - server/win32/Win32WebServer.cpp) + server/win32/Win32WebServer.cpp + server/win32/Win32TempFile.h + server/win32/Win32TempFile.cpp + server/win32/Win32WebRequest.h + server/win32/Win32WebRequest.cpp + server/win32/Win32WebResponse.h + server/win32/Win32WebResponse.cpp + server/win32/Win32Buffer.h + server/win32/Win32Buffer.cpp + ) list(APPEND platform_LIBS Httpapi.lib) endif() diff --git a/src/network/server/win32/Win32Buffer.cpp b/src/network/server/win32/Win32Buffer.cpp new file mode 100644 index 0000000..0588160 --- /dev/null +++ b/src/network/server/win32/Win32Buffer.cpp @@ -0,0 +1,63 @@ +#include "Win32Buffer.h" + +#include "FileLogger.h" + +#ifndef UNICODE +#define UNICODE +#endif + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include + +Win32Buffer::Win32Buffer(unsigned size) +{ + createBuffer(size); +} + +Win32Buffer::~Win32Buffer() +{ + clearBuffer(); +} + +PUCHAR Win32Buffer::getBufferAsUChar() const +{ + return reinterpret_cast(mBuffer); +} + +void* Win32Buffer::getBuffer() const +{ + return mBuffer; +} + +bool Win32Buffer::isValid() const +{ + return mIsValid; +} + +void Win32Buffer::createBuffer(unsigned size) +{ + mIsValid = false; + mBuffer = ::HeapAlloc(::GetProcessHeap(), 0, size); + if (mBuffer == nullptr) + { + MLOG_ERROR("Insufficient resources"); + return; + } + mIsValid = true; +} + +void Win32Buffer::clearBuffer() +{ + if (mBuffer) + { + ::HeapFree(::GetProcessHeap(), 0, mBuffer); + } +} + +void Win32Buffer::reset(unsigned size) +{ + clearBuffer(); + createBuffer(size); +} \ No newline at end of file diff --git a/src/network/server/win32/Win32Buffer.h b/src/network/server/win32/Win32Buffer.h new file mode 100644 index 0000000..142e02c --- /dev/null +++ b/src/network/server/win32/Win32Buffer.h @@ -0,0 +1,24 @@ +#pragma once + +class Win32Buffer +{ +public: + Win32Buffer(unsigned size); + + ~Win32Buffer(); + + void* getBuffer() const; + + PUCHAR getBufferAsUChar() const; + + bool isValid() const; + + void reset(unsigned size); + +private: + void createBuffer(unsigned size); + void clearBuffer(); + + bool mIsValid{ false }; + void* mBuffer{ nullptr }; +}; \ No newline at end of file diff --git a/src/network/server/win32/Win32TempFile.cpp b/src/network/server/win32/Win32TempFile.cpp new file mode 100644 index 0000000..b8f36b0 --- /dev/null +++ b/src/network/server/win32/Win32TempFile.cpp @@ -0,0 +1,53 @@ +#include "Win32TempFile.h" + +#include "FileLogger.h" + +Win32TempFile::Win32TempFile() +{ + if (::GetTempFileName(L".", L"New", 0, &mName[0]) == 0) + { + auto result = ::GetLastError(); + MLOG_ERROR("Failed to set up temp file for buffer with: " << result); + return; + } + + mHandle = ::CreateFile(&mName[0], GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (mHandle == INVALID_HANDLE_VALUE) + { + auto result = ::GetLastError(); + MLOG_ERROR("Failed to create temp file for buffer with: " << result); + return; + } + mIsValid = true; + return; +} + +Win32TempFile::~Win32TempFile() +{ + if (INVALID_HANDLE_VALUE != mHandle) + { + ::CloseHandle(mHandle); + ::DeleteFile(&mName[0]); + } +} + +void Win32TempFile::write(PUCHAR buffer, ULONG size) +{ + if (!mIsValid) + { + return; + } + + ULONG temp_file_bytes_written = 0; + ::WriteFile(mHandle, buffer, size, &temp_file_bytes_written, nullptr); +} + +HANDLE Win32TempFile::getHandle() const +{ + return mHandle; +} + +bool Win32TempFile::isValid() const +{ + return mIsValid; +} \ No newline at end of file diff --git a/src/network/server/win32/Win32TempFile.h b/src/network/server/win32/Win32TempFile.h new file mode 100644 index 0000000..4ebdf54 --- /dev/null +++ b/src/network/server/win32/Win32TempFile.h @@ -0,0 +1,31 @@ +#pragma once + +#ifndef UNICODE +#define UNICODE +#endif + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include + +#include + +class Win32TempFile +{ +public: + Win32TempFile(); + + ~Win32TempFile(); + + bool isValid() const; + + HANDLE getHandle() const; + + void write(PUCHAR buffer, ULONG size); + +private: + bool mIsValid{ false }; + std::wstring mName; + HANDLE mHandle{ 0 }; +}; \ No newline at end of file diff --git a/src/network/server/win32/Win32WebRequest.cpp b/src/network/server/win32/Win32WebRequest.cpp new file mode 100644 index 0000000..fe6f437 --- /dev/null +++ b/src/network/server/win32/Win32WebRequest.cpp @@ -0,0 +1,67 @@ +#include "Win32WebRequest.h" + +#include "StringUtils.h" +#include "HttpRequest.h" + +Win32WebRequest::Win32WebRequest() + : mBuffer(DEFAULT_BUFFER_SIZE) +{ + mIsValid = mBuffer.isValid(); + mHandle = reinterpret_cast(mBuffer.getBuffer()); +} + +bool Win32WebRequest::isValid() const +{ + return mIsValid; +} + +void Win32WebRequest::zeroBufferMemory() +{ + ::RtlZeroMemory(mHandle, mWorkingBufferSize); +} + +PHTTP_REQUEST Win32WebRequest::getHandle() const +{ + return mHandle; +} + +unsigned Win32WebRequest::getBufferSize() const +{ + return mWorkingBufferSize; +} + +void Win32WebRequest::resizeBuffer(unsigned size) +{ + mWorkingBufferSize = size; + mBuffer.reset(mWorkingBufferSize); + if (!mBuffer.isValid()) + { + mIsValid = false; + return; + } + mHandle = reinterpret_cast(mBuffer.getBuffer()); +} + +std::string Win32WebRequest::getUrlFromRequest() const +{ + const std::wstring wide_url = mHandle->CookedUrl.pFullUrl; + return StringUtils::convert(wide_url); +} + +HttpRequest Win32WebRequest::getRequest() const +{ + HttpRequest::Verb verb; + switch (mHandle->Verb) + { + case HttpVerbGET: + verb = HttpRequest::Verb::GET; + case HttpVerbPOST: + verb = HttpRequest::Verb::POST; + default: + verb = HttpRequest::Verb::UNKNOWN; + break; + } + + HttpRequest request(verb, getUrlFromRequest()); + return request; +} \ No newline at end of file diff --git a/src/network/server/win32/Win32WebRequest.h b/src/network/server/win32/Win32WebRequest.h new file mode 100644 index 0000000..745cb46 --- /dev/null +++ b/src/network/server/win32/Win32WebRequest.h @@ -0,0 +1,50 @@ +#pragma once +#ifndef UNICODE +#define UNICODE +#endif + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include + +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0600 +#endif +#include + +#include + +#include "Win32Buffer.h" + +class HttpRequest; + +class Win32WebRequest +{ +public: + Win32WebRequest(); + + bool isValid() const; + + PHTTP_REQUEST getHandle() const; + + unsigned getBufferSize() const; + + void resizeBuffer(unsigned size); + + void zeroBufferMemory(); + + HttpRequest getRequest() const; + +private: + std::string getUrlFromRequest() const; + + + static const unsigned DEFAULT_BUFFER_SIZE{ sizeof(HTTP_REQUEST) + 2048 }; + Win32Buffer mBuffer; + bool mIsValid{ false }; + + unsigned mWorkingBufferSize{ DEFAULT_BUFFER_SIZE }; + PHTTP_REQUEST mHandle{ nullptr }; +}; + diff --git a/src/network/server/win32/Win32WebResponse.cpp b/src/network/server/win32/Win32WebResponse.cpp new file mode 100644 index 0000000..be29164 --- /dev/null +++ b/src/network/server/win32/Win32WebResponse.cpp @@ -0,0 +1,34 @@ +#include "Win32WebResponse.h" + +#include "HttpResponse.h" + +Win32WebResponse::Win32WebResponse(const HttpResponse& response) +{ + RtlZeroMemory((&mResponse), sizeof(*(&mResponse))); + mResponse.StatusCode = response.getStatusCode(); + + std::string reason = response.getResponseReason(); + mResponse.pReason = reason.c_str(); + mResponse.ReasonLength = (USHORT)strlen(reason.c_str()); + + const std::string content_type = "text / html"; + mResponse.Headers.KnownHeaders[HttpHeaderContentType].pRawValue = content_type.c_str(); + mResponse.Headers.KnownHeaders[HttpHeaderContentType].RawValueLength = (USHORT)strlen(content_type.c_str()); + + auto body = response.getBody(); + if (!body.empty()) + { + HTTP_DATA_CHUNK dataChunk; + dataChunk.DataChunkType = HttpDataChunkFromMemory; + dataChunk.FromMemory.pBuffer = body.data(); + dataChunk.FromMemory.BufferLength = (ULONG)strlen(body.data()); + + mResponse.EntityChunkCount = 1; + mResponse.pEntityChunks = &dataChunk; + } +} + +HTTP_RESPONSE& Win32WebResponse::getResponse() +{ + return mResponse; +} \ No newline at end of file diff --git a/src/network/server/win32/Win32WebResponse.h b/src/network/server/win32/Win32WebResponse.h new file mode 100644 index 0000000..16c6831 --- /dev/null +++ b/src/network/server/win32/Win32WebResponse.h @@ -0,0 +1,30 @@ +#pragma once + +#ifndef UNICODE +#define UNICODE +#endif + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include + +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0600 +#endif +#include + +#include + +class HttpResponse; + +class Win32WebResponse +{ +public: + Win32WebResponse(const HttpResponse& response); + + HTTP_RESPONSE& getResponse(); + +private: + HTTP_RESPONSE mResponse; +}; \ No newline at end of file diff --git a/src/network/server/win32/Win32WebServer.cpp b/src/network/server/win32/Win32WebServer.cpp index da438ea..b36ff75 100644 --- a/src/network/server/win32/Win32WebServer.cpp +++ b/src/network/server/win32/Win32WebServer.cpp @@ -1,10 +1,19 @@ #include "Win32WebServer.h" +#include "Win32TempFile.h" +#include "Win32Buffer.h" +#include "Win32WebResponse.h" +#include "Win32WebRequest.h" + +#include "AbstractWebApp.h" +#include "HttpRequest.h" +#include "HttpResponse.h" #include "FileLogger.h" #include "StringUtils.h" -Win32WebServer::Win32WebServer() - : mListenUrl("http://localhost:80/49152") +Win32WebServer::Win32WebServer(AbstractWebApp* webApp) + : mListenUrl("http://localhost:80/49152"), + mWebApp(webApp) { } @@ -55,313 +64,45 @@ void Win32WebServer::initialize() } } -void Win32WebServer::onRequest(PHTTP_REQUEST request) +DWORD Win32WebServer::onRequest(const Win32WebRequest& request) { - const std::wstring wide_url = request->CookedUrl.pFullUrl; - const auto url = StringUtils::convert(wide_url); + auto app_request = request.getRequest(); + auto response = mWebApp->onHttpRequest(app_request); - switch (request->Verb) + DWORD result; + if (app_request.getVerb() == HttpRequest::Verb::POST) { + result = sendHttpPostResponse(request.getHandle()); + } + else + { + result = sendHttpResponse(request.getHandle(), response); + } + + /* case HttpVerbGET: MLOG_INFO("Got a GET request for: " << url); - auto result = sendHttpResponse(request, 200, "OK", "Hey! You hit the server \r\n"); + result = sendHttpResponse(request, 200, "OK", "Hey! You hit the server \r\n"); break; case HttpVerbPOST: MLOG_INFO("Got a POST request for: " << url); result = sendHttpPostResponse(request); break; - default: MLOG_INFO("Got an unknown request for: " << url); result = sendHttpResponse(request, 503, "Not Implemented"); break; - } -} - -void Win32WebServer::initializeHttpResponse(HTTP_RESPONSE& response, USHORT StatusCode, const std::string& reason) -{ - RtlZeroMemory((&response), sizeof(*(&response))); - response.StatusCode = StatusCode; - response.pReason = reason.c_str(); - response.ReasonLength = (USHORT)strlen(reason.c_str()); -} - -#define MAX_ULONG_STR ((ULONG) sizeof("4294967295")) - -DWORD Win32WebServer::sendHttpPostResponse(PHTTP_REQUEST pRequest) -{ - DWORD result; - auto hTempFile = INVALID_HANDLE_VALUE; - - // Allocate space for an entity buffer. Buffer can be increased on demand. - ULONG EntityBufferLength = 2048; - PUCHAR pEntityBuffer = reinterpret_cast(::HeapAlloc(::GetProcessHeap(), 0, (EntityBufferLength))); - if (pEntityBuffer == nullptr) - { - result = ERROR_NOT_ENOUGH_MEMORY; - MLOG_ERROR("Insufficient resources"); - return result; - } - - HTTP_RESPONSE response; - initializeHttpResponse(response, 200, "OK"); - - if (pRequest->Flags & HTTP_REQUEST_FLAG_MORE_ENTITY_BODY_EXISTS) - { - // The entity body is sent over multiple calls. Collect these in a file and send back. Create a temporary file. - TCHAR szTempName[MAX_PATH + 1]; - if (::GetTempFileName(L".", L"New", 0, szTempName) == 0) - { - result = ::GetLastError(); - MLOG_ERROR("Failed to set up temp file for buffer with: " << result); - if (pEntityBuffer) - { - HeapFree(GetProcessHeap(), 0, (pEntityBuffer)); - } - return result; - } - - hTempFile = CreateFile(szTempName, GENERIC_READ | GENERIC_WRITE, - 0, // Do not share. - NULL, // No security descriptor. - CREATE_ALWAYS, // Overrwrite existing. - FILE_ATTRIBUTE_NORMAL, // Normal file. - NULL - ); - if (hTempFile == INVALID_HANDLE_VALUE) - { - result = GetLastError(); - MLOG_ERROR("Failed to create temp file for buffer with: " << result); - if (pEntityBuffer) - { - HeapFree(GetProcessHeap(), 0, (pEntityBuffer)); - } - return result; - } - - DWORD bytesSent; - ULONG TempFileBytesWritten; - CHAR szContentLength[MAX_ULONG_STR]; - HTTP_DATA_CHUNK dataChunk; - - ULONG TotalBytesRead = 0; - ULONG BytesRead = 0; - do - { - // Read the entity chunk from the request. - BytesRead = 0; - result = ::HttpReceiveRequestEntityBody(mWorkingQueue, pRequest->RequestId, 0, - pEntityBuffer, EntityBufferLength, &BytesRead, NULL); - - switch (result) - { - case NO_ERROR: - if (BytesRead != 0) - { - TotalBytesRead += BytesRead; - ::WriteFile(hTempFile, pEntityBuffer, BytesRead, &TempFileBytesWritten, NULL); - } - break; - case ERROR_HANDLE_EOF: - - // - // The last request entity body has been read. - // Send back a response. - // - // To illustrate entity sends via - // HttpSendResponseEntityBody, the response will - // be sent over multiple calls. To do this, - // pass the HTTP_SEND_RESPONSE_FLAG_MORE_DATA - // flag. - - if (BytesRead != 0) - { - TotalBytesRead += BytesRead; - WriteFile( - hTempFile, - pEntityBuffer, - BytesRead, - &TempFileBytesWritten, - NULL - ); - } - - // - // Because the response is sent over multiple - // API calls, add a content-length. - // - // Alternatively, the response could have been - // sent using chunked transfer encoding, by - // passimg "Transfer-Encoding: Chunked". - // - - // NOTE: Because the TotalBytesread in a ULONG - // are accumulated, this will not work - // for entity bodies larger than 4 GB. - // For support of large entity bodies, - // use a ULONGLONG. - // - - - sprintf_s(szContentLength, MAX_ULONG_STR, "%lu", TotalBytesRead); - - ADD_KNOWN_HEADER( - response, - HttpHeaderContentLength, - szContentLength - ); - - result = - HttpSendHttpResponse( - hReqQueue, // ReqQueueHandle - pRequest->RequestId, // Request ID - HTTP_SEND_RESPONSE_FLAG_MORE_DATA, - &response, // HTTP response - NULL, // pReserved1 - &bytesSent, // bytes sent-optional - NULL, // pReserved2 - 0, // Reserved3 - NULL, // LPOVERLAPPED - NULL // pReserved4 - ); - - if (result != NO_ERROR) - { - wprintf( - L"HttpSendHttpResponse failed with %lu \n", - result - ); - goto Done; - } - - // - // Send entity body from a file handle. - // - dataChunk.DataChunkType = - HttpDataChunkFromFileHandle; - - dataChunk.FromFileHandle. - ByteRange.StartingOffset.QuadPart = 0; - - dataChunk.FromFileHandle. - ByteRange.Length.QuadPart = - HTTP_BYTE_RANGE_TO_EOF; - - dataChunk.FromFileHandle.FileHandle = hTempFile; - - result = HttpSendResponseEntityBody( - hReqQueue, - pRequest->RequestId, - 0, // This is the last send. - 1, // Entity Chunk Count. - &dataChunk, - NULL, - NULL, - 0, - NULL, - NULL - ); - - if (result != NO_ERROR) - { - wprintf( - L"HttpSendResponseEntityBody failed %lu\n", - result - ); - } - - goto Done; - - break; - - - default: - wprintf( - L"HttpReceiveRequestEntityBody failed with %lu \n", - result); - goto Done; - } - - } while (TRUE); - } - else - { - // This request does not have an entity body. - // - - result = HttpSendHttpResponse( - hReqQueue, // ReqQueueHandle - pRequest->RequestId, // Request ID - 0, - &response, // HTTP response - NULL, // pReserved1 - &bytesSent, // bytes sent (optional) - NULL, // pReserved2 - 0, // Reserved3 - NULL, // LPOVERLAPPED - NULL // pReserved4 - ); - if (result != NO_ERROR) - { - wprintf(L"HttpSendHttpResponse failed with %lu \n", - result); - } - } - -Done: - - if (pEntityBuffer) - { - FREE_MEM(pEntityBuffer); - } - - if (INVALID_HANDLE_VALUE != hTempFile) - { - CloseHandle(hTempFile); - DeleteFile(szTempName); - } + */ return result; } -DWORD Win32WebServer::sendHttpResponse(PHTTP_REQUEST pRequest, USHORT StatusCode, const std::string& reason, const std::string& message) +DWORD Win32WebServer::sendHttpResponse(PHTTP_REQUEST pRequest, const HttpResponse& appResponse) { - HTTP_RESPONSE response; - RtlZeroMemory((&response), sizeof(*(&response))); - response.StatusCode = StatusCode; - response.pReason = reason.c_str(); - response.ReasonLength = (USHORT)strlen(reason.c_str()); - - const std::string content_type = "text / html"; - response.Headers.KnownHeaders[HttpHeaderContentType].pRawValue = content_type.c_str(); - response.Headers.KnownHeaders[HttpHeaderContentType].RawValueLength = (USHORT)strlen(content_type.c_str()); - - if (!message.empty()) - { - auto entity_string = message; - HTTP_DATA_CHUNK dataChunk; - dataChunk.DataChunkType = HttpDataChunkFromMemory; - dataChunk.FromMemory.pBuffer = entity_string.data(); - dataChunk.FromMemory.BufferLength = (ULONG)strlen(entity_string.data()); - - response.EntityChunkCount = 1; - response.pEntityChunks = &dataChunk; - } + Win32WebResponse response(appResponse); DWORD bytesSent; - DWORD result = ::HttpSendHttpResponse( - mWorkingQueue, // ReqQueueHandle - pRequest->RequestId, // Request ID - 0, // Flags - &response, // HTTP response - NULL, // pReserved1 - &bytesSent, // bytes sent (OPTIONAL) - NULL, // pReserved2 (must be NULL) - 0, // Reserved3 (must be 0) - NULL, // LPOVERLAPPED(OPTIONAL) - NULL // pReserved4 (must be NULL) - ); - + const auto result = ::HttpSendHttpResponse(mWorkingQueue, pRequest->RequestId, 0, &(response.getResponse()), NULL, &bytesSent, NULL, 0, NULL, NULL); if (result != NO_ERROR) { MLOG_ERROR("Http response failed with error: " << result); @@ -369,136 +110,155 @@ DWORD Win32WebServer::sendHttpResponse(PHTTP_REQUEST pRequest, USHORT StatusCode return result; } +#define MAX_ULONG_STR ((ULONG) sizeof("4294967295")) + +DWORD Win32WebServer::sendHttpPostResponse(PHTTP_REQUEST pRequest) +{ + // Allocate space for an entity buffer. Buffer can be increased on demand. + const ULONG entity_buffer_length = 2048; + + Win32Buffer entity_buffer(entity_buffer_length); + if (!entity_buffer.isValid()) + { + return ERROR_NOT_ENOUGH_MEMORY; + } + + HTTP_RESPONSE response; + initializeHttpResponse(response, 200, "OK"); + + DWORD result{ 0 }; + if (pRequest->Flags & HTTP_REQUEST_FLAG_MORE_ENTITY_BODY_EXISTS) + { + Win32TempFile temp_file; + if (!temp_file.isValid()) + { + return 0; + } + + ULONG total_bytes_read = 0; + ULONG bytes_read = 0; + do + { + // Read the entity chunk from the request. + bytes_read = 0; + result = ::HttpReceiveRequestEntityBody(mWorkingQueue, pRequest->RequestId, 0, entity_buffer.getBuffer(), entity_buffer_length, &bytes_read, nullptr); + + switch (result) + { + case NO_ERROR: + if (bytes_read != 0) + { + total_bytes_read += bytes_read; + temp_file.write(entity_buffer.getBufferAsUChar(), bytes_read); + } + break; + case ERROR_HANDLE_EOF: + // The last request entity body has been read. Send back a response. + // + // To illustrate entity sends via HttpSendResponseEntityBody, the response will + // be sent over multiple calls. To do this, pass the HTTP_SEND_RESPONSE_FLAG_MORE_DATA flag. + + if (bytes_read != 0) + { + total_bytes_read += bytes_read; + temp_file.write(entity_buffer.getBufferAsUChar(), bytes_read); + } + + // Because the response is sent over multiple API calls, add a content-length. + // Alternatively, the response could have been sent using chunked transfer encoding, by passimg "Transfer-Encoding: Chunked". + // NOTE: Because the TotalBytesread in a ULONG are accumulated, this will not work for entity bodies larger than 4 GB. + // For support of large entity bodies, use a ULONGLONG. + CHAR szContentLength[MAX_ULONG_STR]; + sprintf_s(szContentLength, MAX_ULONG_STR, "%lu", total_bytes_read); + response.Headers.KnownHeaders[HttpHeaderContentLength].pRawValue = szContentLength; + response.Headers.KnownHeaders[HttpHeaderContentLength].RawValueLength = (USHORT)strlen(szContentLength); + + DWORD bytesSent; + result = ::HttpSendHttpResponse(mWorkingQueue, pRequest->RequestId, HTTP_SEND_RESPONSE_FLAG_MORE_DATA, &response, NULL, &bytesSent, NULL, 0, NULL, NULL); + if (result != NO_ERROR) + { + MLOG_ERROR("HttpSendHttpResponse failed with: " << result); + return; + } + + // Send entity body from a file handle. + HTTP_DATA_CHUNK dataChunk; + dataChunk.DataChunkType = HttpDataChunkFromFileHandle; + dataChunk.FromFileHandle.ByteRange.StartingOffset.QuadPart = 0; + dataChunk.FromFileHandle.ByteRange.Length.QuadPart = HTTP_BYTE_RANGE_TO_EOF; + dataChunk.FromFileHandle.FileHandle = temp_file.getHandle(); + + result = ::HttpSendResponseEntityBody(mWorkingQueue, pRequest->RequestId, 0, 1, &dataChunk, NULL, NULL, 0, NULL, NULL); + if (result != NO_ERROR) + { + MLOG_ERROR("HttpSendResponseEntityBody failed" << result); + } + break; + default: + MLOG_ERROR("HttpReceiveRequestEntityBody failed with: " << result); + break; + } + + } while (true); + } + else + { + DWORD bytesSent; + result = ::HttpSendHttpResponse(mWorkingQueue, pRequest->RequestId, 0, &response, NULL, &bytesSent, NULL, 0, NULL, NULL ); + if (result != NO_ERROR) + { + MLOG_ERROR("HttpSendHttpResponse failed with: " << result); + } + } + return result; +} + void Win32WebServer::run() { - // Allocate a 2 KB buffer. This size should work for most - // requests. The buffer size can be increased if required. Space - // is also required for an HTTP_REQUEST structure. - ULONG RequestBufferLength = sizeof(HTTP_REQUEST) + 2048; - PCHAR pRequestBuffer = reinterpret_cast(::HeapAlloc(::GetProcessHeap(), 0, (RequestBufferLength))); - if (pRequestBuffer == nullptr) + Win32WebRequest request; + if (!request.isValid()) { MLOG_ERROR("Failed to allocate http request buffer"); return; } - PHTTP_REQUEST pRequest = (PHTTP_REQUEST)pRequestBuffer; - // Wait for a new request. This is indicated by a NULL - // request ID. - HTTP_REQUEST_ID requestId; - HTTP_SET_NULL_ID(&requestId); + HTTP_REQUEST_ID request_id; + HTTP_SET_NULL_ID(&request_id); while(true) { - RtlZeroMemory(pRequest, RequestBufferLength); - - DWORD bytesRead; - ULONG result = ::HttpReceiveHttpRequest( - mWorkingQueue, // Req Queue - requestId, // Req ID - 0, // Flags - pRequest, // HTTP request buffer - RequestBufferLength,// req buffer length - &bytesRead, // bytes received - nullptr // LPOVERLAPPED - ); + request.zeroBufferMemory(); + DWORD bytes_read; + auto result = ::HttpReceiveHttpRequest(mWorkingQueue, request_id, 0, request.getHandle(), request.getBufferSize(), &bytes_read, nullptr); if (NO_ERROR == result) { - switch (pRequest->Verb) - { - case HttpVerbGET: - wprintf(L"Got a GET request for %ws \n", - pRequest->CookedUrl.pFullUrl); - - result = SendHttpResponse( - hReqQueue, - pRequest, - 200, - "OK", - "Hey! You hit the server \r\n" - ); - break; - - case HttpVerbPOST: - - wprintf(L"Got a POST request for %ws \n", - pRequest->CookedUrl.pFullUrl); - - result = SendHttpPostResponse(hReqQueue, pRequest); - break; - - default: - wprintf(L"Got a unknown request for %ws \n", - pRequest->CookedUrl.pFullUrl); - - result = SendHttpResponse( - hReqQueue, - pRequest, - 503, - "Not Implemented", - NULL - ); - break; - } - + result = onRequest(request); if (result != NO_ERROR) { break; } - - // - // Reset the Request ID to handle the next request. - // - HTTP_SET_NULL_ID(&requestId); + HTTP_SET_NULL_ID(&request_id); } else if (result == ERROR_MORE_DATA) { - // - // The input buffer was too small to hold the request - // headers. Increase the buffer size and call the - // API again. - // - // When calling the API again, handle the request - // that failed by passing a RequestID. - // - // This RequestID is read from the old buffer. - // - requestId = pRequest->RequestId; + // The input buffer was too small to hold the request headers. Increase the buffer size and call the API again. + request_id = request.getHandle()->RequestId; - // - // Free the old buffer and allocate a new buffer. - // - RequestBufferLength = bytesRead; - FREE_MEM(pRequestBuffer); - pRequestBuffer = (PCHAR)ALLOC_MEM(RequestBufferLength); - - if (pRequestBuffer == NULL) + request.resizeBuffer(bytes_read); + if (!request.isValid()) { result = ERROR_NOT_ENOUGH_MEMORY; break; } - - pRequest = (PHTTP_REQUEST)pRequestBuffer; - } - else if (ERROR_CONNECTION_INVALID == result && - !HTTP_IS_NULL_ID(&requestId)) + else if (ERROR_CONNECTION_INVALID == result && !HTTP_IS_NULL_ID(&request_id)) { - // The TCP connection was corrupted by the peer when - // attempting to handle a request with more buffer. - // Continue to the next request. - - HTTP_SET_NULL_ID(&requestId); + // The TCP connection was corrupted by the peer when attempting to handle a request with more buffer. Continue to the next request. + HTTP_SET_NULL_ID(&request_id); } else { break; } - - } - - if (pRequestBuffer) - { - FREE_MEM(pRequestBuffer); } } \ No newline at end of file diff --git a/src/network/server/win32/Win32WebServer.h b/src/network/server/win32/Win32WebServer.h index 5641ce5..8aba70e 100644 --- a/src/network/server/win32/Win32WebServer.h +++ b/src/network/server/win32/Win32WebServer.h @@ -16,26 +16,31 @@ #include +class AbstractWebApp; +class Win32WebRequest; + +class HttpResponse; + class Win32WebServer { public: - Win32WebServer(); + Win32WebServer(AbstractWebApp* webApp); ~Win32WebServer(); - void initialize(); - void clear(); + void initialize(); + void run(); private: - void onRequest(PHTTP_REQUEST request); + DWORD onRequest(const Win32WebRequest& request); - DWORD sendHttpResponse(PHTTP_REQUEST pRequest, USHORT StatusCode, const std::string& reason, const std::string& message = {}); + DWORD sendHttpResponse(PHTTP_REQUEST pRequest, const HttpResponse& response); DWORD sendHttpPostResponse(PHTTP_REQUEST pRequest); - void initializeHttpResponse(HTTP_RESPONSE& response, USHORT StatusCode, const std::string& reason); + AbstractWebApp* mWebApp{ nullptr }; HANDLE mWorkingQueue{ 0 }; std::string mListenUrl; diff --git a/src/visual_elements/AbstractVisualNode.cpp b/src/visual_elements/AbstractVisualNode.cpp index 5b1bda9..7c1d9d9 100644 --- a/src/visual_elements/AbstractVisualNode.cpp +++ b/src/visual_elements/AbstractVisualNode.cpp @@ -44,7 +44,6 @@ const std::vector& AbstractVisualNode::getChildren() const void AbstractVisualNode::setIsVisible(bool isVisible) { - //std::cout << "Setting " << mName << " visibility to " << isVisible << std::endl; mIsVisible = isVisible; } diff --git a/src/visual_elements/CMakeLists.txt b/src/visual_elements/CMakeLists.txt index 49733ec..d329cae 100644 --- a/src/visual_elements/CMakeLists.txt +++ b/src/visual_elements/CMakeLists.txt @@ -2,8 +2,11 @@ set(MODULE_NAME visual_elements) list(APPEND visual_elements_LIB_INCLUDES GeometryNode.cpp + basic_shapes/RectangleNode.h basic_shapes/RectangleNode.cpp + basic_shapes/CircleNode.h basic_shapes/CircleNode.cpp + basic_shapes/LineNode.h basic_shapes/LineNode.cpp MaterialNode.cpp MeshNode.cpp @@ -14,6 +17,7 @@ list(APPEND visual_elements_LIB_INCLUDES SceneText.cpp Texture.cpp GridNode.cpp + AbstractVisualNode.h AbstractVisualNode.cpp )