コード例 #1
0
/**
 * call the python function to intercept the handshake packet
 *
 * @return PROXY_SEND_QUERY  to send the packet from the client
 *         PROXY_NO_DECISION to pass the server packet unmodified
 */
static network_mysqld_python_stmt_ret
proxy_python_read_handshake(network_mysqld_con *con) {
	network_mysqld_con_python_t *st = con->plugin_con_state;
	network_mysqld_python_stmt_ret ret = PROXY_NO_DECISION;

    if(!CHECK_FUNC(read_handshake))
        return ret;

    PyObject *result = PyObject_CallFunctionObjArgs(
				GET_FUNC(read_handshake), st->proxy, NULL);
	GET_PYTHON_RESULT(read_handshake)

    switch(ret) {
    case PROXY_NO_DECISION:
        break;
    case PROXY_SEND_QUERY:
        g_warning("%s.%d: (read_handshake) return proxy.PROXY_SEND_QUERY is "
					"deprecated, use PROXY_SEND_RESULT instead",
					__FILE__, __LINE__);
        ret = PROXY_SEND_RESULT;
    case PROXY_SEND_RESULT:
        if(network_mysqld_con_python_handle_proxy_response(con, st->proxy))
            network_mysqld_con_send_error(con->client, C("(python) handling "
							"proxy.response failed, check error-log"));
        break;
    default:
        ret = PROXY_NO_DECISION;
        break;
    }
    return ret;
}
コード例 #2
0
static network_mysqld_python_stmt_ret
proxy_python_read_auth(network_mysqld_con *con) {
	network_mysqld_python_stmt_ret ret = PROXY_NO_DECISION;
	network_mysqld_con_python_t *st = con->plugin_con_state;

    if(!CHECK_FUNC(read_auth))
        return ret;

    PyObject *result = PyObject_CallFunctionObjArgs(
				GET_FUNC(read_auth), st->proxy, NULL);
	GET_PYTHON_RESULT(read_auth)

    switch(ret) {
    case PROXY_NO_DECISION:
        break;
    case PROXY_SEND_RESULT:
        /* answer directly */
        if (network_mysqld_con_python_handle_proxy_response(con, st->proxy))
            network_mysqld_con_send_error(con->client, C("(python) handling "
							"proxy.response failed, check error-log"));
        break;
    case PROXY_SEND_QUERY:
        /* something is in the injection queue, pull it from there and replace
		 * the content of original packet
		 */

        if (st->injected.queries->length)
            ret = PROXY_SEND_INJECTION;
        else
            ret = PROXY_NO_DECISION;
        break;
    default:
        ret = PROXY_NO_DECISION;
        break;
    }
	return ret;
}
コード例 #3
0
ファイル: debug-plugin.c プロジェクト: 247687009/SOHU-DBProxy
int plugin_debug_con_handle_stmt(chassis *chas, network_mysqld_con *con, GString *s) {
	gsize i, j;
	GPtrArray *fields;
	GPtrArray *rows;
	GPtrArray *row;

	switch(s->str[NET_HEADER_SIZE]) {
	case COM_QUERY:
		fields = NULL;
		rows = NULL;
		row = NULL;

		/* support the basic commands sent by the mysql shell */
		if (0 == g_ascii_strncasecmp(s->str + NET_HEADER_SIZE + 1, C("select @@version_comment limit 1"))) {
			MYSQL_FIELD *field;

			fields = network_mysqld_proto_fielddefs_new();

			field = network_mysqld_proto_fielddef_new();
			field->name = g_strdup("@@version_comment");
			field->type = FIELD_TYPE_VAR_STRING;
			g_ptr_array_add(fields, field);

			rows = g_ptr_array_new();
			row = g_ptr_array_new();
			g_ptr_array_add(row, g_strdup("MySQL Enterprise Agent"));
			g_ptr_array_add(rows, row);

			network_mysqld_con_send_resultset(con->client, fields, rows);
			
		} else if (0 == g_ascii_strncasecmp(s->str + NET_HEADER_SIZE + 1, C("select USER()"))) {
			MYSQL_FIELD *field;

			fields = network_mysqld_proto_fielddefs_new();
			field = network_mysqld_proto_fielddef_new();
			field->name = g_strdup("USER()");
			field->type = FIELD_TYPE_VAR_STRING;
			g_ptr_array_add(fields, field);

			rows = g_ptr_array_new();
			row = g_ptr_array_new();
			g_ptr_array_add(row, g_strdup("root"));
			g_ptr_array_add(rows, row);

			network_mysqld_con_send_resultset(con->client, fields, rows);
		} else {
			#if 0
			MYSQL_FIELD *field = NULL;
			lua_State *L = chas->priv->sc->L;

			if (0 == luaL_loadstring(L, s->str + NET_HEADER_SIZE + 1) &&
			    0 == lua_pcall(L, 0, 1, 0)) {
				/* let's see what is on the stack
				 * - scalars are turned into strings
				 *   return "foo" 
				 * - 1-dim tables are turned into a single-row result-set
				 *   return { foo = "bar", baz = "foz" }
				 * - 2-dim tables are turned into a multi-row result-set
				 *   return { { foo = "bar" }, { "foz" } }
				 */
				switch (lua_type(L, -1)) {
				case LUA_TTABLE:
					/* take the names from the fields */
					fields = network_mysqld_proto_fielddefs_new();

					lua_pushnil(L);
					while (lua_next(L, -2) != 0) {
						if (lua_istable(L, -1)) {
							/* 2-dim table
							 * 
							 * we only only take the keys from the first row
							 * afterwards we ignore them
							 */
					
							lua_pushnil(L);
							while (lua_next(L, -2) != 0) {
								if (!rows) {
									/* this is the 1st round, add the keys */
									lua_table_key_to_mysql_field(L, fields);
								}

								if (!row) row = g_ptr_array_new();
								if (lua_isboolean(L, -1)) {
									g_ptr_array_add(row, g_strdup(lua_toboolean(L, -1) ? "TRUE" : "FALSE"));
								} else if (lua_isnumber(L, -1)) {
									g_ptr_array_add(row, g_strdup_printf("%.0f", lua_tonumber(L, -1)));
								} else {
									g_ptr_array_add(row, g_strdup(lua_tostring(L, -1)));
								}

								lua_pop(L, 1); /* pop the value, but keep the key on the stack */
							}
					
							if (!rows) rows = g_ptr_array_new();
							g_ptr_array_add(rows, row);

							row = NULL;
						} else {
							/* 1-dim table */
							lua_table_key_to_mysql_field(L, fields);

							if (!row) row = g_ptr_array_new();
							if (lua_isboolean(L, -1)) {
								g_ptr_array_add(row, g_strdup(lua_toboolean(L, -1) ? "TRUE" : "FALSE"));
							} else if (lua_isnumber(L, -1)) {
								g_ptr_array_add(row, g_strdup_printf("%.0f", lua_tonumber(L, -1)));
							} else {
								g_ptr_array_add(row, g_strdup(lua_tostring(L, -1)));
							}
						}

						lua_pop(L, 1); /* pop the value, but keep the key on the stack */
					}

					if (row) {
						/* in 1-dim we have to append the row to the result-set,
						 * in 2-dim this is already done and row is NULL */
						if (!rows) rows = g_ptr_array_new();
						g_ptr_array_add(rows, row);
					}

					break;
				default:
					/* a scalar value */
					fields = network_mysqld_proto_fielddefs_new();
					field = network_mysqld_proto_fielddef_new();
					field->name = g_strdup("lua");
					field->type = FIELD_TYPE_VAR_STRING;
					g_ptr_array_add(fields, field);
		
					rows = g_ptr_array_new();
					row = g_ptr_array_new();
					g_ptr_array_add(row, g_strdup(lua_tostring(L, -1)));
					g_ptr_array_add(rows, row);

					break;
				}

				lua_pop(L, 1); /* get rid of the result */

				network_mysqld_con_send_resultset(con->client, fields, rows);
			}

			/* if we don't have fields for the resultset, we should have a
			 * error-msg on the stack */
			if (!fields) {
				size_t err_len = 0;
				const char *err;

				err = lua_tolstring(L, -1, &err_len);

				network_mysqld_con_send_error(con->client, err, err_len);
				
				lua_pop(L, 1);
			}
			#endif
		}

		/* clean up */
		if (fields) {
			network_mysqld_proto_fielddefs_free(fields);
			fields = NULL;
		}

		if (rows) {
			for (i = 0; i < rows->len; i++) {
				row = rows->pdata[i];

				for (j = 0; j < row->len; j++) {
					g_free(row->pdata[j]);
				}

				g_ptr_array_free(row, TRUE);
			}
			g_ptr_array_free(rows, TRUE);
			rows = NULL;
		}

		break;
	case COM_QUIT:
		break;
	case COM_INIT_DB:
		network_mysqld_con_send_ok(con->client);
		break;
	default:
		network_mysqld_con_send_error(con->client, C("unknown COM_*"));
		break;
	}

	return 0;
}
コード例 #4
0
/**
 * Handle the proxy.response to con.
 * proxy.response
 *   .type can be either ERR, OK or RAW
 *   .resultset (in case of OK)
 *     .fields
 *     .rows
 *   .errmsg (in case of ERR)
 *   .packet (in case of nil)
 *  Note: if error occurred, should set the error string.
 */
int network_mysqld_con_python_handle_proxy_response(network_mysqld_con *con,
			PyObject *proxy){
	assert(proxy);

	PyObject *response = PyObject_GetAttrString(proxy, "response");
	//Note: the response is fetched through the tp_getset, and is a new reference.
	assert(response);
	Py_DECREF(response);

	PyObject *res_type = PyObject_GetAttrString(response, "type");
	if(!res_type){
		network_mysqld_con_send_error(con->client,
					C("Cannot get proxy.response.type"));
		return -1;
	}
	int res_type_int = PyInt_AsLong(res_type);
	Py_DECREF(res_type);

	switch(res_type_int){
	case MYSQLD_PACKET_OK:{
		PyObject *resultset = PyObject_GetAttrString(response, "resultset");
		if(!resultset){
			PyErr_Clear();
			guint64 affected_rows = 0;
			guint64 insert_id = 0;

			PyObject *ar = PyObject_GetAttrString(response, "affected_rows");
			if(!ar)
				PyErr_Clear();
			else if(PyLong_Check(ar))
				affected_rows = PyLong_AsLong(ar);
			else if(PyInt_Check(ar))
				affected_rows = PyInt_AsLong(ar);
			Py_XDECREF(ar);

			PyObject *ii = PyObject_GetAttrString(response, "insert_id");
			if(!ii)
				PyErr_Clear();
			else if(PyLong_Check(ii))
				insert_id = PyLong_AsLong(ii);
			else if(PyInt_Check(ii))
				insert_id = PyInt_AsLong(ii);
			Py_XDECREF(ii);

			network_mysqld_con_send_ok_full(con->client, affected_rows, insert_id, 0x0002, 0);
		}
		else{
			Py_DECREF(resultset);

			GPtrArray *fields = create_fields(resultset);
			if(!fields){
				network_mysqld_con_send_error(con->client,
							C("Cannot get proxy.response.resultset.fields!"));
				PyErr_Print();
				PyErr_Clear();
				return -1;
			}
			if(fields->len <= 0){
				network_mysqld_con_send_error(con->client,
							C("Size of proxy.response.resultset.fields is 0"));
				network_mysqld_proto_fielddefs_free(fields);
				return -1;
			}
			GPtrArray *rows = create_rows(resultset);
			if(!rows){
				network_mysqld_con_send_error(con->client,
							C("Cannot get proxy.response.resultset.rows"));
				PyErr_Print();
				network_mysqld_proto_fielddefs_free(fields);
				return -1;
			}

			network_mysqld_con_send_resultset(con->client, fields, rows);

			if (fields) {
				network_mysqld_proto_fielddefs_free(fields);
				fields = NULL;
			}

			if (rows) {
				guint i;
				for (i = 0; i < rows->len; i++) {
					GPtrArray *row = rows->pdata[i];
					guint j;
					for (j = 0; j < row->len; j++)
						if (row->pdata[j])
							g_free(row->pdata[j]);
					g_ptr_array_free(row, TRUE);
				}
				g_ptr_array_free(rows, TRUE);
				rows = NULL;
			}
		}
		break;}

	case MYSQLD_PACKET_ERR:{
		gint errcode = ER_UNKNOWN_ERROR;
		/** let's call ourself Dynamic SQL ... 07000 is "dynamic SQL error" */
		const gchar *sqlstate = "07000";
		gchar *errmsg = NULL;

		PyObject *err_code = PyObject_GetAttrString(response, "errcode");
		if(!err_code)
			//Here use the default error code: ER_UNKNOWN_ERROR
			PyErr_Clear();
		else{
			errcode = PyInt_AsLong(err_code);
			Py_DECREF(err_code);
		}

		PyObject *sql_state = PyObject_GetAttrString(response, "sqlstate");
		if(!sql_state)
			//Here use the default sql state: 07000
			PyErr_Clear();
		else{
			sqlstate = PyString_AsString(sql_state);
			Py_DECREF(sql_state);
		}

		PyObject *err_msg = PyObject_GetAttrString(response, "errmsg");
		if(!err_msg){
			PyErr_Clear();
			network_mysqld_con_send_error(con->client,
						C("(python) proxy.response.errmsg is nil"));
		}
		else{
			errmsg = PyString_AsString(err_msg);
			Py_DECREF(err_msg);
			network_mysqld_con_send_error_full(con->client, errmsg,
						strlen(errmsg), errcode, sqlstate);
		}

	    break;}

	case MYSQLD_PACKET_RAW:{
		PyObject *packets = PyObject_GetAttrString(response, "packets");
		if(!packets)
			goto queue_reset;

		int i;
		for(i = 0; i < PySequence_Size(packets); i++){
			PyObject *item = PySequence_GetItem(packets, i);
			//If invalid items doesn't influces valid ones before them.
			if(!item)
				goto queue_reset;
			if(!PyString_Check(item)){
				PyErr_SetString(PyExc_ValueError, "proxy.response.packets' "
							"items should be strings.");
				Py_DECREF(item);
				Py_DECREF(packets);
				goto queue_reset;
			}

			network_mysqld_queue_append(con->client, con->client->send_queue,
						PyString_AsString(item), PyString_Size(item));
			Py_DECREF(item);
		}
		Py_DECREF(packets);
queue_reset:
		/* reset the packet-id checks */
		network_mysqld_queue_reset(con->client);
		break;}
	default:
		g_critical("Now the response type is unknown: %d", res_type_int);
		return -1;
	}
	return 0;
}
コード例 #5
0
ファイル: master-plugin.c プロジェクト: jelly140/mysql-proxy
static int network_mysqld_con_handle_stmt(chassis G_GNUC_UNUSED *chas, network_mysqld_con *con, GString *s) {
    gsize i, j;
    GPtrArray *fields;
    GPtrArray *rows;
    GPtrArray *row;


    switch(s->str[NET_HEADER_SIZE]) {
    case COM_QUERY:
        fields = NULL;
        rows = NULL;
        row = NULL;

        if (0 == g_ascii_strncasecmp(s->str + NET_HEADER_SIZE + 1, C("select @@version_comment limit 1"))) {
            MYSQL_FIELD *field;

            fields = network_mysqld_proto_fielddefs_new();

            field = network_mysqld_proto_fielddef_new();
            field->name = g_strdup("@@version_comment");
            field->type = FIELD_TYPE_VAR_STRING;
            g_ptr_array_add(fields, field);

            rows = g_ptr_array_new();
            row = g_ptr_array_new();
            g_ptr_array_add(row, g_strdup("MySQL Enterprise Agent"));
            g_ptr_array_add(rows, row);

            network_mysqld_con_send_resultset(con->client, fields, rows);

        } else if (0 == g_ascii_strncasecmp(s->str + NET_HEADER_SIZE + 1, C("select USER()"))) {
            MYSQL_FIELD *field;

            fields = network_mysqld_proto_fielddefs_new();
            field = network_mysqld_proto_fielddef_new();
            field->name = g_strdup("USER()");
            field->type = FIELD_TYPE_VAR_STRING;
            g_ptr_array_add(fields, field);

            rows = g_ptr_array_new();
            row = g_ptr_array_new();
            g_ptr_array_add(row, g_strdup("root"));
            g_ptr_array_add(rows, row);

            network_mysqld_con_send_resultset(con->client, fields, rows);
        } else {
            network_mysqld_con_send_error(con->client, C("(master-server) query not known"));
        }

        /* clean up */
        if (fields) {
            network_mysqld_proto_fielddefs_free(fields);
            fields = NULL;
        }

        if (rows) {
            for (i = 0; i < rows->len; i++) {
                row = rows->pdata[i];

                for (j = 0; j < row->len; j++) {
                    g_free(row->pdata[j]);
                }

                g_ptr_array_free(row, TRUE);
            }
            g_ptr_array_free(rows, TRUE);
            rows = NULL;
        }

        break;
    case COM_QUIT:
        break;
    case COM_INIT_DB:
        network_mysqld_con_send_ok(con->client);
        break;
    default:
        network_mysqld_con_send_error(con->client, C("unknown COM_*"));
        break;
    }

    return 0;
}
コード例 #6
0
ファイル: master-plugin.c プロジェクト: jelly140/mysql-proxy
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;
}
コード例 #7
0
static network_mysqld_python_stmt_ret
proxy_python_read_query_result(network_mysqld_con *con) {
	network_socket *send_sock = con->client;
	network_socket *recv_sock = con->server;
	injection *inj = NULL;
	network_mysqld_con_python_t *st = con->plugin_con_state;
	network_mysqld_python_stmt_ret ret = PROXY_NO_DECISION;
	GString *packet;

	/**
	 * check if we want to forward the statement to the client
	 * if not, clean the send-queue
	 */
	if (0 == st->injected.queries->length)
		return PROXY_NO_DECISION;

    if(!CHECK_FUNC(read_query_result))
        return ret;

	inj = g_queue_pop_head(st->injected.queries);

	inj->result_queue = con->server->recv_queue->chunks;
	PyObject * injection_obj = Injection_New(inj);
	if(!injection_obj){
		PyErr_Print();
        network_mysqld_con_send_error(con->client,
                    C("PyProxy: Failed to create injection object."));
		con->state = CON_STATE_SEND_ERROR;
        return PROXY_SEND_RESULT;
	}
    PyObject *result = PyObject_CallFunctionObjArgs(
			GET_FUNC(read_query_result), st->proxy, injection_obj, NULL);
	Py_DECREF(injection_obj);
	GET_PYTHON_RESULT(read_query_result)

    if (!con->resultset_is_needed && (PROXY_NO_DECISION != ret)) {
        g_critical("%s: read_query_result() in %s tries to modify the resultset, "
				"but hasn't asked to buffer it in proxy.query.append(..., True). "
				"We ignore the change to the result-set.",
				G_STRLOC, con->config->python_script);
        ret = PROXY_NO_DECISION;
    }

    switch (ret) {
    case PROXY_SEND_RESULT:
		/* we can only replace the result, if we buffer it */
        g_assert_cmpint(con->resultset_is_needed, ==, TRUE);
        while ((packet = g_queue_pop_head(recv_sock->recv_queue->chunks)))
			g_string_free(packet, TRUE);
        if (network_mysqld_con_python_handle_proxy_response(con, st->proxy))
            if (!st->injected.sent_resultset)
                network_mysqld_con_send_error(con->client, C("(python) handling"
								" proxy.response failed, check error-log"));
        /* fall through */
    case PROXY_NO_DECISION:
        if (!st->injected.sent_resultset) {
            // make sure we send only one result-set per client-query
            while ((packet = g_queue_pop_head(recv_sock->recv_queue->chunks)))
                network_mysqld_queue_append_raw(send_sock,
							send_sock->send_queue, packet);
            st->injected.sent_resultset++;
            break;
        }
        g_critical("%s.%d: got asked to send a resultset, but ignoring it as "
					"we already have sent %d resultset(s). injection-id: %d",
					__FILE__, __LINE__, st->injected.sent_resultset, inj->id);
        st->injected.sent_resultset++;

        /* fall through */
    case PROXY_IGNORE_RESULT:
        /* trash the packets for the injection query */

        if (!con->resultset_is_needed) {
            g_critical("%s: we tried to send more than one resultset to the "
						"client, but didn't had them buffered. Now the client "
						"is out of sync may have closed the connection on us. "
						"Please use proxy.queries.append(..., True) to fix this.",
						G_STRLOC);
            break;
        }
        while ((packet = g_queue_pop_head(recv_sock->recv_queue->chunks)))
			g_string_free(packet, TRUE);
        break;
    default:
        /* invalid return code */
        g_message("%s.%d: return-code for read_query_result() was neither "
				"PROXY_SEND_RESULT or PROXY_IGNORE_RESULT, will ignore the result",
                __FILE__, __LINE__);
        while ((packet = g_queue_pop_head(send_sock->send_queue->chunks)))
			g_string_free(packet, TRUE);
        break;
    }
	injection_free(inj);
	return ret;
}