-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathbpacket-1.3.3.tm
141 lines (128 loc) · 3.54 KB
/
bpacket-1.3.3.tm
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
if 0 {
@ bpacket @
binary packet is used to encode and decode data in a way that
is similar to protocol buffers.
it is composed of various parts. data is encoded using a given
template and the template is used on each end to encode/decode
for communication.
@type BPTemplate
| This builds our binary format template. It is utilized by both the
| encoding and decoding end to understand how to build and parse our
| binary packets automatically.
TODO:
* asterix items are marked as required, although this is not
* currently enforced.
> Format
{(*)? (type_name) (...type_args) | (field_num)}
@example
{
set template {
1 flags props | type channel
2 string hid
3 string sid
4 numlist nlist | known
5 varint timestamp
6 list protocols
7 string ruid
8 string op
9 raw raw
10 list tags
11 boolean keepalive
12 list filter
13 string error
14 dict data | {
first_name
last_name
phone_number
address
employer
}
}
set data [dict create \
timestamp [clock microseconds] \
hid 00:00:00:00:00:00 \
sid a-7898 \
props [list 0 10] \
protocols [list a b c] \
ruid MY_EVENT \
keepalive 1 \
data [dict create \
first_name john \
last_name smith \
phone_number 6665554444 \
address "Some address can go here" \
employer "Acme, Inc"
]
]
}
}
set template {
1 boolean compact
2 varint schema
}
namespace eval ::bpacket {
namespace ensemble create
namespace export {[a-z]*}
# the value used to indiciate the start of the header
variable HEADER "\xC0\x8D"
# end of packet - should not be the same as HEADER as we
# will remove any number of $EOF THEN look for HEADER to
# determine if we have multiple packets concatted
variable EOF "\x00\x00"
# holds a hash map of $id -> $type and $type -> $id
# of types that have been registered.
#
# types are required & registered when they are required by a template
if {![info exists ::bpacket::REGISTRY]} {
variable REGISTRY [dict create]
}
# these types are required and will be required automatically
# regardless of the given template.
variable REQUIRED_TYPES [list varint string]
}
namespace eval ::bpacket::decode {
namespace ensemble create
namespace export {[a-z]*}
}
namespace eval ::bpacket::encode {
namespace ensemble create
namespace export {[a-z]*}
}
namespace eval ::bpacket::type {
namespace ensemble create
namespace export {[a-z]*}
}
source -encoding utf-8 [file join \
[file dirname \
[file normalize [info script]] \
] \
bpacket \
utils.tcl
]
if 0 {
@ bpacket create | $type $name ...$args
Allows creation of the various bpacket classes
@arg type {io|stream}
@type {io}
creates a bpacket io object which is responsible for both
encoding and decoding bpackets
@type {stream}
creates a bpacket stream object which receives a stream of
data and outputs valid bpackets when they are found
@arg name {string}
@arg args
@if | $type {io}
@arg template {BPTemplate}
the template that the given io handler should use.
}
proc ::bpacket::create {type name args} {
switch -nocase -- $type {
io {
package require bpacket::classes::io
}
stream {
package require bpacket::classes::stream
}
}
tailcall ::bpacket::classes::[string tolower $type] create $name {*}$args
}