diff --git a/CMakeLists.txt b/CMakeLists.txt index 94b4aa1..ec647cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,21 +21,34 @@ ExternalProject_Add( INSTALL_COMMAND "" ) - add_executable(app - src/main.cpp - src/App.cpp - src/DnaStore.cpp - src/sys.cpp - src/canvas/BackGround.cpp - src/canvas/BackGroundColors.cpp - src/canvas/Canvas.cpp - src/canvas/Circle.cpp - src/canvas/Tree.cpp - src/values/Dna.cpp - src/values/DnaManager.cpp - src/values/mrand.cpp + app/src/main.cpp + app/src/App.cpp + app/src/DnaStore.cpp + app/src/sys.cpp + shared/src/canvas/BackGround.cpp + shared/src/canvas/BackGroundColors.cpp + shared/src/canvas/Canvas.cpp + shared/src/canvas/Circle.cpp + shared/src/canvas/Tree.cpp + shared/src/values/Dna.cpp + shared/src/values/DnaManager.cpp + shared/src/values/mrand.cpp ) # Add include directories -target_include_directories(app PRIVATE inc ${CMAKE_BINARY_DIR}/raylib/include) -target_link_libraries(app ${CMAKE_BINARY_DIR}/raylib/lib/libraylib.a) \ No newline at end of file +target_include_directories(app PRIVATE app/inc shared/inc ${CMAKE_BINARY_DIR}/raylib/include) +target_link_libraries(app ${CMAKE_BINARY_DIR}/raylib/lib/libraylib.a) + +add_executable(server + server/src/server.cpp + shared/src/TcpSocket.cpp +) +# Add include directories +target_include_directories(server PRIVATE server/inc shared/inc) + + +add_executable(client + server/src/client.cpp + shared/src/TcpSocket.cpp +) +target_include_directories(client PRIVATE server/inc shared/inc) \ No newline at end of file diff --git a/inc/App.hpp b/app/inc/App.hpp similarity index 100% rename from inc/App.hpp rename to app/inc/App.hpp diff --git a/inc/DnaStore.hpp b/app/inc/DnaStore.hpp similarity index 100% rename from inc/DnaStore.hpp rename to app/inc/DnaStore.hpp diff --git a/inc/sunShader.hpp b/app/inc/sunShader.hpp similarity index 100% rename from inc/sunShader.hpp rename to app/inc/sunShader.hpp diff --git a/inc/sys.hpp b/app/inc/sys.hpp similarity index 100% rename from inc/sys.hpp rename to app/inc/sys.hpp diff --git a/src/App.cpp b/app/src/App.cpp similarity index 100% rename from src/App.cpp rename to app/src/App.cpp diff --git a/src/DnaStore.cpp b/app/src/DnaStore.cpp similarity index 100% rename from src/DnaStore.cpp rename to app/src/DnaStore.cpp diff --git a/src/main.cpp b/app/src/main.cpp similarity index 100% rename from src/main.cpp rename to app/src/main.cpp diff --git a/src/sys.cpp b/app/src/sys.cpp similarity index 100% rename from src/sys.cpp rename to app/src/sys.cpp diff --git a/server/src/client.cpp b/server/src/client.cpp new file mode 100644 index 0000000..30a72f1 --- /dev/null +++ b/server/src/client.cpp @@ -0,0 +1,40 @@ +#include "TcpSocket.hpp" +#include + +using namespace std; + +char mes[] = "Hello Server!"; + +int main() +{ + int sock = TcpSocket::connectt("localhost", 8888); + + if (sock < 0) + { + printf("Error %d", sock); + return 0; + } + + char tempBuffer[AS_DEFAULT_BUFFER_SIZE + 1]; + ssize_t messageLength; + + // You should do an input loop, so the program won't terminate immediately + string input; + getline(cin, input); + while (input != "exit") + { + TcpSocket::sendt(sock, input.data(), input.size()); + messageLength = TcpSocket::recvt(sock, tempBuffer, AS_DEFAULT_BUFFER_SIZE); + if (messageLength <= 0) + { + break; + } + tempBuffer[messageLength] = 0; + printf("%s\n", tempBuffer); + getline(cin, input); + } + + TcpSocket::closet(sock); + + return 0; +} \ No newline at end of file diff --git a/server/src/server.cpp b/server/src/server.cpp new file mode 100644 index 0000000..03b0f9f --- /dev/null +++ b/server/src/server.cpp @@ -0,0 +1,34 @@ +#include "TcpSocket.hpp" +#include + +using namespace std; + +// use pthread rw_lock to lock db so you can safy clone .db file + +int main() +{ + // When a new client connected: + TcpSocket::OnNewConnectionCallBack onNewConnection = [](int sock, sockaddr_in newSocketInfo) + { + std::cout << "new User" << std::endl; + char tempBuffer[AS_DEFAULT_BUFFER_SIZE + 1]; + ssize_t messageLength; + while ((messageLength = TcpSocket::recvt(sock, tempBuffer, AS_DEFAULT_BUFFER_SIZE)) > 0) + { + tempBuffer[messageLength] = '\0'; + TcpSocket::sendt(sock, tempBuffer, messageLength); + } + std::cout << "del USER" << std::endl; + TcpSocket::closet(sock); + }; + + // Bind the server to a port. + int err = TcpSocket::listent("0.0.0.0", 8888, onNewConnection); + if (err < 0) + { + printf("ERROR %d", err); + return 0; + } + + return 0; +} \ No newline at end of file diff --git a/shared/inc/TcpSocket.hpp b/shared/inc/TcpSocket.hpp new file mode 100644 index 0000000..bf2bd8a --- /dev/null +++ b/shared/inc/TcpSocket.hpp @@ -0,0 +1,28 @@ + + +#include +#include +#include + +#define AS_DEFAULT_BUFFER_SIZE 0x1000 /*4096 bytes*/ + +namespace TcpSocket +{ + + void setTimeout(int seconds, int sock); + + ssize_t sendt(int sock, const void *bytes, size_t byteslength); + + ssize_t recvt(int sock, void *bytes, size_t byteslength); + + void closet(int sock); + + std::string remoteAddress(sockaddr_in &address); + + int remotePort(sockaddr_in &address); + int connectt(const char *host, uint16_t port); + + typedef std::function OnNewConnectionCallBack; + int listent(const char *host, uint16_t port, OnNewConnectionCallBack callback); + +} // namespace TcpSocket diff --git a/inc/canvas/BackGround.hpp b/shared/inc/canvas/BackGround.hpp similarity index 100% rename from inc/canvas/BackGround.hpp rename to shared/inc/canvas/BackGround.hpp diff --git a/inc/canvas/BackGroundColors.hpp b/shared/inc/canvas/BackGroundColors.hpp similarity index 100% rename from inc/canvas/BackGroundColors.hpp rename to shared/inc/canvas/BackGroundColors.hpp diff --git a/inc/canvas/Canvas.hpp b/shared/inc/canvas/Canvas.hpp similarity index 100% rename from inc/canvas/Canvas.hpp rename to shared/inc/canvas/Canvas.hpp diff --git a/inc/canvas/Circle.hpp b/shared/inc/canvas/Circle.hpp similarity index 100% rename from inc/canvas/Circle.hpp rename to shared/inc/canvas/Circle.hpp diff --git a/inc/canvas/Tree.hpp b/shared/inc/canvas/Tree.hpp similarity index 100% rename from inc/canvas/Tree.hpp rename to shared/inc/canvas/Tree.hpp diff --git a/inc/canvas/stb_perlin.h b/shared/inc/canvas/stb_perlin.h similarity index 100% rename from inc/canvas/stb_perlin.h rename to shared/inc/canvas/stb_perlin.h diff --git a/inc/values/Dna.hpp b/shared/inc/values/Dna.hpp similarity index 100% rename from inc/values/Dna.hpp rename to shared/inc/values/Dna.hpp diff --git a/inc/values/DnaManager.hpp b/shared/inc/values/DnaManager.hpp similarity index 100% rename from inc/values/DnaManager.hpp rename to shared/inc/values/DnaManager.hpp diff --git a/inc/values/mrand.hpp b/shared/inc/values/mrand.hpp similarity index 100% rename from inc/values/mrand.hpp rename to shared/inc/values/mrand.hpp diff --git a/shared/src/TcpSocket.cpp b/shared/src/TcpSocket.cpp new file mode 100644 index 0000000..f0c115f --- /dev/null +++ b/shared/src/TcpSocket.cpp @@ -0,0 +1,169 @@ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace TcpSocket +{ + + void setTimeout(int seconds, int sock) + { + struct timeval tv; + tv.tv_sec = seconds; + tv.tv_usec = 0; + + setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)); + setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv)); + } + + ssize_t sendt(int sock, const void *bytes, size_t byteslength) { return send(sock, bytes, byteslength, 0); } + + ssize_t recvt(int sock, void *bytes, size_t byteslength) { return recv(sock, bytes, byteslength, 0); } + + void closet(int sock) + { + shutdown(sock, SHUT_RDWR); + close(sock); + } + + std::string remoteAddress(sockaddr_in &address) + { + char ip[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &(address.sin_addr), ip, INET_ADDRSTRLEN); + + return std::string(ip); + } + + int remotePort(sockaddr_in &address) { return ntohs(address.sin_port); } + + int connectt(const char *host, uint16_t port) + { + struct addrinfo hints, *res, *it; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + + // Get address info from DNS + int status = getaddrinfo(host, NULL, &hints, &res); + if (status != 0) + { + // onError(errno, "Invalid address." + std::string(gai_strerror(status))); + return -1; + } + + sockaddr_in address; + for (it = res; it != NULL; it = it->ai_next) + { + if (it->ai_family == AF_INET) + { // IPv4 + memcpy((void *)(&address), (void *)it->ai_addr, sizeof(sockaddr_in)); + break; // for now, just get the first ip (ipv4). + } + } + + freeaddrinfo(res); + + int sock = socket(AF_INET, SOCK_STREAM, 0); + + if (sock == -1) + { + // onError(errno, "Socket creating error."); + return -2; + } + + address.sin_family = AF_INET; + address.sin_port = htons(port); + + // setTimeout(5, sock); + + // Try to connect. + status = connect(sock, (const sockaddr *)&address, sizeof(sockaddr_in)); + if (status == -1) + { + // onError(errno, "Connection failed to the host."); + close(sock); + return -3; + } + return sock; + } + + typedef std::function OnNewConnectionCallBack; + + int listent(const char *host, uint16_t port, OnNewConnectionCallBack callback) + { + sockaddr_in address; + + int sock = socket(AF_INET, SOCK_STREAM, 0); + + if (sock == -1) + { + // onError(errno, "Socket creating error."); + return -1; + } + + int opt = 1; + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int)); + setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(int)); + + int status = inet_pton(AF_INET, host, &address.sin_addr); + switch (status) + { + case -1: + close(sock); + // onError(errno, "Invalid address. Address type not supported."); + return -2; + case 0: + close(sock); + // onError(errno, "AF_INET is not supported. Please send message to developer."); + return -3; + default: + break; + } + + address.sin_family = AF_INET; + address.sin_port = htons(port); + + if (bind(sock, (const sockaddr *)&address, sizeof(address)) == -1) + { + // onError(errno, "Cannot bind the socket."); + close(sock); + return -4; + } + if (listen(sock, 20) == -1) + { + // onError(errno, "Error: Server can't listen the socket."); + close(sock); + return -5; + } + + sockaddr_in newSocketInfo; + socklen_t newSocketInfoLength = sizeof(newSocketInfo); + + int newSocketFileDescriptor = -1; + while (true) + { + newSocketFileDescriptor = accept(sock, (sockaddr *)&newSocketInfo, &newSocketInfoLength); + if (newSocketFileDescriptor == -1) + { + if (errno == EBADF || errno == EINVAL) + return -6; + + return -7; + } + + std::thread t(callback, newSocketFileDescriptor, newSocketInfo); + t.detach(); + } + + return 0; + } + +} \ No newline at end of file diff --git a/src/canvas/BackGround.cpp b/shared/src/canvas/BackGround.cpp similarity index 100% rename from src/canvas/BackGround.cpp rename to shared/src/canvas/BackGround.cpp diff --git a/src/canvas/BackGroundColors.cpp b/shared/src/canvas/BackGroundColors.cpp similarity index 100% rename from src/canvas/BackGroundColors.cpp rename to shared/src/canvas/BackGroundColors.cpp diff --git a/src/canvas/Canvas.cpp b/shared/src/canvas/Canvas.cpp similarity index 100% rename from src/canvas/Canvas.cpp rename to shared/src/canvas/Canvas.cpp diff --git a/src/canvas/Circle.cpp b/shared/src/canvas/Circle.cpp similarity index 100% rename from src/canvas/Circle.cpp rename to shared/src/canvas/Circle.cpp diff --git a/src/canvas/Tree.cpp b/shared/src/canvas/Tree.cpp similarity index 100% rename from src/canvas/Tree.cpp rename to shared/src/canvas/Tree.cpp diff --git a/src/values/Dna.cpp b/shared/src/values/Dna.cpp similarity index 100% rename from src/values/Dna.cpp rename to shared/src/values/Dna.cpp diff --git a/src/values/DnaManager.cpp b/shared/src/values/DnaManager.cpp similarity index 100% rename from src/values/DnaManager.cpp rename to shared/src/values/DnaManager.cpp diff --git a/src/values/mrand.cpp b/shared/src/values/mrand.cpp similarity index 100% rename from src/values/mrand.cpp rename to shared/src/values/mrand.cpp