00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <errno.h>
00012 #include <stdio.h>
00013 #include <stdlib.h>
00014 #include <string.h>
00015 #include <strings.h>
00016 #include <unistd.h>
00017
00018 #include <libdrizzle/drizzle_server.h>
00019 #include <sqlite3.h>
00020
00021 #define SQLITE_SERVER_VERSION "SQLite Server using libdrizzle 0.1"
00022
00023 #define DRIZZLE_RETURN_CHECK(__ret, __function, __drizzle) \
00024 { \
00025 if ((__ret) != DRIZZLE_RETURN_OK) \
00026 DRIZZLE_RETURN_ERROR(__function, __drizzle) \
00027 }
00028
00029 #define DRIZZLE_RETURN_ERROR(__function, __drizzle) \
00030 { \
00031 printf(__function ":%s\n", drizzle_error(__drizzle)); \
00032 return; \
00033 }
00034
00035 #define DRIZZLE_RETURN_CHECK_VAL(__ret, __function, __drizzle) \
00036 { \
00037 if ((__ret) != DRIZZLE_RETURN_OK) \
00038 { \
00039 printf(__function ":%s\n", drizzle_error(__drizzle)); \
00040 return ret; \
00041 } \
00042 }
00043
00044 typedef struct
00045 {
00046 drizzle_st drizzle;
00047 drizzle_con_st con;
00048 drizzle_result_st result;
00049 drizzle_column_st column;
00050 sqlite3* db;
00051 bool send_columns;
00052 drizzle_verbose_t verbose;
00053 uint64_t rows;
00054 } sqlite_server;
00055
00056 static void server_run(sqlite_server *server);
00057 static int row_cb(void *data, int field_count, char **fields, char **columns);
00058 static drizzle_return_t send_version(sqlite_server *server);
00059 static void usage(char *name);
00060
00061 int main(int argc, char *argv[])
00062 {
00063 int c;
00064 uint32_t count= 0;
00065 const char *host= NULL;
00066 bool mysql= false;
00067 in_port_t port= 0;
00068 drizzle_return_t ret;
00069 sqlite_server server;
00070 drizzle_con_st con_listen;
00071
00072 server.db= NULL;
00073 server.verbose= DRIZZLE_VERBOSE_NEVER;
00074
00075 while((c = getopt(argc, argv, "c:h:mp:v")) != -1)
00076 {
00077 switch(c)
00078 {
00079 case 'c':
00080 count= (uint32_t)atoi(optarg);
00081 break;
00082
00083 case 'h':
00084 host= optarg;
00085 break;
00086
00087 case 'm':
00088 mysql= true;
00089 break;
00090
00091 case 'p':
00092 port= (in_port_t)atoi(optarg);
00093 break;
00094
00095 case 'v':
00096 server.verbose++;
00097 break;
00098
00099 default:
00100 usage(argv[0]);
00101 return 1;
00102 }
00103 }
00104
00105 if (argc != (optind + 1))
00106 {
00107 usage(argv[0]);
00108 return 1;
00109 }
00110
00111 sqlite3_open(argv[optind], &(server.db));
00112 if (server.db == NULL)
00113 {
00114 printf("sqlite3_open: could not open sqlite3 db\n");
00115 return 1;
00116 }
00117
00118 if (drizzle_create(&server.drizzle) == NULL)
00119 {
00120 printf("drizzle_create:NULL\n");
00121 return 1;
00122 }
00123
00124 drizzle_add_options(&server.drizzle, DRIZZLE_FREE_OBJECTS);
00125 drizzle_set_verbose(&server.drizzle, server.verbose);
00126
00127 if (drizzle_con_create(&server.drizzle, &con_listen) == NULL)
00128 {
00129 printf("drizzle_con_create:NULL\n");
00130 return 1;
00131 }
00132
00133 drizzle_con_add_options(&con_listen, DRIZZLE_CON_LISTEN);
00134 drizzle_con_set_tcp(&con_listen, host, port);
00135
00136 if (mysql)
00137 drizzle_con_add_options(&con_listen, DRIZZLE_CON_MYSQL);
00138
00139 if (drizzle_con_listen(&con_listen) != DRIZZLE_RETURN_OK)
00140 {
00141 printf("drizzle_con_listen:%s\n", drizzle_error(&server.drizzle));
00142 return 1;
00143 }
00144
00145 while (1)
00146 {
00147 (void)drizzle_con_accept(&server.drizzle, &server.con, &ret);
00148 if (ret != DRIZZLE_RETURN_OK)
00149 {
00150 printf("drizzle_con_accept:%s\n", drizzle_error(&server.drizzle));
00151 return 1;
00152 }
00153
00154 server_run(&server);
00155
00156 drizzle_con_free(&server.con);
00157
00158 if (count > 0)
00159 {
00160 count--;
00161
00162 if (count == 0)
00163 break;
00164 }
00165 }
00166
00167 drizzle_con_free(&con_listen);
00168 drizzle_free(&server.drizzle);
00169 sqlite3_close(server.db);
00170
00171 return 0;
00172 }
00173
00174 static void server_run(sqlite_server *server)
00175 {
00176 drizzle_return_t ret;
00177 drizzle_command_t command;
00178 uint8_t *data= NULL;
00179 size_t total;
00180 int sqlite_ret;
00181 char *sqlite_err;
00182
00183
00184 drizzle_con_set_protocol_version(&(server->con), 10);
00185 drizzle_con_set_server_version(&(server->con), "libdrizzle+SQLite");
00186 drizzle_con_set_thread_id(&(server->con), 1);
00187 drizzle_con_set_scramble(&(server->con),
00188 (const uint8_t *)"ABCDEFGHIJKLMNOPQRST");
00189 drizzle_con_set_capabilities(&(server->con), DRIZZLE_CAPABILITIES_NONE);
00190 drizzle_con_set_charset(&(server->con), 8);
00191 drizzle_con_set_status(&(server->con), DRIZZLE_CON_STATUS_NONE);
00192 drizzle_con_set_max_packet_size(&(server->con), DRIZZLE_MAX_PACKET_SIZE);
00193
00194 ret= drizzle_handshake_server_write(&(server->con));
00195 DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_server_write",
00196 &(server->drizzle))
00197
00198 ret= drizzle_handshake_client_read(&(server->con));
00199 DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_client_read", &(server->drizzle))
00200
00201 if (drizzle_result_create(&(server->con), &(server->result)) == NULL)
00202 DRIZZLE_RETURN_ERROR("drizzle_result_create", &(server->drizzle))
00203
00204 ret= drizzle_result_write(&(server->con), &(server->result), true);
00205 DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
00206
00207
00208 while (1)
00209 {
00210 drizzle_result_free(&(server->result));
00211 if (data != NULL)
00212 free(data);
00213
00214 data= drizzle_con_command_buffer(&(server->con), &command, &total, &ret);
00215 if (ret == DRIZZLE_RETURN_LOST_CONNECTION ||
00216 (ret == DRIZZLE_RETURN_OK && command == DRIZZLE_COMMAND_QUIT))
00217 {
00218 if (data != NULL)
00219 free(data);
00220 return;
00221 }
00222 DRIZZLE_RETURN_CHECK(ret, "drizzle_con_command_buffer", &(server->drizzle))
00223
00224 if (server->verbose >= DRIZZLE_VERBOSE_INFO)
00225 {
00226 printf("Command=%u Data=%s\n", command,
00227 data == NULL ? "NULL" : (char *)data);
00228 }
00229
00230 if (drizzle_result_create(&(server->con), &(server->result)) == NULL)
00231 DRIZZLE_RETURN_ERROR("drizzle_result_create", &(server->drizzle))
00232
00233 if (command != DRIZZLE_COMMAND_QUERY ||
00234 !strcasecmp((char *)data, "SHOW DATABASES"))
00235 {
00236 ret= drizzle_result_write(&(server->con), &(server->result), true);
00237 DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
00238
00239 if (command == DRIZZLE_COMMAND_FIELD_LIST)
00240 {
00241 drizzle_result_set_eof(&(server->result), true);
00242 ret= drizzle_result_write(&(server->con), &(server->result), true);
00243 DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
00244 }
00245
00246 continue;
00247 }
00248
00249 if (strstr((char *)data, "@@version") != NULL)
00250 {
00251 ret= send_version(server);
00252 if (ret != DRIZZLE_RETURN_OK)
00253 return;
00254
00255 continue;
00256 }
00257
00258 server->send_columns= true;
00259 server->rows= 0;
00260
00261 if (!strcasecmp((char *)data, "SHOW TABLES"))
00262 {
00263 sqlite_ret= sqlite3_exec(server->db,
00264 "SELECT name FROM sqlite_master WHERE type='table'",
00265 row_cb, server, &sqlite_err);
00266 }
00267 else
00268 {
00269 sqlite_ret= sqlite3_exec(server->db, (char *)data, row_cb, server,
00270 &sqlite_err);
00271 }
00272
00273 if (sqlite_ret != SQLITE_OK)
00274 {
00275 if (sqlite_err == NULL)
00276 printf("sqlite3_exec failed\n");
00277 else
00278 {
00279 drizzle_result_set_error_code(&(server->result), (uint16_t)sqlite_ret);
00280 drizzle_result_set_error(&(server->result), sqlite_err);
00281 ret= drizzle_result_write(&(server->con), &(server->result), true);
00282 DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
00283
00284 printf("sqlite3_exec:%s\n", sqlite_err);
00285 sqlite3_free(sqlite_err);
00286 }
00287
00288 return;
00289 }
00290
00291 if (server->rows == 0)
00292 {
00293 drizzle_result_set_column_count(&(server->result), 0);
00294 ret= drizzle_result_write(&(server->con), &(server->result), true);
00295 DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
00296 }
00297 else
00298 {
00299 drizzle_result_set_eof(&(server->result), true);
00300 ret= drizzle_result_write(&(server->con), &(server->result), true);
00301 DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
00302 }
00303 }
00304 }
00305
00306 static int row_cb(void *data, int field_count, char **fields, char **columns)
00307 {
00308 sqlite_server *server= (sqlite_server *)data;
00309 drizzle_return_t ret;
00310 int x;
00311 size_t sizes[8192];
00312
00313 if (server->send_columns == true)
00314 {
00315 server->send_columns= false;
00316 drizzle_result_set_column_count(&(server->result), (uint16_t)field_count);
00317
00318 ret= drizzle_result_write(&(server->con), &(server->result), false);
00319 DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
00320
00321 if (drizzle_column_create(&(server->result), &(server->column)) == NULL)
00322 {
00323 DRIZZLE_RETURN_CHECK_VAL(DRIZZLE_RETURN_MEMORY, "drizzle_column_create",
00324 &(server->drizzle))
00325 }
00326
00327 drizzle_column_set_catalog(&(server->column), "sqlite");
00328 drizzle_column_set_db(&(server->column), "sqlite_db");
00329 drizzle_column_set_table(&(server->column), "sqlite_table");
00330 drizzle_column_set_orig_table(&(server->column), "sqlite_table");
00331 drizzle_column_set_charset(&(server->column), 8);
00332 drizzle_column_set_type(&(server->column), DRIZZLE_COLUMN_TYPE_VARCHAR);
00333
00334 for (x= 0; x < field_count; x++)
00335 {
00336 drizzle_column_set_size(&(server->column),
00337 fields[x] == NULL ?
00338 0 : (uint32_t)strlen(fields[x]));
00339 drizzle_column_set_name(&(server->column), columns[x]);
00340 drizzle_column_set_orig_name(&(server->column), columns[x]);
00341
00342 ret= drizzle_column_write(&(server->result), &(server->column));
00343 DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_column_write", &(server->drizzle))
00344 }
00345
00346 drizzle_column_free(&(server->column));
00347
00348 drizzle_result_set_eof(&(server->result), true);
00349
00350 ret= drizzle_result_write(&(server->con), &(server->result), false);
00351 DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
00352 }
00353
00354 for (x= 0; x < field_count; x++)
00355 {
00356 if (fields[x] == NULL)
00357 sizes[x]= 0;
00358 else
00359 sizes[x]= strlen(fields[x]);
00360 }
00361
00362
00363 drizzle_result_calc_row_size(&(server->result), (drizzle_field_t *)fields,
00364 sizes);
00365
00366 ret= drizzle_row_write(&(server->result));
00367 DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_row_write", &(server->drizzle))
00368
00369 for (x= 0; x < field_count; x++)
00370 {
00371 ret= drizzle_field_write(&(server->result), (drizzle_field_t)fields[x],
00372 sizes[x], sizes[x]);
00373 DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_field_write", &(server->drizzle))
00374 }
00375
00376 server->rows++;
00377
00378 return 0;
00379 }
00380
00381 static drizzle_return_t send_version(sqlite_server *server)
00382 {
00383 drizzle_return_t ret;
00384 drizzle_field_t fields[1];
00385 size_t sizes[1];
00386
00387 fields[0]= (drizzle_field_t)SQLITE_SERVER_VERSION;
00388 sizes[0]= strlen(SQLITE_SERVER_VERSION);
00389
00390 drizzle_result_set_column_count(&(server->result), 1);
00391
00392 ret= drizzle_result_write(&(server->con), &(server->result), false);
00393 DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
00394
00395 if (drizzle_column_create(&(server->result), &(server->column)) == NULL)
00396 {
00397 DRIZZLE_RETURN_CHECK_VAL(DRIZZLE_RETURN_MEMORY, "drizzle_column_create",
00398 &(server->drizzle))
00399 }
00400
00401 drizzle_column_set_catalog(&(server->column), "sqlite");
00402 drizzle_column_set_db(&(server->column), "sqlite_db");
00403 drizzle_column_set_table(&(server->column), "sqlite_table");
00404 drizzle_column_set_orig_table(&(server->column), "sqlite_table");
00405 drizzle_column_set_charset(&(server->column), 8);
00406 drizzle_column_set_type(&(server->column), DRIZZLE_COLUMN_TYPE_VARCHAR);
00407 drizzle_column_set_size(&(server->column), (uint32_t)sizes[0]);
00408 drizzle_column_set_name(&(server->column), "version");
00409 drizzle_column_set_orig_name(&(server->column), "version");
00410
00411 ret= drizzle_column_write(&(server->result), &(server->column));
00412 DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_column_write", &(server->drizzle))
00413
00414 drizzle_column_free(&(server->column));
00415
00416 drizzle_result_set_eof(&(server->result), true);
00417
00418 ret= drizzle_result_write(&(server->con), &(server->result), false);
00419 DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
00420
00421
00422 drizzle_result_calc_row_size(&(server->result), fields, sizes);
00423
00424 ret= drizzle_row_write(&(server->result));
00425 DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_row_write", &(server->drizzle))
00426
00427 ret= drizzle_field_write(&(server->result), fields[0], sizes[0], sizes[0]);
00428 DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_field_write", &(server->drizzle))
00429
00430 ret= drizzle_result_write(&(server->con), &(server->result), true);
00431 DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
00432
00433 return DRIZZLE_RETURN_OK;
00434 }
00435
00436 static void usage(char *name)
00437 {
00438 printf("\nusage: %s [-c <count>] [-h <host>] [-m] [-p <port>] [-v] "
00439 "<sqlite3 db file>\n", name);
00440 printf("\t-c <count> - Number of connections to accept before exiting\n");
00441 printf("\t-h <host> - Host to listen on\n");
00442 printf("\t-m - Use the MySQL protocol\n");
00443 printf("\t-p <port> - Port to listen on\n");
00444 printf("\t-v - Increase verbosity level\n");
00445 }