-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathNetChannel.h
290 lines (240 loc) · 6.64 KB
/
NetChannel.h
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
#ifndef _NET_CHANNEL_
#define _NET_CHANNEL_
#include <queue>
#include <thread>
#include <map>
#include <mutex>
#include "Sockets.h"
#include "NetDefines.h"
#include "NetMsg.h"
//allows proper handling of wrap around
inline int modulus(int x, int m) {
int r = x%m;
return r < 0 ? r + m : r;
}
//data structures
struct Packet
{
bool reliable;
char* data;
int size;
};
struct RPacket//reliable packet structure
{
char* data;
int size;
unsigned int sendtime;
bool recieved;
unsigned int sequence;
unsigned short resends;
int fragment;
int numfragments;
//stores ordered sequence and channel
signed char channel;
unsigned int channel_sequence;
};
//used to reassemble fragments
struct Fragment
{
char* data;
int frags_recieved;
int num_frags;
int sequence;
int curpos;//used for split packets
};
enum NetConstants
{
NumberAcks = 32,//must be the number of bits in an integer or less
//the real number of acks per message is one more than this
NumberWindows = NumberAcks + 1,//dont change this
MaxUnsentAcks = NumberAcks / 2,//number of unsent acks to build up before forcing a ack packet
//these must be < 32, as must fit in an int
ReliableFlagBit = 31,
FragmentFlagBit = 30,
OrderedFlagBit = 29,
MaxSequenceNumber = 33*82, //536870895,//must be a multiple of 33 and less than 2^OrderedFlagBit
NumberReliableFragments = (NumberWindows+8)/2,//20,//must be >= (numwindows+1)/2
SplitFlagBit = 15,//must be less than or equal to max bit number of a short (<= 15)
};
bool sequence_more_recent(unsigned int s1, unsigned int s2);
//this handles data sending, needs to be symmetrical, so one on server
//for each client, and one on client
class NetChannel
{
friend class NetConnection;
friend class Peer;
//ping stuff
unsigned int lastpingtime;
unsigned int rtt;//in ms
//need to calculate and store RTT
//lets add a sequence number to all packets
//and keep list of last idk, 64 with sequence numbers, send times and a space for recieve time
//then calculate RTT from those
std::mutex sendingmutex;//lock this when messing with queues
std::queue<Packet> sending;
std::queue<RPacket> reliable_sending;
bool acks[NumberAcks];//stores if we got last 32 packets
RPacket window[NumberWindows];//sliding window of reliable packets
unsigned char split_sequence;
int sequence, recieved_sequence, last_acked;
int unsent_acks;
Fragment unreliable_fragment;//only supports one at a time
Fragment reliable_frags[NumberReliableFragments];//need to have half the number of these as the number of window frames, so (numwindows+1)/2
//lets just give 16 channels for now
//this stores reliable packets for reordering
int incoming_ordered_sequence[16];
int outgoing_ordered_sequence[16];//this stores last recieved packet in order on each stream
//when get complete packet, if one larger than ordered_Sequence, increment it and push to recieve
//then check ordered_buffer if any packets can now be pushed out, increment if needed
//if more than one larger, push to ordered_buffer
std::map<int, Packet> ordered_buffer[16];
bool server;
Socket* connection;
public:
unsigned int lastreceivetime;
unsigned int lastsendtime;
int state;
Address remoteaddr;
NetChannel()
{
this->Init();
}
~NetChannel()
{
this->Cleanup();
}
void Init();
void Cleanup();
//todo, lets make this work
void Send(char* data, int size)
{
//ok, we need to make copy of data
char* tmp = new char[size];
memcpy(tmp, data, size);
Packet p;
p.size = size;
p.data = tmp;
p.reliable = false;
sendingmutex.lock();
sending.push(p);
sendingmutex.unlock();
}
void Send(char id, char* data, int size)
{
char* tmp = new char[size + 1];
memcpy(tmp + 1, data, size);
tmp[0] = id;
Packet p;
p.size = size + 1;
p.data = tmp;
p.reliable = false;
sendingmutex.lock();
sending.push(p);
sendingmutex.unlock();
}
void SendOOB(char* data, int size)
{
//need to form the packet
char* tmp = new char[size + 4];
NetMsg msg(size + 4, tmp);
msg.WriteInt(-1);//is OOB;
msg.WriteData(data, size);
this->connection->Send(this->remoteaddr, tmp, size + 4);
delete[] tmp;
}
void SendReliable(char* data, int size)
{
//ok, we need to make copy of data
char* tmp = new char[size];
memcpy(tmp, data, size);
RPacket p;
p.size = size;
p.data = tmp;
p.recieved = false;
p.sendtime = 0;
p.sequence = 0;
p.resends = 0;
p.fragment = p.numfragments = 0;
p.channel = -1;//tell system this is not ordered
sendingmutex.lock();
reliable_sending.push(p);
sendingmutex.unlock();
}
void SendReliableOrdered(char* data, int size, unsigned char channel = 0)
{
char* tmp = new char[size];
memcpy(tmp, data, size);
RPacket p;
p.size = size;
p.data = tmp;
p.recieved = false;
p.sendtime = 0;
p.resends = 0;
p.fragment = p.numfragments = 0;
p.channel = channel;
p.sequence = 0;//will fill in later
sendingmutex.lock();
reliable_sending.push(p);
sendingmutex.unlock();
}
//this calls sendreliables
void SendPackets();
private:
void SendReliables();
//little wrapper to keep track of stuff, use me
inline void Send(const Address& addr, const char* data, const int size)
{
this->lastsendtime = NetGetTime();//keeps track of how often to send keep alives
this->connection->Send(addr, data, size);
}
inline void ProcessAck(int ack, int ackbits)
{
//error check
if (sequence_more_recent(ack, this->sequence))// ack > this->sequence)
{
netlog("[NetChan] ERROR: Got ack larger than was ever sent!!\n");
return;
}
//process primary ack number
if (sequence_more_recent(ack, this->last_acked))//ack > this->last_acked)
{
this->last_acked = ack;
for (int i2 = 0; i2 < NumberWindows; i2++)
{
if (window[i2].sequence == ack && window[i2].recieved == false)
{
#ifdef NET_VERBOSE_DEBUG
netlogf("[%s] Got ack for %d\n", this->server ? "Server" : "Client", ack);
#endif
window[i2].recieved = true;
break;
}
}
}
//then process the acks
for (int i = 0; i < NumberAcks; i++)
{
int acked = ackbits & 1 << i;
int id = ack - (NumberAcks - i);
if (acked && id >= 0)
{
for (int i2 = 0; i2 < NumberWindows; i2++)
{
if (window[i2].sequence == id && window[i2].recieved == false)
{
#ifdef NET_VERBOSE_DEBUG
netlogf("[%s] Got ack for %d\n", this->server ? "Server" : "Client", id);
#endif
window[i2].recieved = true;
break;
}
}
}
}
}
int GetAckBits();
//returns if should use packet, is false if is duplicate
bool ProcessHeader(char* data, int size);//this processes the header of incoming packets
void ProcessPacket(char* buffer, int recvsize, std::vector<Packet>& container);//returns char*s of each packet, make sure to delete it
};
#endif