/** * Copy query string from GWBUF buffer to separate memory area. * * @param buf GWBUF buffer including the query * * @return Plain text query if the packet type is COM_QUERY. Otherwise return * a string including the packet type. */ char * modutil_get_query(GWBUF *buf) { uint8_t* packet; mysql_server_cmd_t packet_type; size_t len; char* query_str; packet = GWBUF_DATA(buf); packet_type = packet[4]; switch (packet_type) { case MYSQL_COM_QUIT: len = strlen("[Quit msg]")+1; if ((query_str = (char *)malloc(len+1)) == NULL) { goto retblock; } memcpy(query_str, "[Quit msg]", len); memset(&query_str[len], 0, 1); break; case MYSQL_COM_QUERY: len = MYSQL_GET_PACKET_LEN(packet)-1; /*< distract 1 for packet type byte */ if ((query_str = (char *)malloc(len+1)) == NULL) { goto retblock; } memcpy(query_str, &packet[5], len); memset(&query_str[len], 0, 1); break; default: len = strlen(STRPACKETTYPE(packet_type))+1; if ((query_str = (char *)malloc(len+1)) == NULL) { goto retblock; } memcpy(query_str, STRPACKETTYPE(packet_type), len); memset(&query_str[len], 0, 1); break; } /*< switch */ retblock: return query_str; }
/** * We have data from the client, we must route it to the backend. * This is simply a case of sending it to the connection that was * chosen when we started the client session. * * @param instance The router instance * @param router_session The router session returned from the newSession call * @param queue The queue of data buffers to route * @return if succeed 1, otherwise 0 */ static int routeQuery(ROUTER *instance, void *router_session, GWBUF *queue) { ROUTER_INSTANCE *inst = (ROUTER_INSTANCE *)instance; ROUTER_CLIENT_SES *router_cli_ses = (ROUTER_CLIENT_SES *)router_session; uint8_t *payload = GWBUF_DATA(queue); int mysql_command; int rc; DCB* backend_dcb; bool rses_is_closed; inst->stats.n_queries++; mysql_command = MYSQL_GET_COMMAND(payload); /** Dirty read for quick check if router is closed. */ if (router_cli_ses->rses_closed) { rses_is_closed = true; } else { /** * Lock router client session for secure read of DCBs */ rses_is_closed = !(rses_begin_locked_router_action(router_cli_ses)); } if (!rses_is_closed) { backend_dcb = router_cli_ses->backend_dcb; /** unlock */ rses_end_locked_router_action(router_cli_ses); } if (rses_is_closed || backend_dcb == NULL || SERVER_IS_DOWN(router_cli_ses->backend->server)) { LOGIF(LT, (skygw_log_write( LOGFILE_TRACE|LOGFILE_ERROR, "Error : Failed to route MySQL command %d to backend " "server.%s", mysql_command,rses_is_closed ? " Session is closed." : ""))); rc = 0; goto return_rc; } char* trc = NULL; switch(mysql_command) { case MYSQL_COM_CHANGE_USER: rc = backend_dcb->func.auth( backend_dcb, NULL, backend_dcb->session, queue); break; case MYSQL_COM_QUERY: LOGIF(LOGFILE_TRACE,(trc = modutil_get_SQL(queue))); default: rc = backend_dcb->func.write(backend_dcb, queue); break; } LOGIF(LOGFILE_TRACE,skygw_log_write( LOGFILE_DEBUG|LOGFILE_TRACE, "Routed [%s] to '%s'%s%s", STRPACKETTYPE(mysql_command), backend_dcb->server->unique_name, trc?": ":".", trc?trc:"")); free(trc); return_rc: return rc; }