-
Notifications
You must be signed in to change notification settings - Fork 2
/
pkt_tools.nim
140 lines (117 loc) · 3.75 KB
/
pkt_tools.nim
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
import unsigned, endians, typetraits
when defined(useEnet):
import enet
when defined(useLacewing):
import lw
when not defined(useEnet) and not defined(useLacewing):
{.error: "No networking for pkt_tools, compile with -d:useEnet or -d:useLacewing".}
when defined(networkBigEndian):
template ne16 (a,b): expr = bigEndian16(a,b)
template ne32 (a,b): expr = bigEndian32(a,b)
template ne64 (a,b): expr = bigEndian64(a,b)
elif true or defined(networkLittleEndian):
template ne16 (a,b): expr = littleEndian16(a,b)
template ne32 (a,b): expr = littleEndian32(a,b)
template ne64 (a,b): expr = littleEndian64(a,b)
type
TScalar* = int8 | uint8 | byte | char | bool |
int16| uint16| int32|uint32|
float32|float64|int64|uint64
EShortPacket* = object of EBase
type
PIpkt* = var Ipkt
Ipkt* = object
data: cstring
index*, dataSize*: int
proc initIpkt* (dat:cstring,size:TInteger): IPkt =
IPkt(data:dat, index:0, dataSize:size.int)
when defined(useEnet):
proc initIpkt* (P:PPacket): IPkt =
initIpkt(p.data, p.dataLength)
proc data0* (pkt:PIpkt): ptr char = pkt.data[0].addr
template test_pkt (pkt; right; size): stmt =
if pkt.dataSize - pkt.index < size:
raise newException(EShortPacket, "Not enough bytes in the packet for "& name(type(right)))
proc `>>`* [T: TScalar] (pkt:PIpkt; right:var T) =
const sizeT = sizeof(T)
test_pkt(pkt, right, sizeT)
template data: expr = pkt.data[pkt.index].addr
when sizeT == 2:
ne16(right.addr, data)
elif sizeT == 4:
ne32(right.addr, data)
elif sizeT == 8:
ne64(right.addr, data)
elif sizeT == 1:
right = cast[ptr t](data)[]
pkt.index.inc sizeT
proc `>>`* (pkt:PIpkt; right:var string) =
var len: int16
pkt >> len
test_pkt pkt, right, len
if right.isNil: right = newString(len)
else: right.setLen len.int
copyMem(right.cstring, pkt.data[pkt.index].addr, len)
pkt.index.inc len
proc `>>`* [T] (pkt:PIpkt; right:var seq[T])=
mixin `>>`
var len: int16
pkt >> len
if right.isNil: right.newSeq len.int
else: right.setLen len.int
for idx in 0 .. high(right):
pkt >> right[idx]
proc `>>`* [T] (pkt:PIpkt; right:var openarray[T]) =
mixin `>>`
var len: int16
pkt >> len
assert len.int == right.len
for idx in 0 .. high(right):
pkt >> right[idx]
type
POpkt* = var OPkt
OPkt* = object
bytes: seq[char]
index*: int
proc initOpkt* (size = 512): OPkt =
Opkt(
bytes: newseq[char](size)
)
proc data* (outp: var OPkt): ptr char = outp.bytes[outp.index].addr
proc data0* (outp: var OPkt): ptr char = outp.bytes[0].addr
when defined(useEnet):
proc createPacket* (O:var OPKT; flags: cint): PPacket {.inline.} =
createPacket( o.data0, o.index, flags or NoAllocate.cint )
proc ensureSize*(pkt:var Opkt; size: int) =
if pkt.bytes.len < pkt.index+size:
pkt.bytes.setLen pkt.index+size
proc `<<` * [T:TScalar] (outp: var OPkt; right: T) =
const sizeT = sizeof(T)
outp.ensureSize sizeT
when sizeT == 2:
var right = right
ne16(outp.data, right.addr)
elif sizeT == 4:
var right = right
ne32(outp.data, right.addr)
elif sizeT == 8:
var right = right
ne64(outp.data, right.addr)
elif sizeT == 1:
data(outp)[] = cast[char](right)
inc outp.index, sizeT
proc `<<` * (outp: var OPkt; right: string) =
let strlen = right.len
outp << strlen.int16
outp.ensureSize strlen
copyMem outp.data, right.cstring, strlen
inc outp.index, strlen
proc `<<` * [T] (outp: var OPkt; right: openarray[T]) =
mixin `<<`
outp << right.len.int16
outp.ensureSize right.len * sizeof(T)
for idx in 0 .. high(right):
outp << right[idx]
when defined(useLacewing):
proc send* (udp:LW_UDP; address:LW_Addr; pkt:var OPkt){.inline.}=
udp.send(address, pkt.data0, pkt.index.csize)