diff --git a/server/src/main.cpp b/server/src/main.cpp index 56c150f..af20424 100644 --- a/server/src/main.cpp +++ b/server/src/main.cpp @@ -15,21 +15,18 @@ int main(int argc, char **argv) { std::cout << i << std::endl; });*/ - sosc::TcpClient client; - sosc::TcpServer server; - - server.Listen(1111); - server.Accept(&client); + /*sosc::TcpClient client; + client.Open("127.0.0.1", 1111); client.Send("test"); - std::string got; + std::string got = "abc"; while(client.IsOpen()) { - int length = client.Recv(&got); + int length = client.Receive(&got); if(length > 0) std::cout << got << std::endl; - } + }*/ return 0; } diff --git a/server/src/sock/tcpsock.hpp b/server/src/sock/tcpsock.hpp index 4cd5714..6900612 100644 --- a/server/src/sock/tcpsock.hpp +++ b/server/src/sock/tcpsock.hpp @@ -36,13 +36,16 @@ #define SOSC_TCP_BUFLEN 2048 +#define SOSC_TCP_APPEND 1 +#define SOSC_TCP_BLOCK 2 + namespace sosc { class TcpClient { public: TcpClient(); bool Open(std::string host, std::uint16_t port); - int Recv(std::string* str, bool append = false); + int Receive(std::string* str, int flags = 0); int Send(const std::string& str); bool IsDataReady(); diff --git a/server/src/sock/tcpsock_bsd.cpp b/server/src/sock/tcpsock_bsd.cpp index f46d473..8bd0e50 100644 --- a/server/src/sock/tcpsock_bsd.cpp +++ b/server/src/sock/tcpsock_bsd.cpp @@ -10,14 +10,154 @@ sosc::TcpClient::TcpClient() { this->addr_len = -1; } -bool sosc::TcpClient::Init(std::string host, std::uint16_t port) { +bool sosc::TcpClient::Open(std::string host, std::uint16_t port) { if(this->sock_open) return false; - struct addrinfo hints, *result, *ptr; + struct addrinfo hints, *results, *ptr; + bzero((char*)&hints, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + if(getaddrinfo(host.c_str(), TOSTR(port).c_str(), &hints, &results) != 0) + return false; + + for(ptr = results; ptr != NULL; ptr = ptr->ai_next) { + this->sock = socket(ptr->ai_family, + ptr->ai_socktype, ptr->ai_protocol); + + if(this->sock < 0) { + freeaddrinfo(results); + return false; + } + + if(connect(this->sock, ptr->ai_addr, (int)ptr->ai_addrlen) == 0) + break; + + close(this->sock); + this->sock = -1; + } + + freeaddrinfo(results); + if(this->sock < 0) + return false; + + this->sock_open = true; return true; } +void sosc::TcpClient::Open + (SOSC_SOCK_T sock, SOSC_ADDR_T addr, int addr_len) +{ + if(this->sock_open) + return; + + this->sock = sock; + this->sock_open = true; + + this->addr = addr; + this->addr_len = addr_len; + + char buffer[128]; + inet_ntop(addr.sin_family, (void*)&addr.sin_addr, buffer, 128); + this->ip.Parse(buffer); +} + +int sosc::TcpClient::Receive(std::string* str, int flags) { + if(!this->sock_open) + return -1; + + bool append = (flags & SOSC_TCP_APPEND) != 0, + block = (flags & SOSC_TCP_BLOCK) != 0; + + int total_length = 0; + bool first_recv = true; + while(block ? (first_recv ? true : this->IsDataReady()) + : this->IsDataReady()) + { + int length = recv(this->sock, this->buffer, SOSC_TCP_BUFLEN, 0); + if(length <= 0) { + this->Close(); + return -1; + } + + if(first_recv && !append) + *str = std::string(this->buffer, length); + else + *str += std::string(this->buffer, length); + + total_length += length; + first_recv = false; + } + + return total_length; +} + +int sosc::TcpClient::Send(const std::string& str) { + if(!this->sock_open) + return -1; + + std::string::size_type total_sent = 0; + while(total_sent < str.length()) { + int sent = total_sent == 0 + ? send(this->sock, str.c_str(), str.length(), 0) + : send(this->sock, str.substr(total_sent).c_str(), + str.length() - total_sent, 0); + + if(sent == -1) { + this->Close(); + return -1; + } else + total_sent += sent; + } + + return 0; +} + +bool sosc::TcpClient::IsDataReady() { + if(!this->sock_open) + return false; + + this->SetBlocking(false); + int check = recv(this->sock, this->buffer, 1, MSG_PEEK), + error = errno; + this->SetBlocking(true); + + if(check <= 0) { + if(check != 0 && (error == EWOULDBLOCK || error == EAGAIN)) + return false; + else { + this->Close(); + return false; + } + } else + return true; +} + +void sosc::TcpClient::SetBlocking(bool will_block) { + if(!this->sock_open) + return; + + int flags = fcntl(this->sock, F_GETFL, 0); + flags = will_block ? flags & ~O_NONBLOCK + : flags | O_NONBLOCK; + fcntl(this->sock, F_SETFL, flags); +} + +void sosc::TcpClient::Close() { + if(!this->sock_open) + return; + + this->sock_open = false; + shutdown(this->sock, SHUT_RDWR); + close(this->sock); +} + +sosc::TcpClient::~TcpClient() { + this->Close(); +} + /****************************/ /* END TCPCLIENT CODE */ /****************************/ @@ -25,7 +165,77 @@ bool sosc::TcpClient::Init(std::string host, std::uint16_t port) { /****************************/ sosc::TcpServer::TcpServer() { + this->sock_open = false; +} + +bool sosc::TcpServer::Listen(uint16_t port) { + if(this->sock_open) + return false; + struct addrinfo hints, *result; + bzero((char*)&hints, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + hints.ai_flags = AI_PASSIVE; + + if(getaddrinfo(NULL, TOSTR(port).c_str(), &hints, &result) != 0) + return false; + + this->sock = socket(result->ai_family, + result->ai_socktype, result->ai_protocol); + + if(this->sock < 0) { + freeaddrinfo(result); + return false; + } + + if(bind(this->sock, result->ai_addr, (int)result->ai_addrlen) < 0) { + freeaddrinfo(result); + close(this->sock); + return false; + } + + freeaddrinfo(result); + if(listen(this->sock, SOMAXCONN) < 0) { + close(this->sock); + return false; + } + + this->sock_open = true; + return true; +} + +int sosc::TcpServer::Accept(TcpClient* client) { + if(!this->sock_open) + return -1; + + SOSC_SOCK_T sock; + SOSC_ADDR_T addr; + unsigned int addr_len = sizeof(addr); + + sock = accept(this->sock, (struct sockaddr*)&addr, &addr_len); + if(sock < 0) { + this->Close(); + return -1; + } + + client->Close(); + client->Open(sock, addr, addr_len); + return 0; +} + +void sosc::TcpServer::Close() { + if(!this->sock_open) + return; + + this->sock_open = false; + shutdown(this->sock, SHUT_RDWR); + close(this->sock); +} + +sosc::TcpServer::~TcpServer() { + this->Close(); } /****************************/ diff --git a/server/src/sock/tcpsock_win.cpp b/server/src/sock/tcpsock_win.cpp index 9b54442..1cbf5cd 100644 --- a/server/src/sock/tcpsock_win.cpp +++ b/server/src/sock/tcpsock_win.cpp @@ -1,7 +1,7 @@ #include "tcpsock.hpp" #ifdef _WIN32 -void init_wsa() { +static void init_wsa() { static bool is_inited = false; if(is_inited) return; @@ -80,7 +80,7 @@ void sosc::TcpClient::Open this->ip.Parse(buffer); } -int sosc::TcpClient::Recv(std::string* str, bool append) { +int sosc::TcpClient::Receive(std::string* str, bool append) { if(!this->sock_open) return -1; diff --git a/server/src/sock/websock.cpp b/server/src/sock/websock.cpp index 8b13789..703da89 100644 --- a/server/src/sock/websock.cpp +++ b/server/src/sock/websock.cpp @@ -1 +1 @@ - +#include "websock.hpp" diff --git a/server/src/sock/websock.hpp b/server/src/sock/websock.hpp index 90b6e7b..bf07f01 100644 --- a/server/src/sock/websock.hpp +++ b/server/src/sock/websock.hpp @@ -1,6 +1,16 @@ #ifndef SOSC_WEBSOCK_H #define SOSC_WEBSOCK_H +#include "tcpsock.hpp" +namespace sosc { +class WebSocketClient { + +}; + +class WebSocketServer { + +}; +} #endif