1
2 /*
3 * Copyright (C) Yichun Zhang (agentzh)
4 */
5
6
7 #ifndef NGX_HTTP_RDS_UTILS_H
8 #define NGX_HTTP_RDS_UTILS_H
9
10
11 #include <stdint.h>
12
13
14 static ngx_inline ngx_int_t
ngx_http_rds_parse_header(ngx_http_request_t * r,ngx_buf_t * b,ngx_http_rds_header_t * header)15 ngx_http_rds_parse_header(ngx_http_request_t *r, ngx_buf_t *b,
16 ngx_http_rds_header_t *header)
17 {
18 ssize_t rest;
19
20 rest = sizeof(uint8_t) /* endian type */
21 + sizeof(uint32_t) /* format version */
22 + sizeof(uint8_t) /* result type */
23
24 + sizeof(uint16_t) /* standard error code */
25 + sizeof(uint16_t) /* driver-specific error code */
26
27 + sizeof(uint16_t) /* driver-specific errstr len */
28 + 0 /* driver-specific errstr data */
29 + sizeof(uint64_t) /* affected rows */
30 + sizeof(uint64_t) /* insert id */
31 + sizeof(uint16_t) /* column count */
32 ;
33
34 if (b->last - b->pos < rest) {
35 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
36 "rds: header is incomplete in the buf");
37 return NGX_ERROR;
38 }
39
40 /* check endian type */
41
42 if (*(uint8_t *) b->pos !=
43 #if (NGX_HAVE_LITTLE_ENDIAN)
44 0
45 #else /* big endian */
46 1
47 #endif
48 )
49 {
50 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
51 "rds: endian type in the header differ");
52 return NGX_ERROR;
53 }
54
55 b->pos += sizeof(uint8_t);
56
57 /* check RDS format version number */
58
59 if (*(uint32_t *) b->pos != (uint32_t) resty_dbd_stream_version) {
60 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
61 "rds: RDS format version differ");
62 return NGX_ERROR;
63 }
64
65 dd("RDS format version: %d", (int) *(uint32_t *) b->pos);
66
67 b->pos += sizeof(uint32_t);
68
69 /* check RDS result type */
70
71 if (*b->pos != 0) {
72 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
73 "rds: RDS result type must be 0 for now");
74 return NGX_ERROR;
75 }
76
77 b->pos++;
78
79 /* save the standard error code */
80
81 header->std_errcode = *(uint16_t *) b->pos;
82
83 b->pos += sizeof(uint16_t);
84
85 /* save the driver-specific error code */
86
87 header->drv_errcode = *(uint16_t *) b->pos;
88
89 b->pos += sizeof(uint16_t);
90
91 /* save the error string length */
92
93 header->errstr.len = *(uint16_t *) b->pos;
94
95 b->pos += sizeof(uint16_t);
96
97 dd("errstr len: %d", (int) header->errstr.len);
98
99 /* check the rest data's size */
100
101 rest = header->errstr.len
102 + sizeof(uint64_t) /* affected rows */
103 + sizeof(uint64_t) /* insert id */
104 + sizeof(uint16_t) /* column count */
105 ;
106
107 if (b->last - b->pos < rest) {
108 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
109 "rds: header is incomplete in the buf");
110 return NGX_ERROR;
111 }
112
113 /* save the error string data */
114
115 header->errstr.data = b->pos;
116
117 b->pos += header->errstr.len;
118
119 /* save affected rows */
120
121 header->affected_rows = *(uint64_t *) b->pos;
122
123 b->pos += sizeof(uint64_t);
124
125 /* save insert id */
126
127 header->insert_id = *(uint64_t *)b->pos;
128
129 b->pos += sizeof(uint64_t);
130
131 /* save column count */
132
133 header->col_count = *(uint16_t *) b->pos;
134
135 b->pos += sizeof(uint16_t);
136
137 dd("saved column count: %d", (int) header->col_count);
138
139 return NGX_OK;
140 }
141
142
143 static ngx_inline ngx_int_t
ngx_http_rds_parse_col(ngx_http_request_t * r,ngx_buf_t * b,ngx_http_rds_column_t * col)144 ngx_http_rds_parse_col(ngx_http_request_t *r, ngx_buf_t *b,
145 ngx_http_rds_column_t *col)
146 {
147 ssize_t rest;
148
149 rest = sizeof(uint16_t) /* std col type */
150 + sizeof(uint16_t) /* driver col type */
151 + sizeof(uint16_t) /* col name str len */
152 ;
153
154 if (b->last - b->pos < rest) {
155 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
156 "rds: column spec is incomplete in the buf");
157 return NGX_ERROR;
158 }
159
160 /* save standard column type */
161 col->std_type = *(uint16_t *) b->pos;
162 b->pos += sizeof(uint16_t);
163
164 /* save driver-specific column type */
165 col->drv_type = *(uint16_t *) b->pos;
166 b->pos += sizeof(uint16_t);
167
168 /* read column name string length */
169
170 col->name.len = *(uint16_t *) b->pos;
171 b->pos += sizeof(uint16_t);
172
173 if (col->name.len == 0) {
174 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
175 "rds_csv: column name empty");
176 return NGX_ERROR;
177 }
178
179 rest = col->name.len;
180
181 if (b->last - b->pos < rest) {
182 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
183 "rds: column name string is incomplete in the buf");
184 return NGX_ERROR;
185 }
186
187 /* save the column name string data */
188
189 col->name.data = ngx_palloc(r->pool, col->name.len);
190 if (col->name.data == NULL) {
191 return NGX_ERROR;
192 }
193
194 ngx_memcpy(col->name.data, b->pos, col->name.len);
195 b->pos += col->name.len;
196
197 dd("saved column name \"%.*s\" (len %d, offset %d)",
198 (int) col->name.len, col->name.data,
199 (int) col->name.len, (int) (b->pos - b->start));
200
201 return NGX_OK;
202 }
203
204
205 #endif /* NGX_HTTP_RDS_UTILS_H */
206