Files
VoidNet/src/TcpClientWindows.cpp
xX-TheDoctor-Xx e5ca02be0d TcpServer's OnMessage is now an vector called OnMessageFunctions, each plugin will occupy an index in this vector
Readded receive_data method to VoidNetClient.hpp
Minor fixes
2016-08-15 17:46:29 +01:00

162 lines
4.2 KiB
C++

#include "TcpClient.hpp"
#include "Utility.hpp"
#include "Config.hpp"
#include "Handshake.hpp"
#include <iostream>
TcpClient::TcpClient(const SOCKET & socket)
{
tcp_socket = socket;
}
bool TcpClient::initialize(const std::string &ip, uint16 port)
{
if (ip.size() == 0 || std::count(ip.begin(), ip.end(), '.') != 4)
return false;
if (port == 0)
return false;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
uint16 code = getaddrinfo(ip.c_str(), std::to_string(port).c_str(), &hints, &result);
if (code != 0)
{
if (Config::GetUsingConsole())
std::cerr << code << std::endl; // display more info
WSACleanup();
return false;
}
tcp_socket = ::socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (tcp_socket == INVALID_SOCKET)
{
if (Config::GetUsingConsole())
std::cerr << WSAGetLastError() << std::endl; // display more info
freeaddrinfo(result);
WSACleanup();
return false;
}
return initialized = true;
}
TcpClient::~TcpClient()
{
freeaddrinfo(result);
WSACleanup();
Utility::Delete(result);
}
void TcpClient::Shutdown()
{
NetworkMessage message;
message.sender = id;
message.distribution_mode = Server;
message.tag = DISCONNECT;
SendMessage(message);
uint16 code = closesocket(tcp_socket);
if (code == SOCKET_ERROR)
{
if (Config::GetUsingConsole())
std::cerr << WSAGetLastError() << std::endl; // display more info
}
closesocket(tcp_socket);
WSACleanup();
}
bool TcpClient::Connect()
{
if (!initialized)
{
if (ip.size() == 0 || std::count(ip.begin(), ip.end(), '.') != 4 && port == 0 && !initialize(ip, port))
return false;
}
else return false;
uint16 connect_code = connect(tcp_socket, result->ai_addr, result->ai_addrlen);
if (connect_code == SOCKET_ERROR)
return false;
NetworkBuffer buffer(receive_data_array());
if (buffer.valid)
{
Handshake handshake = Handshake::DecodeHandshake(buffer.body);
if (handshake.con_code == ConnectionCode::Accept)
{
receive = true;
OnConnect(handshake.id);
return true;
}
}
return false;
}
bool TcpClient::DataAvailable(int32 &size)
{
return ioctlsocket(tcp_socket, FIONREAD, reinterpret_cast<u_long*>(size)) != NO_ERROR && size > 0;
}
const NetworkBuffer &TcpClient::receive_data_array()
{
NetworkBuffer buffer;
int32 temp;
if (DataAvailable(temp) && temp > sizeof(int32))
{
byte *header = new byte[sizeof(int32)]();
if (recv(tcp_socket, reinterpret_cast<char*>(header), sizeof(int32), 0) != sizeof(int32))
//invalid header
return NetworkBuffer();
buffer.header = std::vector<byte>(header, header + sizeof(int32));
}
else
return NetworkBuffer();
int32 body_size = Utility::BitConverter::ToInt32(buffer.header);
byte *body = new byte[body_size]();
int16 received_bytes = recv(tcp_socket, reinterpret_cast<char*>(body), body_size, 0);
if (received_bytes == SOCKET_ERROR || received_bytes != body_size || WSAGetLastError() != 0)
{
//there was a problem receiving the body of the message or theres no body to receive
return NetworkBuffer();
}
buffer.body = std::vector<byte>(body, body + body_size);
buffer.valid = true;
return buffer;
}
void TcpClient::send_network_message(const NetworkMessage &message, TcpClient *client)
{
NetworkBuffer buffer = NetworkMessage::EncodeMessage(message);
int32 lenght = Utility::BitConverter::ToInt32(buffer.header);
int32 bytes_sent = send(client->tcp_socket, reinterpret_cast<char*>(buffer.body.data()), lenght, 0);
if (bytes_sent == SOCKET_ERROR || bytes_sent != lenght || WSAGetLastError() != 0)
{
//something went wrong couldnt send anything/some data
}
}
void TcpClient::SendBytes(const std::vector<byte>& bytes)
{
int32 bytes_sent = send(tcp_socket, reinterpret_cast<const char*>(bytes.data()), bytes.size(), 0);
if (bytes_sent == SOCKET_ERROR || bytes_sent != bytes.size() || WSAGetLastError() != 0)
{
//something went wrong couldnt send anything/some data
}
}
void TcpClient::SendBytes(byte * bytes, uint32 size)
{
int32 bytes_sent = send(tcp_socket, reinterpret_cast<const char*>(bytes), size, 0);
if (bytes_sent == SOCKET_ERROR || bytes_sent != size || WSAGetLastError() != 0)
{
//something went wrong couldnt send anything/some data
}
}