1 #ifndef TP_H_INCLUDED
2 #define TP_H_INCLUDED
3 
4 #include <stdlib.h>
5 #include <string.h>
6 #include <assert.h>
7 #include <stdarg.h>
8 
9 #include <msgpuck.h>
10 #include <sha1.h>
11 #include <base64.h>
12 
13 
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17 
18 #define tpfunction_unused __attribute__((unused))
19 
20 #if !defined __GNUC_MINOR__ || defined __INTEL_COMPILER || \
21 	defined __SUNPRO_C || defined __SUNPRO_CC
22 #define TP_GCC_VERSION(major, minor) 0
23 #else
24 #define TP_GCC_VERSION(major, minor) (__GNUC__ > (major) || \
25 	(__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
26 #endif
27 
28 #if !defined(__has_builtin)
29 #define __has_builtin(x) 0 /* clang */
30 #endif
31 
32 #if TP_GCC_VERSION(2, 9) || __has_builtin(__builtin_expect)
33 #define tplikely(x) __builtin_expect(!!(x), 1)
34 #define tpunlikely(x) __builtin_expect(!!(x), 0)
35 #else
36 #define tplikely(x) (x)
37 #define tpunlikely(x) (x)
38 #endif
39 
40 /* {{{ API declaration */
41 struct tp;
42 
43 /* available types */
44 enum tp_type {
45 	TP_NIL = MP_NIL,
46 	TP_UINT = MP_UINT,
47 	TP_INT = MP_INT,
48 	TP_STR = MP_STR,
49 	TP_BIN = MP_BIN,
50 	TP_ARRAY = MP_ARRAY,
51 	TP_MAP = MP_MAP,
52 	TP_BOOL = MP_BOOL,
53 	TP_FLOAT = MP_FLOAT,
54 	TP_DOUBLE = MP_DOUBLE,
55 	TP_EXT = MP_EXT
56 };
57 
58 /* header */
59 enum tp_header_key_t {
60 	TP_CODE = 0x00,
61 	TP_SYNC = 0x01
62 };
63 
64 /* request body */
65 enum tp_body_key_t {
66 	TP_SPACE = 0x10,
67 	TP_INDEX = 0x11,
68 	TP_LIMIT = 0x12,
69 	TP_OFFSET = 0x13,
70 	TP_ITERATOR = 0x14,
71 	TP_KEY = 0x20,
72 	TP_TUPLE = 0x21,
73 	TP_FUNCTION = 0x22,
74 	TP_USERNAME = 0x23,
75 	TP_EXPRESSION = 0x27,
76 	TP_SERVER_ID = 0x02,
77 	TP_LSN = 0x03,
78 	TP_TIMESTAMP = 0x04,
79 	TP_SERVER_UUID = 0x24,
80 	TP_CLUSTER_UUID = 0x25,
81 	TP_VCLOCK = 0x26
82 };
83 
84 /* response body */
85 enum tp_response_key_t {
86 	TP_DATA = 0x30,
87 	TP_ERROR = 0x31
88 };
89 
90 /* request types */
91 enum tp_request_type {
92 	TP_SELECT = 1,
93 	TP_INSERT = 2,
94 	TP_REPLACE = 3,
95 	TP_UPDATE = 4,
96 	TP_DELETE = 5,
97 	TP_CALL = 6,
98 	TP_AUTH = 7,
99 	TP_EVAL = 8,
100 	TP_PING = 64,
101 	TP_JOIN = 65,
102 	TP_SUBSCRIBE = 66
103 };
104 
105 enum tp_iterator_type {
106 	TP_ITERATOR_EQ = 0,
107 	TP_ITERATOR_REQ,
108 	TP_ITERATOR_ALL,
109 	TP_ITERATOR_LT,
110 	TP_ITERATOR_LE,
111 	TP_ITERATOR_GE,
112 	TP_ITERATOR_GT,
113 	TP_ITERATOR_BITS_ALL_SET,
114 	TP_ITERATOR_BITS_ANY_SET,
115 	TP_ITERATOR_BITS_ALL_NON_SET,
116 	TP_ITERATOR_OVERLAPS,
117 	TP_ITERATOR_NEIGHBOR
118 };
119 
120 static const uint32_t SCRAMBLE_SIZE = 20;
121 
122 typedef char *(*tp_reserve)(struct tp *p, size_t req, size_t *size);
123 
124 /**
125  * tp greetings object - points to parts of a greetings buffer.
126  */
127 struct tpgreeting {
128 	const char *description; /* Points to a text containg tarantool name and version */
129 	const char *salt_base64; /* Points to connection salt in base64 encoding */
130 };
131 
132 /*
133  * Main tp request object - points to a request buffer.
134  *
135  * All fields except tp->p should not be accessed directly.
136  * Appropriate accessors should be used instead.
137 */
138 struct tp {
139 	char *s, *p, *e;       /* start, pos, end */
140 	char *size;            /* pointer to length field of current request */
141 	char *sync;            /* pointer to sync field of current request */
142 	tp_reserve reserve;    /* realloc function pointer */
143 	void *obj;             /* realloc function pointer */
144 };
145 
146 /**
147  * Struct for iterating msgpack array
148  *
149  * struct tp_array_itr itr;
150  * if (tp_array_itr_init(&itr, buf, buf_size))
151  * 	panic("It's not a valid array!.");
152  * while (tp_array_itr_next(&itr)) {
153  * 	mp_print(itr.elem, itr.elem_end);
154  * 	// or do smth else with itr.elem
155  * }
156  */
157 struct tp_array_itr {
158 	const char *data; /* pointer to the beginning of array */
159 	const char *first_elem; /* pointer to the first element of array */
160 	const char *elem; /* pointer to current element of array */
161 	const char *elem_end; /* pointer to current element end of array */
162 	uint32_t elem_count; /* number of elements in array */
163 	int cur_index; /* index of current element */
164 };
165 
166 /**
167  * Struct for iterating msgpack map
168  *
169  * struct tp_map_itr itr;
170  * if (tp_map_itr_init(&itr, buf, buf_size))
171  * 	panic("It's not a valid map!.");
172  * while(tp_map_itr_next(&itr)) {
173  * 	mp_print(itr.key, itr.key_end);
174  * 	mp_print(itr.value, itr.value_end);
175  * 	// or do smth else with itr.key and itr.value
176  * }
177  */
178 struct tp_map_itr {
179 	const char *data; /* pointer to the beginning of map */
180 	const char *first_key; /* pointer to the first key of map */
181 	const char *key; /* pointer to current key of map */
182 	const char *key_end; /* pointer to current key end */
183 	const char *value; /* pointer to current value of map */
184 	const char *value_end; /* pointer to current value end */
185 	uint32_t pair_count; /* number of key-values pairs in array */
186 	int cur_index; /* index of current pair */
187 };
188 
189 /**
190  * tp response object - points to parts of a response buffer
191  */
192 struct tpresponse {
193 	uint64_t bitmap;               /* bitmap of field IDs that was read from response */
194 	const char *buf;               /* points to beginning of buffer */
195 	uint32_t code;                 /* response code (0 is success, or errno if not) */
196 	uint64_t sync;                 /* synchronization id */
197 	const char *error;             /* error message (NULL if not present) */
198 	const char *error_end;         /* end of error message (NULL if not present) */
199 	const char *data;              /* tuple data (NULL if not present) */
200 	const char *data_end;          /* end if tuple data (NULL if not present) */
201 	struct tp_array_itr tuple_itr; /* internal iterator over tuples */
202 	struct tp_array_itr field_itr; /* internal iterator over tuple fields */
203 };
204 
205 /**
206  * Receive greetings from the server.
207  * Note, the input buffer is not copied,
208  * so freeing or reusing the input buffer will invalidate tpgreeting struct
209  * For example salt is used for authorization (tp_auth).
210  * Returns 0 if buffer is too small or greetings size (128) on success
211  */
212 static inline ssize_t
213 tp_greeting(struct tpgreeting *g, char *buf, size_t size);
214 
215 /**
216  * Main request initialization function.
217  *
218  * buf     - current buffer, may be NULL
219  * size    - current buffer size
220  * reserve - reallocation function, may be NULL
221  * obj     - pointer to be passed to the reallocation function as
222  *           context
223  *
224  * Either a buffer pointer or a reserve function must be
225  * provided.
226  * If reserve function is provided, data must be manually freed
227  * when the buffer is no longer needed.
228  *  (e.g. free(p->s) or tp_free(p) );
229  */
230 static inline void
231 tp_init(struct tp *p, char *buf, size_t size,
232         tp_reserve reserve, void *obj);
233 
234 /**
235  * A common reallocation function, can be used
236  * for 'reserve' param in tp_init().
237  * Resizes the buffer twice the previous size using realloc().
238  *
239  * struct tp req;
240  * tp_init(&req, NULL, tp_realloc, NULL);
241  * tp_ping(&req); // will call the reallocator
242  *
243  * data must be manually freed when the buffer is no longer
244  * needed.
245  * (e.g. free(p->s) or tp_free(p) );
246  * if realloc will return NULL, then you must destroy previous memory.
247  * (e.g.
248  * if (tp_realloc(p, ..) == NULL) {
249  * 	tp_free(p)
250  * 	return NULL;
251  * }
252 */
253 tpfunction_unused static inline char *
254 tp_realloc(struct tp *p, size_t required, size_t *size);
255 
256 /**
257  * Free function for use in a pair with tp_realloc.
258  * Don't use it when tp inited with static buffer!
259  */
260 static inline void
261 tp_free(struct tp *p);
262 
263 /**
264  * Get currently allocated buffer pointer
265  */
266 static inline char *
267 tp_buf(struct tp *p);
268 
269 /**
270  * Get currently allocated buffer size
271  */
272 static inline size_t
273 tp_size(struct tp *p);
274 
275 /**
276  * Get the size of data in the buffer
277  */
278 static inline size_t
279 tp_used(struct tp *p);
280 
281 /**
282  * Get the size available for write
283  */
284 static inline size_t
285 tp_unused(struct tp *p);
286 
287 /**
288  * Create a ping request.
289  *
290  * char buf[64];
291  * struct tp req;
292  * tp_init(&req, buf, sizeof(buf), NULL, NULL);
293  * tp_ping(&req);
294  */
295 static inline char *
296 tp_ping(struct tp *p);
297 
298 /**
299  * Create an auth request.
300  *
301  * salt_base64 must be gathered from tpgreeting struct,
302  * that is initialized during tp_greeting call.
303  *
304  * tp_auth(p, greet.salt_base64, "admin", 5, "pass", 4);
305  */
306 static inline char *
307 tp_auth(struct tp *p, const char *salt_base64, const char *user, int ulen, const char *pass, int plen);
308 
309 /**
310  * Append a select request.
311  *
312  * char buf[64];
313  * struct tp req;
314  * tp_init(&req, buf, sizeof(buf), NULL, NULL);
315  * tp_select(&req, 0, 0, 0, 100);
316  * tp_key(&req, 1);
317  * tp_sz(&req, "key");
318  */
319 static inline char *
320 tp_select(struct tp *p, uint32_t space, uint32_t index,
321 	  uint32_t offset, enum tp_iterator_type iterator, uint32_t limit);
322 
323 /**
324  * Create an insert request.
325  *
326  * char buf[64];
327  * struct tp req;
328  * tp_init(&req, buf, sizeof(buf), NULL, NULL);
329  * tp_insert(&req, 0);
330  * tp_tuple(&req, 2);
331  * tp_sz(&req, "key");
332  * tp_sz(&req, "value");
333  */
334 static inline char *
335 tp_insert(struct tp *p, uint32_t space);
336 
337 /**
338  * Create a replace request.
339  *
340  * char buf[64];
341  * struct tp req;
342  * tp_init(&req, buf, sizeof(buf), NULL, NULL);
343  * tp_insert(&req, 0);
344  * tp_tuple(&req, 2);
345  * tp_sz(&req, "key");
346  * tp_sz(&req, "value");
347  */
348 static inline char *
349 tp_replace(struct tp *p, uint32_t space);
350 
351 /**
352  * Create a delete request.
353  *
354  * char buf[64];
355  * struct tp req;
356  * tp_init(&req, buf, sizeof(buf), NULL, NULL);
357  * tp_delete(&req, 0);
358  * tp_key(&req, 1);
359  * tp_sz(&req, "key");
360  */
361 static inline char *
362 tp_delete(struct tp *p, uint32_t space);
363 
364 /**
365  * Create an update request.
366  *
367  * char buf[64];
368  * struct tp req;
369  * tp_init(&req, buf, sizeof(buf), NULL, NULL);
370  * tp_update(&req, 0); // update of space 0
371  * tp_key(&req, 1); // key with one part
372  * tp_sz(&req, "key"); // one and only part of the key
373  * tp_updatebegin(&req, 2); // update with two operations
374  * tp_op(&req, "+", 2); // add to field 2 ..
375  * tp_encode_uint(&req, 1); // .. a value 1
376  * tp_op(&req, "=", 3); // set a field 3 ..
377  * tp_sz(&req, "value"); // .. a value "value"
378  */
379 static inline char *
380 tp_update(struct tp *p, uint32_t space);
381 
382 /**
383  * Begin update operations.
384  * See tp_update description for details.
385  */
386 static inline char *
387 tp_updatebegin(struct tp *p, uint32_t op_count);
388 
389 /**
390  * Add an update operation.
391  * See tp_update description.
392  * Operation op could be:
393  * "=" - assign operation argument to field <field_no>;
394  *  will extend the tuple if <field_no> == <max_field_no> + 1
395  * "#" - delete <argument> fields starting from <field_no>
396  * "!" - insert <argument> before <field_no>
397  * The following operation(s) are only defined for integer
398  * types:
399  * "+" - add argument to field <field_no>, argument
400  * are integer
401  * "-" - subtract argument from the field <field_no>
402  * "&" - bitwise AND of argument and field <field_no>
403  * "^" - bitwise XOR of argument and field <field_no>
404  * "|" - bitwise OR of argument and field <field_no>
405  */
406 static inline char *
407 tp_op(struct tp *p, char op, uint32_t field_no);
408 
409 /**
410  * Create a call request.
411  *
412  * char buf[64];
413  * struct tp req;
414  * tp_init(&req, buf, sizeof(buf), NULL, NULL);
415  *
416  * char proc[] = "hello_proc";
417  * tp_call(&req, proc, sizeof(proc) - 1);
418  * tp_encode_array(&req, 2);
419  * tp_sz(&req, "arg1");
420  * tp_sz(&req, "arg2");
421  */
422 static inline char *
423 tp_call(struct tp *p, const char *function, int len);
424 
425 /**
426  *
427  */
428 static inline char *
429 tp_format(struct tp *p, const char *format, ...);
430 
431 /**
432  * Write a tuple header
433  * Same as tp_encode_array, added for compatibility.
434  */
435 static inline char *
436 tp_tuple(struct tp *p, uint32_t field_count);
437 
438 /**
439  * Write a key header
440  * Same as tp_encode_array, added for compatibility.
441  */
442 static inline char *
443 tp_key(struct tp *p, uint32_t part_count);
444 
445 /**
446  * Add an uint value to the request
447  */
448 static inline char *
449 tp_encode_uint(struct tp *p, uint64_t num);
450 
451 /**
452  * Add an int value to the request
453  * the value must be less than zero
454  */
455 static inline char *
456 tp_encode_int(struct tp *p, int64_t num);
457 
458 /**
459  * Add a string value to the request, with length provided.
460  */
461 static inline char *
462 tp_encode_str(struct tp *p, const char *str, uint32_t len);
463 
464 /**
465  * Add a zero-end string value to the request.
466  */
467 static inline char *
468 tp_encode_sz(struct tp *p, const char *str);
469 
470 /**
471  * Add a zero-end string value to the request.
472  * (added for compatibility with tarantool 1.5 connector)
473  */
474 static inline char *
475 tp_sz(struct tp *p, const char *str);
476 
477 /**
478  * Add a nil value to the request
479  */
480 static inline char *
481 tp_encode_nil(struct tp *p);
482 
483 /**
484  * Add binary data to the request.
485  */
486 static inline char *
487 tp_encode_bin(struct tp *p, const char *str, uint32_t len);
488 
489 /**
490  * Add an array to the request with a given size
491  *
492  * tp_encode_array(p, 3);
493  * tp_encode_uint(p, 1);
494  * tp_encode_uint(p, 2);
495  * tp_encode_uint(p, 3);
496  */
497 static inline char *
498 tp_encode_array(struct tp *p, uint32_t size);
499 
500 /**
501  * Add a map to the request with a given size
502  *
503  * tp_encode_array(p, 2);
504  * tp_encode_sz(p, "name");
505  * tp_encode_sz(p, "Alan");
506  * tp_encode_sz(p, "birth");
507  * tp_encode_uint(p, 1912);
508  */
509 static inline char *
510 tp_encode_map(struct tp *p, uint32_t size);
511 
512 /**
513  * Add a bool value to the request.
514  */
515 static inline char *
516 tp_encode_bool(struct tp *p, bool val);
517 
518 /**
519  * Add a float value to the request.
520  */
521 static inline char *
522 tp_encode_float(struct tp *p, float num);
523 
524 /**
525  * Add a double float value to the request.
526  */
527 static inline char *
528 tp_encode_double(struct tp *p, double num);
529 
530 /**
531  * Set the current request id.
532  */
533 static inline void
534 tp_reqid(struct tp *p, uint32_t reqid);
535 
536 /**
537  * Ensure that buffer has enough space to fill size bytes, resize
538  * buffer if needed. Returns -1 on error, and new allocated size
539  * of success.
540  */
541 static inline ssize_t
542 tp_ensure(struct tp *p, size_t size);
543 
544 /**
545  * Initialize struct tpresponse with a data buffer.
546  * Returns -1 if an error occured
547  * Returns 0 if buffer contains only part of the response
548  * Return size in bytes of the response in buffer on success
549  */
550 static inline ssize_t
551 tp_reply(struct tpresponse *r, const char * const buf, size_t size);
552 
553 /**
554  * Return the current request id
555  */
556 static inline uint32_t
557 tp_getreqid(struct tpresponse *r);
558 
559 /**
560  * Check if the response has a tuple.
561  * Automatically checked during tp_next() iteration.
562  */
563 static inline int
564 tp_hasdata(struct tpresponse *r);
565 
566 /**
567  * Get tuple count in response
568  */
569 static inline uint32_t
570 tp_tuplecount(const struct tpresponse *r);
571 
572 /**
573  * Skip to the next tuple or to the first tuple after rewind
574  */
575 static inline int
576 tp_next(struct tpresponse *r);
577 
578 /**
579  * Check if there is one more tuple.
580  */
581 static inline int
582 tp_hasnext(struct tpresponse *r);
583 
584 /**
585  * Rewind iteration to the first tuple.
586  * Note that initialization of tpresponse via tp_reply
587  * rewinds tuple iteration automatically
588  */
589 static inline void
590 tp_rewind(struct tpresponse *r);
591 
592 /**
593  * Get the current tuple data, all fields.
594  */
595 static inline const char *
596 tp_gettuple(struct tpresponse *r);
597 
598 /**
599  * Get the current tuple size in bytes.
600  */
601 static inline uint32_t
602 tp_tuplesize(struct tpresponse *r);
603 
604 /**
605  *  Get a pointer to the end of the current tuple.
606  */
607 static inline const char *
608 tp_tupleend(struct tpresponse *r);
609 
610 /**
611  * Skip to the next field.
612  */
613 static inline int
614 tp_nextfield(struct tpresponse *r);
615 
616 /**
617  * Get the current field.
618  */
619 static inline const char *
620 tp_getfield(struct tpresponse *r);
621 
622 /*
623  * Rewind iteration to the first tuple field of the current tuple.
624  * Note that iterating tuples of the response
625  * rewinds field iteration automatically
626  */
627 static inline void
628 tp_rewindfield(struct tpresponse *r);
629 
630 /*
631  * Check if the current tuple has one more field.
632  */
633 static inline int
634 tp_hasnextfield(struct tpresponse *r);
635 
636 
637 /**
638  * Get the current field size in bytes.
639  */
640 static inline uint32_t
641 tp_getfieldsize(struct tpresponse *r);
642 
643 /*
644  * Determine MsgPack type by first byte of encoded data.
645  */
646 static inline enum tp_type
647 tp_typeof(const char c);
648 
649 /**
650  * Read unsigned integer value
651  */
652 static inline uint64_t
653 tp_get_uint(const char *field);
654 
655 /**
656  * Read signed integer value
657  */
658 static inline int64_t
659 tp_get_int(const char *field);
660 
661 /**
662  * Read float value
663  */
664 static inline float
665 tp_get_float(const char *field);
666 
667 /**
668  * Read double value
669  */
670 static inline double
671 tp_get_double(const char *field);
672 
673 /**
674  * Read bool value
675  */
676 static inline bool
677 tp_get_bool(const char *field);
678 
679 /**
680  * Read string value
681  */
682 static inline const char *
683 tp_get_str(const char *field, uint32_t *size);
684 
685 /**
686  * Read binary data value
687  */
688 static inline const char *
689 tp_get_bin(const char *field, uint32_t *size);
690 
691 
692 /**
693  * Init msgpack iterator by a pointer to msgpack array beginning.
694  * First element will be accessible after tp_array_itr_next call.
695  * Returns -1 on error
696  */
697 static inline int
698 tp_array_itr_init(struct tp_array_itr *itr, const char *data, size_t size);
699 
700 /**
701  * Iterate to next position.
702  * return true if success, or false if there are no elements left
703  */
704 static inline bool
705 tp_array_itr_next(struct tp_array_itr *itr);
706 
707 /**
708  * Reset iterator to the beginning. First element will be
709  * accessible after tp_array_itr_next call.
710  * return true if success, or false if there are no elements left
711  */
712 static inline void
713 tp_array_itr_reset(struct tp_array_itr *itr);
714 
715 /**
716  * Init msgpack map iterator by a pointer to msgpack map beginning.
717  * First element will be accessible after tp_map_itr_next call.
718  * Returns -1 on error
719  */
720 static inline int
721 tp_map_itr_init(struct tp_map_itr *itr, const char *data, size_t size);
722 
723 /**
724  * Iterate to next position.
725  * return true if success, or false if there are no pairs left
726  */
727 static inline bool
728 tp_map_itr_next(struct tp_map_itr *itr);
729 
730 /**
731  * Reset iterator to the beginning. First pair will be
732  * accessible after tp_map_itr_next call.
733  * return true if success, or false if there are no pairs left
734  */
735 static inline void
736 tp_map_itr_reset(struct tp_map_itr *itr);
737 
738 /* }}} */
739 
740 
741 /* {{{ Implementation */
742 
743 /**
744  * Receive greetings from the server.
745  * Note, the input buffer is not copied,
746  * so freeing or reusing the input buffer will invalidate tpgreeting struct
747  * For example salt is used for authorization (tp_auth).
748  * Returns 0 if buffer is too small or greetings size (128) on success
749  */
750 static inline ssize_t
tp_greeting(struct tpgreeting * g,char * buf,size_t size)751 tp_greeting(struct tpgreeting *g, char *buf, size_t size)
752 {
753 	if (size < 128)
754 		return 0;
755 	g->description = buf;
756 	g->salt_base64 = buf + 64;
757 	return 128;
758 }
759 
760 
761 /**
762  * Get currently allocated buffer pointer
763  */
764 static inline char *
tp_buf(struct tp * p)765 tp_buf(struct tp *p)
766 {
767 	return p->s;
768 }
769 
770 /**
771  * Get currently allocated buffer size
772  */
773 static inline size_t
tp_size(struct tp * p)774 tp_size(struct tp *p)
775 {
776 	return p->e - p->s;
777 }
778 
779 /**
780  * Get the size of data in the buffer
781  */
782 static inline size_t
tp_used(struct tp * p)783 tp_used(struct tp *p)
784 {
785 	return p->p - p->s;
786 }
787 
788 /**
789  * Get the size available for write
790  */
791 static inline size_t
tp_unused(struct tp * p)792 tp_unused(struct tp *p)
793 {
794 	return p->e - p->p;
795 }
796 
797 /**
798  * A common reallocation function, can be used
799  * for 'reserve' param in tp_init().
800  * Resizes the buffer twice the previous size using realloc().
801  *
802  * struct tp req;
803  * tp_init(&req, NULL, tp_realloc, NULL);
804  * tp_ping(&req); // will call the reallocator
805  *
806  * data must be manually freed when the buffer is no longer
807  * needed.
808  * (e.g. free(p->s) or tp_free(p) );
809  * if realloc will return NULL, then you must destroy previous memory.
810  * (e.g.
811  * if (tp_realloc(p, ..) == NULL) {
812  * 	tp_free(p)
813  * 	return NULL;
814  * }
815 */
816 tpfunction_unused static char *
tp_realloc(struct tp * p,size_t required,size_t * size)817 tp_realloc(struct tp *p, size_t required, size_t *size)
818 {
819 	size_t toalloc = tp_size(p) * 2;
820 	if (tpunlikely(toalloc < required))
821 		toalloc = tp_size(p) + required;
822 	*size = toalloc;
823 	return (char *) realloc(p->s, toalloc);
824 }
825 
826 /**
827  * Free function for use in a pair with tp_realloc.
828  * Don't use it when tp inited with static buffer!
829  */
830 static inline void
tp_free(struct tp * p)831 tp_free(struct tp *p)
832 {
833 	free(p->s);
834 }
835 
836 /**
837  * Main initialization function.
838  *
839  * buf     - current buffer, may be NULL
840  * size    - current buffer size
841  * reserve - reallocation function, may be NULL
842  * obj     - pointer to be passed to the reallocation function as
843  *           context
844  *
845  * Either a buffer pointer or a reserve function must be
846  * provided.
847  * If reserve function is provided, data must be manually freed
848  * when the buffer is no longer needed.
849  *  (e.g. free(p->s) or tp_free(p) );
850  */
851 static inline void
tp_init(struct tp * p,char * buf,size_t size,tp_reserve reserve,void * obj)852 tp_init(struct tp *p, char *buf, size_t size,
853         tp_reserve reserve, void *obj)
854 {
855 	p->s = buf;
856 	p->p = p->s;
857 	p->e = p->s + size;
858 	p->size = NULL;
859 	p->sync = NULL;
860 	p->reserve = reserve;
861 	p->obj = obj;
862 }
863 
864 /**
865  * Ensure that buffer has enough space to fill size bytes, resize
866  * buffer if needed. Returns -1 on error, and new allocated size
867  * on success.
868  */
869 static inline ssize_t
tp_ensure(struct tp * p,size_t size)870 tp_ensure(struct tp *p, size_t size)
871 {
872 	if (tplikely(tp_unused(p) >= size))
873 		return 0;
874 	if (tpunlikely(p->reserve == NULL))
875 		return -1;
876 	size_t sz;
877 	char *np = p->reserve(p, size, &sz);
878 	if (tpunlikely(np == NULL))
879 		return -1;
880 	if (tplikely(p->size))
881 		p->size = (np + (((char *)p->size) - p->s));
882 	if (tplikely(p->sync))
883 		p->sync = (np + (((char *)p->sync) - p->s));
884 	p->p = np + (p->p - p->s);
885 	p->s = np;
886 	p->e = np + sz;
887 	return sz;
888 }
889 
890 /**
891  * Accept data of specified size.
892  * This is a function for internal use, and is not part of an API
893  */
894 static inline char *
tp_add(struct tp * p,size_t size)895 tp_add(struct tp *p, size_t size)
896 {
897 	void *ptr = p->p;
898 	p->p += size;
899 	assert(p->size);
900 	*p->size = 0xce;
901 	*(uint32_t*)(p->size + 1) = mp_bswap_u32(p->p - p->size - 5);
902 	return (char *) ptr;
903 }
904 
905 /**
906  * Internal
907  * Function for getting size of header
908  */
909 static inline uint32_t
tpi_sizeof_header(uint32_t code)910 tpi_sizeof_header(uint32_t code)
911 {
912 	return 5 + mp_sizeof_map(2) +
913 		mp_sizeof_uint(TP_CODE) +
914 		mp_sizeof_uint(code)	+
915 		mp_sizeof_uint(TP_SYNC) +
916 		5;
917 }
918 
919 /**
920  * Internal
921  * Function for encoding header
922  */
923 static inline char *
tpi_encode_header(struct tp * p,uint32_t code)924 tpi_encode_header(struct tp* p, uint32_t code)
925 {
926 	p->size = p->p;
927 	char *h = mp_encode_map(p->p + 5, 2);
928 	h = mp_encode_uint(h, TP_CODE);
929 	h = mp_encode_uint(h, code);
930 	h = mp_encode_uint(h, TP_SYNC);
931 	p->sync = h;
932 	*h = 0xce;
933 	*(uint32_t*)(h + 1) = 0;
934 	h += 5;
935 	return h;
936 }
937 
938 /**
939  * Create a ping request.
940  *
941  * char buf[64];
942  * struct tp req;
943  * tp_init(&req, buf, sizeof(buf), NULL, NULL);
944  * tp_ping(&req);
945  */
946 static inline char *
tp_ping(struct tp * p)947 tp_ping(struct tp *p)
948 {
949 	int hsz = tpi_sizeof_header(TP_PING);
950 	int  sz = mp_sizeof_map(0);
951 	if (tpunlikely(tp_ensure(p, sz + hsz) == -1))
952 		return NULL;
953 	char *h = tpi_encode_header(p, TP_PING);
954 	h = mp_encode_map(h, 0);
955 	return tp_add(p, sz + hsz);
956 }
957 
958 /**
959  * Append a select request.
960  *
961  * char buf[64];
962  * struct tp req;
963  * tp_init(&req, buf, sizeof(buf), NULL, NULL);
964  * tp_select(&req, 0, 0, 0, 100);
965  * tp_key(&req, 1);
966  * tp_sz(&req, "key");
967  */
968 static inline char *
tp_select(struct tp * p,uint32_t space,uint32_t index,uint32_t offset,enum tp_iterator_type iterator,uint32_t limit)969 tp_select(struct tp *p, uint32_t space, uint32_t index,
970 	  uint32_t offset, enum tp_iterator_type iterator, uint32_t limit)
971 {
972 	int hsz = tpi_sizeof_header(TP_SELECT);
973 	int  sz = mp_sizeof_map(6) +
974 		mp_sizeof_uint(TP_SPACE) +
975 		mp_sizeof_uint(space) +
976 		mp_sizeof_uint(TP_INDEX) +
977 		mp_sizeof_uint(index) +
978 		mp_sizeof_uint(TP_OFFSET) +
979 		mp_sizeof_uint(offset) +
980 		mp_sizeof_uint(TP_LIMIT) +
981 		mp_sizeof_uint(limit) +
982 		mp_sizeof_uint(TP_ITERATOR) +
983 		mp_sizeof_uint(iterator) +
984 		mp_sizeof_uint(TP_KEY);
985 	if (tpunlikely(tp_ensure(p, sz + hsz) == -1))
986 		return NULL;
987 	char *h = tpi_encode_header(p, TP_SELECT);
988 	h = mp_encode_map(h, 6);
989 	h = mp_encode_uint(h, TP_SPACE);
990 	h = mp_encode_uint(h, space);
991 	h = mp_encode_uint(h, TP_INDEX);
992 	h = mp_encode_uint(h, index);
993 	h = mp_encode_uint(h, TP_OFFSET);
994 	h = mp_encode_uint(h, offset);
995 	h = mp_encode_uint(h, TP_LIMIT);
996 	h = mp_encode_uint(h, limit);
997 	h = mp_encode_uint(h, TP_ITERATOR);
998 	h = mp_encode_uint(h, iterator);
999 	h = mp_encode_uint(h, TP_KEY);
1000 	return tp_add(p, sz + hsz);
1001 }
1002 
1003 /**
1004  * Internal
1005  * Function for encoding insert or replace request
1006  */
1007 static inline char *
tpi_encode_store(struct tp * p,enum tp_request_type type,uint32_t space)1008 tpi_encode_store(struct tp *p, enum tp_request_type type, uint32_t space)
1009 {
1010 	int hsz = tpi_sizeof_header(type);
1011 	int sz = mp_sizeof_map(2) +
1012 		mp_sizeof_uint(TP_SPACE) +
1013 		mp_sizeof_uint(space) +
1014 		mp_sizeof_uint(TP_TUPLE);
1015 	if (tpunlikely(tp_ensure(p, sz + hsz) == -1))
1016 		return NULL;
1017 	char *h = tpi_encode_header(p, type);
1018 	h = mp_encode_map(h, 2);
1019 	h = mp_encode_uint(h, TP_SPACE);
1020 	h = mp_encode_uint(h, space);
1021 	h = mp_encode_uint(h, TP_TUPLE);
1022 	return tp_add(p, sz + hsz);
1023 }
1024 
1025 /**
1026  * Create an insert request.
1027  *
1028  * char buf[64];
1029  * struct tp req;
1030  * tp_init(&req, buf, sizeof(buf), NULL, NULL);
1031  * tp_insert(&req, 0);
1032  * tp_tuple(&req, 2);
1033  * tp_sz(&req, "key");
1034  * tp_sz(&req, "value");
1035  */
1036 static inline char *
tp_insert(struct tp * p,uint32_t space)1037 tp_insert(struct tp *p, uint32_t space)
1038 {
1039 	return tpi_encode_store(p, TP_INSERT, space);
1040 }
1041 
1042 /**
1043  * Create a replace request.
1044  *
1045  * char buf[64];
1046  * struct tp req;
1047  * tp_init(&req, buf, sizeof(buf), NULL, NULL);
1048  * tp_insert(&req, 0);
1049  * tp_tuple(&req, 2);
1050  * tp_sz(&req, "key");
1051  * tp_sz(&req, "value");
1052  */
1053 static inline char *
tp_replace(struct tp * p,uint32_t space)1054 tp_replace(struct tp *p, uint32_t space)
1055 {
1056 	return tpi_encode_store(p, TP_REPLACE, space);
1057 }
1058 
1059 /**
1060  * Create a delete request.
1061  *
1062  * char buf[64];
1063  * struct tp req;
1064  * tp_init(&req, buf, sizeof(buf), NULL, NULL);
1065  * tp_delete(&req, 0);
1066  * tp_key(&req, 1);
1067  * tp_sz(&req, "key");
1068  */
1069 static inline char *
tp_delete(struct tp * p,uint32_t space)1070 tp_delete(struct tp *p, uint32_t space)
1071 {
1072 	int hsz = tpi_sizeof_header(TP_DELETE);
1073 	int  sz = mp_sizeof_map(2) +
1074 		mp_sizeof_uint(TP_SPACE) +
1075 		mp_sizeof_uint(space) +
1076 		mp_sizeof_uint(TP_KEY);
1077 	if (tpunlikely(tp_ensure(p, sz + hsz) == -1))
1078 		return NULL;
1079 	char *h = tpi_encode_header(p, TP_DELETE);
1080 	h = mp_encode_uint(h, TP_SPACE);
1081 	h = mp_encode_uint(h, space);
1082 	h = mp_encode_uint(h, TP_KEY);
1083 	return tp_add(p, sz + hsz);
1084 }
1085 
1086 /**
1087  * Create a call request.
1088  *
1089  * char buf[64];
1090  * struct tp req;
1091  * tp_init(&req, buf, sizeof(buf), NULL, NULL);
1092  *
1093  * char proc[] = "hello_proc";
1094  * tp_call(&req, proc, sizeof(proc) - 1);
1095  * tp_encode_array(&req, 2);
1096  * tp_sz(&req, "arg1");
1097  * tp_sz(&req, "arg2");
1098  */
1099 static inline char *
tp_call(struct tp * p,const char * function,int len)1100 tp_call(struct tp *p, const char *function, int len)
1101 {
1102 	int hsz = tpi_sizeof_header(TP_CALL);
1103 	int  sz = mp_sizeof_map(2) +
1104 		mp_sizeof_uint(TP_FUNCTION) +
1105 		mp_sizeof_str(len) +
1106 		mp_sizeof_uint(TP_TUPLE);
1107 	if (tpunlikely(tp_ensure(p, sz + hsz) == -1))
1108 		return NULL;
1109 	char *h = tpi_encode_header(p, TP_CALL);
1110 	h = mp_encode_map(h, 2);
1111 	h = mp_encode_uint(h, TP_FUNCTION);
1112 	h = mp_encode_str(h, function, len);
1113 	h = mp_encode_uint(h, TP_TUPLE);
1114 	return tp_add(p, sz + hsz);
1115 }
1116 
1117 /**
1118  * Create an eval request.
1119  *
1120  * char buf[64];
1121  * struct tp req;
1122  * tp_init(&req, buf, sizeof(buf), NULL, NULL);
1123  *
1124  * char proc[] = "hello_proc";
1125  * tp_eval(&req, proc, sizeof(proc) - 1);
1126  * tp_encode_array(&req, 2);
1127  * tp_sz(&req, "arg1");
1128  * tp_sz(&req, "arg2");
1129  */
1130 static inline char *
tp_eval(struct tp * p,const char * expr,int len)1131 tp_eval(struct tp *p, const char *expr, int len)
1132 {
1133 	int hsz = tpi_sizeof_header(TP_EVAL);
1134 	int  sz = mp_sizeof_map(2) +
1135 		mp_sizeof_uint(TP_FUNCTION) +
1136 		mp_sizeof_str(len) +
1137 		mp_sizeof_uint(TP_TUPLE);
1138 	if (tpunlikely(tp_ensure(p, sz + hsz) == -1))
1139 		return NULL;
1140 	char *h = tpi_encode_header(p, TP_EVAL);
1141 	h = mp_encode_map(h, 2);
1142 	h = mp_encode_uint(h, TP_EXPRESSION);
1143 	h = mp_encode_str(h, expr, len);
1144 	h = mp_encode_uint(h, TP_TUPLE);
1145 	return tp_add(p, sz + hsz);
1146 }
1147 
1148 /**
1149  * Create an update request.
1150  *
1151  * char buf[64];
1152  * struct tp req;
1153  * tp_init(&req, buf, sizeof(buf), NULL, NULL);
1154  * tp_update(&req, 0); // update of space 0
1155  * tp_key(&req, 1); // key with one part
1156  * tp_sz(&req, "key"); // one and only part of the key
1157  * tp_updatebegin(&req, 2); // update with two operations
1158  * tp_op(&req, "+", 2); // add to field 2 ..
1159  * tp_encode_uint(&req, 1); // .. a value 1
1160  * tp_op(&req, "=", 3); // set a field 3 ..
1161  * tp_sz(&req, "value"); // .. a value "value"
1162  */
1163 static inline char *
tp_update(struct tp * p,uint32_t space)1164 tp_update(struct tp *p, uint32_t space)
1165 {
1166 	int hsz = tpi_sizeof_header(TP_UPDATE);
1167 	int  sz = mp_sizeof_map(3) +
1168 		mp_sizeof_uint(TP_SPACE) +
1169 		mp_sizeof_uint(space) +
1170 		mp_sizeof_uint(TP_KEY);
1171 	if (tpunlikely(tp_ensure(p, sz + hsz) == -1))
1172 		return NULL;
1173 	char *h = tpi_encode_header(p, TP_UPDATE);
1174 	h = mp_encode_map(h, 3);
1175 	h = mp_encode_uint(h, TP_SPACE);
1176 	h = mp_encode_uint(h, space);
1177 	h = mp_encode_uint(h, TP_KEY);
1178 	return tp_add(p, sz + hsz);
1179 }
1180 
1181 /**
1182  * Begin update operations.
1183  * See tp_update description for details.
1184  */
1185 static inline char *
tp_updatebegin(struct tp * p,uint32_t op_count)1186 tp_updatebegin(struct tp *p, uint32_t op_count)
1187 {
1188 	int sz = mp_sizeof_uint(TP_TUPLE) + mp_sizeof_array(op_count);
1189 	if (tpunlikely(tp_ensure(p, sz) == -1))
1190 		return NULL;
1191 	char *h = mp_encode_uint(p->p, TP_TUPLE);
1192 	mp_encode_array(h, op_count);
1193 	return tp_add(p, sz);
1194 }
1195 
1196 /**
1197  * Add an update operation.
1198  * See tp_update description.
1199  * Operation op could be:
1200  * "=" - assign operation argument to field <field_no>;
1201  *  will extend the tuple if <field_no> == <max_field_no> + 1
1202  * "#" - delete <argument> fields starting from <field_no>
1203  * "!" - insert <argument> before <field_no>
1204  * The following operation(s) are only defined for integer
1205  * types:
1206  * "+" - add argument to field <field_no>, argument
1207  * are integer
1208  * "-" - subtract argument from the field <field_no>
1209  * "&" - bitwise AND of argument and field <field_no>
1210  * "^" - bitwise XOR of argument and field <field_no>
1211  * "|" - bitwise OR of argument and field <field_no>
1212  */
1213 static inline char *
tp_op(struct tp * p,char op,uint32_t field_no)1214 tp_op(struct tp *p, char op, uint32_t field_no)
1215 {
1216 	int sz = mp_sizeof_array(3) +
1217 		mp_sizeof_str(1) +
1218 		mp_sizeof_uint(field_no);
1219 	if (tpunlikely(tp_ensure(p, sz) == -1))
1220 		return NULL;
1221 	char *h = mp_encode_array(p->p, 3);
1222 	h = mp_encode_str(h, &op, 1);
1223 	h = mp_encode_uint(h, field_no);
1224 	return tp_add(p, sz);
1225 }
1226 
1227 /**
1228  * Add an slice operation
1229  * See tp_update description.
1230  */
1231 static inline char *
tp_op_splice(struct tp * p,uint32_t field_no,uint32_t offset,uint32_t cut_limit,const char * paste,uint32_t paste_len)1232 tp_op_splice(struct tp *p, uint32_t field_no,
1233 	     uint32_t offset, uint32_t cut_limit,
1234 	     const char *paste, uint32_t paste_len)
1235 {
1236 	int sz = mp_sizeof_array(5) +
1237 		mp_sizeof_str(1) +
1238 		mp_sizeof_uint(field_no) +
1239 		mp_sizeof_uint(field_no) +
1240 		mp_sizeof_uint(field_no) +
1241 		mp_sizeof_str(paste_len);
1242 	if (tpunlikely(tp_ensure(p, sz) == -1))
1243 		return NULL;
1244 	char *h = mp_encode_array(p->p, 5);
1245 	h = mp_encode_str(h, ":", 1);
1246 	h = mp_encode_uint(h, field_no);
1247 	h = mp_encode_uint(h, offset);
1248 	h = mp_encode_uint(h, cut_limit);
1249 	h = mp_encode_str(h, paste, paste_len);
1250 	return tp_add(p, sz);
1251 }
1252 
1253 
1254 /**
1255  * Internal
1256  * tpi_xor
1257  * The function is for internal use, not part of the API
1258  */
1259 static inline void
tpi_xor(unsigned char * to,const unsigned char * left,const unsigned char * right,uint32_t len)1260 tpi_xor(unsigned char *to, const unsigned char *left,
1261        const unsigned char *right, uint32_t len)
1262 {
1263 	const uint8_t *end = to + len;
1264 	while (to < end)
1265 		*to++= *left++ ^ *right++;
1266 }
1267 
1268 /**
1269  * Internal
1270  * tpi_scramble_prepare
1271  * The function is for internal use, not part of the API
1272  */
1273 static inline void
tpi_scramble_prepare(void * out,const void * salt,const void * password,int password_len)1274 tpi_scramble_prepare(void *out, const void *salt, const void *password,
1275 		 int password_len)
1276 {
1277 	unsigned char hash1[SCRAMBLE_SIZE];
1278 	unsigned char hash2[SCRAMBLE_SIZE];
1279 	SHA1_CTX ctx;
1280 
1281 	SHA1Init(&ctx);
1282 	SHA1Update(&ctx, (const unsigned char *) password, password_len);
1283 	SHA1Final(hash1, &ctx);
1284 
1285 	SHA1Init(&ctx);
1286 	SHA1Update(&ctx, hash1, SCRAMBLE_SIZE);
1287 	SHA1Final(hash2, &ctx);
1288 
1289 	SHA1Init(&ctx);
1290 	SHA1Update(&ctx, (const unsigned char *) salt, SCRAMBLE_SIZE);
1291 	SHA1Update(&ctx, hash2, SCRAMBLE_SIZE);
1292 	SHA1Final((unsigned char *) out, &ctx);
1293 
1294 	tpi_xor((unsigned char *) out, hash1, (const unsigned char *) out,
1295 	       SCRAMBLE_SIZE);
1296 }
1297 
1298 /**
1299  * Create an auth request.
1300  *
1301  * salt_base64 must be gathered from tpgreeting struct,
1302  * that is initialized during tp_greeting call.
1303  *
1304  * tp_auth(p, greet.salt_base64, "admin", 5, "pass", 4);
1305  */
1306 static inline char *
tp_auth(struct tp * p,const char * salt_base64,const char * user,int ulen,const char * pass,int plen)1307 tp_auth(struct tp *p, const char *salt_base64, const char *user,
1308 	int ulen, const char *pass, int plen)
1309 {
1310 	int hsz = tpi_sizeof_header(TP_AUTH);
1311 	int  sz = mp_sizeof_array(2) +
1312 		      mp_sizeof_str(0) +
1313 		      mp_sizeof_str(SCRAMBLE_SIZE);
1314 	if (tpunlikely(tp_ensure(p, sz + hsz) == -1))
1315 		return NULL;
1316 	char *h = tpi_encode_header(p, TP_AUTH);
1317 	h = mp_encode_map(h, 2);
1318 	h = mp_encode_uint(h, TP_USERNAME);
1319 	h = mp_encode_str(h, user, ulen);
1320 	h = mp_encode_uint(h, TP_TUPLE);
1321 	h = mp_encode_array(h, 2);
1322 	h = mp_encode_str(h, "chap-sha1", 9);
1323 
1324 	char salt[64];
1325 	base64_decode(salt_base64, 44, salt, 64);
1326 	char scramble[SCRAMBLE_SIZE];
1327 	tpi_scramble_prepare(scramble, salt, pass, plen);
1328 	h = mp_encode_str(h, scramble, SCRAMBLE_SIZE);
1329 
1330 	return tp_add(p, sz + hsz);
1331 }
1332 
1333 /**
1334  * Create an deauth (auth as a guest) request.
1335  *
1336  * tp_deauth(p);
1337  */
1338 static inline char *
tp_deauth(struct tp * p)1339 tp_deauth(struct tp *p)
1340 {
1341 	int hsz = tpi_sizeof_header(TP_AUTH);
1342 	int  sz = mp_sizeof_array(0);
1343 	if (tpunlikely(tp_ensure(p, sz + hsz) == -1))
1344 		return NULL;
1345 	p->size = p->p;
1346 	char *h = tpi_encode_header(p, TP_AUTH);
1347 	h = mp_encode_map(h, 2);
1348 	h = mp_encode_uint(h, TP_USERNAME);
1349 	h = mp_encode_str(h, "guest", 5);
1350 	h = mp_encode_uint(h, TP_TUPLE);
1351 	h = mp_encode_array(h, 0);
1352 
1353 	return tp_add(p, sz + hsz);
1354 }
1355 
1356 /**
1357  * Set the current request id.
1358  */
1359 static inline void
tp_reqid(struct tp * p,uint32_t reqid)1360 tp_reqid(struct tp *p, uint32_t reqid)
1361 {
1362 	assert(p->sync != NULL);
1363 	char *h = p->sync;
1364 	*h = 0xce;
1365 	*(uint32_t*)(h + 1) = mp_bswap_u32(reqid);
1366 }
1367 
1368 /**
1369  * Add a nil value to the request
1370  */
1371 static inline char *
tp_encode_nil(struct tp * p)1372 tp_encode_nil(struct tp *p)
1373 {
1374 	int sz = mp_sizeof_nil();
1375 	if (tpunlikely(tp_ensure(p, sz) == -1))
1376 		return NULL;
1377 	mp_encode_nil(p->p);
1378 	return tp_add(p, sz);
1379 }
1380 
1381 /**
1382  * Add an uint value to the request
1383  */
1384 static inline char *
tp_encode_uint(struct tp * p,uint64_t num)1385 tp_encode_uint(struct tp *p, uint64_t num)
1386 {
1387 	int sz = mp_sizeof_uint(num);
1388 	if (tpunlikely(tp_ensure(p, sz) == -1))
1389 		return NULL;
1390 	mp_encode_uint(p->p, num);
1391 	return tp_add(p, sz);
1392 }
1393 
1394 /**
1395  * Add an int value to the request
1396  * the value must be less than zero
1397  */
1398 static inline char *
tp_encode_int(struct tp * p,int64_t num)1399 tp_encode_int(struct tp *p, int64_t num)
1400 {
1401 	int sz = mp_sizeof_int(num);
1402 	if (tpunlikely(tp_ensure(p, sz) == -1))
1403 		return NULL;
1404 	mp_encode_int(p->p, num);
1405 	return tp_add(p, sz);
1406 }
1407 
1408 /**
1409  * Add a string value to the request, with length provided.
1410  */
1411 static inline char *
tp_encode_str(struct tp * p,const char * str,uint32_t len)1412 tp_encode_str(struct tp *p, const char *str, uint32_t len)
1413 {
1414 	int sz = mp_sizeof_str(len);
1415 	if (tpunlikely(tp_ensure(p, sz) == -1))
1416 		return NULL;
1417 	mp_encode_str(p->p, str, len);
1418 	return tp_add(p, sz);
1419 }
1420 
1421 /**
1422  * Add a zero-end string value to the request.
1423  */
1424 static inline char *
tp_encode_sz(struct tp * p,const char * str)1425 tp_encode_sz(struct tp *p, const char *str)
1426 {
1427 	uint32_t len = (uint32_t)strlen(str);
1428 	int sz = mp_sizeof_str(len);
1429 	if (tpunlikely(tp_ensure(p, sz) == -1))
1430 		return NULL;
1431 	mp_encode_str(p->p, str, len);
1432 	return tp_add(p, sz);
1433 }
1434 
1435 /**
1436  * Add a zero-end string value to the request.
1437  * (added for compatibility with tarantool 1.5 connector)
1438  */
1439 static inline char *
tp_sz(struct tp * p,const char * str)1440 tp_sz(struct tp *p, const char *str)
1441 {
1442 	return tp_encode_sz(p, str);
1443 }
1444 
1445 /**
1446  * Add binary data to the request.
1447  */
1448 static inline char *
tp_encode_bin(struct tp * p,const char * str,uint32_t len)1449 tp_encode_bin(struct tp *p, const char *str, uint32_t len)
1450 {
1451 	int sz = mp_sizeof_bin(len);
1452 	if (tpunlikely(tp_ensure(p, sz) == -1))
1453 		return NULL;
1454 	mp_encode_bin(p->p, str, len);
1455 	return tp_add(p, sz);
1456 }
1457 
1458 /**
1459  * Add an array to the request with a given size
1460  *
1461  * tp_encode_array(p, 3);
1462  * tp_encode_uint(p, 1);
1463  * tp_encode_uint(p, 2);
1464  * tp_encode_uint(p, 3);
1465  */
1466 static inline char *
tp_encode_array(struct tp * p,uint32_t size)1467 tp_encode_array(struct tp *p, uint32_t size)
1468 {
1469 	int sz = mp_sizeof_array(size);
1470 	if (tpunlikely(tp_ensure(p, sz) == -1))
1471 		return NULL;
1472 	mp_encode_array(p->p, size);
1473 	return tp_add(p, sz);
1474 }
1475 
1476 /**
1477  * Add a map to the request with a given size
1478  *
1479  * tp_encode_array(p, 2);
1480  * tp_encode_sz(p, "name");
1481  * tp_encode_sz(p, "Alan");
1482  * tp_encode_sz(p, "birth");
1483  * tp_encode_uint(p, 1912);
1484  */
1485 static inline char *
tp_encode_map(struct tp * p,uint32_t size)1486 tp_encode_map(struct tp *p, uint32_t size)
1487 {
1488 	int sz = mp_sizeof_map(size);
1489 	if (tpunlikely(tp_ensure(p, sz) == -1))
1490 		return NULL;
1491 	mp_encode_map(p->p, size);
1492 	return tp_add(p, sz);
1493 }
1494 
1495 /**
1496  * Add a bool value to the request.
1497  */
1498 static inline char *
tp_encode_bool(struct tp * p,bool val)1499 tp_encode_bool(struct tp *p, bool val)
1500 {
1501 	int sz = mp_sizeof_bool(val);
1502 	if (tpunlikely(tp_ensure(p, sz) == -1))
1503 		return NULL;
1504 	mp_encode_bool(p->p, val);
1505 	return tp_add(p, sz);
1506 }
1507 
1508 /**
1509  * Add a float value to the request.
1510  */
1511 static inline char *
tp_encode_float(struct tp * p,float num)1512 tp_encode_float(struct tp *p, float num)
1513 {
1514 	int sz = mp_sizeof_float(num);
1515 	if (tpunlikely(tp_ensure(p, sz) == -1))
1516 		return NULL;
1517 	mp_encode_float(p->p, num);
1518 	return tp_add(p, sz);
1519 }
1520 
1521 /**
1522  * Add a double float value to the request.
1523  */
1524 static inline char *
tp_encode_double(struct tp * p,double num)1525 tp_encode_double(struct tp *p, double num)
1526 {
1527 	int sz = mp_sizeof_double(num);
1528 	if (tpunlikely(tp_ensure(p, sz) == -1))
1529 		return NULL;
1530 	mp_encode_double(p->p, num);
1531 	return tp_add(p, sz);
1532 }
1533 
1534 /**
1535  *
1536  */
1537 static inline char *
tp_format(struct tp * p,const char * format,...)1538 tp_format(struct tp *p, const char *format, ...)
1539 {
1540 	va_list args;
1541 	va_start(args, format);
1542 	size_t unused = tp_unused(p);
1543 	size_t sz = mp_vformat(p->p, unused, format, args);
1544 	if (sz > unused) {
1545 		if (tpunlikely(tp_ensure(p, sz) == -1)) {
1546 			va_end(args);
1547 			return NULL;
1548 		}
1549 		mp_vformat(p->p, unused, format, args);
1550 	}
1551 	va_end(args);
1552 	return tp_add(p, sz);
1553 }
1554 
1555 
1556 /**
1557  * Write a tuple header
1558  * Same as tp_encode_array, added for compatibility.
1559  */
1560 static inline char *
tp_tuple(struct tp * p,uint32_t field_count)1561 tp_tuple(struct tp *p, uint32_t field_count)
1562 {
1563 	return tp_encode_array(p, field_count);
1564 }
1565 
1566 /**
1567  * Write a key header
1568  * Same as tp_encode_array, added for compatibility.
1569  */
1570 static inline char *
tp_key(struct tp * p,uint32_t part_count)1571 tp_key(struct tp *p, uint32_t part_count)
1572 {
1573 	return tp_encode_array(p, part_count);
1574 }
1575 
1576 /**
1577  * Init msgpack iterator by a pointer to msgpack array begin.
1578  * First element will be accessible after tp_array_itr_next call.
1579  * Returns -1 on error
1580  */
1581 static inline int
tp_array_itr_init(struct tp_array_itr * itr,const char * data,size_t size)1582 tp_array_itr_init(struct tp_array_itr *itr, const char *data, size_t size)
1583 {
1584 	memset(itr, 0, sizeof(*itr));
1585 	if (size == 0 || mp_typeof(*data) != MP_ARRAY)
1586 		return -1;
1587 	const char *e = data;
1588 	if (mp_check(&e, data + size))
1589 		return -1;
1590 	itr->data = data;
1591 	itr->first_elem = data;
1592 	itr->elem_count = mp_decode_array(&itr->first_elem);
1593 	itr->cur_index = -1;
1594 	return 0;
1595 }
1596 
1597 /**
1598  * Iterate to next position.
1599  * return true if success, or false if there are no elements left
1600  */
1601 static inline bool
tp_array_itr_next(struct tp_array_itr * itr)1602 tp_array_itr_next(struct tp_array_itr *itr)
1603 {
1604 	itr->cur_index++;
1605 	if ((uint32_t)itr->cur_index >= itr->elem_count)
1606 		return false;
1607 	if (itr->cur_index == 0)
1608 		itr->elem = itr->first_elem;
1609 	else
1610 		itr->elem = itr->elem_end;
1611 	itr->elem_end = itr->elem;
1612 	mp_next(&itr->elem_end);
1613 	return true;
1614 }
1615 
1616 /**
1617  * Reset iterator to the beginning. First element will be
1618  * accessible after tp_array_itr_next call.
1619  * return true if success, or false if there are no elements left
1620  */
1621 static inline void
tp_array_itr_reset(struct tp_array_itr * itr)1622 tp_array_itr_reset(struct tp_array_itr *itr)
1623 {
1624 	itr->cur_index = -1;
1625 	itr->elem = 0;
1626 	itr->elem_end = 0;
1627 }
1628 
1629 /**
1630  * Init msgpack map iterator by a pointer to msgpack map begin.
1631  * First element will be accessible after tp_map_itr_next call.
1632  * Returns -1 on error
1633  */
1634 static inline int
tp_map_itr_init(struct tp_map_itr * itr,const char * data,size_t size)1635 tp_map_itr_init(struct tp_map_itr *itr, const char *data, size_t size)
1636 {
1637 	memset(itr, 0, sizeof(*itr));
1638 	if (size == 0 || mp_typeof(*data) != MP_MAP)
1639 		return -1;
1640 	const char *e = data;
1641 	if (mp_check(&e, data + size))
1642 		return -1;
1643 	itr->data = data;
1644 	itr->first_key = data;
1645 	itr->pair_count = mp_decode_map(&itr->first_key);
1646 	itr->cur_index = -1;
1647 	return 0;
1648 }
1649 
1650 /**
1651  * Iterate to next position.
1652  * return true if success, or false if there are no pairs left
1653  */
1654 static inline bool
tp_map_itr_next(struct tp_map_itr * itr)1655 tp_map_itr_next(struct tp_map_itr *itr)
1656 {
1657 	itr->cur_index++;
1658 	if ((uint32_t)itr->cur_index >= itr->pair_count)
1659 		return false;
1660 	if (itr->cur_index == 0)
1661 		itr->key = itr->first_key;
1662 	else
1663 		itr->key = itr->value_end;
1664 	itr->key_end = itr->key;
1665 	mp_next(&itr->key_end);
1666 	itr->value = itr->key_end;
1667 	itr->value_end = itr->value;
1668 	mp_next(&itr->value_end);
1669 	return true;
1670 }
1671 
1672 /**
1673  * Reset iterator to the beginning. First pair will be
1674  * accessible after tp_map_itr_next call.
1675  * return true if success, or false if there are no pairs left
1676  */
1677 static inline void
tp_map_itr_reset(struct tp_map_itr * itr)1678 tp_map_itr_reset(struct tp_map_itr *itr)
1679 {
1680 	itr->cur_index = -1;
1681 	itr->key = 0;
1682 	itr->key_end = 0;
1683 	itr->value = 0;
1684 	itr->value_end = 0;
1685 }
1686 
1687 /**
1688  * Initialize struct tpresponse with a data buffer.
1689  * Returns -1 if an error occured
1690  * Returns 0 if buffer contains only part of the response
1691  * Return size in bytes of the response in buffer on success
1692  */
1693 static inline ssize_t
tp_reply(struct tpresponse * r,const char * const buf,size_t size)1694 tp_reply(struct tpresponse *r, const char * const buf, size_t size)
1695 {
1696 	memset(r, 0, sizeof(*r));
1697 	if (size == 0)
1698 		return 0;
1699 	const char *p = buf;
1700 	/* len */
1701 	const char *test = p;
1702 	if (mp_check(&test, buf + size))
1703 		return -1;
1704 	if (mp_typeof(*p) != MP_UINT)
1705 		return -1;
1706 	uint32_t len = mp_decode_uint(&p);
1707 	if (size < len + (uint32_t)(p - buf))
1708 		return 0;
1709 	/* header */
1710 	test = p;
1711 	if (mp_check(&test, buf + size))
1712 		return -1;
1713 	if (mp_typeof(*p) != MP_MAP)
1714 		return -1;
1715 	uint32_t n = mp_decode_map(&p);
1716 	while (n-- > 0) {
1717 		if (mp_typeof(*p) != MP_UINT)
1718 			return -1;
1719 		uint32_t key = mp_decode_uint(&p);
1720 		if (mp_typeof(*p) != MP_UINT)
1721 			return -1;
1722 		switch (key) {
1723 		case TP_SYNC:
1724 			if (mp_typeof(*p) != MP_UINT)
1725 				return -1;
1726 			r->sync = mp_decode_uint(&p);
1727 			break;
1728 		case TP_CODE:
1729 			if (mp_typeof(*p) != MP_UINT)
1730 				return -1;
1731 			r->code = mp_decode_uint(&p);
1732 			break;
1733 		default:
1734 			mp_next(&p);
1735 			break;
1736 		}
1737 		r->bitmap |= (1ULL << key);
1738 	}
1739 
1740 	/* body */
1741 	if (p == buf + len + 5)
1742 		return len + 5; /* no body */
1743 	test = p;
1744 	if (mp_check(&test, buf + size))
1745 		return -1;
1746 	if (mp_typeof(*p) != MP_MAP)
1747 		return -1;
1748 	n = mp_decode_map(&p);
1749 	while (n-- > 0) {
1750 		uint32_t key = mp_decode_uint(&p);
1751 		switch (key) {
1752 		case TP_ERROR: {
1753 			if (mp_typeof(*p) != MP_STR)
1754 				return -1;
1755 			uint32_t elen = 0;
1756 			r->error = mp_decode_str(&p, &elen);
1757 			r->error_end = r->error + elen;
1758 			break;
1759 		}
1760 		case TP_DATA: {
1761 			if (mp_typeof(*p) != MP_ARRAY)
1762 				return -1;
1763 			r->data = p;
1764 			mp_next(&p);
1765 			r->data_end = p;
1766 			break;
1767 		}
1768 		default:
1769 			mp_next(&p);
1770 			break;
1771 		}
1772 		r->bitmap |= (1ULL << key);
1773 	}
1774 	if (r->data) {
1775 		if (tp_array_itr_init(&r->tuple_itr, r->data, r->data_end - r->data))
1776 			return -1;
1777 	}
1778 	return p - buf;
1779 }
1780 
1781 /**
1782  * Return the current response id
1783  */
1784 static inline uint32_t
tp_getreqid(struct tpresponse * r)1785 tp_getreqid(struct tpresponse *r)
1786 {
1787 	return r->sync;
1788 }
1789 
1790 /**
1791  * Check if the response has a tuple.
1792  * Automatically checked during tp_next() iteration.
1793  */
1794 static inline int
tp_hasdata(struct tpresponse * r)1795 tp_hasdata(struct tpresponse *r)
1796 {
1797 	return r->tuple_itr.elem_count > 0;
1798 }
1799 
1800 /**
1801  * Get tuple count in response
1802  */
1803 static inline uint32_t
tp_tuplecount(const struct tpresponse * r)1804 tp_tuplecount(const struct tpresponse *r)
1805 {
1806 	return r->tuple_itr.elem_count;
1807 }
1808 
1809 /**
1810  * Rewind iteration to the first tuple.
1811  * Note that initialization of tpresponse via tp_reply
1812  * rewinds tuple iteration automatically
1813  */
1814 static inline void
tp_rewind(struct tpresponse * r)1815 tp_rewind(struct tpresponse *r)
1816 {
1817 	tp_array_itr_reset(&r->tuple_itr);
1818 	memset(&r->field_itr, 0, sizeof(r->field_itr));
1819 }
1820 
1821 /**
1822  * Skip to the next tuple or to the first tuple after rewind
1823  */
1824 static inline int
tp_next(struct tpresponse * r)1825 tp_next(struct tpresponse *r)
1826 {
1827 	if (!tp_array_itr_next(&r->tuple_itr)) {
1828 		memset(&r->field_itr, 0, sizeof(r->field_itr));
1829 		return 0;
1830 	}
1831 	tp_array_itr_init(&r->field_itr, r->tuple_itr.elem, r->tuple_itr.elem_end - r->tuple_itr.elem);
1832 	return 1;
1833 
1834 }
1835 
1836 /**
1837  * Check if there is one more tuple.
1838  */
1839 static inline int
tp_hasnext(struct tpresponse * r)1840 tp_hasnext(struct tpresponse *r)
1841 {
1842 	return (uint32_t)(r->tuple_itr.cur_index + 1) < r->tuple_itr.elem_count;
1843 }
1844 
1845 /**
1846  * Get the current tuple data, all fields.
1847  */
1848 static inline const char *
tp_gettuple(struct tpresponse * r)1849 tp_gettuple(struct tpresponse *r)
1850 {
1851 	return r->tuple_itr.elem;
1852 }
1853 
1854 /**
1855  * Get the current tuple size in bytes.
1856  */
1857 static inline uint32_t
tp_tuplesize(struct tpresponse * r)1858 tp_tuplesize(struct tpresponse *r)
1859 {
1860 	return (uint32_t)(r->tuple_itr.elem_end - r->tuple_itr.elem);
1861 }
1862 
1863 /**
1864  *  Get a pointer to the end of the current tuple.
1865  */
1866 static inline const char *
tp_tupleend(struct tpresponse * r)1867 tp_tupleend(struct tpresponse *r)
1868 {
1869 	return r->tuple_itr.elem_end;
1870 }
1871 
1872 /*
1873  * Rewind iteration to the first tuple field of the current tuple.
1874  * Note that iterating tuples of the response
1875  * rewinds field iteration automatically
1876  */
1877 static inline void
tp_rewindfield(struct tpresponse * r)1878 tp_rewindfield(struct tpresponse *r)
1879 {
1880 	tp_array_itr_reset(&r->field_itr);
1881 }
1882 
1883 /**
1884  * Skip to the next field.
1885  */
1886 static inline int
tp_nextfield(struct tpresponse * r)1887 tp_nextfield(struct tpresponse *r)
1888 {
1889 	return tp_array_itr_next(&r->field_itr);
1890 }
1891 
1892 /*
1893  * Check if the current tuple has one more field.
1894  */
1895 static inline int
tp_hasnextfield(struct tpresponse * r)1896 tp_hasnextfield(struct tpresponse *r)
1897 {
1898 	return (uint32_t)(r->field_itr.cur_index + 1) < r->field_itr.elem_count;
1899 }
1900 
1901 
1902 /**
1903  * Get the current field.
1904  */
1905 static inline const char *
tp_getfield(struct tpresponse * r)1906 tp_getfield(struct tpresponse *r)
1907 {
1908 	return r->field_itr.elem;
1909 }
1910 
1911 /**
1912  * Get the current field size in bytes.
1913  */
1914 static inline uint32_t
tp_getfieldsize(struct tpresponse * r)1915 tp_getfieldsize(struct tpresponse *r)
1916 {
1917 	return (uint32_t)(r->field_itr.elem_end - r->field_itr.elem);
1918 }
1919 
1920 /*
1921  * Determine MsgPack type by first byte of encoded data.
1922  */
1923 static inline enum tp_type
tp_typeof(const char c)1924 tp_typeof(const char c)
1925 {
1926 	return (enum tp_type) mp_typeof(c);
1927 }
1928 
1929 /**
1930  * Read unsigned integer value
1931  */
1932 static inline uint64_t
tp_get_uint(const char * field)1933 tp_get_uint(const char *field)
1934 {
1935 	return mp_decode_uint(&field);
1936 }
1937 
1938 /**
1939  * Read signed integer value
1940  */
1941 static inline int64_t
tp_get_int(const char * field)1942 tp_get_int(const char *field)
1943 {
1944 	return mp_decode_int(&field);
1945 }
1946 
1947 /**
1948  * Read float value
1949  */
1950 static inline float
tp_get_float(const char * field)1951 tp_get_float(const char *field)
1952 {
1953 	return mp_decode_float(&field);
1954 }
1955 
1956 /**
1957  * Read double value
1958  */
1959 static inline double
tp_get_double(const char * field)1960 tp_get_double(const char *field)
1961 {
1962 	return mp_decode_double(&field);
1963 }
1964 
1965 /**
1966  * Read bool value
1967  */
1968 static inline bool
tp_get_bool(const char * field)1969 tp_get_bool(const char *field)
1970 {
1971 	return mp_decode_bool(&field);
1972 }
1973 
1974 /**
1975  * Read string value
1976  */
1977 static inline const char *
tp_get_str(const char * field,uint32_t * size)1978 tp_get_str(const char *field, uint32_t *size)
1979 {
1980 	return mp_decode_str(&field, size);
1981 }
1982 
1983 /**
1984  * Read binary data value
1985  */
1986 static inline const char *
tp_get_bin(const char * field,uint32_t * size)1987 tp_get_bin(const char *field, uint32_t *size)
1988 {
1989 	return mp_decode_bin(&field, size);
1990 }
1991 
1992 /* }}} */
1993 
1994 #ifdef __cplusplus
1995 } /* extern "C" */
1996 #endif
1997 
1998 #endif
1999