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