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