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