Wayland example window
This commit is contained in:
parent
160b746182
commit
26f54c4581
30 changed files with 825 additions and 22 deletions
|
@ -20,8 +20,12 @@ list(APPEND core_LIB_INCLUDES
|
|||
file_utilities/BinaryFile.cpp
|
||||
file_utilities/File.cpp
|
||||
file_utilities/FileFormats.cpp
|
||||
memory/SharedMemory.cpp
|
||||
RandomUtils.cpp
|
||||
StringUtils.cpp
|
||||
http/HttpResponse.cpp)
|
||||
http/HttpResponse.cpp
|
||||
http/HttpHeader.cpp
|
||||
http/HttpRequest.cpp)
|
||||
|
||||
# add the executable
|
||||
add_library(core SHARED ${core_LIB_INCLUDES} ${core_HEADERS})
|
||||
|
@ -30,6 +34,7 @@ target_include_directories(core PUBLIC
|
|||
"${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/file_utilities"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/loggers"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/memory"
|
||||
)
|
||||
set_target_properties( core PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )
|
||||
set_property(TARGET core PROPERTY FOLDER src)
|
22
src/core/RandomUtils.cpp
Normal file
22
src/core/RandomUtils.cpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
#include "RandomUtils.h"
|
||||
|
||||
#include <random>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
std::vector<unsigned> RandomUtils::getRandomVecUnsigned(std::size_t size)
|
||||
{
|
||||
std::random_device rnd_device;
|
||||
|
||||
std::mt19937 mersenne_engine {rnd_device()};
|
||||
std::uniform_int_distribution<unsigned> dist {0, 9};
|
||||
|
||||
auto generator = [&dist, &mersenne_engine]()
|
||||
{
|
||||
return dist(mersenne_engine);
|
||||
};
|
||||
|
||||
std::vector<unsigned> vec(size);
|
||||
std::generate(std::begin(vec), std::end(vec), generator);
|
||||
return vec;
|
||||
}
|
10
src/core/RandomUtils.h
Normal file
10
src/core/RandomUtils.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
class RandomUtils
|
||||
{
|
||||
public:
|
||||
|
||||
static std::vector<unsigned> getRandomVecUnsigned(std::size_t size);
|
||||
};
|
|
@ -13,6 +13,7 @@ public:
|
|||
static constexpr char EQUALS = '=';
|
||||
static constexpr char DOUBLE_QUOTE = '"';
|
||||
static constexpr char SINGLE_QUOTE = '\'';
|
||||
static constexpr char COLON = ':';
|
||||
|
||||
static bool IsAlphaNumeric(char c);
|
||||
static bool IsSpace(char c);
|
||||
|
|
80
src/core/http/HttpHeader.cpp
Normal file
80
src/core/http/HttpHeader.cpp
Normal file
|
@ -0,0 +1,80 @@
|
|||
#include "HttpHeader.h"
|
||||
#include "StringUtils.h"
|
||||
|
||||
|
||||
void HttpHeader::parse(const std::vector<std::string >& message)
|
||||
{
|
||||
std::string tag;
|
||||
std::string value;
|
||||
bool foundDelimiter{false};
|
||||
for (const auto& line : message)
|
||||
{
|
||||
for(std::size_t idx = 0; idx< line.size(); idx++)
|
||||
{
|
||||
const auto c = line[idx];
|
||||
if (c == StringUtils::COLON)
|
||||
{
|
||||
foundDelimiter = true;
|
||||
}
|
||||
else if(foundDelimiter)
|
||||
{
|
||||
value.push_back(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
tag.push_back(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tag.empty() || value.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (tag == "Host")
|
||||
{
|
||||
mHost = value;
|
||||
}
|
||||
else if (tag == "User-Agent")
|
||||
{
|
||||
mUserAgent = value;
|
||||
}
|
||||
else if (tag == "Accept")
|
||||
{
|
||||
mAccept = value;
|
||||
}
|
||||
else if (tag == "Accept-Language")
|
||||
{
|
||||
mAcceptLanguage = value;
|
||||
}
|
||||
else if (tag == "Accept-Encoding")
|
||||
{
|
||||
mAcceptEncoding = value;
|
||||
}
|
||||
else if (tag == "Connection")
|
||||
{
|
||||
mConnection = value;
|
||||
}
|
||||
else if (tag == "Referer")
|
||||
{
|
||||
mReferer = value;
|
||||
}
|
||||
else if (tag == "Sec-Fetch-Dest")
|
||||
{
|
||||
mSecFetchDest = value;
|
||||
}
|
||||
else if (tag == "Sec-Fetch-Mode")
|
||||
{
|
||||
mSecFetchMode = value;
|
||||
}
|
||||
else if (tag == "Sec-Fetch-Site")
|
||||
{
|
||||
mSecFetchSite = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
mOtherFields[tag] = value;
|
||||
}
|
||||
|
||||
}
|
26
src/core/http/HttpHeader.h
Normal file
26
src/core/http/HttpHeader.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
class HttpHeader
|
||||
{
|
||||
public:
|
||||
void parse(const std::vector<std::string >& message);
|
||||
|
||||
private:
|
||||
|
||||
std::string mHost;
|
||||
std::string mUserAgent;
|
||||
std::string mAccept;
|
||||
std::string mAcceptLanguage;
|
||||
std::string mAcceptEncoding;
|
||||
std::string mConnection;
|
||||
std::string mReferer;
|
||||
std::string mSecFetchDest;
|
||||
std::string mSecFetchMode;
|
||||
std::string mSecFetchSite;
|
||||
|
||||
std::map<std::string, std::string> mOtherFields;
|
||||
};
|
68
src/core/http/HttpRequest.cpp
Normal file
68
src/core/http/HttpRequest.cpp
Normal file
|
@ -0,0 +1,68 @@
|
|||
#include "HttpRequest.h"
|
||||
|
||||
#include "StringUtils.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
void HttpRequest::parseMessage(const std::string& message)
|
||||
{
|
||||
std::stringstream ss(message);
|
||||
|
||||
std::string buffer;
|
||||
bool firstLine {true};
|
||||
|
||||
std::vector<std::string> headers;
|
||||
while(std::getline(ss, buffer, '\n'))
|
||||
{
|
||||
if (firstLine)
|
||||
{
|
||||
parseFirstLine(buffer);
|
||||
firstLine = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
headers.push_back(buffer);
|
||||
}
|
||||
}
|
||||
mHeader.parse(headers);
|
||||
}
|
||||
|
||||
void HttpRequest::parseFirstLine(const std::string& line)
|
||||
{
|
||||
bool inPath{false};
|
||||
bool inMethod{true};
|
||||
bool inProtocol{false};
|
||||
|
||||
for (std::size_t idx=0; idx<line.size();idx++)
|
||||
{
|
||||
const auto c = line[idx];
|
||||
if (inPath)
|
||||
{
|
||||
if (StringUtils::IsSpace(c))
|
||||
{
|
||||
inPath = false;
|
||||
inMethod = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
mMethod.push_back(c);
|
||||
}
|
||||
}
|
||||
else if (inMethod)
|
||||
{
|
||||
if (StringUtils::IsSpace(c))
|
||||
{
|
||||
inMethod = false;
|
||||
inProtocol = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
mPath.push_back(c);
|
||||
}
|
||||
}
|
||||
else if (inProtocol)
|
||||
{
|
||||
mProtocolVersion.push_back(c);
|
||||
}
|
||||
}
|
||||
}
|
22
src/core/http/HttpRequest.h
Normal file
22
src/core/http/HttpRequest.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
#pragma once
|
||||
|
||||
#include "HttpHeader.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
class HttpRequest
|
||||
{
|
||||
public:
|
||||
HttpRequest() = default;
|
||||
|
||||
void parseMessage(const std::string& message);
|
||||
|
||||
private:
|
||||
|
||||
void parseFirstLine(const std::string& line);
|
||||
|
||||
HttpHeader mHeader;
|
||||
std::string mMethod;
|
||||
std::string mPath;
|
||||
std::string mProtocolVersion;
|
||||
};
|
|
@ -5,11 +5,6 @@
|
|||
class HttpResponse
|
||||
{
|
||||
|
||||
std::string mHttpVersion;
|
||||
std::string mResponseCode;
|
||||
std::string mContentType;
|
||||
std::string mBody;
|
||||
|
||||
public:
|
||||
|
||||
HttpResponse();
|
||||
|
@ -23,4 +18,10 @@ public:
|
|||
std::string GetHeaderString() const;
|
||||
|
||||
std::string ToString() const;
|
||||
|
||||
private:
|
||||
std::string mHttpVersion;
|
||||
std::string mResponseCode;
|
||||
std::string mContentType;
|
||||
std::string mBody;
|
||||
};
|
||||
|
|
68
src/core/memory/SharedMemory.cpp
Normal file
68
src/core/memory/SharedMemory.cpp
Normal file
|
@ -0,0 +1,68 @@
|
|||
#include "SharedMemory.h"
|
||||
|
||||
#include "RandomUtils.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
void SharedMemory::allocate(const std::string& namePrefix, std::size_t size)
|
||||
{
|
||||
createFile(namePrefix);
|
||||
|
||||
if (!mIsValid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int ret{-1};
|
||||
do {
|
||||
ret = ftruncate(mFileDescriptor, size);
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
close(mFileDescriptor);
|
||||
mIsValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
int SharedMemory::getFileDescriptor() const
|
||||
{
|
||||
return mFileDescriptor;
|
||||
}
|
||||
|
||||
bool SharedMemory::isValid() const
|
||||
{
|
||||
return mIsValid;
|
||||
}
|
||||
|
||||
void SharedMemory::createFile(const std::string& namePrefix)
|
||||
{
|
||||
unsigned retries = 100;
|
||||
do {
|
||||
const auto name = getRandomName(namePrefix);
|
||||
--retries;
|
||||
|
||||
const int fd = shm_open(name.c_str(), O_RDWR | O_CREAT | O_EXCL, 0600);
|
||||
if (fd >= 0)
|
||||
{
|
||||
shm_unlink(name.c_str());
|
||||
mFileDescriptor = fd;
|
||||
mIsValid = true;
|
||||
break;
|
||||
}
|
||||
} while (retries > 0 && errno == EEXIST);
|
||||
}
|
||||
|
||||
std::string SharedMemory::getRandomName(const std::string& namePrefix) const
|
||||
{
|
||||
std::string randomSuffix;
|
||||
for (const auto entry : RandomUtils::getRandomVecUnsigned(6))
|
||||
{
|
||||
randomSuffix += std::to_string(entry);
|
||||
}
|
||||
return namePrefix + randomSuffix;
|
||||
}
|
22
src/core/memory/SharedMemory.h
Normal file
22
src/core/memory/SharedMemory.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
class SharedMemory
|
||||
{
|
||||
public:
|
||||
void allocate(const std::string& namePrefix, std::size_t size);
|
||||
|
||||
int getFileDescriptor() const;
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
private:
|
||||
|
||||
void createFile(const std::string& namePrefix);
|
||||
|
||||
std::string getRandomName(const std::string& namePrefix) const;
|
||||
|
||||
int mFileDescriptor{0};
|
||||
bool mIsValid{false};
|
||||
};
|
|
@ -8,11 +8,13 @@ list(APPEND network_HEADERS
|
|||
NetworkManager.h
|
||||
sockets/Socket.h
|
||||
sockets/SocketInterface.h
|
||||
sockets/ISocketMessageHandler.h
|
||||
)
|
||||
|
||||
list(APPEND network_LIB_INCLUDES
|
||||
NetworkManager.cpp
|
||||
sockets/Socket.cpp
|
||||
web/HttpMessageHandler.cpp
|
||||
)
|
||||
|
||||
add_library(network SHARED ${network_LIB_INCLUDES} ${platform_INCLUDES} ${network_HEADERS})
|
||||
|
@ -20,6 +22,7 @@ add_library(network SHARED ${network_LIB_INCLUDES} ${platform_INCLUDES} ${networ
|
|||
target_include_directories(network PUBLIC
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/sockets"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/web"
|
||||
"${PROJECT_SOURCE_DIR}/src/core/http"
|
||||
)
|
||||
set_target_properties( network PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#include "UnixSocketInterface.h"
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
|
||||
NetworkManager::NetworkManager()
|
||||
: mActiveSockets(),
|
||||
mSocketInterface()
|
||||
|
@ -29,6 +31,7 @@ void NetworkManager::Initialize()
|
|||
|
||||
void NetworkManager::RunHttpServer()
|
||||
{
|
||||
std::cout << "Running http server" << std::endl;
|
||||
if (!mSocketInterface)
|
||||
{
|
||||
Initialize();
|
||||
|
@ -40,6 +43,19 @@ void NetworkManager::RunHttpServer()
|
|||
mSocketInterface->Run(socket);
|
||||
}
|
||||
|
||||
void NetworkManager::RunHttpClient()
|
||||
{
|
||||
std::cout << "Running http client" << std::endl;
|
||||
if (!mSocketInterface)
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
auto socket = Socket::Create();
|
||||
mSocketInterface->InitializeSocket(socket, "127.0.0.1");
|
||||
mSocketInterface->Write(socket, "Hello Friend");
|
||||
}
|
||||
|
||||
void NetworkManager::ShutDown()
|
||||
{
|
||||
|
||||
|
|
|
@ -20,11 +20,14 @@ public:
|
|||
|
||||
void RunHttpServer();
|
||||
|
||||
void RunHttpClient();
|
||||
|
||||
void ShutDown();
|
||||
|
||||
private:
|
||||
std::vector<SocketPtr> mActiveSockets;
|
||||
ISocketInterfaceUPtr mSocketInterface;
|
||||
|
||||
};
|
||||
|
||||
using NetworkManagerUPtr = std::unique_ptr<NetworkManager>;
|
||||
|
|
10
src/network/sockets/ISocketMessageHandler.h
Normal file
10
src/network/sockets/ISocketMessageHandler.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
class ISocketMessageHandler
|
||||
{
|
||||
public:
|
||||
virtual ~ISocketMessageHandler() = default;
|
||||
virtual std::string onMessage(const std::string& message) = 0;
|
||||
};
|
|
@ -47,3 +47,14 @@ unsigned Socket::GetPort() const
|
|||
{
|
||||
return mPort;
|
||||
}
|
||||
|
||||
std::string Socket::getAddress() const
|
||||
{
|
||||
return mAddress;
|
||||
}
|
||||
|
||||
|
||||
void Socket::setAddress(const std::string& address)
|
||||
{
|
||||
mAddress = address;
|
||||
}
|
||||
|
|
|
@ -26,11 +26,15 @@ public:
|
|||
|
||||
void SetMessage(const std::string& message);
|
||||
|
||||
std::string getAddress() const;
|
||||
void setAddress(const std::string& address);
|
||||
|
||||
private:
|
||||
|
||||
SocketHandle mHandle;
|
||||
unsigned mPort{0};
|
||||
std::string mMessage;
|
||||
std::string mAddress;
|
||||
};
|
||||
|
||||
using SocketPtr = std::unique_ptr<Socket>;
|
||||
|
|
|
@ -13,9 +13,11 @@ public:
|
|||
|
||||
virtual ~ISocketInterface() = default;
|
||||
|
||||
virtual void InitializeSocket(const SocketPtr& socket) = 0;
|
||||
virtual void InitializeSocket(const SocketPtr& socket, const std::string& address = {}) = 0;
|
||||
virtual void Listen(const SocketPtr& socket) = 0;
|
||||
virtual void Run(const SocketPtr& socket) = 0;
|
||||
|
||||
virtual void Write(const SocketPtr& socket, const std::string& message) = 0;
|
||||
};
|
||||
|
||||
using ISocketInterfaceUPtr = std::unique_ptr<ISocketInterface>;
|
||||
|
|
|
@ -2,17 +2,20 @@
|
|||
|
||||
#include "HttpResponse.h"
|
||||
|
||||
#include "HttpMessageHandler.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
UnixSocketInterface::UnixSocketInterface()
|
||||
: mBufferSize(1024)
|
||||
{
|
||||
|
||||
mMessageHandler = std::make_unique<HttpMessageHandler>();
|
||||
}
|
||||
|
||||
std::unique_ptr<UnixSocketInterface> UnixSocketInterface::Create()
|
||||
|
@ -20,10 +23,61 @@ std::unique_ptr<UnixSocketInterface> UnixSocketInterface::Create()
|
|||
return std::make_unique<UnixSocketInterface>();
|
||||
}
|
||||
|
||||
void UnixSocketInterface::InitializeSocket(const SocketPtr& socketPtr)
|
||||
UnixSocketInterface::~UnixSocketInterface()
|
||||
{
|
||||
auto handle = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
}
|
||||
|
||||
void UnixSocketInterface::InitializeSocket(const SocketPtr& socketPtr, const std::string& address)
|
||||
{
|
||||
auto handle = ::socket(AF_INET, SOCK_STREAM, 0);
|
||||
socketPtr->SetHandle(handle);
|
||||
|
||||
if (!address.empty())
|
||||
{
|
||||
socketPtr->setAddress(address);
|
||||
}
|
||||
}
|
||||
|
||||
void UnixSocketInterface::Write(const SocketPtr& socket, const std::string& message)
|
||||
{
|
||||
if(socket->GetHandle() < 0)
|
||||
{
|
||||
std::cerr << "Error opening socket" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
const auto port = static_cast<int>(socket->GetPort());
|
||||
struct sockaddr_in serv_addr;
|
||||
memset(&serv_addr, 0, sizeof(serv_addr));
|
||||
serv_addr.sin_family = AF_INET;
|
||||
|
||||
inet_aton(socket->getAddress().c_str(), &serv_addr.sin_addr);
|
||||
serv_addr.sin_port = htons(port);
|
||||
|
||||
int result = connect(socket->GetHandle(), (struct sockaddr *)&serv_addr, sizeof(serv_addr));
|
||||
if(result< 0)
|
||||
{
|
||||
std::cerr << "Error connecting to socket" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
auto n = write(socket->GetHandle(), message.c_str(), message.length());
|
||||
if (n < 0)
|
||||
{
|
||||
std::cerr << "Error on write" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer[mBufferSize] = {0};
|
||||
int res = read(socket->GetHandle(), buffer, mBufferSize);
|
||||
if (res < 0)
|
||||
{
|
||||
std::cerr << "Error on read" << std::endl;
|
||||
return;
|
||||
}
|
||||
socket->SetMessage(buffer);
|
||||
std::cout << "Here is the message: " << buffer << std::endl;
|
||||
}
|
||||
|
||||
void UnixSocketInterface::Listen(const SocketPtr& socket)
|
||||
|
@ -34,7 +88,7 @@ void UnixSocketInterface::Listen(const SocketPtr& socket)
|
|||
return;
|
||||
}
|
||||
|
||||
int port = static_cast<int>(socket->GetPort());
|
||||
const auto port = static_cast<int>(socket->GetPort());
|
||||
struct sockaddr_in serv_addr;
|
||||
memset(&serv_addr, 0, sizeof(serv_addr));
|
||||
serv_addr.sin_family = AF_INET;
|
||||
|
@ -63,8 +117,7 @@ void UnixSocketInterface::Run(const SocketPtr& socket)
|
|||
socklen_t clilen = sizeof(cli_addr);
|
||||
while(true)
|
||||
{
|
||||
auto new_socket_handle = accept(socket->GetHandle(),
|
||||
(struct sockaddr *) &cli_addr, &clilen);
|
||||
const auto new_socket_handle = accept(socket->GetHandle(), (struct sockaddr *) &cli_addr, &clilen);
|
||||
if (new_socket_handle < 0)
|
||||
{
|
||||
std::cerr << "Error on accept" << std::endl;
|
||||
|
@ -81,11 +134,8 @@ void UnixSocketInterface::Run(const SocketPtr& socket)
|
|||
socket->SetMessage(buffer);
|
||||
std::cout << "Here is the message: " << buffer << std::endl;
|
||||
|
||||
HttpResponse response;
|
||||
response.SetBody("Hello world!");
|
||||
|
||||
auto response_message = response.ToString();
|
||||
n = write(new_socket_handle, response_message.c_str(), response_message.length());
|
||||
const auto response = mMessageHandler->onMessage(buffer);
|
||||
n = write(new_socket_handle, response.c_str(), response.length());
|
||||
if (n < 0)
|
||||
{
|
||||
std::cerr << "Error on write" << std::endl;
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#include <memory>
|
||||
#include <map>
|
||||
|
||||
class ISocketMessageHandler;
|
||||
|
||||
class UnixSocketInterface : public ISocketInterface
|
||||
{
|
||||
|
||||
|
@ -13,19 +15,22 @@ public:
|
|||
|
||||
UnixSocketInterface();
|
||||
|
||||
virtual ~UnixSocketInterface() = default;
|
||||
virtual ~UnixSocketInterface();
|
||||
|
||||
static std::unique_ptr<UnixSocketInterface> Create();
|
||||
|
||||
void InitializeSocket(const SocketPtr& socket) override;
|
||||
void InitializeSocket(const SocketPtr& socket, const std::string& address = {}) override;
|
||||
|
||||
void Listen(const SocketPtr& socket) override;
|
||||
|
||||
void Write(const SocketPtr& socket, const std::string& message) override;
|
||||
|
||||
void Run(const SocketPtr& socket) override;
|
||||
|
||||
private:
|
||||
|
||||
std::size_t mBufferSize { 0 };
|
||||
std::unique_ptr<ISocketMessageHandler> mMessageHandler;
|
||||
};
|
||||
|
||||
using UnixSocketInterfacePtr = std::unique_ptr<UnixSocketInterface>;
|
||||
|
|
17
src/network/web/HttpMessageHandler.cpp
Normal file
17
src/network/web/HttpMessageHandler.cpp
Normal file
|
@ -0,0 +1,17 @@
|
|||
#include "HttpMessageHandler.h"
|
||||
|
||||
#include "HttpRequest.h"
|
||||
#include "HttpResponse.h"
|
||||
|
||||
std::string HttpMessageHandler::onMessage(const std::string& message)
|
||||
{
|
||||
HttpRequest request;
|
||||
request.parseMessage(message);
|
||||
|
||||
HttpResponse response;
|
||||
response.SetBody("Hello world!");
|
||||
|
||||
const auto response_message = response.ToString();
|
||||
|
||||
return response_message;
|
||||
}
|
9
src/network/web/HttpMessageHandler.h
Normal file
9
src/network/web/HttpMessageHandler.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include "ISocketMessageHandler.h"
|
||||
|
||||
class HttpMessageHandler : public ISocketMessageHandler
|
||||
{
|
||||
public:
|
||||
std::string onMessage(const std::string& message) override;
|
||||
};
|
|
@ -11,10 +11,36 @@ list(APPEND platform_INCLUDES
|
|||
ui_interfaces/x11/XcbLayerInterface.cpp
|
||||
ui_interfaces/x11/XcbTextInterface.cpp
|
||||
ui_interfaces/x11/XcbKeyboard.cpp
|
||||
ui_interfaces/x11/GlxInterface.cpp)
|
||||
ui_interfaces/x11/GlxInterface.cpp
|
||||
|
||||
ui_interfaces/wayland/WaylandWindowInterface.cpp
|
||||
)
|
||||
|
||||
list(APPEND platform_LIBS
|
||||
X11 X11-xcb xcb )
|
||||
|
||||
|
||||
find_path(
|
||||
WAYLAND_CLIENT_INCLUDE_DIR
|
||||
NAMES wayland-client.h
|
||||
)
|
||||
|
||||
find_path(
|
||||
WAYLAND_EXTENSIONS_INCLUDE_DIR
|
||||
NAMES xdg-shell-client-protocol.h
|
||||
HINTS ENV WAYLAND_EXTENSION_DIR
|
||||
)
|
||||
|
||||
find_library(
|
||||
WAYLAND_CLIENT_LIBRARY
|
||||
NAMES wayland-client libwayland-client
|
||||
)
|
||||
|
||||
list(APPEND platform_INCLUDES
|
||||
ui_interfaces/win32/Win32UIInterface.h
|
||||
${WAYLAND_EXTENSIONS_INCLUDE_DIR}/xdg-shell-protocol.cpp
|
||||
)
|
||||
|
||||
else()
|
||||
list(APPEND platform_INCLUDES
|
||||
ui_interfaces/win32/Win32UIInterface.h
|
||||
|
@ -38,15 +64,18 @@ target_include_directories(windows PUBLIC
|
|||
"${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/managers"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/ui_interfaces/x11"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/ui_interfaces/wayland"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/ui_interfaces/win32"
|
||||
"${PROJECT_SOURCE_DIR}/src/core"
|
||||
"${PROJECT_SOURCE_DIR}/src/geometry"
|
||||
"${PROJECT_SOURCE_DIR}/src/graphics"
|
||||
"${PROJECT_SOURCE_DIR}/src/ui_elements"
|
||||
"${PROJECT_SOURCE_DIR}/src/ui_elements/widgets"
|
||||
${WAYLAND_CLIENT_INCLUDE_DIR}
|
||||
${WAYLAND_EXTENSIONS_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
target_link_libraries(windows PUBLIC ${platform_LIBS} core geometry graphics ui_elements)
|
||||
target_link_libraries(windows PUBLIC ${platform_LIBS} core geometry graphics ui_elements ${WAYLAND_CLIENT_LIBRARY})
|
||||
|
||||
set_property(TARGET windows PROPERTY FOLDER src)
|
||||
set_target_properties( windows PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )
|
|
@ -0,0 +1 @@
|
|||
#include "WaylandWindowInterface.h"
|
263
src/windows/ui_interfaces/wayland/WaylandWindowInterface.h
Normal file
263
src/windows/ui_interfaces/wayland/WaylandWindowInterface.h
Normal file
|
@ -0,0 +1,263 @@
|
|||
#pragma once
|
||||
|
||||
#include "wayland-client.h"
|
||||
#include "xdg-shell-client-protocol.h"
|
||||
|
||||
#include "Window.h"
|
||||
#include "SharedMemory.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
class WaylandWindowInterface
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
WaylandWindowInterface()
|
||||
{
|
||||
auto registry_handle_global = [](void *data, struct wl_registry *registry,
|
||||
uint32_t name, const char *interface, uint32_t version)
|
||||
{
|
||||
auto thisClass = static_cast<WaylandWindowInterface*>(data);
|
||||
|
||||
printf("interface: '%s', version: %d, name: %d\n", interface, version, name);
|
||||
|
||||
if (strcmp(interface, wl_compositor_interface.name) == 0)
|
||||
{
|
||||
thisClass->setCompositor(static_cast<wl_compositor*>(wl_registry_bind(registry, name, &wl_compositor_interface, 4)));
|
||||
}
|
||||
else if (strcmp(interface, wl_shm_interface.name) == 0)
|
||||
{
|
||||
thisClass->setSharedMemory(static_cast<wl_shm*>(wl_registry_bind(registry, name, &wl_shm_interface, 1)));
|
||||
}
|
||||
else if (strcmp(interface, xdg_wm_base_interface.name) == 0)
|
||||
{
|
||||
thisClass->setXdgBase(static_cast<xdg_wm_base*>(wl_registry_bind(registry, name, &xdg_wm_base_interface, 1)));
|
||||
}
|
||||
};
|
||||
|
||||
auto registry_handle_global_remove = [](void *data, struct wl_registry *registry,
|
||||
uint32_t name)
|
||||
{
|
||||
// This space deliberately left blank;
|
||||
};
|
||||
|
||||
mRegistryListener.global = registry_handle_global;
|
||||
mRegistryListener.global_remove = registry_handle_global_remove;
|
||||
}
|
||||
|
||||
void setXdgBase(xdg_wm_base* xdg_base)
|
||||
{
|
||||
mXdgBase = xdg_base;
|
||||
auto xdg_ping_handler = [](void *data, struct xdg_wm_base *xdg_wm_base, uint32_t serial)
|
||||
{
|
||||
auto thisClass = static_cast<WaylandWindowInterface*>(data);
|
||||
thisClass->doXdgPong(serial);
|
||||
};
|
||||
mXdgBaseListener.ping = xdg_ping_handler;
|
||||
xdg_wm_base_add_listener(mXdgBase, &mXdgBaseListener, this);
|
||||
}
|
||||
|
||||
void doXdgPong(uint32_t serial)
|
||||
{
|
||||
xdg_wm_base_pong(mXdgBase, serial);
|
||||
}
|
||||
|
||||
void setCompositor(wl_compositor* compositor)
|
||||
{
|
||||
mCompositor = compositor;
|
||||
}
|
||||
|
||||
void setSharedMemory(wl_shm* shared_memory)
|
||||
{
|
||||
mWlSharedMemory = shared_memory;
|
||||
}
|
||||
|
||||
void connect()
|
||||
{
|
||||
mDisplay = wl_display_connect(nullptr);
|
||||
|
||||
if (!mDisplay)
|
||||
{
|
||||
std::cout << "Display connect error" << std::endl;
|
||||
}
|
||||
|
||||
auto registry = wl_display_get_registry(mDisplay);
|
||||
if (!registry)
|
||||
{
|
||||
std::cout << "Failed to get registry" << std::endl;
|
||||
}
|
||||
|
||||
wl_registry_add_listener(registry, &mRegistryListener, this);
|
||||
wl_display_roundtrip(mDisplay);
|
||||
}
|
||||
|
||||
void createSurface()
|
||||
{
|
||||
mSurface = wl_compositor_create_surface(mCompositor);
|
||||
mXdgSurface = xdg_wm_base_get_xdg_surface(mXdgBase, mSurface);
|
||||
|
||||
auto xdg_surface_configure = [](void *data, struct xdg_surface *xdg_surface, uint32_t serial)
|
||||
{
|
||||
auto thisClass = static_cast<WaylandWindowInterface*>(data);
|
||||
thisClass->onXdgSurfaceConfigure(data, xdg_surface, serial);
|
||||
};
|
||||
mXdgSurfaceListener.configure = xdg_surface_configure;
|
||||
|
||||
xdg_surface_add_listener(mXdgSurface, &mXdgSurfaceListener, this);
|
||||
|
||||
mXdgTopLevel = xdg_surface_get_toplevel(mXdgSurface);
|
||||
xdg_toplevel_set_title(mXdgTopLevel, "Example client");
|
||||
|
||||
wl_surface_commit(mSurface);
|
||||
}
|
||||
|
||||
void onXdgSurfaceConfigure(void *data, struct xdg_surface *xdg_surface, uint32_t serial)
|
||||
{
|
||||
xdg_surface_ack_configure(xdg_surface, serial);
|
||||
|
||||
auto buffer = draw_frame();
|
||||
wl_surface_attach(mSurface, buffer, 0, 0);
|
||||
//wl_surface_damage(mSurface, 0, 0, UINT32_MAX, UINT32_MAX);
|
||||
wl_surface_commit(mSurface);
|
||||
}
|
||||
|
||||
wl_buffer* draw_frame()
|
||||
{
|
||||
const auto width = mWindow->GetWidth();
|
||||
const auto height = mWindow->GetHeight();
|
||||
|
||||
const int bitDepth = 4;
|
||||
|
||||
const int stride = width * bitDepth;
|
||||
//const int numBuffers = 2; // i.e. front/back
|
||||
const int numBuffers = 1;
|
||||
const int shm_pool_size = height * stride * numBuffers;
|
||||
|
||||
initializeSharedBuffer(shm_pool_size);
|
||||
|
||||
if (!mSharedMemory->isValid())
|
||||
{
|
||||
std::cout << "Failed to allocate shared memory" << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!mPoolData)
|
||||
{
|
||||
std::cout << "Failed to mmap pool" << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto pool = wl_shm_create_pool(mWlSharedMemory, mSharedMemory->getFileDescriptor(), shm_pool_size);
|
||||
|
||||
int index = 0;
|
||||
// int offset = height * stride * index; // Two buffers, offset to starting point of second
|
||||
int offset = 0;
|
||||
|
||||
mWorkingBuffer = wl_shm_pool_create_buffer(pool, offset, width, height, stride, WL_SHM_FORMAT_XRGB8888);
|
||||
|
||||
wl_shm_pool_destroy(pool);
|
||||
close(mSharedMemory->getFileDescriptor());
|
||||
|
||||
drawCheckerboard(width, height, offset);
|
||||
|
||||
munmap(mPoolData, shm_pool_size);
|
||||
|
||||
auto wl_buffer_release = [](void *data, struct wl_buffer *wl_buffer)
|
||||
{
|
||||
wl_buffer_destroy(wl_buffer);
|
||||
};
|
||||
mBufferListener.release = wl_buffer_release;
|
||||
|
||||
wl_buffer_add_listener(mWorkingBuffer, &mBufferListener, nullptr);
|
||||
|
||||
return mWorkingBuffer;
|
||||
}
|
||||
|
||||
void drawCheckerboard(int width, int height, int offset)
|
||||
{
|
||||
uint32_t *pixels = (uint32_t *)&mPoolData[offset];
|
||||
for (int y = 0; y < height; ++y)
|
||||
{
|
||||
for (int x = 0; x < width; ++x)
|
||||
{
|
||||
if ((x + y / 8 * 8) % 16 < 8)
|
||||
{
|
||||
pixels[y * width + x] = 0xFF666666;
|
||||
}
|
||||
else
|
||||
{
|
||||
pixels[y * width + x] = 0xFFEEEEEE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void disconnect()
|
||||
{
|
||||
if (mDisplay)
|
||||
{
|
||||
wl_display_disconnect(mDisplay);
|
||||
}
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
while (wl_display_dispatch(mDisplay) != -1) {
|
||||
/* This space deliberately left blank */
|
||||
}
|
||||
}
|
||||
|
||||
void initializeSharedBuffer(int size)
|
||||
{
|
||||
mSharedMemory = std::make_unique<SharedMemory>();
|
||||
mSharedMemory->allocate("/wl_shm-XXXXXX", size);
|
||||
|
||||
if (!mSharedMemory->isValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
mPoolData = static_cast<uint8_t*>(mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, mSharedMemory->getFileDescriptor(), 0));
|
||||
if (mPoolData == MAP_FAILED)
|
||||
{
|
||||
close(mSharedMemory->getFileDescriptor());
|
||||
mPoolData = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void addWindow(mt::Window* window)
|
||||
{
|
||||
mWindow = window;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
mt::Window* mWindow{nullptr};
|
||||
|
||||
wl_display* mDisplay{nullptr};
|
||||
wl_compositor* mCompositor{nullptr};
|
||||
wl_registry_listener mRegistryListener;
|
||||
|
||||
xdg_wm_base* mXdgBase{nullptr};
|
||||
xdg_wm_base_listener mXdgBaseListener;
|
||||
|
||||
wl_surface* mSurface{nullptr};
|
||||
xdg_surface* mXdgSurface{nullptr};
|
||||
xdg_surface_listener mXdgSurfaceListener{nullptr};
|
||||
|
||||
xdg_toplevel* mXdgTopLevel{nullptr};
|
||||
|
||||
wl_shm* mWlSharedMemory{nullptr};
|
||||
std::unique_ptr<SharedMemory> mSharedMemory;
|
||||
uint8_t* mPoolData{nullptr};
|
||||
wl_shm_pool* mPool{nullptr};
|
||||
|
||||
wl_buffer* mWorkingBuffer{nullptr};
|
||||
wl_buffer_listener mBufferListener;
|
||||
};
|
|
@ -15,8 +15,11 @@ list(APPEND TestFiles
|
|||
graphics/TestRasterizer.cpp
|
||||
ipc/TestDbus.cpp
|
||||
image/TestPngWriter.cpp
|
||||
network/TestNetworkManagerClient.cpp
|
||||
network/TestNetworkManagerServer.cpp
|
||||
publishing/TestPdfWriter.cpp
|
||||
video/TestVideoDecoder.cpp
|
||||
windows/TestWaylandWindow.cpp
|
||||
web/TestMarkdownParser.cpp
|
||||
web/TestXmlParser.cpp)
|
||||
|
||||
|
@ -28,8 +31,11 @@ list(APPEND TestNames
|
|||
TestRasterizer
|
||||
TestDbus
|
||||
TestPngWriter
|
||||
TestNetworkManagerClient
|
||||
TestNetworkManagerServer
|
||||
TestPdfWriter
|
||||
TestVideoDecoder
|
||||
TestWaylandWindow
|
||||
TestMarkdownParser
|
||||
TestXmlParser)
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include "Image.h"
|
||||
#include "PngWriter.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
int main()
|
||||
{
|
||||
unsigned width = 200;
|
||||
|
|
12
test/network/TestNetworkManagerClient.cpp
Normal file
12
test/network/TestNetworkManagerClient.cpp
Normal file
|
@ -0,0 +1,12 @@
|
|||
#include "NetworkManager.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << "into main" << std::endl;
|
||||
auto network_manager = NetworkManager::Create();
|
||||
|
||||
network_manager->RunHttpClient();
|
||||
return 0;
|
||||
}
|
12
test/network/TestNetworkManagerServer.cpp
Normal file
12
test/network/TestNetworkManagerServer.cpp
Normal file
|
@ -0,0 +1,12 @@
|
|||
#include "NetworkManager.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << "into main" << std::endl;
|
||||
auto network_manager = NetworkManager::Create();
|
||||
|
||||
network_manager->RunHttpServer();
|
||||
return 0;
|
||||
}
|
23
test/windows/TestWaylandWindow.cpp
Normal file
23
test/windows/TestWaylandWindow.cpp
Normal file
|
@ -0,0 +1,23 @@
|
|||
#include "WaylandWindowInterface.h"
|
||||
|
||||
#include "Window.h"
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
WaylandWindowInterface window_interface;
|
||||
window_interface.connect();
|
||||
|
||||
auto window = mt::Window::Create();
|
||||
window->SetSize(800, 600);
|
||||
|
||||
window_interface.addWindow(window.get());
|
||||
|
||||
window_interface.createSurface();
|
||||
|
||||
window_interface.run();
|
||||
|
||||
window_interface.disconnect();
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue