1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
#include <Networking/TCPClient.hpp>
#include <UserExperience/UserInterface.hpp>
namespace Networking
{
// We will only receive up to 256 bytes per cycle.
constexpr int BufferSize = 256;
void TCPClient::SendRawBytes(ByteArray &Bytes)
{
// Send data.
int32_t Result = send(m_Socket, (char *)Bytes.data(), (int)Bytes.size(), 0);
if(Result == -1)
INFO_ASSERT(STR("[000F:00002B00] Server closed the connection unexpectedly."));
}
ByteArray TCPClient::ReceiveRawBytes()
{
ByteArray ReceivedBytes;
uint8_t RecvBuffer[BufferSize];
// Attempt to receive a packet.
while(true)
{
int32_t Received = recv(m_Socket, (char*)RecvBuffer, BufferSize, 0);
// No more bytes left to receive.
if(Received < 0)
break;
// Emplace all received bytes.
for(int n = 0; n < Received; ++n)
{
ReceivedBytes.push_back(RecvBuffer[n]);
}
// No more bytes left to receive.
if(Received < BufferSize)
break;
}
// Stay in sync with client.
ByteArray Array = { 1 };
SendRawBytes(Array);
return ReceivedBytes;
}
void TCPClient::SendBytes(ByteArray &Bytes)
{
// Encrypt outgoing data.
ByteArray EncryptionKey;
EncryptionKey.insert(
EncryptionKey.begin(),
m_EncryptionKey,
m_EncryptionKey + sizeof m_EncryptionKey
);
Wrapper::Encryption Encryption; Encryption.Start(EncryptionKey);
ByteArray Encrypted = Encryption.Encrypt(Bytes);
SendRawBytes(Encrypted);
}
ByteArray TCPClient::ReceiveBytes()
{
// Decrypt incoming data.
ByteArray ReceivedBytes = ReceiveRawBytes();
ByteArray EncryptionKey;
EncryptionKey.insert(
EncryptionKey.begin(),
m_EncryptionKey,
m_EncryptionKey + sizeof m_EncryptionKey
);
Wrapper::Encryption Encryption; Encryption.Start(EncryptionKey);
ByteArray Decrypted = Encryption.Decrypt(ReceivedBytes);
return Decrypted;
}
bool TCPClient::Start(uint32_t ServerAddress, uint16_t ServerPort)
{
const int32_t version = 0x101;
// Initialise WinSocks.
if(WSAStartup(version, &m_WinSocks))
return false;
// Create an IPv4 socket.
m_Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(m_Socket == INVALID_SOCKET)
return false;
// Set up client context.
m_Context.sin_addr.s_addr = ServerAddress;
m_Context.sin_family = AF_INET;
m_Context.sin_port = htons(ServerPort);
// Attempt connection.
if(connect(m_Socket, (sockaddr *)&m_Context, sizeof m_Context))
return false;
// Initialise encryption wrapper.
ByteArray EncryptionKey = ReceiveRawBytes();
if(EncryptionKey.empty())
return false;
std::memcpy(m_EncryptionKey, EncryptionKey.data(), EncryptionKey.size());
return true;
}
void TCPClient::Kill()
{
if(m_Socket)
closesocket(m_Socket);
WSACleanup();
}
}
|