blob: 28726b0fb5beccc81c0372754eba5a43750fea74 [file] [log] [blame]
Ratan Gupta07c462a2016-12-14 00:40:30 +05301#include "slp.hpp"
2
3#include <string.h>
4
5#include <string>
6#include <algorithm>
7
8#include "endian.hpp"
9#include "slp_meta.hpp"
10
11namespace slp
12{
13
14namespace parser
15{
16
17namespace internal
18{
19
20std::tuple<int, Message> parseHeader(const buffer& buff)
21{
22 /* 0 1 2 3
23 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
24 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
25 | Version | Function-ID | Length |
26 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
27 | Length, contd.|O|F|R| reserved |Next Ext Offset|
28 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
29 | Next Extension Offset, contd.| XID |
30 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
31 | Language Tag Length | Language Tag \
32 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
33
34 Message req {0};
35 int rc = slp::SUCCESS;
36
37 std::copy_n(buff.data(),
38 slp::header::SIZE_VERSION,
39 &req.header.version);
40
41 std::copy_n(buff.data() + slp::header::OFFSET_FUNCTION,
42 slp::header::SIZE_VERSION,
43 &req.header.functionID);
44
45 std::copy_n(buff.data() + slp::header::OFFSET_LENGTH,
46 slp::header::SIZE_LENGTH,
47 req.header.length.data());
48
49 std::copy_n(buff.data() + slp::header::OFFSET_FLAGS,
50 slp::header::SIZE_FLAGS,
51 (uint8_t*)&req.header.flags);
52
53 req.header.flags = endian::from_network(req.header.flags);
54 std::copy_n(buff.data() + slp::header::OFFSET_EXT,
55 slp::header::SIZE_EXT,
56 req.header.extOffset.data());
57
58 std::copy_n(buff.data() + slp::header::OFFSET_XID,
59 slp::header::SIZE_XID,
60 (uint8_t*)&req.header.xid);
61
62 req.header.xid = endian::from_network(req.header.xid);
63
64 uint16_t langtagLen;
65
66 std::copy_n(buff.data() + slp::header::OFFSET_LANG_LEN,
67 slp::header::SIZE_LANG,
68 (uint8_t*)&langtagLen);
69
70
71 langtagLen = endian::from_network(langtagLen);
72
73
74 req.header.langtag.insert(0, (const char*)buff.data() +
75 slp::header::OFFSET_LANG,
76 langtagLen);
77
78 /* check for the validity of the function */
79 if (req.header.functionID < static_cast<uint8_t>
80 (slp::FunctionType::SRVRQST)
81 || req.header.functionID > static_cast<uint8_t>(slp::FunctionType::SAADV))
82 {
83 rc = static_cast<int>(slp::Error::PARSE_ERROR);
84 }
85
86 return std::make_tuple(rc, std::move(req));
87}
88
89
90int parseSrvTypeRqst(const buffer& buff, Message& req)
91{
92
93
94 /* 0 1 2 3
95 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
96 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
97 | length of PRList | <PRList> String \
98 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
99 | length of Naming Authority | <Naming Authority String> \
100 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
101 | length of <scope-list> | <scope-list> String \
102 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
103
104 /* Enforce SLPv2 service type request size limits. */
105 if (buff.size() < slp::request::MIN_SRVTYPE_LEN)
106 {
107 return (int)slp::Error::PARSE_ERROR;
108 }
109
110 /* Parse the PRList. */
111 uint16_t prListLen;
112 std::copy_n(buff.data() + slp::request::OFFSET_PR_LEN,
113 slp::request::SIZE_PRLIST,
114 (uint8_t*)&prListLen);
115
116 prListLen = endian::from_network(prListLen);
117
118 req.body.srvtyperqst.prList.insert(0, (const char*)buff.data() +
119 slp::request::OFFSET_PR,
120 prListLen);
121
122 uint8_t pos = slp::request::OFFSET_PR + prListLen;
123
124 /* Parse the Naming Authority. */
125 uint16_t namingAuthLen;
126 std::copy_n(buff.data() + pos,
127 slp::request::SIZE_NAMING,
128 (uint8_t*)&namingAuthLen);
129
130 pos += slp::request::SIZE_NAMING;
131
132 namingAuthLen = endian::from_network(namingAuthLen);
133
134 if (namingAuthLen == 0 || namingAuthLen == 0xffff)
135 {
136 req.body.srvtyperqst.namingAuth = "";
137 }
138 else
139 {
140 req.body.srvtyperqst.namingAuth.insert(0, (const char*)buff.data() +
141 pos,
142 namingAuthLen);
143 }
144
145 pos += namingAuthLen;
146
147 /* Parse the <scope-list>. */
148 uint16_t scopeListLen;
149 std::copy_n(buff.data() + pos,
150 slp::request::SIZE_SCOPE,
151 (uint8_t*)&scopeListLen);
152
153 pos += slp::request::SIZE_SCOPE;
154
155 scopeListLen = endian::from_network(scopeListLen);
156
157 req.body.srvtyperqst.scopeList.insert(0, (const char*)buff.data() + pos,
158 scopeListLen);
159
160 return slp::SUCCESS;
161}
162
163int parseSrvRqst(const buffer& buff, Message& req)
164{
165 /* 0 1 2 3
166 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
167 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
168 | length of <PRList> | <PRList> String \
169 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
170 | length of <service-type> | <service-type> String \
171 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
172 | length of <scope-list> | <scope-list> String \
173 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
174 | length of predicate string | Service Request <predicate> \
175 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
176 | length of <SLP SPI> string | <SLP SPI> String \
177 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
178
179 /* Enforce v2 service request size limits. */
180 if (buff.size() < slp::request::MIN_SRV_LEN)
181 {
182 return (int)slp::Error::PARSE_ERROR;
183 }
184
185 /* 1) Parse the PRList. */
186 uint16_t prListLen;
187 std::copy_n(buff.data() + slp::request::OFFSET_PR_LEN,
188 slp::request::SIZE_PRLIST,
189 (uint8_t*)&prListLen);
190
191 auto pos = slp::request::OFFSET_PR_LEN + slp::request::SIZE_PRLIST;
192
193 prListLen = endian::from_network(prListLen);
194
195 req.body.srvrqst.prList.insert(0, (const char*)buff.data() + pos,
196 prListLen);
197
198 pos += prListLen;
199
200
201 /* 2) Parse the <service-type> string. */
202 uint16_t srvTypeLen;
203 std::copy_n(buff.data() + pos,
204 slp::request::SIZE_SERVICE_TYPE,
205 (uint8_t*)&srvTypeLen);
206
207 srvTypeLen = endian::from_network(srvTypeLen);
208
209 pos += slp::request::SIZE_SERVICE_TYPE;
210
211 req.body.srvrqst.srvType.insert(0, (const char*)buff.data() + pos,
212 srvTypeLen);
213
214 pos += srvTypeLen;
215
216 /* 3) Parse the <scope-list> string. */
217 uint16_t scopeListLen;
218 std::copy_n(buff.data() + pos,
219 slp::request::SIZE_SCOPE,
220 (uint8_t*)&scopeListLen);
221
222 scopeListLen = endian::from_network(scopeListLen);
223
224 pos += slp::request::SIZE_SCOPE;
225
226 req.body.srvrqst.scopeList.insert(0, (const char*)buff.data() + pos,
227 scopeListLen);
228
229 pos += scopeListLen;
230
231 /* 4) Parse the <predicate> string. */
232 uint16_t predicateLen;
233 std::copy_n(buff.data() + pos,
234 slp::request::SIZE_PREDICATE,
235 (uint8_t*)&predicateLen);
236
237 predicateLen = endian::from_network(predicateLen);
238 pos += slp::request::SIZE_PREDICATE;
239
240 req.body.srvrqst.predicate.insert(0, (const char*)buff.data() + pos,
241 predicateLen);
242
243 pos += predicateLen;
244
245 /* 5) Parse the <SLP SPI> string. */
246 uint16_t spistrLen;
247 std::copy_n(buff.data() + pos,
248 slp::request::SIZE_SLPI,
249 (uint8_t*)&spistrLen);
250
251 spistrLen = endian::from_network(spistrLen);
252 pos += slp::request::SIZE_SLPI;
253
254 req.body.srvrqst.spistr.insert(0, (const char*)buff.data() + pos,
255 spistrLen);
256
257 return slp::SUCCESS;
258}
259}//namespace internal
260
261std::tuple<int, Message> parseBuffer(const buffer& buff)
262{
263 Message req;
264 int rc = slp::SUCCESS;
265 /* parse the header first */
266 std::tie(rc, req) = internal::parseHeader(buff);
267 if (!rc)
268 {
269 /* switch on the function id to parse the body */
270 switch (req.header.functionID)
271 {
272 case (uint8_t)slp::FunctionType::SRVTYPERQST:
273 rc = internal::parseSrvTypeRqst(buff, req);
274 break;
275 case (uint8_t)slp::FunctionType::SRVRQST:
276 rc = internal::parseSrvRqst(buff, req);
277 break;
278 default:
279 rc = (int)slp::Error::MSG_NOT_SUPPORTED;
280 }
281 }
282 return std::make_tuple(rc, std::move(req));
283}
284}//namespace parser
285}//namespace slp