1 /*
2  * twemproxy - A fast and lightweight proxy for memcached protocol.
3  * Copyright (C) 2011 Twitter, Inc.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #ifndef _NC_PROTO_H_
19 #define _NC_PROTO_H_
20 
21 #include <nc_core.h>
22 
23 #ifdef NC_LITTLE_ENDIAN
24 
25 #define str4cmp(m, c0, c1, c2, c3)                                                          \
26     (*(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0))
27 
28 #define str5cmp(m, c0, c1, c2, c3, c4)                                                      \
29     (str4cmp(m, c0, c1, c2, c3) && (m[4] == c4))
30 
31 #define str6cmp(m, c0, c1, c2, c3, c4, c5)                                                  \
32     (str4cmp(m, c0, c1, c2, c3) &&                                                          \
33         (((uint32_t *) m)[1] & 0xffff) == ((c5 << 8) | c4))
34 
35 #define str7cmp(m, c0, c1, c2, c3, c4, c5, c6)                                              \
36     (str6cmp(m, c0, c1, c2, c3, c4, c5) && (m[6] == c6))
37 
38 #define str8cmp(m, c0, c1, c2, c3, c4, c5, c6, c7)                                          \
39     (str4cmp(m, c0, c1, c2, c3) &&                                                          \
40         (((uint32_t *) m)[1] == ((c7 << 24) | (c6 << 16) | (c5 << 8) | c4)))
41 
42 #define str9cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8)                                      \
43     (str8cmp(m, c0, c1, c2, c3, c4, c5, c6, c7) && m[8] == c8)
44 
45 #define str10cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9)                                 \
46     (str8cmp(m, c0, c1, c2, c3, c4, c5, c6, c7) &&                                          \
47         (((uint32_t *) m)[2] & 0xffff) == ((c9 << 8) | c8))
48 
49 #define str11cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10)                            \
50     (str10cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9) && (m[10] == c10))
51 
52 #define str12cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11)                       \
53     (str8cmp(m, c0, c1, c2, c3, c4, c5, c6, c7) &&                                          \
54         (((uint32_t *) m)[2] == ((c11 << 24) | (c10 << 16) | (c9 << 8) | c8)))
55 
56 #else
57 
58 #define str4cmp(m, c0, c1, c2, c3)                                                          \
59     (m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3)
60 
61 #define str5cmp(m, c0, c1, c2, c3, c4)                                                      \
62     (str4cmp(m, c0, c1, c2, c3) && (m[4] == c4))
63 
64 #define str6cmp(m, c0, c1, c2, c3, c4, c5)                                                  \
65     (str5cmp(m, c0, c1, c2, c3, c4) && m[5] == c5)
66 
67 #define str7cmp(m, c0, c1, c2, c3, c4, c5, c6)                                              \
68     (str6cmp(m, c0, c1, c2, c3, c4, c5) && m[6] == c6)
69 
70 #define str8cmp(m, c0, c1, c2, c3, c4, c5, c6, c7)                                          \
71     (str7cmp(m, c0, c1, c2, c3, c4, c5, c6) && m[7] == c7)
72 
73 #define str9cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8)                                      \
74     (str8cmp(m, c0, c1, c2, c3, c4, c5, c6, c7) && m[8] == c8)
75 
76 #define str10cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9)                                 \
77     (str9cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8) && m[9] == c9)
78 
79 #define str11cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10)                            \
80     (str10cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9) && m[10] == c10)
81 
82 #define str12cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11)                       \
83     (str11cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10) && m[11] == c11)
84 
85 #endif
86 
87 #define str3icmp(m, c0, c1, c2)                                                             \
88     ((m[0] == c0 || m[0] == (c0 ^ 0x20)) &&                                                 \
89      (m[1] == c1 || m[1] == (c1 ^ 0x20)) &&                                                 \
90      (m[2] == c2 || m[2] == (c2 ^ 0x20)))
91 
92 #define str4icmp(m, c0, c1, c2, c3)                                                         \
93     (str3icmp(m, c0, c1, c2) && (m[3] == c3 || m[3] == (c3 ^ 0x20)))
94 
95 #define str5icmp(m, c0, c1, c2, c3, c4)                                                     \
96     (str4icmp(m, c0, c1, c2, c3) && (m[4] == c4 || m[4] == (c4 ^ 0x20)))
97 
98 #define str6icmp(m, c0, c1, c2, c3, c4, c5)                                                 \
99     (str5icmp(m, c0, c1, c2, c3, c4) && (m[5] == c5 || m[5] == (c5 ^ 0x20)))
100 
101 #define str7icmp(m, c0, c1, c2, c3, c4, c5, c6)                                             \
102     (str6icmp(m, c0, c1, c2, c3, c4, c5) &&                                                 \
103      (m[6] == c6 || m[6] == (c6 ^ 0x20)))
104 
105 #define str8icmp(m, c0, c1, c2, c3, c4, c5, c6, c7)                                         \
106     (str7icmp(m, c0, c1, c2, c3, c4, c5, c6) &&                                             \
107      (m[7] == c7 || m[7] == (c7 ^ 0x20)))
108 
109 #define str9icmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8)                                     \
110     (str8icmp(m, c0, c1, c2, c3, c4, c5, c6, c7) &&                                         \
111      (m[8] == c8 || m[8] == (c8 ^ 0x20)))
112 
113 #define str10icmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9)                                \
114     (str9icmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8) &&                                     \
115      (m[9] == c9 || m[9] == (c9 ^ 0x20)))
116 
117 #define str11icmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10)                           \
118     (str10icmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9) &&                                \
119      (m[10] == c10 || m[10] == (c10 ^ 0x20)))
120 
121 #define str12icmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11)                      \
122     (str11icmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10) &&                           \
123      (m[11] == c11 || m[11] == (c11 ^ 0x20)))
124 
125 #define str13icmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12)                 \
126     (str12icmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11) &&                      \
127      (m[12] == c12 || m[12] == (c12 ^ 0x20)))
128 
129 #define str14icmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13)            \
130     (str13icmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12) &&                 \
131      (m[13] == c13 || m[13] == (c13 ^ 0x20)))
132 
133 #define str15icmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14)       \
134     (str14icmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) &&            \
135      (m[14] == c14 || m[14] == (c14 ^ 0x20)))
136 
137 #define str16icmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15)  \
138     (str15icmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14) &&       \
139      (m[15] == c15 || m[15] == (c15 ^ 0x20)))
140 
141 #define str17icmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16)  \
142     (str16icmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15) &&       \
143      (m[16] == c16 || m[16] == (c16 ^ 0x20)))
144 
145 void memcache_parse_req(struct msg *r);
146 void memcache_parse_rsp(struct msg *r);
147 bool memcache_failure(const struct msg *r);
148 void memcache_pre_coalesce(struct msg *r);
149 void memcache_post_coalesce(struct msg *r);
150 rstatus_t memcache_add_auth(struct context *ctx, struct conn *c_conn, struct conn *s_conn);
151 rstatus_t memcache_fragment(struct msg *r, uint32_t nserver, struct msg_tqh *frag_msgq);
152 rstatus_t memcache_reply(struct msg *r);
153 void memcache_post_connect(struct context *ctx, struct conn *conn, struct server *server);
154 void memcache_swallow_msg(struct conn *conn, struct msg *pmsg, struct msg *msg);
155 
156 void redis_parse_req(struct msg *r);
157 void redis_parse_rsp(struct msg *r);
158 bool redis_failure(const struct msg *r);
159 void redis_pre_coalesce(struct msg *r);
160 void redis_post_coalesce(struct msg *r);
161 rstatus_t redis_add_auth(struct context *ctx, struct conn *c_conn, struct conn *s_conn);
162 rstatus_t redis_fragment(struct msg *r, uint32_t nserver, struct msg_tqh *frag_msgq);
163 rstatus_t redis_reply(struct msg *r);
164 void redis_post_connect(struct context *ctx, struct conn *conn, struct server *server);
165 void redis_swallow_msg(struct conn *conn, struct msg *pmsg, struct msg *msg);
166 
167 #endif
168