frnetlib/src/Socket.cpp
Fred Nicolson e0e956cf78 Socket::reconfigure_socket called on connection to apply options
'TCP_NODELAY' is set automatically on connection now.
2016-12-31 11:14:26 +00:00

108 lines
2.8 KiB
C++

//
// Created by fred on 06/12/16.
//
#include <netinet/tcp.h>
#include "frnetlib/Socket.h"
namespace fr
{
#ifdef _WIN32
WSADATA Socket::wsaData = WSADATA();
uint32_t Socket::instance_count = 0;
#endif // _WIN32
Socket::Socket() noexcept
: is_blocking(true),
is_connected(false)
{
#ifdef _WIN32
if(instance_count == 0)
{
int wsa_result = WSAStartup(MAKEWORD(2, 2), &wsaData);
if(wsa_result != 0)
{
std::cout << "Failed to initialise WSA." << std::endl;
return;
}
}
instance_count++;
#endif // _WIN32
}
Socket::Status Socket::send(const Packet &packet)
{
if(!is_connected)
return Socket::Disconnected;
//Get packet data
std::string data = packet.get_buffer();
//Prepend packet length
uint32_t length = htonl((uint32_t)data.size());
data.insert(0, "1234");
memcpy(&data[0], &length, sizeof(uint32_t));
//Send it
return send_raw(data.c_str(), data.size());
}
Socket::Status Socket::receive(Packet &packet)
{
if(!is_connected)
return Socket::Disconnected;
Socket::Status status;
//Try to read packet length
uint32_t packet_length = 0;
status = receive_all(&packet_length, sizeof(packet_length));
if(status != Socket::Status::Success)
return status;
packet_length = ntohl(packet_length);
//Now we've got the length, read the rest of the data in
std::string data(packet_length, 'c');
status = receive_all(&data[0], packet_length);
if(status != Socket::Status::Success)
return status;
//Set the packet to what we've read
packet.set_buffer(std::move(data));
return Socket::Status::Success;
}
Socket::Status Socket::receive_all(void *dest, size_t buffer_size)
{
if(!is_connected)
return Socket::Disconnected;
ssize_t bytes_remaining = buffer_size;
size_t bytes_read = 0;
while(bytes_remaining > 0)
{
size_t received = 0;
char *arr = (char*)dest;
Status status = receive_raw(&arr[bytes_read], (size_t)bytes_remaining, received);
if(status != fr::Socket::Success)
return status;
bytes_remaining -= received;
bytes_read += received;
}
return Socket::Status::Success;
}
void Socket::shutdown()
{
::shutdown(get_socket_descriptor(), 0);
}
void Socket::reconfigure_socket()
{
//todo: Perhaps allow for these settings to be modified
int one = 1;
setsockopt(get_socket_descriptor(), SOL_TCP, TCP_NODELAY, &one, sizeof(one));
}
}