1
/* Copyright (C) 2000-2003 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
19
Low level functions for storing data to be send to the MySQL client.
20
The actual communction is handled by the net_xxx functions in net_serv.cc
22
#include <drizzled/server_includes.h>
23
#include <drizzled/drizzled_error_messages.h>
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008 Sun Microsystems
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; version 2 of the License.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
#include <drizzled/gettext.h>
22
#include <drizzled/error.h>
23
#include "drizzled/my_error.h"
24
#include <drizzled/query_id.h>
25
#include <drizzled/sql_state.h>
26
#include <drizzled/session.h>
27
#include "drizzled/internal/my_sys.h"
28
#include "drizzled/internal/m_string.h"
33
#include "oldlibdrizzle.h"
36
#define PROTOCOL_VERSION 10
40
extern uint32_t global_thread_id;
44
using namespace drizzled;
46
static const uint32_t DRIZZLE_TCP_PORT= 4427;
25
47
static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
26
/* Declared non-static only because of the embedded library. */
27
static void net_send_error_packet(THD *thd, uint sql_errno, const char *err);
28
static void write_eof_packet(THD *thd, NET *net,
29
uint server_status, uint total_warn_count);
31
bool Protocol::net_store_data(const uchar *from, size_t length)
33
ulong packet_length=packet->length();
35
The +9 comes from that strings of length longer than 16M require
36
9 bytes to be stored (see net_store_length).
38
if (packet_length+9+length > packet->alloced_length() &&
39
packet->realloc(packet_length+9+length))
41
uchar *to= net_store_length((uchar*) packet->ptr()+packet_length, length);
42
memcpy(to,from,length);
43
packet->length((uint) (to+length-(uchar*) packet->ptr()));
51
net_store_data() - extended version with character set conversion.
53
It is optimized for short strings whose length after
54
conversion is garanteed to be less than 251, which accupies
55
exactly one byte to store length. It allows not to use
56
the "convert" member as a temporary buffer, conversion
57
is done directly to the "packet" member.
58
The limit 251 is good enough to optimize send_fields()
59
because column, table, database names fit into this limit.
62
bool Protocol::net_store_data(const uchar *from, size_t length,
63
const CHARSET_INFO * const from_cs,
64
const CHARSET_INFO * const to_cs)
67
/* Calculate maxumum possible result length */
68
uint conv_length= to_cs->mbmaxlen * length / from_cs->mbminlen;
69
if (conv_length > 250)
72
For strings with conv_length greater than 250 bytes
73
we don't know how many bytes we will need to store length: one or two,
74
because we don't know result length until conversion is done.
75
For example, when converting from utf8 (mbmaxlen=3) to latin1,
76
conv_length=300 means that the result length can vary between 100 to 300.
77
length=100 needs one byte, length=300 needs to bytes.
79
Thus conversion directly to "packet" is not worthy.
80
Let's use "convert" as a temporary buffer.
82
return (convert->copy((const char*) from, length, from_cs,
83
to_cs, &dummy_errors) ||
84
net_store_data((const uchar*) convert->ptr(), convert->length()));
87
ulong packet_length= packet->length();
88
ulong new_length= packet_length + conv_length + 1;
90
if (new_length > packet->alloced_length() && packet->realloc(new_length))
93
char *length_pos= (char*) packet->ptr() + packet_length;
94
char *to= length_pos + 1;
96
to+= copy_and_convert(to, conv_length, to_cs,
97
(const char*) from, length, from_cs, &dummy_errors);
99
net_store_length((uchar*) length_pos, to - length_pos - 1);
100
packet->length((uint) (to - packet->ptr()));
106
Send a error string to client.
109
net_printf_error and net_send_error are low-level functions
110
that shall be used only when a new connection is being
111
established or at server startup.
113
For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's
114
critical that every error that can be intercepted is issued in one
115
place only, my_message_sql.
117
void net_send_error(THD *thd, uint sql_errno, const char *err)
120
assert(err && err[0]);
123
It's one case when we can push an error even though there
124
is an OK or EOF already.
126
thd->main_da.can_overwrite_status= true;
128
/* Abort multi-result sets */
129
thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
131
net_send_error_packet(thd, sql_errno, err);
133
thd->main_da.can_overwrite_status= false;
49
static uint32_t connect_timeout;
50
static uint32_t read_timeout;
51
static uint32_t write_timeout;
52
static uint32_t retry_count;
53
static uint32_t buffer_length;
54
static char* bind_address;
56
const char* ListenDrizzleProtocol::getHost(void) const
61
in_port_t ListenDrizzleProtocol::getPort(void) const
67
port= DRIZZLE_TCP_PORT;
69
if ((env = getenv("DRIZZLE_TCP_PORT")))
70
port= (uint32_t) atoi(env);
75
return (in_port_t) port;
78
plugin::Client *ListenDrizzleProtocol::getClient(int fd)
81
new_fd= acceptTcp(fd);
85
return new (nothrow) ClientDrizzleProtocol(new_fd, using_mysql41_protocol);
88
ClientDrizzleProtocol::ClientDrizzleProtocol(int fd, bool using_mysql41_protocol_arg):
89
using_mysql41_protocol(using_mysql41_protocol_arg)
96
if (drizzleclient_net_init_sock(&net, fd, 0, buffer_length))
99
drizzleclient_net_set_read_timeout(&net, read_timeout);
100
drizzleclient_net_set_write_timeout(&net, write_timeout);
101
net.retry_count=retry_count;
104
ClientDrizzleProtocol::~ClientDrizzleProtocol()
107
drizzleclient_vio_close(net.vio);
110
int ClientDrizzleProtocol::getFileDescriptor(void)
112
return drizzleclient_net_get_sd(&net);
115
bool ClientDrizzleProtocol::isConnected()
120
bool ClientDrizzleProtocol::isReading(void)
122
return net.reading_or_writing == 1;
125
bool ClientDrizzleProtocol::isWriting(void)
127
return net.reading_or_writing == 2;
130
bool ClientDrizzleProtocol::flush()
134
bool ret= drizzleclient_net_write(&net, (unsigned char*) packet.ptr(),
140
void ClientDrizzleProtocol::close(void)
144
drizzleclient_net_close(&net);
145
drizzleclient_net_end(&net);
149
bool ClientDrizzleProtocol::authenticate()
151
bool connection_is_valid;
153
/* Use "connect_timeout" value during connection phase */
154
drizzleclient_net_set_read_timeout(&net, connect_timeout);
155
drizzleclient_net_set_write_timeout(&net, connect_timeout);
157
connection_is_valid= checkConnection();
159
if (connection_is_valid)
163
sendError(session->main_da.sql_errno(), session->main_da.message());
167
/* Connect completed, set read/write timeouts back to default */
168
drizzleclient_net_set_read_timeout(&net, read_timeout);
169
drizzleclient_net_set_write_timeout(&net, write_timeout);
173
bool ClientDrizzleProtocol::readCommand(char **l_packet, uint32_t *packet_length)
176
This thread will do a blocking read from the client which
177
will be interrupted when the next command is received from
178
the client, the connection is closed or "net_wait_timeout"
179
number of seconds has passed
182
/* We can do this much more efficiently with poll timeouts or watcher thread,
183
disabling for now, which means net_wait_timeout == read_timeout. */
184
drizzleclient_net_set_read_timeout(&net,
185
session->variables.net_wait_timeout);
190
*packet_length= drizzleclient_net_read(&net);
191
if (*packet_length == packet_error)
193
/* Check if we can continue without closing the connection */
195
if(net.last_errno== CR_NET_PACKET_TOO_LARGE)
196
my_error(ER_NET_PACKET_TOO_LARGE, MYF(0));
197
if (session->main_da.status() == Diagnostics_area::DA_ERROR)
198
sendError(session->main_da.sql_errno(), session->main_da.message());
203
return false; // We have to close it.
210
*l_packet= (char*) net.read_pos;
213
'packet_length' contains length of data, as it was stored in packet
214
header. In case of malformed header, drizzleclient_net_read returns zero.
215
If packet_length is not zero, drizzleclient_net_read ensures that the returned
216
number of bytes was actually read from network.
217
There is also an extra safety measure in drizzleclient_net_read:
218
it sets packet[packet_length]= 0, but only for non-zero packets.
221
if (*packet_length == 0) /* safety */
223
/* Initialize with COM_SLEEP packet */
224
(*l_packet)[0]= (unsigned char) COM_SLEEP;
227
else if (using_mysql41_protocol)
229
/* Map from MySQL commands to Drizzle commands. */
230
switch ((int)(*l_packet)[0])
234
case 2: /* INIT_DB */
238
case 8: /* SHUTDOWN */
239
(*l_packet)[0]= (unsigned char) COM_SHUTDOWN;
243
(*l_packet)[0]= (unsigned char) COM_SHUTDOWN;
248
/* Just drop connection for MySQL commands we don't support. */
249
(*l_packet)[0]= (unsigned char) COM_QUIT;
255
/* Do not rely on drizzleclient_net_read, extra safety against programming errors. */
256
(*l_packet)[*packet_length]= '\0'; /* safety */
259
/* See comment above. */
260
/* Restore read timeout value */
261
drizzleclient_net_set_read_timeout(&net,
262
session->variables.net_read_timeout);
268
404
int2store(buff,sql_errno);
271
/* The first # is to make the protocol backward compatible */
407
/* The first # is to make the client backward compatible */
273
pos= (uchar*) stpcpy((char*) buff+3, drizzle_errno_to_sqlstate(sql_errno));
409
pos= (unsigned char*) strcpy((char*) buff+3, drizzle_errno_to_sqlstate(sql_errno));
410
pos+= strlen(drizzle_errno_to_sqlstate(sql_errno));
275
length= (uint) (strmake((char*) pos, err, DRIZZLE_ERRMSG_SIZE-1) -
412
char *tmp= strncpy((char*)pos, err, DRIZZLE_ERRMSG_SIZE-1);
413
tmp+= strlen((char*)pos);
415
length= (uint32_t)(tmp-(char*)buff);
277
416
err= (char*) buff;
279
VOID(net_write_command(net,(uchar) 255, (uchar*) "", 0, (uchar*) err,
286
Faster net_store_length when we know that length is less than 65536.
287
We keep a separate version for that range because it's widely used in
290
uint is used as agrument type because of MySQL type conventions:
292
- ulong for 0..4294967296
293
- uint64_t for bigger numbers.
296
static uchar *net_store_length_fast(uchar *packet, uint length)
300
*packet=(uchar) length;
304
int2store(packet,(uint) length);
309
Send the status of the current statement execution over network.
311
@param thd in fact, carries two parameters, NET for the transport and
312
Diagnostics_area as the source of status information.
314
In MySQL, there are two types of SQL statements: those that return
315
a result set and those that return status information only.
317
If a statement returns a result set, it consists of 3 parts:
318
- result set meta-data
319
- variable number of result set rows (can be 0)
320
- followed and terminated by EOF or ERROR packet
322
Once the client has seen the meta-data information, it always
323
expects an EOF or ERROR to terminate the result set. If ERROR is
324
received, the result set rows are normally discarded (this is up
325
to the client implementation, libmysql at least does discard them).
326
EOF, on the contrary, means "successfully evaluated the entire
327
result set". Since we don't know how many rows belong to a result
328
set until it's evaluated, EOF/ERROR is the indicator of the end
329
of the row stream. Note, that we can not buffer result set rows
330
on the server -- there may be an arbitrary number of rows. But
331
we do buffer the last packet (EOF/ERROR) in the Diagnostics_area and
332
delay sending it till the very end of execution (here), to be able to
333
change EOF to an ERROR if commit failed or some other error occurred
334
during the last cleanup steps taken after execution.
336
A statement that does not return a result set doesn't send result
337
set meta-data either. Instead it returns one of:
340
Similarly to the EOF/ERROR of the previous statement type, OK/ERROR
341
packet is "buffered" in the diagnostics area and sent to the client
342
in the end of statement.
344
@pre The diagnostics area is assigned or disabled. It can not be empty
345
-- we assume that every SQL statement or COM_* command
346
generates OK, ERROR, or EOF status.
348
@post The status information is encoded to protocol format and sent to the
351
@return We conventionally return void, since the only type of error
352
that can happen here is a NET (transport) error, and that one
353
will become visible when we attempt to read from the NET the
355
Diagnostics_area::is_sent is set for debugging purposes only.
358
void net_end_statement(THD *thd)
360
assert(! thd->main_da.is_sent);
362
/* Can not be true, but do not take chances in production. */
363
if (thd->main_da.is_sent)
366
switch (thd->main_da.status()) {
367
case Diagnostics_area::DA_ERROR:
368
/* The query failed, send error to log and abort bootstrap. */
370
thd->main_da.sql_errno(),
371
thd->main_da.message());
373
case Diagnostics_area::DA_EOF:
375
thd->main_da.server_status(),
376
thd->main_da.total_warn_count());
378
case Diagnostics_area::DA_OK:
380
thd->main_da.server_status(),
381
thd->main_da.total_warn_count(),
382
thd->main_da.affected_rows(),
383
thd->main_da.last_insert_id(),
384
thd->main_da.message());
386
case Diagnostics_area::DA_DISABLED:
388
case Diagnostics_area::DA_EMPTY:
391
net_send_ok(thd, thd->server_status, thd->total_warn_count,
395
thd->main_da.is_sent= true;
399
/****************************************************************************
400
Functions used by the protocol functions (like net_send_ok) to store
401
strings and numbers in the header result packet.
402
****************************************************************************/
404
/* The following will only be used for short strings < 65K */
406
uchar *net_store_data(uchar *to, const uchar *from, size_t length)
408
to=net_store_length_fast(to,length);
409
memcpy(to,from,length);
413
uchar *net_store_data(uchar *to,int32_t from)
416
uint length=(uint) (int10_to_str(from,buff,10)-buff);
417
to=net_store_length_fast(to,length);
418
memcpy(to,buff,length);
422
uchar *net_store_data(uchar *to,int64_t from)
425
uint length=(uint) (int64_t10_to_str(from,buff,10)-buff);
426
to=net_store_length_fast(to,length);
427
memcpy(to,buff,length);
432
/*****************************************************************************
433
Default Protocol functions
434
*****************************************************************************/
436
void Protocol::init(THD *thd_arg)
439
packet= &thd->packet;
440
convert= &thd->convert_buffer;
444
Finish the result set with EOF packet, as is expected by the client,
445
if there is an error evaluating the next row and a continue handler
449
void Protocol::end_partial_result_set(THD *thd)
451
net_send_eof(thd, thd->server_status, 0 /* no warnings, we're inside SP */);
455
bool Protocol::flush()
457
return net_flush(&thd->net);
418
drizzleclient_net_write_command(&net,(unsigned char) 255, (unsigned char*) "", 0, (unsigned char*) err, length);
420
session->main_da.can_overwrite_status= false;
462
424
Send name and type of result to client.
464
426
Sum fields has table name empty and field_name.
466
@param THD Thread data object
467
@param list List of items to send to client
468
@param flag Bit mask with the following functions:
428
@param Session Thread data object
429
@param list List of items to send to client
430
@param flag Bit mask with the following functions:
469
431
- 1 send number of rows
470
432
- 2 send default values
471
433
- 4 don't write eof packet
476
1 Error (Note that in this case the error is not sent to the
438
1 Error (Note that in this case the error is not sent to the
479
bool Protocol::send_fields(List<Item> *list, uint flags)
441
bool ClientDrizzleProtocol::sendFields(List<Item> *list)
481
443
List_iterator_fast<Item> it(*list);
445
unsigned char buff[80];
484
446
String tmp((char*) buff,sizeof(buff),&my_charset_bin);
485
Protocol_text prot(thd);
486
String *local_packet= prot.storage_packet();
487
const CHARSET_INFO * const thd_charset= thd->variables.character_set_results;
489
if (flags & SEND_NUM_ROWS)
490
{ // Packet with number of elements
491
uchar *pos= net_store_length(buff, list->elements);
492
(void) my_net_write(&thd->net, buff, (size_t) (pos-buff));
448
unsigned char *row_pos= drizzleclient_net_store_length(buff, list->elements);
449
(void) drizzleclient_net_write(&net, buff, (size_t) (row_pos-buff));
495
451
while ((item=it++))
498
const CHARSET_INFO * const cs= system_charset_info;
500
455
item->make_field(&field);
502
prot.prepare_for_resend();
505
if (prot.store(STRING_WITH_LEN("def"), cs, thd_charset) ||
506
prot.store(field.db_name, (uint) strlen(field.db_name),
508
prot.store(field.table_name, (uint) strlen(field.table_name),
510
prot.store(field.org_table_name, (uint) strlen(field.org_table_name),
512
prot.store(field.col_name, (uint) strlen(field.col_name),
514
prot.store(field.org_col_name, (uint) strlen(field.org_col_name),
516
local_packet->realloc(local_packet->length()+12))
459
if (store(STRING_WITH_LEN("def")) ||
460
store(field.db_name) ||
461
store(field.table_name) ||
462
store(field.org_table_name) ||
463
store(field.col_name) ||
464
store(field.org_col_name) ||
465
packet.realloc(packet.length()+12))
519
468
/* Store fixed length fields */
520
pos= (char*) local_packet->ptr()+local_packet->length();
521
*pos++= 12; // Length of packed fields
522
if (item->collation.collation == &my_charset_bin || thd_charset == NULL)
469
pos= (char*) packet.ptr()+packet.length();
470
*pos++= 12; // Length of packed fields
472
int2store(pos, field.charsetnr);
473
int4store(pos+2, field.length);
475
if (using_mysql41_protocol)
525
int2store(pos, field.charsetnr);
526
int4store(pos+2, field.length);
477
/* Switch to MySQL field numbering. */
480
case DRIZZLE_TYPE_LONG:
484
case DRIZZLE_TYPE_DOUBLE:
488
case DRIZZLE_TYPE_NULL:
492
case DRIZZLE_TYPE_TIMESTAMP:
496
case DRIZZLE_TYPE_LONGLONG:
500
case DRIZZLE_TYPE_DATETIME:
504
case DRIZZLE_TYPE_DATE:
508
case DRIZZLE_TYPE_VARCHAR:
512
case DRIZZLE_TYPE_DECIMAL:
516
case DRIZZLE_TYPE_ENUM:
520
case DRIZZLE_TYPE_BLOB:
530
/* With conversion */
532
int2store(pos, thd_charset->number);
534
For TEXT/BLOB columns, field_length describes the maximum data
535
length in bytes. There is no limit to the number of characters
536
that a TEXT column can store, as long as the data fits into
537
the designated space.
538
For the rest of textual columns, field_length is evaluated as
539
char_count * mbmaxlen, where character count is taken from the
540
definition of the column. In other words, the maximum number
541
of characters here is limited by the column definition.
543
max_char_len= field.length / item->collation.collation->mbmaxlen;
544
int4store(pos+2, max_char_len * thd_charset->mbmaxlen);
527
/* Add one to compensate for tinyint removal from enum. */
528
pos[6]= field.type + 1;
547
531
int2store(pos+7,field.flags);
548
532
pos[9]= (char) field.decimals;
549
pos[10]= 0; // For the future
550
pos[11]= 0; // For the future
533
pos[10]= 0; // For the future
534
pos[11]= 0; // For the future
553
local_packet->length((uint) (pos - local_packet->ptr()));
554
if (flags & SEND_DEFAULTS)
555
item->send(&prot, &tmp); // Send default value
557
break; /* purecov: inspected */
537
packet.length((uint32_t) (pos - packet.ptr()));
560
if (flags & SEND_EOF)
563
Mark the end of meta-data result set, and store thd->server_status,
564
to show that there is no cursor.
565
Send no warning information, as it will be sent at statement end.
567
write_eof_packet(thd, &thd->net, thd->server_status, thd->total_warn_count);
569
return(prepare_for_send(list));
543
Mark the end of meta-data result set, and store session->server_status,
544
to show that there is no cursor.
545
Send no warning information, as it will be sent at statement end.
547
writeEOFPacket(session->server_status, session->total_warn_count);
572
551
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES),
573
MYF(0)); /* purecov: inspected */
574
return(1); /* purecov: inspected */
578
bool Protocol::write()
580
return(my_net_write(&thd->net, (uchar*) packet->ptr(),
586
Send \\0 end terminated string.
588
@param from NullS or \\0 terminated string
591
In most cases one should use store(from, length) instead of this function
599
bool Protocol::store(const char *from, const CHARSET_INFO * const cs)
603
uint length= strlen(from);
604
return store(from, length, cs);
609
Send a set of strings as one long string with ',' in between.
612
bool Protocol::store(I_List<i_string>* str_list)
615
String tmp(buf, sizeof(buf), &my_charset_bin);
617
I_List_iterator<i_string> it(*str_list);
626
if ((len= tmp.length()))
627
len--; // Remove last ','
628
return store((char*) tmp.ptr(), len, tmp.charset());
632
/****************************************************************************
633
Functions to handle the simple (default) protocol where everything is
634
This protocol is the one that is used by default between the MySQL server
635
and client when you are not using prepared statements.
637
All data are sent as 'packed-string-length' followed by 'string-data'
638
****************************************************************************/
640
void Protocol_text::prepare_for_resend()
645
bool Protocol_text::store_null()
556
bool ClientDrizzleProtocol::store(Field *from)
560
char buff[MAX_FIELD_WIDTH];
561
String str(buff,sizeof(buff), &my_charset_bin);
565
return netStoreData((const unsigned char *)str.ptr(), str.length());
568
bool ClientDrizzleProtocol::store(void)
648
571
buff[0]= (char)251;
649
return packet->append(buff, sizeof(buff), PACKET_BUFFER_EXTRA_ALLOC);
654
Auxilary function to convert string to the given character set
655
and store in network buffer.
658
bool Protocol::store_string_aux(const char *from, size_t length,
659
const CHARSET_INFO * const fromcs,
660
const CHARSET_INFO * const tocs)
662
/* 'tocs' is set 0 when client issues SET character_set_results=NULL */
663
if (tocs && !my_charset_same(fromcs, tocs) &&
664
fromcs != &my_charset_bin &&
665
tocs != &my_charset_bin)
667
/* Store with conversion */
668
return net_store_data((uchar*) from, length, fromcs, tocs);
670
/* Store without conversion */
671
return net_store_data((uchar*) from, length);
675
bool Protocol_text::store(const char *from, size_t length,
676
const CHARSET_INFO * const fromcs,
677
const CHARSET_INFO * const tocs)
679
return store_string_aux(from, length, fromcs, tocs);
683
bool Protocol_text::store(const char *from, size_t length,
684
const CHARSET_INFO * const fromcs)
686
const CHARSET_INFO * const tocs= this->thd->variables.character_set_results;
687
return store_string_aux(from, length, fromcs, tocs);
691
bool Protocol_text::store_tiny(int64_t from)
694
return net_store_data((uchar*) buff,
695
(size_t) (int10_to_str((int) from, buff, -10) - buff));
699
bool Protocol_text::store_short(int64_t from)
702
return net_store_data((uchar*) buff,
703
(size_t) (int10_to_str((int) from, buff, -10) -
708
bool Protocol_text::store_long(int64_t from)
711
return net_store_data((uchar*) buff,
712
(size_t) (int10_to_str((long int)from, buff,
713
(from <0)?-10:10)-buff));
717
bool Protocol_text::store_int64_t(int64_t from, bool unsigned_flag)
572
return packet.append(buff, sizeof(buff), PACKET_BUFFER_EXTRA_ALLOC);
575
bool ClientDrizzleProtocol::store(int32_t from)
578
return netStoreData((unsigned char*) buff,
579
(size_t) (internal::int10_to_str(from, buff, -10) - buff));
582
bool ClientDrizzleProtocol::store(uint32_t from)
585
return netStoreData((unsigned char*) buff,
586
(size_t) (internal::int10_to_str(from, buff, 10) - buff));
589
bool ClientDrizzleProtocol::store(int64_t from)
720
return net_store_data((uchar*) buff,
721
(size_t) (int64_t10_to_str(from,buff,
722
unsigned_flag ? 10 : -10)-
727
bool Protocol_text::store_decimal(const my_decimal *d)
729
char buff[DECIMAL_MAX_STR_LENGTH];
730
String str(buff, sizeof(buff), &my_charset_bin);
731
(void) my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str);
732
return net_store_data((uchar*) str.ptr(), str.length());
736
bool Protocol_text::store(float from, uint32_t decimals, String *buffer)
738
buffer->set_real((double) from, decimals, thd->charset());
739
return net_store_data((uchar*) buffer->ptr(), buffer->length());
743
bool Protocol_text::store(double from, uint32_t decimals, String *buffer)
745
buffer->set_real(from, decimals, thd->charset());
746
return net_store_data((uchar*) buffer->ptr(), buffer->length());
750
bool Protocol_text::store(Field *field)
752
if (field->is_null())
754
char buff[MAX_FIELD_WIDTH];
755
String str(buff,sizeof(buff), &my_charset_bin);
756
const CHARSET_INFO * const tocs= this->thd->variables.character_set_results;
758
field->val_str(&str);
760
return store_string_aux(str.ptr(), str.length(), str.charset(), tocs);
766
Second_part format ("%06") needs to change when
767
we support 0-6 decimals for time.
770
bool Protocol_text::store(DRIZZLE_TIME *tm)
774
length= sprintf(buff, "%04d-%02d-%02d %02d:%02d:%02d",
782
length+= sprintf(buff+length, ".%06d",
783
(int)tm->second_part);
784
return net_store_data((uchar*) buff, length);
788
bool Protocol_text::store_date(DRIZZLE_TIME *tm)
790
char buff[MAX_DATE_STRING_REP_LENGTH];
791
size_t length= my_date_to_str(tm, buff);
792
return net_store_data((uchar*) buff, length);
798
Second_part format ("%06") needs to change when
799
we support 0-6 decimals for time.
802
bool Protocol_text::store_time(DRIZZLE_TIME *tm)
806
uint day= (tm->year || tm->month) ? 0 : tm->day;
807
length= sprintf(buff, "%s%02ld:%02d:%02d",
809
(long) day*24L+(long) tm->hour,
813
length+= sprintf(buff+length, ".%06d", (int)tm->second_part);
814
return net_store_data((uchar*) buff, length);
592
return netStoreData((unsigned char*) buff,
593
(size_t) (internal::int64_t10_to_str(from, buff, -10) - buff));
596
bool ClientDrizzleProtocol::store(uint64_t from)
599
return netStoreData((unsigned char*) buff,
600
(size_t) (internal::int64_t10_to_str(from, buff, 10) - buff));
603
bool ClientDrizzleProtocol::store(double from, uint32_t decimals, String *buffer)
605
buffer->set_real(from, decimals, session->charset());
606
return netStoreData((unsigned char*) buffer->ptr(), buffer->length());
609
bool ClientDrizzleProtocol::store(const char *from, size_t length)
611
return netStoreData((const unsigned char *)from, length);
614
bool ClientDrizzleProtocol::wasAborted(void)
616
return net.error && net.vio != 0;
619
bool ClientDrizzleProtocol::haveMoreData(void)
621
return drizzleclient_net_more_data(&net);
624
bool ClientDrizzleProtocol::haveError(void)
626
return net.error || net.vio == 0;
629
bool ClientDrizzleProtocol::checkConnection(void)
639
if (drizzleclient_net_peer_addr(&net, ip, &peer_port, NI_MAXHOST))
641
my_error(ER_BAD_HOST_ERROR, MYF(0), session->security_ctx.ip.c_str());
645
session->security_ctx.ip.assign(ip);
647
drizzleclient_net_keepalive(&net, true);
649
uint32_t server_capabilites;
651
/* buff[] needs to big enough to hold the server_version variable */
652
char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH + 64];
654
server_capabilites= CLIENT_BASIC_FLAGS;
656
if (using_mysql41_protocol)
657
server_capabilites|= CLIENT_PROTOCOL_MYSQL41;
660
server_capabilites|= CLIENT_COMPRESS;
661
#endif /* HAVE_COMPRESS */
663
end= buff + strlen(VERSION);
664
if ((end - buff) >= SERVER_VERSION_LENGTH)
665
end= buff + (SERVER_VERSION_LENGTH - 1);
666
memcpy(buff, VERSION, end - buff);
670
int4store((unsigned char*) end, global_thread_id);
673
/* We don't use scramble anymore. */
674
memset(end, 'X', SCRAMBLE_LENGTH_323);
675
end+= SCRAMBLE_LENGTH_323;
676
*end++= 0; /* an empty byte for some reason */
678
int2store(end, server_capabilites);
679
/* write server characteristics: up to 16 bytes allowed */
680
end[2]=(char) default_charset_info->number;
681
int2store(end+3, session->server_status);
682
memset(end+5, 0, 13);
685
/* Write scramble tail. */
686
memset(end, 'X', SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323);
687
end+= (SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323);
688
*end++= 0; /* an empty byte for some reason */
690
/* At this point we write connection message and read reply */
691
if (drizzleclient_net_write_command(&net
692
, (unsigned char) PROTOCOL_VERSION
693
, (unsigned char*) ""
695
, (unsigned char*) buff
696
, (size_t) (end-buff))
697
|| (pkt_len= drizzleclient_net_read(&net)) == packet_error
698
|| pkt_len < MIN_HANDSHAKE_SIZE)
700
my_error(ER_HANDSHAKE_ERROR, MYF(0), session->security_ctx.ip.c_str());
704
if (packet.alloc(buffer_length))
705
return false; /* The error is set by alloc(). */
707
client_capabilities= uint2korr(net.read_pos);
710
client_capabilities|= ((uint32_t) uint2korr(net.read_pos + 2)) << 16;
711
session->max_client_packet_length= uint4korr(net.read_pos + 4);
712
end= (char*) net.read_pos + 32;
715
Disable those bits which are not supported by the server.
716
This is a precautionary measure, if the client lies. See Bug#27944.
718
client_capabilities&= server_capabilites;
720
if (end >= (char*) net.read_pos + pkt_len + 2)
722
my_error(ER_HANDSHAKE_ERROR, MYF(0), session->security_ctx.ip.c_str());
726
net.return_status= &session->server_status;
729
char *passwd= strchr(user, '\0')+1;
730
uint32_t user_len= passwd - user - 1;
734
Old clients send null-terminated string as password; new clients send
735
the size (1 byte) + string (not null-terminated). Hence in case of empty
736
password both send '\0'.
738
This strlen() can't be easily deleted without changing client.
740
Cast *passwd to an unsigned char, so that it doesn't extend the sign for
741
*passwd > 127 and become 2**32-127+ after casting to uint.
743
uint32_t passwd_len= client_capabilities & CLIENT_SECURE_CONNECTION ?
744
(unsigned char)(*passwd++) : strlen(passwd);
745
l_db= client_capabilities & CLIENT_CONNECT_WITH_DB ? l_db + passwd_len + 1 : 0;
747
/* strlen() can't be easily deleted without changing client */
748
uint32_t db_len= l_db ? strlen(l_db) : 0;
750
if (passwd + passwd_len + db_len > (char *) net.read_pos + pkt_len)
752
my_error(ER_HANDSHAKE_ERROR, MYF(0), session->security_ctx.ip.c_str());
756
/* If username starts and ends in "'", chop them off */
757
if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
764
session->security_ctx.user.assign(user);
766
return session->checkUser(passwd, passwd_len, l_db);
769
bool ClientDrizzleProtocol::netStoreData(const unsigned char *from, size_t length)
771
size_t packet_length= packet.length();
773
The +9 comes from that strings of length longer than 16M require
774
9 bytes to be stored (see drizzleclient_net_store_length).
776
if (packet_length+9+length > packet.alloced_length() &&
777
packet.realloc(packet_length+9+length))
779
unsigned char *to= drizzleclient_net_store_length((unsigned char*) packet.ptr()+packet_length, length);
780
memcpy(to,from,length);
781
packet.length((size_t) (to+length-(unsigned char*) packet.ptr()));
786
Format EOF packet according to the current client and
787
write it to the network output buffer.
790
void ClientDrizzleProtocol::writeEOFPacket(uint32_t server_status,
791
uint32_t total_warn_count)
793
unsigned char buff[5];
795
Don't send warn count during SP execution, as the warn_list
796
is cleared between substatements, and mysqltest gets confused
798
uint32_t tmp= min(total_warn_count, (uint32_t)65535);
799
buff[0]= DRIZZLE_PROTOCOL_NO_MORE_DATA;
800
int2store(buff+1, tmp);
802
The following test should never be true, but it's better to do it
803
because if 'is_fatal_error' is set the server is not going to execute
804
other queries (see the if test in dispatch_command / COM_QUERY)
806
if (session->is_fatal_error)
807
server_status&= ~SERVER_MORE_RESULTS_EXISTS;
808
int2store(buff + 3, server_status);
809
drizzleclient_net_write(&net, buff, 5);
812
static ListenDrizzleProtocol *listen_obj= NULL;
814
static int init(plugin::Registry ®istry)
816
listen_obj= new ListenDrizzleProtocol("drizzle_protocol", false);
817
registry.add(listen_obj);
821
static int deinit(plugin::Registry ®istry)
823
registry.remove(listen_obj);
828
static DRIZZLE_SYSVAR_UINT(port, port, PLUGIN_VAR_RQCMDARG,
829
N_("Port number to use for connection or 0 for "
830
"default to, in order of "
831
"preference, drizzle.cnf, $DRIZZLE_TCP_PORT, "
832
"built-in default (4427)."),
833
NULL, NULL, 0, 0, 65535, 0);
834
static DRIZZLE_SYSVAR_UINT(connect_timeout, connect_timeout,
835
PLUGIN_VAR_RQCMDARG, N_("Connect Timeout."),
836
NULL, NULL, 10, 1, 300, 0);
837
static DRIZZLE_SYSVAR_UINT(read_timeout, read_timeout, PLUGIN_VAR_RQCMDARG,
838
N_("Read Timeout."), NULL, NULL, 30, 1, 300, 0);
839
static DRIZZLE_SYSVAR_UINT(write_timeout, write_timeout, PLUGIN_VAR_RQCMDARG,
840
N_("Write Timeout."), NULL, NULL, 60, 1, 300, 0);
841
static DRIZZLE_SYSVAR_UINT(retry_count, retry_count, PLUGIN_VAR_RQCMDARG,
842
N_("Retry Count."), NULL, NULL, 10, 1, 100, 0);
843
static DRIZZLE_SYSVAR_UINT(buffer_length, buffer_length, PLUGIN_VAR_RQCMDARG,
844
N_("Buffer length."), NULL, NULL, 16384, 1024,
846
static DRIZZLE_SYSVAR_STR(bind_address, bind_address, PLUGIN_VAR_READONLY,
847
N_("Address to bind to."), NULL, NULL, NULL);
849
static drizzle_sys_var* sys_variables[]= {
850
DRIZZLE_SYSVAR(port),
851
DRIZZLE_SYSVAR(connect_timeout),
852
DRIZZLE_SYSVAR(read_timeout),
853
DRIZZLE_SYSVAR(write_timeout),
854
DRIZZLE_SYSVAR(retry_count),
855
DRIZZLE_SYSVAR(buffer_length),
856
DRIZZLE_SYSVAR(bind_address),
860
DRIZZLE_DECLARE_PLUGIN
866
"Drizzle Protocol Module",
868
init, /* Plugin Init */
869
deinit, /* Plugin Deinit */
870
NULL, /* status variables */
871
sys_variables, /* system variables */
872
NULL /* config options */
874
DRIZZLE_DECLARE_PLUGIN_END;