binrpc.h 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2006 iptelorg GmbH
  5. *
  6. * This file is part of ser, a free SIP server.
  7. *
  8. * ser is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version
  12. *
  13. * For a license to use the ser software under conditions
  14. * other than those described here, or to purchase support for this
  15. * software, please contact iptel.org by e-mail at the following addresses:
  16. * [email protected]
  17. *
  18. * ser is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU General Public License
  24. * along with this program; if not, write to the Free Software
  25. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  26. */
  27. /* History:
  28. * --------
  29. * 2006-02-08 created by andrei
  30. * 2006-11-03 replies with no payload are allowed (andrei)
  31. */
  32. /* binrpc is supposed to be a minimalist binary rpc implementation */
  33. /* packet header:
  34. * (big endian where it applies)
  35. * 4b 4b 4b 2b 2b <var> <var>
  36. * | MAGIC | VERS || FLAGS | LL | CL || total_len ... || cookie ... |
  37. * total_len = payload len (doesn't include the packet header)
  38. * LL = total length len -1 (number of bytes on which total len is
  39. * represented)
  40. * CL = cookie length -1 (number of bytes on which the cookie is represented)
  41. * E.g.: LL= 0 => total_len is represented on 1 byte (LL+1)
  42. * CL= 3 => cookie is represneted on 4 bytes (CL+1)
  43. */
  44. /* record format:
  45. * 1b 3b 4b
  46. * |S | size | type || <optional value len> ... || <optional value> ... ||
  47. *
  48. * if S==0, size is the size (in bytes) of the value (if size==0 => null value)
  49. * if S==1, optional_value_len is present, and size is it's size
  50. * (if size==0 => and type==array or struct => marks end, else
  51. * error, reserved)
  52. * Examples:
  53. * int (type=0) 0x1234 -> 0x20 0x12 0x34 (optimal)
  54. * 0x90 0x02 0x12 0x34 (suboptimal)
  55. * 0xA0 0x00 0x02 0x12 0x34 (even worse)
  56. * 0x07 -> 0x10 0x07 (optimal)
  57. * 0x00 -> 0x00 (optimal)
  58. * 0x10 0x00
  59. *
  60. * str (type=1) - strings are 0 terminated (an extra 0 is added to them
  61. * to make the format easier to parse when asciiz strings
  62. * are required); the length includes the terminating 0
  63. * "abcdef" -> 0x71 "abcdef" 0x00
  64. * "abcdefhij"-> 0x91 0x0A "abcdefhij" 0x00
  65. * "" -> 0x11 0x00 (0 len str)
  66. * 65535 bytes
  67. * (using str for it) -> 0xB1 0x01 0x00 0x00 array 0x00
  68. *
  69. * bytes (type=6) -like str but not 0 terminated
  70. * "abcdef" -> 0x66 "abcdef"
  71. * 65535 bytes * -> 0xA6 0xff 0xff bytes
  72. *
  73. * arrays (array type=4)
  74. * arrays are implemented as anonymous value lists:
  75. * array_start value1, value2, ..., array_end
  76. * (start) (1st int) (2nd elem) (end array)
  77. * ints [ 0x01 0x02 ] -> 0x04 0x10 0x01 0x10 0x02 0x84
  78. * combo [ 0x07 "abc"] -> 0x04 0x10 0x07 0x41 "abc" 0x00 0x84
  79. *
  80. * structs (struct type=3)
  81. * structs are implemented as avp list:
  82. * struct_start, avp1, avp2 .., struct_end
  83. * an avp is a named value pair: name, value.
  84. * - name behaves like a normal string, but has a diff. type (5)
  85. * - avps are legal only inside structs.
  86. * avp example: name part (str) val part (int here)
  87. * "test", int 0x0b -> 0x55 "test" 0x00 0x10 0x0b
  88. *
  89. * struct example:
  90. * (start) (avps) (end)
  91. * struct{ 0x03 (name ) (val)
  92. * intval: int 0x3 -> 0x75 "intval" 0x00 0x10 0x3
  93. * s: str "abc"- 0x25 "s" 0x00 0x41 "abc" 0x00
  94. * } 0x83
  95. *
  96. * Limitations: for now avps cannot have array values =>
  97. * structs cannot contain arrays.
  98. */
  99. #ifndef _binrpc_h
  100. #define _binrpc_h
  101. #include "../../str.h"
  102. #include <string.h>
  103. #define BINRPC_MAGIC 0xA
  104. #define BINRPC_VERS 1
  105. /* sizes & offsets */
  106. #define BINRPC_FIXED_HDR_SIZE 2
  107. #define BINRPC_TLEN_OFFSET BINRPC_FIXED_HDR_SIZE
  108. #define BINRPC_MIN_HDR_SIZE (BINRPC_FIXED_HDR_SIZE+2)
  109. #define BINRPC_MAX_HDR_SIZE (BINRPC_FIXED_HDR_SIZE+4+4)
  110. #define BINRPC_MIN_RECORD_SIZE 1
  111. /* min pkt size: min header + min. len (1) + min. cookie (1)*/
  112. #define BINRPC_MIN_PKT_SIZE BINRPC_MIN_HDR_SIZE
  113. /* message types */
  114. #define BINRPC_REQ 0
  115. #define BINRPC_REPL 1
  116. #define BINRPC_FAULT 3
  117. /* values types */
  118. #define BINRPC_T_INT 0
  119. #define BINRPC_T_STR 1 /* 0 term, for easier parsing */
  120. #define BINRPC_T_DOUBLE 2
  121. #define BINRPC_T_STRUCT 3
  122. #define BINRPC_T_ARRAY 4
  123. #define BINRPC_T_AVP 5 /* allowed only in structs */
  124. #define BINRPC_T_BYTES 6 /* like STR, but not 0 term */
  125. #define BINRPC_T_ALL 0xf /* wildcard type, will match any record type
  126. in the packet (not allowed inside the pkt)*/
  127. /* errors */
  128. #define E_BINRPC_INVAL -1 /* invalid function call parameters */
  129. #define E_BINRPC_OVERFLOW -2 /* buffer overflow */
  130. #define E_BINRPC_BADPKT -3 /* something went really bad, the packet is
  131. corrupted*/
  132. #define E_BINRPC_MORE_DATA -4 /* parsing error: more bytes are needed,
  133. just repeat the failed op, when you have
  134. more bytes available */
  135. #define E_BINRPC_EOP -5 /* end of packet reached */
  136. #define E_BINRPC_NOTINIT -6 /* parse ctx not initialized */
  137. #define E_BINRPC_TYPE -7 /* unkown type for record, or requested
  138. type doesn't match record type */
  139. #define E_BINRPC_RECORD -8 /* bad record (unexpected, bad struct a.s.o)*/
  140. #define E_BINRPC_BUG -9 /* internal error, bug */
  141. #define E_BINRPC_LAST -10 /* used to count the errors, keep always
  142. last */
  143. /* flags */
  144. #define BINRPC_F_INIT 1
  145. struct binrpc_pkt{ /* binrpc body */
  146. unsigned char* body;
  147. unsigned char* end;
  148. unsigned char* crt; /*private */
  149. };
  150. struct binrpc_parse_ctx{
  151. /* header */
  152. unsigned int tlen; /* total len */
  153. unsigned int cookie;
  154. int type; /* request, reply, error */
  155. /* parsing info */
  156. unsigned int flags; /* parsing flags */
  157. unsigned int offset; /* current offset (inside payload) */
  158. unsigned int in_struct;
  159. unsigned int in_array;
  160. };
  161. struct binrpc_val{
  162. str name; /* used only in structs */
  163. int type;
  164. union{
  165. str strval;
  166. double fval;
  167. int intval;
  168. int end;
  169. }u;
  170. };
  171. /* helper functions */
  172. /* return int size: minimum number of bytes needed to represent it
  173. * if i=0 returns 0 */
  174. inline static int binrpc_get_int_len(int i)
  175. {
  176. int size;
  177. for (size=4; size && ((i & (0xff<<24))==0); i<<=8, size--);
  178. return size;
  179. }
  180. /* adds a start or end tag (valid only for STRUCT or ARRAY for now */
  181. inline static int binrpc_add_tag(struct binrpc_pkt* pkt, int type, int end)
  182. {
  183. if (pkt->crt>=pkt->end) return E_BINRPC_OVERFLOW;
  184. *pkt->crt=(end<<7)|type;
  185. pkt->crt++;
  186. return 0;
  187. }
  188. /* writes a minimal int, returns the new offset and sets
  189. * len to the number of bytes written (<=4)
  190. * to check for oveflow use: returned_value-p != *len
  191. * (Note: if *len==0 using the test above succeeds even if p>=end)
  192. */
  193. inline static unsigned char* binrpc_write_int( unsigned char* p,
  194. unsigned char* end,
  195. int i, int *len)
  196. {
  197. int size;
  198. for (size=4; size && ((i & (0xff<<24))==0); i<<=8, size--);
  199. *len=size;
  200. for(; (p<end) && (size); p++, size--){
  201. *p=(unsigned char)(i>>24);
  202. i<<=8;
  203. }
  204. return p;
  205. }
  206. /* API functions */
  207. /* initialize a binrpc_pkt structure, for packet creation
  208. * params: pkt - binrpc body structure that will be initialized
  209. * buf, b_len - destination buffer/len
  210. * returns -1 on error, 0 on success
  211. *
  212. * Example usage:
  213. * binrpc_init_pkt(pkt, body, BODY_SIZE);
  214. * binrpc_addint(pkt, 1);
  215. * binrpc_addstr(pkt, "test", sizeof("test")-1);
  216. * ...
  217. * bytes=binrpc_build_hdr(pkt, BINRPC_REQ, 0x123, hdr_buf, HDR_BUF_LEN);
  218. * writev(sock, {{ hdr, bytes}, {pkt->body, pkt->crt-pkt->body}} , 2)*/
  219. inline static int binrpc_init_pkt(struct binrpc_pkt *pkt,
  220. unsigned char* buf, int b_len)
  221. {
  222. if (b_len<BINRPC_MIN_RECORD_SIZE)
  223. return E_BINRPC_OVERFLOW;
  224. pkt->body=buf;
  225. pkt->end=buf+b_len;
  226. pkt->crt=pkt->body;
  227. return 0;
  228. };
  229. /* used to update internal contents if the original buffer
  230. * (from binrpc_init_pkt) was realloc'ed (and has grown) */
  231. inline static int binrpc_pkt_update_buf(struct binrpc_pkt *pkt,
  232. unsigned char* new_buf,
  233. int new_len)
  234. {
  235. if ((int)(pkt->crt-pkt->body)>new_len){
  236. return E_BINRPC_OVERFLOW;
  237. }
  238. pkt->crt=new_buf+(pkt->crt-pkt->body);
  239. pkt->body=new_buf;
  240. pkt->end=new_buf+new_len;
  241. return 0;
  242. }
  243. /* builds a binrpc header for the binrpc pkt. body pkt and writes it in buf
  244. * params:
  245. * type - binrpc packet type (request, reply, fault)
  246. * body_len - body len
  247. * cookie - binrpc cookie value
  248. * buf,len - destination buffer & len
  249. * returns -1 on error, number of bytes written on success */
  250. inline static int binrpc_build_hdr( int type, int body_len,
  251. unsigned int cookie,
  252. unsigned char* buf, int b_len)
  253. {
  254. unsigned char* p;
  255. int len_len;
  256. int c_len;
  257. len_len=binrpc_get_int_len(body_len);
  258. c_len=binrpc_get_int_len(cookie);
  259. if (len_len==0) len_len=1; /* we can't have 0 len */
  260. if (c_len==0) c_len=1; /* we can't have 0 len */
  261. /* size check: 2 bytes header + len_len + cookie len*/
  262. if (b_len<(BINRPC_FIXED_HDR_SIZE+len_len+c_len)){
  263. goto error_len;
  264. }
  265. p=buf;
  266. *p=(BINRPC_MAGIC << 4) | BINRPC_VERS;
  267. p++;
  268. *p=(type<<4)|((len_len-1)<<2)|(c_len-1);
  269. p++;
  270. for(;len_len>0; len_len--,p++){
  271. *p=(unsigned char)(body_len>>((len_len-1)*8));
  272. }
  273. for(;c_len>0; c_len--,p++){
  274. *p=(unsigned char)(cookie>>((c_len-1)*8));
  275. }
  276. return (int)(p-buf);
  277. error_len:
  278. return E_BINRPC_OVERFLOW;
  279. }
  280. #define binrpc_pkt_len(pkt) ((int)((pkt)->crt-(pkt)->body))
  281. /* changes the length of a header (enough space must be availale) */
  282. inline static int binrpc_hdr_change_len(unsigned char* hdr, int hdr_len,
  283. int new_len)
  284. {
  285. int len_len;
  286. binrpc_write_int(&hdr[BINRPC_TLEN_OFFSET], hdr+hdr_len, new_len, &len_len);
  287. return 0;
  288. }
  289. /* int format: size BINRPC_T_INT <val> */
  290. inline static int binrpc_add_int_type(struct binrpc_pkt* pkt, int i, int type)
  291. {
  292. unsigned char* p;
  293. int size;
  294. p=binrpc_write_int(pkt->crt+1, pkt->end, i, &size);
  295. if ((pkt->crt>=pkt->end) || ((int)(p-pkt->crt-1)!=size))
  296. goto error_len;
  297. *(pkt->crt)=(size<<4) | type;
  298. pkt->crt=p;
  299. return 0;
  300. error_len:
  301. return E_BINRPC_OVERFLOW;
  302. }
  303. /* double format: FIXME: for now a hack: fixed point represented in
  304. * an int (=> max 3 decimals, < MAX_INT/1000) */
  305. #define binrpc_add_double_type(pkt, f, type)\
  306. binrpc_add_int_type((pkt), (int)((f)*1000), (type))
  307. /* skip bytes bytes (leaves an empty space, for possible future use)
  308. * WARNING: use with care, low level function
  309. */
  310. inline static int binrpc_add_skip(struct binrpc_pkt* pkt, int bytes)
  311. {
  312. if ((pkt->crt+bytes)>=pkt->end)
  313. return E_BINRPC_OVERFLOW;
  314. pkt->crt+=bytes;
  315. return 0;
  316. }
  317. /*
  318. * adds only the string mark and len, you'll have to memcpy the contents
  319. * manually later (and also use binrpc_add_skip(pkt, l) or increase
  320. * pkt->crt directly if you want to continue adding to this pkt).
  321. * Usefull for optimizing str writing (e.g. writev(iovec))
  322. * WARNING: use with care, low level function, binrpc_addstr or
  323. * binrpc_add_str_type are probably what you want.
  324. * WARNING1: BINRPC_T_STR and BINRPC_T_AVP must be 0 term, the len passed to
  325. * this function, must include the \0 in this case.
  326. */
  327. inline static int binrpc_add_str_mark(struct binrpc_pkt* pkt, int type,
  328. int l)
  329. {
  330. int size;
  331. unsigned char* p;
  332. if (pkt->crt>=pkt->end) goto error_len;
  333. if (l<8){
  334. size=l;
  335. p=pkt->crt+1;
  336. }else{ /* we need a separate len */
  337. p=binrpc_write_int(pkt->crt+1, pkt->end, l, &size);
  338. if (((int)(p-pkt->crt-1)!=size))
  339. goto error_len;
  340. size|=8; /* mark it as having external len */
  341. }
  342. *(pkt->crt)=(size)<<4|type;
  343. pkt->crt=p;
  344. return 0;
  345. error_len:
  346. return E_BINRPC_OVERFLOW;
  347. }
  348. inline static int binrpc_add_str_type(struct binrpc_pkt* pkt, char* s, int len,
  349. int type)
  350. {
  351. int size;
  352. int l;
  353. int zero_term; /* whether or not to add an extra 0 at the end */
  354. unsigned char* p;
  355. zero_term=((type==BINRPC_T_STR)||(type==BINRPC_T_AVP));
  356. l=len+zero_term;
  357. if (l<8){
  358. size=l;
  359. p=pkt->crt+1;
  360. }else{ /* we need a separate len */
  361. p=binrpc_write_int(pkt->crt+1, pkt->end, l, &size);
  362. /* if ((int)(p-pkt->crt)<(size+1)) goto error_len; - not needed,
  363. * caught by the next check */
  364. size|=8; /* mark it as having external len */
  365. }
  366. if ((p+l)>pkt->end) goto error_len;
  367. *(pkt->crt)=(size)<<4|type;
  368. memcpy(p, s, len);
  369. if (zero_term) p[len]=0;
  370. pkt->crt=p+l;
  371. return 0;
  372. error_len:
  373. return E_BINRPC_OVERFLOW;
  374. }
  375. /* adds an avp (name, value) pair, usefull to add structure members */
  376. inline static int binrpc_addavp(struct binrpc_pkt* pkt, struct binrpc_val* avp)
  377. {
  378. int ret;
  379. unsigned char* bak;
  380. bak=pkt->crt;
  381. ret=binrpc_add_str_type(pkt, avp->name.s, avp->name.len, BINRPC_T_AVP);
  382. if (ret<0) return ret;
  383. switch (avp->type){
  384. case BINRPC_T_INT:
  385. ret=binrpc_add_int_type(pkt, avp->u.intval, avp->type);
  386. break;
  387. case BINRPC_T_STR:
  388. case BINRPC_T_BYTES:
  389. ret=binrpc_add_str_type(pkt, avp->u.strval.s,
  390. avp->u.strval.len,
  391. avp->type);
  392. break;
  393. case BINRPC_T_STRUCT:
  394. case BINRPC_T_ARRAY:
  395. ret=binrpc_add_tag(pkt, avp->type, 0);
  396. break;
  397. case BINRPC_T_DOUBLE:
  398. ret=binrpc_add_double_type(pkt, avp->u.fval, avp->type);
  399. break;
  400. default:
  401. ret=E_BINRPC_BUG;
  402. }
  403. if (ret<0)
  404. pkt->crt=bak; /* roll back */
  405. return ret;
  406. }
  407. #define binrpc_addint(pkt, i) binrpc_add_int_type((pkt), (i), BINRPC_T_INT)
  408. #define binrpc_adddouble(pkt, f) \
  409. binrpc_add_double_type((pkt), (f), BINRPC_T_DOUBLE)
  410. #define binrpc_addstr(pkt, s, len) \
  411. binrpc_add_str_type((pkt), (s), (len), BINRPC_T_STR)
  412. #define binrpc_addbytes(pkt, s, len) \
  413. binrpc_add_str_type((pkt), (s), (len), BINRPC_T_BYTES)
  414. /* struct type format:
  415. * start : 0000 | BINRPC_T_STRUCT
  416. * end: 1000 | BINRPC_T_STRUCT
  417. */
  418. #define binrpc_start_struct(pkt) binrpc_add_tag((pkt), BINRPC_T_STRUCT, 0)
  419. #define binrpc_end_struct(pkt) binrpc_add_tag((pkt), BINRPC_T_STRUCT, 1)
  420. #define binrpc_start_array(pkt) binrpc_add_tag((pkt), BINRPC_T_ARRAY, 0)
  421. #define binrpc_end_array(pkt) binrpc_add_tag((pkt), BINRPC_T_ARRAY, 1)
  422. static inline int binrpc_addfault( struct binrpc_pkt* pkt,
  423. int code,
  424. char* s, int len)
  425. {
  426. int ret;
  427. unsigned char* bak;
  428. bak=pkt->crt;
  429. if ((ret=binrpc_addint(pkt, code))<0)
  430. return ret;
  431. ret=binrpc_addstr(pkt, s, len);
  432. if (ret<0)
  433. pkt->crt=bak; /* roll back */
  434. return ret;
  435. }
  436. /* parsing incoming messages */
  437. static inline unsigned char* binrpc_read_int( int* i,
  438. int len,
  439. unsigned char* s,
  440. unsigned char* end,
  441. int *err
  442. )
  443. {
  444. unsigned char* start;
  445. start=s;
  446. *i=0;
  447. *err=0;
  448. for(;len>0; len--, s++){
  449. if (s>=end){
  450. *err=E_BINRPC_MORE_DATA;
  451. return start;
  452. }
  453. *i<<=8;
  454. *i|=*s;
  455. };
  456. return s;
  457. }
  458. /* initialize parsing context, it tries to read the whole message header,
  459. * if there is not enough data, sets *err to E_BINRPC_MORE_DATA. In this
  460. * case just redo the call when more data is available (len is bigger)
  461. * on success sets *err to 0 and returns the current position in buf
  462. * (=> you can discard the content between buf & the returned value).
  463. * On error buf is returned back, and *err set.
  464. */
  465. static inline unsigned char* binrpc_parse_init( struct binrpc_parse_ctx* ctx,
  466. unsigned char* buf,
  467. int len,
  468. int *err
  469. )
  470. {
  471. int len_len, c_len;
  472. unsigned char *p;
  473. *err=0;
  474. ctx->tlen=0; /* init to 0 */
  475. ctx->cookie=0; /* init to 0 */
  476. if (len<BINRPC_MIN_PKT_SIZE){
  477. *err=E_BINRPC_MORE_DATA;
  478. goto error;
  479. }
  480. if (buf[0]!=((BINRPC_MAGIC<<4)|BINRPC_VERS)){
  481. *err=E_BINRPC_BADPKT;
  482. goto error;
  483. }
  484. ctx->type=buf[1]>>4;
  485. /* type check */
  486. switch(ctx->type){
  487. case BINRPC_REQ:
  488. case BINRPC_REPL:
  489. case BINRPC_FAULT:
  490. break;
  491. default:
  492. *err=E_BINRPC_BADPKT;
  493. goto error;
  494. }
  495. len_len=((buf[1]>>2) & 3) + 1;
  496. c_len=(buf[1]&3) + 1;
  497. if ((BINRPC_TLEN_OFFSET+len_len+c_len)>len){
  498. *err=E_BINRPC_MORE_DATA;
  499. goto error;
  500. }
  501. p=binrpc_read_int((int*)&ctx->tlen, len_len, &buf[BINRPC_TLEN_OFFSET],
  502. &buf[len], err);
  503. /* empty packets (replies) are allowed
  504. if (ctx->tlen==0){
  505. *err=E_BINRPC_BADPKT;
  506. goto error;
  507. } */
  508. p=binrpc_read_int((int*)&ctx->cookie, c_len, p, &buf[len], err);
  509. ctx->offset=0;
  510. ctx->flags|=BINRPC_F_INIT;
  511. return p;
  512. error:
  513. return buf;
  514. }
  515. /* returns bytes needed (till the end of the packet)
  516. * on error (non. init ctx) returns < 0
  517. */
  518. inline static int binrpc_bytes_needed(struct binrpc_parse_ctx *ctx)
  519. {
  520. if (ctx->flags & BINRPC_F_INIT)
  521. return ctx->tlen-ctx->offset;
  522. return E_BINRPC_NOTINIT;
  523. }
  524. /* prefill v with the requested type, if type==BINRPC_T_ALL it
  525. * will be replaced by the actual record type
  526. * known problems: no support for arrays inside STRUCT
  527. * returns position after the record and *err==0 if succesfull
  528. * original position and *err<0 if not */
  529. inline static unsigned char* binrpc_read_record(struct binrpc_parse_ctx* ctx,
  530. unsigned char* buf,
  531. unsigned char* end,
  532. struct binrpc_val* v,
  533. int* err
  534. )
  535. {
  536. int type;
  537. int len;
  538. int end_tag;
  539. int tmp;
  540. unsigned char* p;
  541. int i;
  542. p=buf;
  543. end_tag=0;
  544. *err=0;
  545. if (!(ctx->flags & BINRPC_F_INIT)){
  546. *err=E_BINRPC_NOTINIT;
  547. goto error;
  548. }
  549. if (ctx->offset>=ctx->tlen){
  550. *err=E_BINRPC_EOP;
  551. goto error;
  552. }
  553. if (p>=end){
  554. *err=E_BINRPC_MORE_DATA;
  555. goto error;
  556. }
  557. /* read type_len */
  558. type=*p & 0xf;
  559. len=*p>>4;
  560. p++;
  561. if (len & 8){
  562. end_tag=1; /* possible end mark for array or structs */
  563. /* we have to read len bytes and use them as the new len */
  564. p=binrpc_read_int(&len, len&7, p, end, err);
  565. if (*err<0)
  566. goto error;
  567. }
  568. if ((p+len)>end){
  569. *err=E_BINRPC_MORE_DATA;
  570. goto error;
  571. }
  572. if ((v->type!=type) && (v->type !=BINRPC_T_ALL)){
  573. goto error_type;
  574. }
  575. v->type=type;
  576. if (ctx->in_struct){
  577. switch(type){
  578. case BINRPC_T_STRUCT:
  579. if (end_tag){
  580. ctx->in_struct--;
  581. v->u.end=1;
  582. }else{
  583. goto error_record;
  584. }
  585. break;
  586. case BINRPC_T_AVP:
  587. /* name | value */
  588. v->name.s=(char*)p;
  589. v->name.len=(len-1); /* don't include 0 term */
  590. p+=len;
  591. if (p>=end){
  592. *err=E_BINRPC_MORE_DATA;
  593. goto error;
  594. }
  595. /* avp value type */
  596. type=*p & 0xf;
  597. if ((type!=BINRPC_T_AVP) && (type!=BINRPC_T_ARRAY)){
  598. tmp=ctx->in_struct;
  599. ctx->in_struct=0; /* hack to parse a normal record */
  600. v->type=type; /* hack */
  601. p=binrpc_read_record(ctx, p, end, v, err);
  602. if (err<0){
  603. ctx->in_struct=tmp;
  604. goto error;
  605. }else{
  606. ctx->in_struct+=tmp;
  607. /* the offset is already updated => skip */
  608. goto no_offs_update;
  609. }
  610. }else{
  611. goto error_record;
  612. }
  613. break;
  614. default:
  615. goto error_record;
  616. }
  617. }else{
  618. switch(type){
  619. case BINRPC_T_INT:
  620. p=binrpc_read_int(&v->u.intval, len, p, end, err);
  621. break;
  622. case BINRPC_T_STR:
  623. v->u.strval.s=(char*)p;
  624. v->u.strval.len=(len-1); /* don't include terminating 0 */
  625. p+=len;
  626. break;
  627. case BINRPC_T_BYTES:
  628. v->u.strval.s=(char*)p;
  629. v->u.strval.len=len;
  630. p+=len;
  631. case BINRPC_T_STRUCT:
  632. if (end_tag)
  633. goto error_record;
  634. v->u.end=0;
  635. ctx->in_struct++;
  636. break;
  637. case BINRPC_T_ARRAY:
  638. if (end_tag){
  639. if (ctx->in_array>0){
  640. ctx->in_array--;
  641. v->u.end=1;
  642. }else
  643. goto error_record;
  644. }else{
  645. ctx->in_array++;
  646. v->u.end=0;
  647. }
  648. break;
  649. case BINRPC_T_DOUBLE: /* FIXME: hack: represented as fixed point
  650. inside an int */
  651. p=binrpc_read_int(&i, len, p, end, err);
  652. v->u.fval=((double)i)/1000;
  653. break;
  654. default:
  655. goto error_type;
  656. }
  657. }
  658. ctx->offset+=(int)(p-buf);
  659. no_offs_update:
  660. return p;
  661. error_type:
  662. *err=E_BINRPC_TYPE;
  663. return buf;
  664. error_record:
  665. *err=E_BINRPC_RECORD;
  666. error:
  667. return buf;
  668. }
  669. /* reads/skips an entire struct
  670. * the struct start/end are saved in v->u.strval.s, v->u.strval.len
  671. * return: - new buffer position and set *err to 0 if successfull
  672. * - original buffer and *err<0 on error */
  673. inline static unsigned char* binrpc_read_struct(struct binrpc_parse_ctx* ctx,
  674. unsigned char* buf,
  675. unsigned char* end,
  676. struct binrpc_val* v,
  677. int* err
  678. )
  679. {
  680. int type;
  681. int len;
  682. int end_tag;
  683. unsigned char* p;
  684. int in_struct;
  685. *err=0;
  686. p=buf;
  687. end_tag=0;
  688. if (!(ctx->flags & BINRPC_F_INIT)){
  689. *err=E_BINRPC_NOTINIT;
  690. goto error;
  691. }
  692. if (ctx->offset>=ctx->tlen){
  693. *err=E_BINRPC_EOP;
  694. goto error;
  695. }
  696. if (p>=end){
  697. *err=E_BINRPC_MORE_DATA;
  698. goto error;
  699. }
  700. /* read type_len */
  701. type=*p & 0xf;
  702. len=*p>>4;
  703. p++;
  704. if (len & 8){
  705. end_tag=1; /* possible end mark for array or structs */
  706. /* we have to read len bytes and use them as the new len */
  707. p=binrpc_read_int(&len, len&7, p, end, err);
  708. if (*err<0)
  709. goto error;
  710. }
  711. if ((p+len)>=end){
  712. *err=E_BINRPC_MORE_DATA;
  713. goto error;
  714. }
  715. if (type!=BINRPC_T_STRUCT){
  716. goto error_type;
  717. }
  718. if (end_tag){
  719. goto error_record;
  720. }
  721. p+=len; /* len should be 0 for a struct tag */
  722. in_struct=1;
  723. v->type=type;
  724. v->u.strval.s=(char*)p; /* it will conain the inside of the struc */
  725. while(in_struct){
  726. /* read name */
  727. type=*p & 0xf;
  728. len=*p>>4;
  729. p++;
  730. if (len & 8){
  731. end_tag=1; /* possible end mark for array or structs */
  732. /* we have to read len bytes and use them as the new len */
  733. p=binrpc_read_int(&len, len&7, p, end, err);
  734. if (*err<0)
  735. goto error;
  736. }
  737. if ((type==BINRPC_T_STRUCT) && end_tag){
  738. in_struct--;
  739. if (in_struct<0)
  740. goto error_record;
  741. continue;
  742. }else if (type!=BINRPC_T_AVP){
  743. goto error_record;
  744. }
  745. /* skip over it */
  746. p+=len;
  747. if (p>=end){
  748. *err=E_BINRPC_MORE_DATA;
  749. goto error;
  750. }
  751. /* read value */
  752. type=*p & 0xf;
  753. len=*p>>4;
  754. p++;
  755. if (len & 8){
  756. end_tag=1; /* possible end mark for array or structs */
  757. /* we have to read len bytes and use them as the new len */
  758. p=binrpc_read_int(&len, len&7, p, end, err);
  759. if (*err<0)
  760. goto error;
  761. }
  762. if (type==BINRPC_T_STRUCT){
  763. if (end_tag)
  764. goto error_record;
  765. in_struct++;
  766. };
  767. p+=len;
  768. if (p>=end){
  769. *err=E_BINRPC_MORE_DATA;
  770. goto error;
  771. }
  772. }
  773. /* don't include the end tag */;
  774. v->u.strval.len=(int)(p-(unsigned char*)v->u.strval.s)-1;
  775. return p;
  776. error_type:
  777. *err=E_BINRPC_RECORD;
  778. return buf;
  779. error_record:
  780. *err=E_BINRPC_TYPE;
  781. error:
  782. return buf;
  783. }
  784. /* error code to string */
  785. const char* binrpc_error(int err);
  786. #endif