1er commit
This commit is contained in:
167
include/network/DataBuffer.h
Normal file
167
include/network/DataBuffer.h
Normal file
@@ -0,0 +1,167 @@
|
||||
#ifndef MCLIB_COMMON_DATA_BUFFER_H_
|
||||
#define MCLIB_COMMON_DATA_BUFFER_H_
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
||||
namespace td{
|
||||
|
||||
class DataBuffer{
|
||||
private:
|
||||
typedef std::vector<std::uint8_t> Data;
|
||||
Data m_Buffer;
|
||||
std::size_t m_ReadOffset = 0;
|
||||
|
||||
public:
|
||||
typedef Data::iterator iterator;
|
||||
typedef Data::const_iterator const_iterator;
|
||||
typedef Data::reference reference;
|
||||
typedef Data::const_reference const_reference;
|
||||
|
||||
DataBuffer();
|
||||
DataBuffer(const DataBuffer& other);
|
||||
DataBuffer(const DataBuffer& other, std::size_t offset);
|
||||
DataBuffer(DataBuffer&& other);
|
||||
DataBuffer(const std::string& str);
|
||||
|
||||
DataBuffer& operator=(const DataBuffer& other);
|
||||
DataBuffer& operator=(DataBuffer&& other);
|
||||
|
||||
template <typename T>
|
||||
void Append(T data){
|
||||
std::size_t size = sizeof(data);
|
||||
std::size_t end_pos = m_Buffer.size();
|
||||
m_Buffer.resize(m_Buffer.size() + size);
|
||||
memcpy(&m_Buffer[end_pos], &data, size);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
DataBuffer& operator<<(T data){
|
||||
// Switch to big endian
|
||||
//std::reverse((std::uint8_t*)&data, (std::uint8_t*)&data + sizeof(T));
|
||||
Append(data);
|
||||
return *this;
|
||||
}
|
||||
|
||||
DataBuffer& operator<<(std::string str){
|
||||
m_Buffer.insert(m_Buffer.end(), str.begin(), str.end());
|
||||
return *this;
|
||||
}
|
||||
|
||||
DataBuffer& operator<<(DataBuffer& data){
|
||||
m_Buffer.insert(m_Buffer.end(), data.begin(), data.end());
|
||||
return *this;
|
||||
}
|
||||
|
||||
DataBuffer& operator<<(const DataBuffer& data){
|
||||
m_Buffer.insert(m_Buffer.end(), data.begin(), data.end());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
DataBuffer& operator>>(T& data){
|
||||
assert(m_ReadOffset + sizeof(T) <= GetSize());
|
||||
data = *(T*)&m_Buffer[m_ReadOffset];
|
||||
//std::reverse((std::uint8_t*)&data, (std::uint8_t*)&data + sizeof(T));
|
||||
m_ReadOffset += sizeof(T);
|
||||
return *this;
|
||||
}
|
||||
|
||||
DataBuffer& operator>>(DataBuffer& data){
|
||||
data.Resize(GetSize() - m_ReadOffset);
|
||||
std::copy(m_Buffer.begin() + m_ReadOffset, m_Buffer.end(), data.begin());
|
||||
m_ReadOffset = m_Buffer.size();
|
||||
return *this;
|
||||
}
|
||||
|
||||
DataBuffer& operator>>(std::string& str){
|
||||
std::size_t stringSize = strlen((const char*) m_Buffer.data() + m_ReadOffset) + 1; // including null character
|
||||
str.resize(stringSize);
|
||||
std::copy(m_Buffer.begin() + m_ReadOffset, m_Buffer.begin() + m_ReadOffset + stringSize, str.begin());
|
||||
m_ReadOffset += stringSize;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void ReadSome(char* buffer, std::size_t amount){
|
||||
assert(m_ReadOffset + amount <= GetSize());
|
||||
std::copy_n(m_Buffer.begin() + m_ReadOffset, amount, buffer);
|
||||
m_ReadOffset += amount;
|
||||
}
|
||||
|
||||
void ReadSome(std::uint8_t* buffer, std::size_t amount){
|
||||
assert(m_ReadOffset + amount <= GetSize());
|
||||
std::copy_n(m_Buffer.begin() + m_ReadOffset, amount, buffer);
|
||||
m_ReadOffset += amount;
|
||||
}
|
||||
|
||||
void ReadSome(DataBuffer& buffer, std::size_t amount){
|
||||
assert(m_ReadOffset + amount <= GetSize());
|
||||
buffer.Resize(amount);
|
||||
std::copy_n(m_Buffer.begin() + m_ReadOffset, amount, buffer.begin());
|
||||
m_ReadOffset += amount;
|
||||
}
|
||||
|
||||
void ReadSome(std::string& buffer, std::size_t amount){
|
||||
assert(m_ReadOffset + amount <= GetSize());
|
||||
buffer.resize(amount);
|
||||
std::copy_n(m_Buffer.begin() + m_ReadOffset, amount, buffer.begin());
|
||||
m_ReadOffset += amount;
|
||||
}
|
||||
|
||||
void Resize(std::size_t size){
|
||||
m_Buffer.resize(size);
|
||||
}
|
||||
|
||||
void Reserve(std::size_t amount){
|
||||
m_Buffer.reserve(amount);
|
||||
}
|
||||
|
||||
void erase(iterator it){
|
||||
m_Buffer.erase(it);
|
||||
}
|
||||
|
||||
void Clear(){
|
||||
m_Buffer.clear();
|
||||
m_ReadOffset = 0;
|
||||
}
|
||||
|
||||
bool IsFinished() const{
|
||||
return m_ReadOffset >= m_Buffer.size();
|
||||
}
|
||||
|
||||
std::uint8_t* data(){
|
||||
return m_Buffer.data();
|
||||
}
|
||||
|
||||
const std::uint8_t* data() const{
|
||||
return m_Buffer.data();
|
||||
}
|
||||
|
||||
std::size_t GetReadOffset() const{ return m_ReadOffset; }
|
||||
void SetReadOffset(std::size_t pos);
|
||||
|
||||
std::string ToString() const;
|
||||
std::size_t GetSize() const;
|
||||
bool IsEmpty() const;
|
||||
std::size_t GetRemaining() const;
|
||||
|
||||
iterator begin();
|
||||
iterator end();
|
||||
const_iterator begin() const;
|
||||
const_iterator end() const;
|
||||
|
||||
reference operator[](Data::size_type i){ return m_Buffer[i]; }
|
||||
const_reference operator[](Data::size_type i) const{ return m_Buffer[i]; }
|
||||
|
||||
bool ReadFile(const std::string& fileName);
|
||||
bool WriteFile(const std::string& fileName);
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const DataBuffer& buffer);
|
||||
|
||||
} // ns td
|
||||
|
||||
#endif
|
||||
56
include/network/IPAddress.h
Normal file
56
include/network/IPAddress.h
Normal file
@@ -0,0 +1,56 @@
|
||||
#ifndef NETWORK_IPADDRESS_H_
|
||||
#define NETWORK_IPADDRESS_H_
|
||||
|
||||
#include <string>
|
||||
#include <iosfwd>
|
||||
#include <vector>
|
||||
|
||||
namespace td {
|
||||
namespace network {
|
||||
|
||||
/* IPv4 address */
|
||||
class IPAddress {
|
||||
private:
|
||||
std::uint32_t m_Address;
|
||||
bool m_Valid;
|
||||
|
||||
public:
|
||||
/* Create an invalid address */
|
||||
IPAddress() noexcept;
|
||||
|
||||
/* Initialize by string IP */
|
||||
IPAddress(const std::string& str);
|
||||
|
||||
/* Initialize by string IP */
|
||||
IPAddress(const std::wstring& str);
|
||||
|
||||
/* Initialize by octets */
|
||||
IPAddress(std::uint8_t octet1, std::uint8_t octet2, std::uint8_t octet3, std::uint8_t octet4) noexcept;
|
||||
|
||||
/* Get the specific octet. 1-4 */
|
||||
std::uint8_t GetOctet(std::uint8_t num) const;
|
||||
|
||||
/* Set the specific octet. 1-4 */
|
||||
void SetOctet(std::uint8_t num, std::uint8_t value);
|
||||
|
||||
/* Make sure the IP is valid. It will be invalid if the host wasn't found. */
|
||||
bool IsValid() const noexcept { return m_Valid; }
|
||||
|
||||
std::string ToString() const;
|
||||
|
||||
static IPAddress LocalAddress();
|
||||
|
||||
bool operator==(const IPAddress& right);
|
||||
bool operator!=(const IPAddress& right);
|
||||
bool operator==(bool b);
|
||||
};
|
||||
|
||||
typedef std::vector<IPAddress> IPAddresses;
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const IPAddress& addr);
|
||||
std::wostream& operator<<(std::wostream& os, const IPAddress& addr);
|
||||
|
||||
} // ns network
|
||||
} // ns td
|
||||
|
||||
#endif
|
||||
32
include/network/Network.h
Normal file
32
include/network/Network.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef NETWORK_NETWORK_H_
|
||||
#define NETWORK_NETWORK_H_
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <ws2tcpip.h>
|
||||
#pragma comment(lib, "ws2_32.lib")
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include "network/Socket.h"
|
||||
#include "network/IPAddress.h"
|
||||
#include "network/UDPSocket.h"
|
||||
#include "network/TCPSocket.h"
|
||||
|
||||
namespace td {
|
||||
namespace network {
|
||||
|
||||
class Dns {
|
||||
public:
|
||||
static IPAddresses Resolve(const std::string& host);
|
||||
};
|
||||
|
||||
} // ns network
|
||||
} // ns td
|
||||
|
||||
#endif
|
||||
90
include/network/Socket.h
Normal file
90
include/network/Socket.h
Normal file
@@ -0,0 +1,90 @@
|
||||
#ifndef NETWORK_SOCKET_H_
|
||||
#define NETWORK_SOCKET_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#include "network/DataBuffer.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <ws2tcpip.h>
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
|
||||
#define closesocket close
|
||||
#endif
|
||||
|
||||
#ifndef INVALID_SOCKET
|
||||
#define INVALID_SOCKET -1
|
||||
#endif
|
||||
|
||||
#define REMOVE_COPY(className) \
|
||||
className(const className &) = delete;\
|
||||
className& operator=(const className &) = delete
|
||||
|
||||
namespace td {
|
||||
namespace network {
|
||||
|
||||
class IPAddress;
|
||||
|
||||
typedef int SocketHandle;
|
||||
|
||||
class Socket {
|
||||
public:
|
||||
enum Status { Connected, Disconnected, Error };
|
||||
enum Type { TCP, UDP };
|
||||
|
||||
private:
|
||||
bool m_Blocking;
|
||||
Type m_Type;
|
||||
Status m_Status;
|
||||
|
||||
protected:
|
||||
SocketHandle m_Handle;
|
||||
|
||||
Socket(Type type);
|
||||
void SetStatus(Status status);
|
||||
|
||||
public:
|
||||
virtual ~Socket();
|
||||
|
||||
Socket(Socket&& rhs) = default;
|
||||
Socket& operator=(Socket&& rhs) = default;
|
||||
|
||||
bool SetBlocking(bool block);
|
||||
bool IsBlocking() const noexcept;
|
||||
|
||||
Type GetType() const noexcept;
|
||||
Status GetStatus() const noexcept;
|
||||
SocketHandle GetHandle() const noexcept;
|
||||
|
||||
bool Connect(const std::string& ip, std::uint16_t port);
|
||||
virtual bool Connect(const IPAddress& address, std::uint16_t port) = 0;
|
||||
|
||||
void Disconnect();
|
||||
|
||||
std::size_t Send(const std::string& data);
|
||||
std::size_t Send(DataBuffer& buffer);
|
||||
|
||||
virtual std::size_t Send(const uint8_t* data, std::size_t size) = 0;
|
||||
virtual DataBuffer Receive(std::size_t amount) = 0;
|
||||
|
||||
virtual std::size_t Receive(DataBuffer& buffer, std::size_t amount) = 0;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<Socket> SocketPtr;
|
||||
|
||||
} // ns network
|
||||
} // ns td
|
||||
|
||||
#endif
|
||||
|
||||
34
include/network/TCPListener.h
Normal file
34
include/network/TCPListener.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
#include "TCPSocket.h"
|
||||
|
||||
namespace td{
|
||||
namespace network{
|
||||
|
||||
class TCPListener{
|
||||
int m_Handle;
|
||||
std::uint16_t m_Port;
|
||||
int m_MaxConnections;
|
||||
|
||||
public:
|
||||
TCPListener();
|
||||
~TCPListener();
|
||||
|
||||
bool listen(std::uint16_t port, int maxConnections);
|
||||
bool accept(TCPSocket& newSocket);
|
||||
|
||||
void destroy();
|
||||
bool close();
|
||||
bool setBlocking(bool blocking);
|
||||
|
||||
std::uint16_t getListeningPort() const{
|
||||
return m_Port;
|
||||
}
|
||||
int getMaximumConnections() const{
|
||||
return m_MaxConnections;
|
||||
}
|
||||
|
||||
REMOVE_COPY(TCPListener);
|
||||
};
|
||||
|
||||
} // namespace network
|
||||
} // namespace td
|
||||
39
include/network/TCPSocket.h
Normal file
39
include/network/TCPSocket.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef NETWORK_TCP_SOCKET_H_
|
||||
#define NETWORK_TCP_SOCKET_H_
|
||||
|
||||
#include "network/IPAddress.h"
|
||||
#include "network/Socket.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace td {
|
||||
namespace network {
|
||||
|
||||
class TCPListener;
|
||||
|
||||
class TCPSocket : public Socket {
|
||||
private:
|
||||
IPAddress m_RemoteIP;
|
||||
uint16_t m_Port;
|
||||
sockaddr_in m_RemoteAddr;
|
||||
|
||||
public:
|
||||
TCPSocket();
|
||||
TCPSocket(TCPSocket&& other);
|
||||
|
||||
virtual bool Connect(const IPAddress& address, std::uint16_t port);
|
||||
virtual std::size_t Send(const std::uint8_t* data, std::size_t size);
|
||||
virtual DataBuffer Receive(std::size_t amount);
|
||||
virtual std::size_t Receive(DataBuffer& buffer, std::size_t amount);
|
||||
|
||||
REMOVE_COPY(TCPSocket);
|
||||
|
||||
friend class TCPListener;
|
||||
};
|
||||
|
||||
void SendPacket(const DataBuffer& data, network::TCPSocket& socket);
|
||||
|
||||
} // ns network
|
||||
} // ns td
|
||||
|
||||
#endif
|
||||
29
include/network/UDPSocket.h
Normal file
29
include/network/UDPSocket.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef NETWORK_UDP_SOCKET_H_
|
||||
#define NETWORK_UDP_SOCKET_H_
|
||||
|
||||
#include "network/IPAddress.h"
|
||||
#include "network/Socket.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace td {
|
||||
namespace network {
|
||||
|
||||
class UDPSocket : public Socket {
|
||||
private:
|
||||
IPAddress m_RemoteIP;
|
||||
uint16_t m_Port;
|
||||
sockaddr_in m_RemoteAddr;
|
||||
|
||||
public:
|
||||
UDPSocket();
|
||||
|
||||
bool Connect(const IPAddress& address, std::uint16_t port);
|
||||
std::size_t Send(const std::uint8_t* data, std::size_t size);
|
||||
DataBuffer Receive(std::size_t amount);
|
||||
};
|
||||
|
||||
} // ns network
|
||||
} // ns td
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user