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