static int lua_proto_append_response_packet (lua_State *L) { GString *packet; network_mysqld_auth_response *auth_response; gboolean needs_auto_capabilities = TRUE; guint32 server_capabilities; luaL_checktype(L, 1, LUA_TTABLE); /* extract the server_capabilities first as we need them to create the struct */ lua_getfield_literal(L, -1, C("server_capabilities")); if (lua_isnil(L, -1)) { return luaL_error(L, ".server_capabilities has to be set"); } else if (lua_isnumber(L, -1)) { server_capabilities = lua_tointeger(L, -1); } else { return luaL_error(L, ".server_capabilities has to be a number"); } lua_pop(L, 1); packet = g_string_new(NULL); auth_response = network_mysqld_auth_response_new(server_capabilities); lua_getfield_literal(L, -1, C("capabilities")); if (!lua_isnil(L, -1)) { auth_response->client_capabilities = lua_tointeger(L, -1); needs_auto_capabilities = FALSE; } lua_pop(L, 1); LUA_IMPORT_INT(auth_response, max_packet_size); LUA_IMPORT_INT(auth_response, charset); LUA_IMPORT_STR(auth_response, username); LUA_IMPORT_STR_FROM(auth_response, auth_plugin_data, "response"); LUA_IMPORT_STR(auth_response, auth_plugin_name); LUA_IMPORT_STR(auth_response, database); if (network_mysqld_proto_append_auth_response(packet, auth_response)) { network_mysqld_auth_response_free(auth_response); g_string_free(packet, TRUE); luaL_error(L, "to_response_packet() failed"); g_string_free(packet, TRUE); return 0; } network_mysqld_auth_response_free(auth_response); lua_pushlstring(L, S(packet)); g_string_free(packet, TRUE); return 1; }
static network_mysqld_lua_stmt_ret master_lua_read_query(network_mysqld_con *con) { network_mysqld_con_lua_t *st = con->plugin_con_state; char command = -1; network_socket *recv_sock = con->client; GList *chunk = recv_sock->recv_queue->chunks->head; GString *packet = chunk->data; if (packet->len < NET_HEADER_SIZE) return PROXY_SEND_QUERY; /* packet too short */ command = packet->str[NET_HEADER_SIZE + 0]; if (COM_QUERY == command) { /* we need some more data after the COM_QUERY */ if (packet->len < NET_HEADER_SIZE + 2) return PROXY_SEND_QUERY; /* LOAD DATA INFILE is nasty */ if (packet->len - NET_HEADER_SIZE - 1 >= sizeof("LOAD ") - 1 && 0 == g_ascii_strncasecmp(packet->str + NET_HEADER_SIZE + 1, C("LOAD "))) return PROXY_SEND_QUERY; } /* reset the query status */ network_injection_queue_reset(st->injected.queries); /* ok, here we go */ #ifdef HAVE_LUA_H switch(network_mysqld_con_lua_register_callback(con, con->config->lua_script)) { case REGISTER_CALLBACK_SUCCESS: break; case REGISTER_CALLBACK_LOAD_FAILED: network_mysqld_con_send_error(con->client, C("MySQL Proxy Lua script failed to load. Check the error log.")); con->state = CON_STATE_SEND_ERROR; return PROXY_SEND_RESULT; case REGISTER_CALLBACK_EXECUTE_FAILED: network_mysqld_con_send_error(con->client, C("MySQL Proxy Lua script failed to execute. Check the error log.")); con->state = CON_STATE_SEND_ERROR; return PROXY_SEND_RESULT; } if (st->L) { lua_State *L = st->L; network_mysqld_lua_stmt_ret ret = PROXY_NO_DECISION; g_assert(lua_isfunction(L, -1)); lua_getfenv(L, -1); g_assert(lua_istable(L, -1)); /** * reset proxy.response to a empty table */ lua_getfield(L, -1, "proxy"); g_assert(lua_istable(L, -1)); lua_newtable(L); lua_setfield(L, -2, "response"); lua_pop(L, 1); /** * get the call back */ lua_getfield_literal(L, -1, C("read_query")); if (lua_isfunction(L, -1)) { /* pass the packet as parameter */ lua_pushlstring(L, packet->str + NET_HEADER_SIZE, packet->len - NET_HEADER_SIZE); if (lua_pcall(L, 1, 1, 0) != 0) { /* hmm, the query failed */ g_critical("(read_query) %s", lua_tostring(L, -1)); lua_pop(L, 2); /* fenv + errmsg */ /* perhaps we should clean up ?*/ return PROXY_SEND_QUERY; } else { if (lua_isnumber(L, -1)) { ret = lua_tonumber(L, -1); } lua_pop(L, 1); } switch (ret) { case PROXY_SEND_RESULT: /* check the proxy.response table for content, * */ if (network_mysqld_con_lua_handle_proxy_response(con, con->config->lua_script)) { /** * handling proxy.response failed * * send a ERR packet */ network_mysqld_con_send_error(con->client, C("(lua) handling proxy.response failed, check error-log")); } break; case PROXY_NO_DECISION: /** * PROXY_NO_DECISION and PROXY_SEND_QUERY may pick another backend */ break; case PROXY_SEND_QUERY: /* send the injected queries * * injection_new(..., query); * * */ if (st->injected.queries->length) { ret = PROXY_SEND_INJECTION; } break; default: break; } lua_pop(L, 1); /* fenv */ } else { lua_pop(L, 2); /* fenv + nil */ } g_assert(lua_isfunction(L, -1)); if (ret != PROXY_NO_DECISION) { return ret; } } else { network_mysqld_con_handle_stmt(NULL, con, packet); return PROXY_SEND_RESULT; } #endif return PROXY_NO_DECISION; }