mariadb/server-tools/instance-manager/mysql_connection.cc
unknown 50ceea65cf Merge mysql.com:/home/my/mysql-5.1
into  mysql.com:/home/my/mysql-new


BitKeeper/etc/ignore:
  auto-union
BUILD/SETUP.sh:
  Auto merged
CMakeLists.txt:
  Auto merged
client/get_password.c:
  Auto merged
client/mysqldump.c:
  Auto merged
client/mysqltest.c:
  Auto merged
cmd-line-utils/readline/bind.c:
  Auto merged
cmd-line-utils/readline/display.c:
  Auto merged
cmd-line-utils/readline/histexpand.c:
  Auto merged
cmd-line-utils/readline/history.c:
  Auto merged
cmd-line-utils/readline/readline.c:
  Auto merged
cmd-line-utils/readline/text.c:
  Auto merged
dbug/user.r:
  Auto merged
extra/yassl/src/handshake.cpp:
  Auto merged
include/config-win.h:
  Auto merged
include/m_string.h:
  Auto merged
include/my_global.h:
  Auto merged
include/my_pthread.h:
  Auto merged
include/mysql/plugin.h:
  Auto merged
include/mysql_com.h:
  Auto merged
include/thr_alarm.h:
  Auto merged
libmysql/CMakeLists.txt:
  Auto merged
libmysql/Makefile.shared:
  Auto merged
libmysql/dll.c:
  Auto merged
libmysql/get_password.c:
  Auto merged
libmysql/libmysql.c:
  Auto merged
libmysqld/Makefile.am:
  Auto merged
mysql-test/lib/mtr_cases.pl:
  Auto merged
mysql-test/mysql-test-run.pl:
  Auto merged
mysql-test/r/alter_table.result:
  Auto merged
mysql-test/r/change_user.result:
  Auto merged
mysql-test/r/create.result:
  Auto merged
mysql-test/r/innodb.result:
  Auto merged
mysql-test/r/merge.result:
  Auto merged
mysql-test/r/mix2_myisam.result:
  Auto merged
mysql-test/r/mysqldump.result:
  Auto merged
mysql-test/r/query_cache.result:
  Auto merged
mysql-test/r/subselect.result:
  Auto merged
mysql-test/valgrind.supp:
  Auto merged
mysql-test/r/view.result:
  Auto merged
mysql-test/suite/rpl/r/rpl_events.result:
  Auto merged
mysql-test/suite/rpl/t/rpl_switch_stm_row_mixed.test:
  Auto merged
mysql-test/t/create.test:
  Auto merged
mysql-test/t/mysqldump.test:
  Auto merged
mysql-test/t/query_cache.test:
  Auto merged
mysql-test/t/subselect.test:
  Auto merged
mysql-test/t/variables.test:
  Auto merged
mysql-test/t/view.test:
  Auto merged
mysys/mf_iocache.c:
  Auto merged
mysys/mf_tempfile.c:
  Auto merged
mysys/my_atomic.c:
  Auto merged
mysys/my_bit.c:
  Auto merged
mysys/my_bitmap.c:
  Auto merged
mysys/my_compress.c:
  Auto merged
mysys/my_create.c:
  Auto merged
mysys/my_delete.c:
  Auto merged
mysys/my_error.c:
  Auto merged
mysys/my_init.c:
  Auto merged
mysys/my_open.c:
  Auto merged
mysys/my_realloc.c:
  Auto merged
mysys/my_rename.c:
  Auto merged
mysys/my_symlink.c:
  Auto merged
mysys/my_sync.c:
  Auto merged
mysys/my_thr_init.c:
  Auto merged
mysys/thr_alarm.c:
  Auto merged
mysys/thr_lock.c:
  Auto merged
scripts/make_binary_distribution.sh:
  Auto merged
server-tools/instance-manager/mysql_connection.cc:
  Auto merged
sql/CMakeLists.txt:
  Auto merged
sql/Makefile.am:
  Auto merged
sql/events.cc:
  Auto merged
sql/field.cc:
  Auto merged
sql/field.h:
  Auto merged
sql/filesort.cc:
  Auto merged
sql/gen_lex_hash.cc:
  Auto merged
sql/ha_ndbcluster.cc:
  Auto merged
sql/ha_partition.h:
  Auto merged
sql/handler.h:
  Auto merged
sql/item.cc:
  Auto merged
sql/item.h:
  Auto merged
sql/item_cmpfunc.cc:
  Auto merged
sql/item_func.cc:
  Auto merged
sql/item_func.h:
  Auto merged
sql/item_strfunc.cc:
  Auto merged
sql/item_strfunc.h:
  Auto merged
sql/item_subselect.cc:
  Auto merged
sql/lock.cc:
  Auto merged
sql/log.cc:
  Auto merged
sql/log_event.cc:
  Auto merged
sql/net_serv.cc:
  Auto merged
sql/opt_range.cc:
  Auto merged
sql/partition_info.cc:
  Auto merged
sql/rpl_injector.cc:
  Auto merged
sql/set_var.cc:
  Auto merged
sql/slave.cc:
  Auto merged
sql/slave.h:
  Auto merged
sql/sp_head.cc:
  Auto merged
sql/sql_acl.cc:
  Auto merged
sql/sql_base.cc:
  Auto merged
sql/sql_cache.cc:
  Auto merged
sql/sql_class.h:
  Auto merged
sql/sql_delete.cc:
  Auto merged
sql/sql_load.cc:
  Auto merged
sql/sql_plugin.cc:
  Auto merged
sql/sql_prepare.cc:
  Auto merged
sql/sql_repl.cc:
  Auto merged
sql/sql_test.cc:
  Auto merged
sql/sql_union.cc:
  Auto merged
sql/sql_update.cc:
  Auto merged
sql/sql_yacc.yy:
  Auto merged
sql/table.cc:
  Auto merged
sql/table.h:
  Auto merged
sql/unireg.cc:
  Auto merged
sql/share/errmsg.txt:
  Auto merged
storage/csv/ha_tina.cc:
  Auto merged
storage/csv/ha_tina.h:
  Auto merged
storage/myisam/CMakeLists.txt:
  Auto merged
storage/myisam/ft_boolean_search.c:
  Auto merged
storage/myisam/ft_eval.c:
  Auto merged
storage/myisam/ft_nlq_search.c:
  Auto merged
storage/myisam/ft_parser.c:
  Auto merged
storage/myisam/ft_static.c:
  Auto merged
storage/myisam/ft_stopwords.c:
  Auto merged
storage/myisam/ft_test1.c:
  Auto merged
storage/myisam/ft_update.c:
  Auto merged
storage/myisam/ha_myisam.cc:
  Auto merged
storage/myisam/mi_check.c:
  Auto merged
storage/myisam/mi_create.c:
  Auto merged
storage/myisam/mi_delete.c:
  Auto merged
storage/myisam/mi_delete_all.c:
  Auto merged
storage/myisam/mi_dynrec.c:
  Auto merged
storage/myisam/mi_key.c:
  Auto merged
storage/myisam/mi_packrec.c:
  Auto merged
storage/myisam/mi_range.c:
  Auto merged
storage/myisam/mi_search.c:
  Auto merged
storage/myisam/mi_test1.c:
  Auto merged
storage/myisam/mi_test2.c:
  Auto merged
storage/myisam/mi_test3.c:
  Auto merged
storage/myisam/mi_unique.c:
  Auto merged
storage/myisam/mi_write.c:
  Auto merged
storage/myisam/myisamchk.c:
  Auto merged
storage/myisam/myisamdef.h:
  Auto merged
storage/myisam/myisampack.c:
  Auto merged
storage/myisam/sort.c:
  Auto merged
storage/myisam/sp_test.c:
  Auto merged
support-files/mysql.spec.sh:
  Auto merged
tests/mysql_client_test.c:
  Auto merged
configure.in:
  Manual merge
dbug/dbug.c:
  Restore to original state in Maria tree
  The big diff comes from a wrong pull from 5.0 -> 5.1 after backporting dbug to 5.0 from 5.1
include/Makefile.am:
  Manual merge
include/my_atomic.h:
  Ignore changes
include/my_base.h:
  Manual merge
include/my_dbug.h:
  Use orginal my_dbug.h from maria tree
include/my_handler.h:
  Manual merge
include/my_sys.h:
  Manual merge
include/myisam.h:
  Manual merge
mysql-test/lib/mtr_report.pl:
  Manual merge
mysql-test/r/myisam.result:
  Manual merge
mysql-test/suite/binlog/r/binlog_unsafe.result:
  Manual merge
mysql-test/suite/binlog/t/binlog_unsafe.test:
  Manual merge
mysql-test/suite/rpl/r/rpl_row_flsh_tbls.result:
  Manual merge
mysql-test/suite/rpl/r/rpl_switch_stm_row_mixed.result:
  No changes
mysql-test/suite/rpl/t/rpl_row_flsh_tbls.test:
  Manual merge
mysql-test/t/change_user.test:
  Manual merge
mysql-test/t/disabled.def:
  Manual merge
mysql-test/t/merge.test:
  No changes
mysql-test/t/myisam.test:
  Manual merge
mysys/Makefile.am:
  Manual merge
mysys/array.c:
  Manual merge
mysys/mf_keycache.c:
  Manual merge
mysys/my_getsystime.c:
  Manual merge
mysys/my_handler.c:
  Manual merge
mysys/my_pread.c:
  Manual merge
mysys/safemalloc.c:
  Manual merge
sql/ha_partition.cc:
  Manual merge
sql/handler.cc:
  Manual merge
sql/lex.h:
  Manual merge
sql/mysql_priv.h:
  Manual merge
sql/mysqld.cc:
  Manual merge
sql/set_var.h:
  Manual merge
sql/sql_class.cc:
  Manual merge
sql/sql_insert.cc:
  Manual merge
sql/sql_parse.cc:
  Manual merge
sql/sql_select.cc:
  Manual merge
sql/sql_show.cc:
  Manual merge
sql/sql_table.cc:
  Manual merge
storage/myisam/mi_checksum.c:
  No changes
storage/myisam/mi_extra.c:
  Manual merge
storage/myisam/mi_open.c:
  Manual merge
storage/myisammrg/ha_myisammrg.cc:
  Manual merge
strings/strmake.c:
  No changes
2008-04-28 19:24:05 +03:00

363 lines
9.5 KiB
C++

/* Copyright (C) 2004-2006 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#if defined(__GNUC__) && defined(USE_PRAGMA_IMPLEMENTATION)
#pragma implementation
#endif
#include <my_global.h>
#include <mysql.h>
#include <my_sys.h>
#include "mysql_connection.h"
#include <m_string.h>
#include <violite.h>
#include "command.h"
#include "log.h"
#include "messages.h"
#include "mysqld_error.h"
#include "mysql_manager_error.h"
#include "parse.h"
#include "priv.h"
#include "protocol.h"
#include "thread_registry.h"
#include "user_map.h"
Mysql_connection::Mysql_connection(Thread_registry *thread_registry_arg,
User_map *user_map_arg,
struct st_vio *vio_arg, ulong
connection_id_arg)
:vio(vio_arg),
connection_id(connection_id_arg),
thread_registry(thread_registry_arg),
user_map(user_map_arg)
{
}
/*
NET subsystem requieres its user to provide my_net_local_init extern
C function (exactly as declared below). my_net_local_init is called by
my_net_init and is supposed to set NET controlling variables.
See also priv.h for variables description.
*/
C_MODE_START
void my_net_local_init(NET *net)
{
net->max_packet= net_buffer_length;
my_net_set_read_timeout(net, (uint)net_read_timeout);
my_net_set_write_timeout(net, (uint)net_write_timeout);
net->retry_count= net_retry_count;
net->max_packet_size= max_allowed_packet;
}
C_MODE_END
/*
Every resource, which we can fail to acquire, is allocated in init().
This function is complementary to cleanup().
*/
bool Mysql_connection::init()
{
/* Allocate buffers for network I/O */
if (my_net_init(&net, vio))
return TRUE;
net.return_status= &status;
/* Initialize random number generator */
{
ulong seed1= (ulong) &rand_st + rand();
ulong seed2= (ulong) rand() + (ulong) time(0);
my_rnd_init(&rand_st, seed1, seed2);
}
/* Fill scramble - server's random message used for handshake */
create_random_string(scramble, SCRAMBLE_LENGTH, &rand_st);
/* We don't support transactions, every query is atomic */
status= SERVER_STATUS_AUTOCOMMIT;
thread_registry->register_thread(&thread_info);
return FALSE;
}
void Mysql_connection::cleanup()
{
net_end(&net);
thread_registry->unregister_thread(&thread_info);
}
Mysql_connection::~Mysql_connection()
{
/* vio_delete closes the socket if necessary */
vio_delete(vio);
}
void Mysql_connection::main()
{
log_info("Connection %lu: accepted.", (unsigned long) connection_id);
if (check_connection())
{
log_info("Connection %lu: failed to authorize the user.",
(unsigned long) connection_id);
return;
}
log_info("Connection %lu: the user was authorized successfully.",
(unsigned long) connection_id);
vio_keepalive(vio, TRUE);
while (!net.error && net.vio && !thread_registry->is_shutdown())
{
if (do_command())
break;
}
}
int Mysql_connection::check_connection()
{
ulong pkt_len=0; // to hold client reply length
/* buffer for the first packet */ /* packet contains: */
uchar buff[MAX_VERSION_LENGTH + 1 + // server version, 0-ended
4 + // connection id
SCRAMBLE_LENGTH + 2 + // scramble (in 2 pieces)
18]; // server variables: flags,
// charset number, status,
uchar *pos= buff;
ulong server_flags;
memcpy(pos, mysqlmanager_version.str, mysqlmanager_version.length + 1);
pos+= mysqlmanager_version.length + 1;
int4store((uchar*) pos, connection_id);
pos+= 4;
/*
Old clients does not understand long scrambles, but can ignore packet
tail: that's why first part of the scramble is placed here, and second
part at the end of packet (even though we don't support old clients,
we must follow standard packet format.)
*/
memcpy(pos, scramble, SCRAMBLE_LENGTH_323);
pos+= SCRAMBLE_LENGTH_323;
*pos++= '\0';
server_flags= CLIENT_LONG_FLAG | CLIENT_PROTOCOL_41 |
CLIENT_SECURE_CONNECTION;
/*
18-bytes long section for various flags/variables
Every flag occupies a bit in first half of ulong; int2store will
gracefully pick up all flags.
*/
int2store(pos, server_flags);
pos+= 2;
*pos++= (char) default_charset_info->number; // global mysys variable
int2store(pos, status); // connection status
pos+= 2;
bzero(pos, 13); // not used now
pos+= 13;
/* second part of the scramble, null-terminated */
memcpy(pos, scramble + SCRAMBLE_LENGTH_323,
SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1);
pos+= SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1;
/* write connection message and read reply */
enum { MIN_HANDSHAKE_SIZE= 2 };
if (net_write_command(&net, protocol_version, (uchar*) "", 0,
buff, pos - buff) ||
(pkt_len= my_net_read(&net)) == packet_error ||
pkt_len < MIN_HANDSHAKE_SIZE)
{
net_send_error(&net, ER_HANDSHAKE_ERROR);
return 1;
}
client_capabilities= uint2korr(net.read_pos);
if (!(client_capabilities & CLIENT_PROTOCOL_41))
{
net_send_error_323(&net, ER_NOT_SUPPORTED_AUTH_MODE);
return 1;
}
client_capabilities|= ((ulong) uint2korr(net.read_pos + 2)) << 16;
pos= net.read_pos + 32;
/* At least one byte for username and one byte for password */
if (pos >= net.read_pos + pkt_len + 2)
{
/*TODO add user and password handling in error messages*/
net_send_error(&net, ER_HANDSHAKE_ERROR);
return 1;
}
const char *user= (char*) pos;
const char *password= strend(user)+1;
ulong password_len= *password++;
LEX_STRING user_name= { (char *) user, password - user - 2 };
if (password_len != SCRAMBLE_LENGTH)
{
net_send_error(&net, ER_ACCESS_DENIED_ERROR);
return 1;
}
if (user_map->authenticate(&user_name, password, scramble))
{
net_send_error(&net, ER_ACCESS_DENIED_ERROR);
return 1;
}
net_send_ok(&net, connection_id, NULL);
return 0;
}
int Mysql_connection::do_command()
{
char *packet;
ulong packet_length;
/* We start to count packets from 0 for each new command */
net.pkt_nr= 0;
if ((packet_length=my_net_read(&net)) == packet_error)
{
/* Check if we can continue without closing the connection */
if (net.error != 3) // what is 3 - find out
return 1;
if (thread_registry->is_shutdown())
return 1;
net_send_error(&net, net.last_errno);
net.error= 0;
return 0;
}
else
{
if (thread_registry->is_shutdown())
return 1;
packet= (char*) net.read_pos;
enum enum_server_command command= (enum enum_server_command)
(uchar) *packet;
log_info("Connection %lu: received packet (length: %lu; command: %d).",
(unsigned long) connection_id,
(unsigned long) packet_length,
(int) command);
return dispatch_command(command, packet + 1);
}
}
int Mysql_connection::dispatch_command(enum enum_server_command command,
const char *packet)
{
switch (command) {
case COM_QUIT: // client exit
log_info("Connection %lu: received QUIT command.",
(unsigned long) connection_id);
return 1;
case COM_PING:
log_info("Connection %lu: received PING command.",
(unsigned long) connection_id);
net_send_ok(&net, connection_id, NULL);
return 0;
case COM_QUERY:
{
log_info("Connection %lu: received QUERY command: '%s'.",
(unsigned long) connection_id,
(const char *) packet);
if (Command *com= parse_command(packet))
{
int res= 0;
log_info("Connection %lu: query parsed successfully.",
(unsigned long) connection_id);
res= com->execute(&net, connection_id);
delete com;
if (!res)
{
log_info("Connection %lu: query executed successfully",
(unsigned long) connection_id);
}
else
{
log_info("Connection %lu: can not execute query (error: %d).",
(unsigned long) connection_id,
(int) res);
net_send_error(&net, res);
}
}
else
{
log_error("Connection %lu: can not parse query: out ot resources.",
(unsigned long) connection_id);
net_send_error(&net,ER_OUT_OF_RESOURCES);
}
return 0;
}
default:
log_info("Connection %lu: received unsupported command (%d).",
(unsigned long) connection_id,
(int) command);
net_send_error(&net, ER_UNKNOWN_COM_ERROR);
return 0;
}
return 0; /* Just to make compiler happy. */
}
void Mysql_connection::run()
{
if (init())
log_error("Connection %lu: can not init handler.",
(unsigned long) connection_id);
else
{
main();
cleanup();
}
delete this;
}
/*
vim: fdm=marker
*/