15
15
* You should have received a copy of the GNU General Public License
16
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
20
#include "config.h"
21
21
#include <drizzled/gettext.h>
22
22
#include <drizzled/error.h>
23
23
#include <drizzled/query_id.h>
24
#include <drizzled/error/sql_state.h>
24
#include <drizzled/sql_state.h>
25
25
#include <drizzled/session.h>
26
26
#include "drizzled/internal/m_string.h"
27
27
#include <algorithm>
28
#include <boost/program_options.hpp>
29
#include <drizzled/module/option_map.h>
30
#include "drizzled/util/tokenize.h"
31
30
#include "errmsg.h"
32
#include "mysql_protocol.h"
33
#include "mysql_password.h"
31
#include "oldlibdrizzle.h"
34
32
#include "options.h"
36
#include "drizzled/identifier.h"
38
#define PROTOCOL_VERSION 10
40
namespace po= boost::program_options;
41
34
using namespace std;
42
35
using namespace drizzled;
44
namespace drizzle_plugin
47
std::vector<std::string> ClientMySQLProtocol::mysql_admin_ip_addresses;
37
#define PROTOCOL_VERSION 10
39
extern uint32_t global_thread_id;
48
41
static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
50
static port_constraint port;
51
static timeout_constraint connect_timeout;
52
static timeout_constraint read_timeout;
53
static timeout_constraint write_timeout;
54
static retry_constraint retry_count;
55
static buffer_constraint buffer_length;
57
static uint32_t random_seed1;
58
static uint32_t random_seed2;
59
static const uint32_t random_max= 0x3FFFFFFF;
60
static const double random_max_double= (double)0x3FFFFFFF;
63
ProtocolCounters *ListenMySQLProtocol::mysql_counters= new ProtocolCounters();
65
ListenMySQLProtocol::~ListenMySQLProtocol()
68
void ListenMySQLProtocol::addCountersToTable()
70
counters.push_back(new drizzled::plugin::ListenCounter(new std::string("connection_count"), &getCounters()->connectionCount));
71
counters.push_back(new drizzled::plugin::ListenCounter(new std::string("connected"), &getCounters()->connected));
72
counters.push_back(new drizzled::plugin::ListenCounter(new std::string("failed_connections"), &getCounters()->failedConnections));
75
const std::string ListenMySQLProtocol::getHost(void) const
43
static uint32_t connect_timeout;
44
static uint32_t read_timeout;
45
static uint32_t write_timeout;
46
static uint32_t retry_count;
47
static uint32_t buffer_length;
48
static char* bind_address;
50
const char* ListenMySQLProtocol::getHost(void) const
80
55
in_port_t ListenMySQLProtocol::getPort(void) const
57
return (in_port_t) port;
85
60
plugin::Client *ListenMySQLProtocol::getClient(int fd)
154
126
drizzleclient_net_close(&net);
155
127
drizzleclient_net_end(&net);
156
if (is_admin_connection)
157
counters->adminConnected.decrement();
159
counters->connected.decrement();
163
131
bool ClientMySQLProtocol::authenticate()
165
133
bool connection_is_valid;
166
if (is_admin_connection)
168
counters->adminConnectionCount.increment();
169
counters->adminConnected.increment();
173
counters->connectionCount.increment();
174
counters->connected.increment();
177
135
/* Use "connect_timeout" value during connection phase */
178
drizzleclient_net_set_read_timeout(&net, connect_timeout.get());
179
drizzleclient_net_set_write_timeout(&net, connect_timeout.get());
136
drizzleclient_net_set_read_timeout(&net, connect_timeout);
137
drizzleclient_net_set_write_timeout(&net, connect_timeout);
181
139
connection_is_valid= checkConnection();
183
141
if (connection_is_valid)
185
if (not is_admin_connection and (counters->connected > counters->max_connections))
187
std::string errmsg(ER(ER_CON_COUNT_ERROR));
188
sendError(ER_CON_COUNT_ERROR, errmsg.c_str());
189
counters->failedConnections.increment();
198
145
sendError(session->main_da.sql_errno(), session->main_da.message());
199
counters->failedConnections.increment();
203
149
/* Connect completed, set read/write timeouts back to default */
204
drizzleclient_net_set_read_timeout(&net, read_timeout.get());
205
drizzleclient_net_set_write_timeout(&net, write_timeout.get());
150
drizzleclient_net_set_read_timeout(&net, read_timeout);
151
drizzleclient_net_set_write_timeout(&net, write_timeout);
911
791
drizzleclient_net_write(&net, buff, 5);
915
Store an integer with simple packing into a output package
917
buffer Store the packed integer here
918
length integers to store
920
This is mostly used to store lengths of strings. We have to cast
921
the result for the LL() becasue of a bug in Forte CC compiler.
924
Position in 'buffer' after the packed length
927
unsigned char *ClientMySQLProtocol::storeLength(unsigned char *buffer, uint64_t length)
929
if (length < (uint64_t) 251LL)
931
*buffer=(unsigned char) length;
934
/* 251 is reserved for NULL */
935
if (length < (uint64_t) 65536LL)
938
int2store(buffer,(uint32_t) length);
941
if (length < (uint64_t) 16777216LL)
944
int3store(buffer,(uint32_t) length);
948
int8store(buffer,length);
952
void ClientMySQLProtocol::makeScramble(char *scramble)
954
/* This is the MySQL algorithm with minimal changes. */
955
random_seed1= (random_seed1 * 3 + random_seed2) % random_max;
956
random_seed2= (random_seed1 + random_seed2 + 33) % random_max;
957
uint32_t seed= static_cast<uint32_t>((static_cast<double>(random_seed1) / random_max_double) * 0xffffffff);
960
uint32_t pointer_seed;
961
memcpy(&pointer_seed, &pointer, 4);
962
uint32_t random1= (seed + pointer_seed) % random_max;
963
uint32_t random2= (seed + session->variables.pseudo_thread_id + net.vio->get_fd()) % random_max;
965
for (char *end= scramble + SCRAMBLE_LENGTH; scramble != end; scramble++)
967
random1= (random1 * 3 + random2) % random_max;
968
random2= (random1 + random2 + 33) % random_max;
969
*scramble= static_cast<char>((static_cast<double>(random1) / random_max_double) * 94 + 33);
973
void ClientMySQLProtocol::mysql_compose_ip_addresses(vector<string> options)
975
for (vector<string>::iterator it= options.begin();
979
tokenize(*it, mysql_admin_ip_addresses, ",", true);
983
794
static ListenMySQLProtocol *listen_obj= NULL;
984
plugin::Create_function<MySQLPassword> *mysql_password= NULL;
986
static int init(drizzled::module::Context &context)
988
/* Initialize random seeds for the MySQL algorithm with minimal changes. */
989
time_t seed_time= time(NULL);
990
random_seed1= seed_time % random_max;
991
random_seed2= (seed_time / 2) % random_max;
993
const module::option_map &vm= context.getOptions();
995
mysql_password= new plugin::Create_function<MySQLPassword>(MySQLPasswordName);
996
context.add(mysql_password);
998
listen_obj= new ListenMySQLProtocol("mysql_protocol", vm["bind-address"].as<std::string>(), true);
999
listen_obj->addCountersToTable();
1000
context.add(listen_obj);
1001
context.registerVariable(new sys_var_constrained_value_readonly<in_port_t>("port", port));
1002
context.registerVariable(new sys_var_constrained_value<uint32_t>("connect_timeout", connect_timeout));
1003
context.registerVariable(new sys_var_constrained_value<uint32_t>("read_timeout", read_timeout));
1004
context.registerVariable(new sys_var_constrained_value<uint32_t>("write_timeout", write_timeout));
1005
context.registerVariable(new sys_var_constrained_value<uint32_t>("retry_count", retry_count));
1006
context.registerVariable(new sys_var_constrained_value<uint32_t>("buffer_length", buffer_length));
1007
context.registerVariable(new sys_var_const_string_val("bind_address",
1008
vm["bind-address"].as<std::string>()));
1010
context.registerVariable(new sys_var_uint32_t_ptr("max-connections", &ListenMySQLProtocol::mysql_counters->max_connections));
1015
static void init_options(drizzled::module::option_context &context)
1018
po::value<port_constraint>(&port)->default_value(3306),
1019
_("Port number to use for connection or 0 for default to with MySQL "
1021
context("connect-timeout",
1022
po::value<timeout_constraint>(&connect_timeout)->default_value(10),
1023
_("Connect Timeout."));
1024
context("read-timeout",
1025
po::value<timeout_constraint>(&read_timeout)->default_value(30),
1026
_("Read Timeout."));
1027
context("write-timeout",
1028
po::value<timeout_constraint>(&write_timeout)->default_value(60),
1029
_("Write Timeout."));
1030
context("retry-count",
1031
po::value<retry_constraint>(&retry_count)->default_value(10),
1033
context("buffer-length",
1034
po::value<buffer_constraint>(&buffer_length)->default_value(16384),
1035
_("Buffer length."));
1036
context("bind-address",
1037
po::value<string>()->default_value(""),
1038
_("Address to bind to."));
1039
context("max-connections",
1040
po::value<uint32_t>(&ListenMySQLProtocol::mysql_counters->max_connections)->default_value(1000),
1041
_("Maximum simultaneous connections."));
1042
context("admin-ip-addresses",
1043
po::value<vector<string> >()->composing()->notifier(&ClientMySQLProtocol::mysql_compose_ip_addresses),
1044
_("A restrictive IP address list for incoming admin connections."));
1047
} /* namespace drizzle_plugin */
796
static int init(drizzled::plugin::Registry ®istry)
798
listen_obj= new ListenMySQLProtocol("mysql_protocol", true);
799
registry.add(listen_obj);
803
static int deinit(drizzled::plugin::Registry ®istry)
805
registry.remove(listen_obj);
810
static DRIZZLE_SYSVAR_UINT(port, port, PLUGIN_VAR_RQCMDARG,
811
N_("Port number to use for connection or 0 for default to with MySQL "
813
NULL, NULL, 3306, 0, 65535, 0);
814
static DRIZZLE_SYSVAR_UINT(connect_timeout, connect_timeout,
815
PLUGIN_VAR_RQCMDARG, N_("Connect Timeout."),
816
NULL, NULL, 10, 1, 300, 0);
817
static DRIZZLE_SYSVAR_UINT(read_timeout, read_timeout, PLUGIN_VAR_RQCMDARG,
818
N_("Read Timeout."), NULL, NULL, 30, 1, 300, 0);
819
static DRIZZLE_SYSVAR_UINT(write_timeout, write_timeout, PLUGIN_VAR_RQCMDARG,
820
N_("Write Timeout."), NULL, NULL, 60, 1, 300, 0);
821
static DRIZZLE_SYSVAR_UINT(retry_count, retry_count, PLUGIN_VAR_RQCMDARG,
822
N_("Retry Count."), NULL, NULL, 10, 1, 100, 0);
823
static DRIZZLE_SYSVAR_UINT(buffer_length, buffer_length, PLUGIN_VAR_RQCMDARG,
824
N_("Buffer length."), NULL, NULL, 16384, 1024,
826
static DRIZZLE_SYSVAR_STR(bind_address, bind_address, PLUGIN_VAR_READONLY,
827
N_("Address to bind to."), NULL, NULL, NULL);
829
static drizzle_sys_var* system_variables[]= {
830
DRIZZLE_SYSVAR(port),
831
DRIZZLE_SYSVAR(connect_timeout),
832
DRIZZLE_SYSVAR(read_timeout),
833
DRIZZLE_SYSVAR(write_timeout),
834
DRIZZLE_SYSVAR(retry_count),
835
DRIZZLE_SYSVAR(buffer_length),
836
DRIZZLE_SYSVAR(bind_address),
1049
840
DRIZZLE_DECLARE_PLUGIN
1051
842
DRIZZLE_VERSION_ID,
1055
846
"MySQL Protocol Module",
1056
847
PLUGIN_LICENSE_GPL,
1057
drizzle_plugin::init, /* Plugin Init */
1059
drizzle_plugin::init_options /* config options */
848
init, /* Plugin Init */
849
deinit, /* Plugin Deinit */
850
NULL, /* status variables */
851
system_variables, /* system variables */
852
NULL /* config options */
1061
854
DRIZZLE_DECLARE_PLUGIN_END;