gfcp_network_test.go 6.36 KB
Newer Older
1
2
// Copyright © 2015 Daniel Fu <daniel820313@gmail.com>.
// Copyright © 2019 Loki 'l0k18' Verloren <stalker.loki@protonmail.ch>.
Jeffrey H. Johnson's avatar
Jeffrey H. Johnson committed
3
4
// Copyright © 2021 Gridfinity, LLC. <admin@gridfinity.com>.
// Copyright © 2021 Jeffrey H. Johnson <jeff@gridfinity.com>.
5
6
7
8
9
10
//
// All rights reserved.
//
// All use of this code is governed by the MIT license.
// The complete license is available in the LICENSE file.

11
package gfcp_test
12
13
14
15
16
17
18
19
20
21

import (
	"bytes"
	"container/list"
	"encoding/binary"
	"fmt"
	"math/rand"
	"sync"
	"testing"
	"time"
22

23
	"go.gridfinity.dev/gfcp"
24
25
26
)

func iclock() int32 {
Jeffrey H. Johnson's avatar
Jeffrey H. Johnson committed
27
	return int32(gfcp.CurrentMs())
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
}

type DelayPacket struct {
	_ptr  []byte
	_size int
	_ts   int32
}

func (
	p *DelayPacket,
) Init(
	size int,
	src []byte,
) {
	p._ptr = make(
		[]byte,
		size,
	)
	p._size = size
	copy(
		p._ptr,
		src[:size],
	)
}

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
func (
	p *DelayPacket,
) ptr() []byte {
	return p._ptr
}

func (
	p *DelayPacket,
) size() int {
	return p._size
}

func (
	p *DelayPacket,
) ts() int32 {
	return p._ts
}

func (
	p *DelayPacket,
) setts(
	ts int32,
) {
	p._ts = ts
}
78

79
type (
80
81
82
	DelayTunnel struct {
		*list.List
	}
83
	LatencySimulator struct {
84
85
86
87
88
89
90
91
92
		current  int32
		lostrate int
		rttmin   int
		rttmax   int
		nmax     int
		p12      DelayTunnel
		p21      DelayTunnel
		r12      *rand.Rand
		r21      *rand.Rand
93
94
	}
)
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113

func (
	p *LatencySimulator,
) Init(
	lostrate,
	rttmin,
	rttmax,
	nmax int,
) {
	p.r12 = rand.New(
		rand.NewSource(
			9,
		),
	)
	p.r21 = rand.New(
		rand.NewSource(
			99,
		),
	)
114
115
116
117
118
119
	p.p12 = DelayTunnel{
		list.New(),
	}
	p.p21 = DelayTunnel{
		list.New(),
	}
120
	p.current = iclock()
121
122
123
	p.lostrate = (lostrate / 2)
	p.rttmin = (rttmin / 2)
	p.rttmax = (rttmax / 2)
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
	p.nmax = nmax
}

func (
	p *LatencySimulator,
) send(
	peer int,
	data []byte,
	size int,
) int {
	rnd := 0
	if peer == 0 {
		rnd = p.r12.Intn(
			100,
		)
	} else {
		rnd = p.r21.Intn(
			100,
		)
	}
	if rnd < p.lostrate {
		return 0
	}
	pkt := &DelayPacket{}
	pkt.Init(
		size,
		data,
	)
	p.current = iclock()
	delay := p.rttmin
	if p.rttmax > p.rttmin {
		delay += rand.Int() % (p.rttmax - p.rttmin)
	}
	pkt.setts(
158
159
160
		p.current + int32(
			delay,
		),
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
	)
	if peer == 0 {
		p.p12.PushBack(
			pkt,
		)
	} else {
		p.p21.PushBack(
			pkt,
		)
	}
	return 1
}

func (
	p *LatencySimulator,
) recv(
	peer int,
	data []byte,
	maxsize int,
) int32 {
	var it *list.Element
	if peer == 0 {
		it = p.p21.Front()
		if p.p21.Len() == 0 {
			return -1
		}
	} else {
		it = p.p12.Front()
		if p.p12.Len() == 0 {
			return -1
		}
	}
	pkt := it.Value.(*DelayPacket)
	p.current = iclock()
	if p.current < pkt.ts() {
		return -2
	}
	if maxsize < pkt.size() {
		return -3
	}
	if peer == 0 {
202
203
204
		p.p21.Remove(
			it,
		)
205
	} else {
206
207
208
		p.p12.Remove(
			it,
		)
209
210
211
212
213
214
215
216
217
218
219
220
221
	}
	maxsize = pkt.size()
	copy(
		data,
		pkt.ptr()[:maxsize],
	)
	return int32(maxsize)
}

var vnet *LatencySimulator

func test(
	mode int,
222
	t *testing.T,
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
) {
	vnet = &LatencySimulator{}
	vnet.Init(
		10,
		60,
		125,
		1000,
	)

	output1 := func(
		buf []byte,
		size int,
	) {
		if vnet.send(
			0,
			buf,
			size,
		) != 1 {
241
242
243
244
245
			t.Log(
				fmt.Sprintf(
					"\noutput[1]: vnet.send: size=%v",
					size,
				),
246
			)
247
248
249
250
251
252
253
254
255
256
257
		}
	}
	output2 := func(
		buf []byte,
		size int,
	) {
		if vnet.send(
			1,
			buf,
			size,
		) != 1 {
258
259
260
261
262
			t.Log(
				fmt.Sprintf(
					"\noutput[2]: vnet.send: size=%v",
					size,
				),
263
			)
264
265
		}
	}
266
	gfcp1 := gfcp.NewGFCP(
267
268
269
		0x11223344,
		output1,
	)
270
	gfcp2 := gfcp.NewGFCP(
271
272
273
274
		0x11223344,
		output2,
	)

275
276
277
	current := uint32(
		iclock(),
	)
278
279
280
281
282
283
284
	slap := current + 20
	index := 0
	next := 0
	var sumrtt uint32
	count := 0
	maxrtt := 0

285
	gfcp1.WndSize(
286
287
288
		128,
		128,
	)
289
	gfcp2.WndSize(
290
291
292
293
294
		128,
		128,
	)

	if mode == 0 {
295
		gfcp1.NoDelay(
296
297
298
299
300
			0,
			10,
			0,
			0,
		)
301
		gfcp2.NoDelay(
302
303
304
305
306
307
			0,
			10,
			0,
			0,
		)
	} else if mode == 1 {
308
		gfcp1.NoDelay(
309
310
311
312
313
			0,
			10,
			0,
			1,
		)
314
		gfcp2.NoDelay(
315
316
317
318
319
320
			0,
			10,
			0,
			1,
		)
	} else {
321
		gfcp1.NoDelay(
322
323
324
325
326
			1,
			10,
			2,
			1,
		)
327
		gfcp2.NoDelay(
328
329
330
331
332
333
334
			1,
			10,
			2,
			1,
		)
	}

335
336
337
338
	buffer := make(
		[]byte,
		2000,
	)
339
340
341
342
343
	var hr int32

	ts1 := iclock()

	for {
344
345
346
		time.Sleep(
			(1 * time.Millisecond),
		)
347
348
349
		current = uint32(
			iclock(),
		)
350
351
		gfcp1.Update()
		gfcp2.Update()
352
353
354
355
356
357
358
359

		for ; current >= slap; slap += 20 {
			buf := new(
				bytes.Buffer,
			)
			binary.Write(
				buf,
				binary.LittleEndian,
360
361
362
				uint32(
					index,
				),
363
364
365
366
367
			)
			index++
			binary.Write(
				buf,
				binary.LittleEndian,
368
				current,
369
			)
370
			gfcp1.Send(
371
372
373
374
375
376
377
378
379
380
381
382
383
				buf.Bytes(),
			)
		}

		for {
			hr = vnet.recv(
				1,
				buffer,
				2000,
			)
			if hr < 0 {
				break
			}
384
			gfcp2.Input(
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
				buffer[:hr],
				true,
				false,
			)
		}

		for {
			hr = vnet.recv(
				0,
				buffer,
				2000,
			)
			if hr < 0 {
				break
			}
400
			gfcp1.Input(
401
402
403
404
405
406
407
				buffer[:hr],
				true,
				false,
			)
		}

		for {
408
			hr = int32(
409
				gfcp2.Recv(
410
411
					buffer[:10],
				),
412
			)
413
414
415
416
417
418
419
420
421
422
423
424
			if hr < 0 {
				break
			}
			buf := bytes.NewReader(
				buffer,
			)
			var sn uint32
			binary.Read(
				buf,
				binary.LittleEndian,
				&sn,
			)
425
			gfcp2.Send(
426
427
428
429
430
				buffer[:hr],
			)
		}

		for {
431
			hr = int32(
432
				gfcp1.Recv(
433
434
					buffer[:10],
				),
435
			)
436
437
438
439
440
441
			buf := bytes.NewReader(
				buffer,
			)
			if hr < 0 {
				break
			}
442
			var ts, sn, rtt uint32
443
444
445
446
447
448
449
450
451
452
			binary.Read(
				buf,
				binary.LittleEndian,
				&sn,
			)
			binary.Read(
				buf,
				binary.LittleEndian,
				&ts,
			)
453
			rtt = (current - ts)
454

455
456
457
			if sn != uint32(
				next,
			) {
458
459
460
461
462
463
464
				println(
					"ERROR sn ",
					count,
					"<->",
					next,
					sn,
				)
465
466
467
468
469
470
				return
			}

			next++
			sumrtt += rtt
			count++
471
472
473
474
475
476
			if rtt > uint32(
				maxrtt,
			) {
				maxrtt = int(
					rtt,
				)
477
478
479
480
481
482
483
484
485
486
487
488
			}

		}

		if next > 100 {
			break
		}
	}

	ts1 = iclock() - ts1

	names := []string{
489
490
491
		"=== Test 1/3:\tConfiguration: Default",
		"=== Test 2/3:\tConfiguration: Regular",
		"=== Test 3/3:\tConfiguration: Tweaked",
492
493
494
495
496
497
498
	}
	fmt.Printf(
		"\n%s\n\t\tElapsed Time:\t%d ms",
		names[mode],
		ts1,
	)
	fmt.Printf(
499
		"\n\t\tAverage RTT:\t%d ms\n\t\tMaximum RTT:\t%d ms\n",
500
501
502
503
504
		int(sumrtt/uint32(count)),
		maxrtt,
	)
}

505
506
507
func TestNetwork(
	t *testing.T,
) {
508
509
	test(
		0,
510
		t,
511
512
513
	)
	test(
		1,
514
		t,
515
516
517
	)
	test(
		2,
518
		t,
519
520
521
522
523
524
	)
}

func BenchmarkFlush(
	b *testing.B,
) {
525
	GFcp := gfcp.NewGFCP(
526
527
528
529
		1,
		func(
			buf []byte,
			size int,
530
531
		) {
		})
532
	GFcp.SndBuf = make(
533
534
		[]gfcp.Segment,
		2048,
535
	)
536
537
	for k := range GFcp.SndBuf {
		GFcp.SndBuf[k].Kxmit = 1
538
		GFcp.SndBuf[k].GFcpResendTs = gfcp.CurrentMs() + 1000
539
540
541
542
543
544
	}
	b.ResetTimer()
	b.ReportAllocs()
	var mu sync.Mutex
	for i := 0; i < b.N; i++ {
		mu.Lock()
545
		GFcp.Flush(
546
547
548
549
550
			false,
		)
		mu.Unlock()
	}
}