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>
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>
22
23
#include <drizzled/error.h>
23
#include <drizzled/query_id.h>
24
24
#include <drizzled/sql_state.h>
25
#include <libdrizzle/pack.h>
26
#include <drizzled/protocol.h>
25
27
#include <drizzled/session.h>
26
#include "drizzled/internal/my_sys.h"
27
#include "drizzled/internal/m_string.h"
32
#include "drizzle_protocol.h"
35
#define PROTOCOL_VERSION 10
39
extern uint32_t global_thread_id;
42
using namespace drizzled;
45
namespace drizzle_protocol
49
static const uint32_t DRIZZLE_TCP_PORT= 4427;
50
29
static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
52
static uint32_t connect_timeout;
53
static uint32_t read_timeout;
54
static uint32_t write_timeout;
55
static uint32_t retry_count;
56
static uint32_t buffer_length;
57
static char* bind_address;
59
const char* ListenDrizzleProtocol::getHost(void) const
64
in_port_t ListenDrizzleProtocol::getPort(void) const
70
port= DRIZZLE_TCP_PORT;
72
if ((env = getenv("DRIZZLE_TCP_PORT")))
73
port= (uint32_t) atoi(env);
78
return (in_port_t) port;
81
plugin::Client *ListenDrizzleProtocol::getClient(int fd)
84
new_fd= acceptTcp(fd);
88
return new (nothrow) ClientDrizzleProtocol(new_fd, using_mysql41_protocol);
91
ClientDrizzleProtocol::ClientDrizzleProtocol(int fd, bool using_mysql41_protocol_arg):
92
using_mysql41_protocol(using_mysql41_protocol_arg)
99
if (drizzleclient_net_init_sock(&net, fd, 0, buffer_length))
102
drizzleclient_net_set_read_timeout(&net, read_timeout);
103
drizzleclient_net_set_write_timeout(&net, write_timeout);
104
net.retry_count=retry_count;
107
ClientDrizzleProtocol::~ClientDrizzleProtocol()
110
drizzleclient_vio_close(net.vio);
113
int ClientDrizzleProtocol::getFileDescriptor(void)
115
return drizzleclient_net_get_sd(&net);
118
bool ClientDrizzleProtocol::isConnected()
123
bool ClientDrizzleProtocol::isReading(void)
125
return net.reading_or_writing == 1;
128
bool ClientDrizzleProtocol::isWriting(void)
130
return net.reading_or_writing == 2;
133
bool ClientDrizzleProtocol::flush()
137
bool ret= drizzleclient_net_write(&net, (unsigned char*) packet.ptr(),
143
void ClientDrizzleProtocol::close(void)
147
drizzleclient_net_close(&net);
148
drizzleclient_net_end(&net);
152
bool ClientDrizzleProtocol::authenticate()
154
bool connection_is_valid;
156
/* Use "connect_timeout" value during connection phase */
157
drizzleclient_net_set_read_timeout(&net, connect_timeout);
158
drizzleclient_net_set_write_timeout(&net, connect_timeout);
160
connection_is_valid= checkConnection();
162
if (connection_is_valid)
166
sendError(session->main_da.sql_errno(), session->main_da.message());
170
/* Connect completed, set read/write timeouts back to default */
171
drizzleclient_net_set_read_timeout(&net, read_timeout);
172
drizzleclient_net_set_write_timeout(&net, write_timeout);
176
bool ClientDrizzleProtocol::readCommand(char **l_packet, uint32_t *packet_length)
179
This thread will do a blocking read from the client which
180
will be interrupted when the next command is received from
181
the client, the connection is closed or "net_wait_timeout"
182
number of seconds has passed
185
/* We can do this much more efficiently with poll timeouts or watcher thread,
186
disabling for now, which means net_wait_timeout == read_timeout. */
187
drizzleclient_net_set_read_timeout(&net,
188
session->variables.net_wait_timeout);
193
*packet_length= drizzleclient_net_read(&net);
194
if (*packet_length == packet_error)
196
/* Check if we can continue without closing the connection */
198
if(net.last_errno== CR_NET_PACKET_TOO_LARGE)
199
my_error(ER_NET_PACKET_TOO_LARGE, MYF(0));
200
if (session->main_da.status() == Diagnostics_area::DA_ERROR)
201
sendError(session->main_da.sql_errno(), session->main_da.message());
206
return false; // We have to close it.
213
*l_packet= (char*) net.read_pos;
216
'packet_length' contains length of data, as it was stored in packet
217
header. In case of malformed header, drizzleclient_net_read returns zero.
218
If packet_length is not zero, drizzleclient_net_read ensures that the returned
219
number of bytes was actually read from network.
220
There is also an extra safety measure in drizzleclient_net_read:
221
it sets packet[packet_length]= 0, but only for non-zero packets.
224
if (*packet_length == 0) /* safety */
226
/* Initialize with COM_SLEEP packet */
227
(*l_packet)[0]= (unsigned char) COM_SLEEP;
230
else if (using_mysql41_protocol)
232
/* Map from MySQL commands to Drizzle commands. */
233
switch ((int)(*l_packet)[0])
237
case 2: /* INIT_DB */
241
case 8: /* SHUTDOWN */
242
(*l_packet)[0]= (unsigned char) COM_SHUTDOWN;
246
(*l_packet)[0]= (unsigned char) COM_SHUTDOWN;
251
/* Just drop connection for MySQL commands we don't support. */
252
(*l_packet)[0]= (unsigned char) COM_QUIT;
258
/* Do not rely on drizzleclient_net_read, extra safety against programming errors. */
259
(*l_packet)[*packet_length]= '\0'; /* safety */
262
/* See comment above. */
263
/* Restore read timeout value */
264
drizzleclient_net_set_read_timeout(&net,
265
session->variables.net_read_timeout);
30
/* Declared non-static only because of the embedded library. */
31
static void net_send_error_packet(Session *session, uint32_t sql_errno, const char *err);
32
static void write_eof_packet(Session *session, NET *net,
33
uint32_t server_status, uint32_t total_warn_count);
35
bool Protocol::net_store_data(const unsigned char *from, size_t length)
37
size_t packet_length= packet->length();
39
The +9 comes from that strings of length longer than 16M require
40
9 bytes to be stored (see net_store_length).
42
if (packet_length+9+length > packet->alloced_length() &&
43
packet->realloc(packet_length+9+length))
45
unsigned char *to= net_store_length((unsigned char*) packet->ptr()+packet_length, length);
46
memcpy(to,from,length);
47
packet->length((size_t) (to+length-(unsigned char*) packet->ptr()));
55
net_store_data() - extended version with character set conversion.
57
It is optimized for short strings whose length after
58
conversion is garanteed to be less than 251, which accupies
59
exactly one byte to store length. It allows not to use
60
the "convert" member as a temporary buffer, conversion
61
is done directly to the "packet" member.
62
The limit 251 is good enough to optimize send_fields()
63
because column, table, database names fit into this limit.
66
bool Protocol::net_store_data(const unsigned char *from, size_t length,
67
const CHARSET_INFO * const from_cs,
68
const CHARSET_INFO * const to_cs)
70
uint32_t dummy_errors;
71
/* Calculate maxumum possible result length */
72
uint32_t conv_length= to_cs->mbmaxlen * length / from_cs->mbminlen;
73
if (conv_length > 250)
76
For strings with conv_length greater than 250 bytes
77
we don't know how many bytes we will need to store length: one or two,
78
because we don't know result length until conversion is done.
79
For example, when converting from utf8 (mbmaxlen=3) to latin1,
80
conv_length=300 means that the result length can vary between 100 to 300.
81
length=100 needs one byte, length=300 needs to bytes.
83
Thus conversion directly to "packet" is not worthy.
84
Let's use "convert" as a temporary buffer.
86
return (convert->copy((const char*) from, length, from_cs,
87
to_cs, &dummy_errors) ||
88
net_store_data((const unsigned char*) convert->ptr(), convert->length()));
91
size_t packet_length= packet->length();
92
size_t new_length= packet_length + conv_length + 1;
94
if (new_length > packet->alloced_length() && packet->realloc(new_length))
97
char *length_pos= (char*) packet->ptr() + packet_length;
98
char *to= length_pos + 1;
100
to+= copy_and_convert(to, conv_length, to_cs,
101
(const char*) from, length, from_cs, &dummy_errors);
103
net_store_length((unsigned char*) length_pos, to - length_pos - 1);
104
packet->length((uint) (to - packet->ptr()));
110
Send a error string to client.
113
net_printf_error and net_send_error are low-level functions
114
that shall be used only when a new connection is being
115
established or at server startup.
117
For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's
118
critical that every error that can be intercepted is issued in one
119
place only, my_message_sql.
121
void net_send_error(Session *session, uint32_t sql_errno, const char *err)
124
assert(err && err[0]);
127
It's one case when we can push an error even though there
128
is an OK or EOF already.
130
session->main_da.can_overwrite_status= true;
132
/* Abort multi-result sets */
133
session->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
135
net_send_error_packet(session, sql_errno, err);
137
session->main_da.can_overwrite_status= false;
418
283
length= (uint32_t)(tmp-(char*)buff);
419
284
err= (char*) buff;
421
drizzleclient_net_write_command(&net,(unsigned char) 255, (unsigned char*) "", 0, (unsigned char*) err, length);
423
session->main_da.can_overwrite_status= false;
286
net_write_command(net,(unsigned char) 255, (unsigned char*) "", 0, (unsigned char*) err, length);
292
Faster net_store_length when we know that length is less than 65536.
293
We keep a separate version for that range because it's widely used in
296
uint32_t is used as agrument type because of MySQL type conventions:
297
- uint32_t for 0..65536
298
- ulong for 0..4294967296
299
- uint64_t for bigger numbers.
302
static unsigned char *net_store_length_fast(unsigned char *packet, uint32_t length)
306
*packet=(unsigned char) length;
310
int2store(packet,(uint32_t) length);
316
Send the status of the current statement execution over network.
318
@param session in fact, carries two parameters, NET for the transport and
319
Diagnostics_area as the source of status information.
321
In MySQL, there are two types of SQL statements: those that return
322
a result set and those that return status information only.
324
If a statement returns a result set, it consists of 3 parts:
325
- result set meta-data
326
- variable number of result set rows (can be 0)
327
- followed and terminated by EOF or ERROR packet
329
Once the client has seen the meta-data information, it always
330
expects an EOF or ERROR to terminate the result set. If ERROR is
331
received, the result set rows are normally discarded (this is up
332
to the client implementation, libmysql at least does discard them).
333
EOF, on the contrary, means "successfully evaluated the entire
334
result set". Since we don't know how many rows belong to a result
335
set until it's evaluated, EOF/ERROR is the indicator of the end
336
of the row stream. Note, that we can not buffer result set rows
337
on the server -- there may be an arbitrary number of rows. But
338
we do buffer the last packet (EOF/ERROR) in the Diagnostics_area and
339
delay sending it till the very end of execution (here), to be able to
340
change EOF to an ERROR if commit failed or some other error occurred
341
during the last cleanup steps taken after execution.
343
A statement that does not return a result set doesn't send result
344
set meta-data either. Instead it returns one of:
347
Similarly to the EOF/ERROR of the previous statement type, OK/ERROR
348
packet is "buffered" in the diagnostics area and sent to the client
349
in the end of statement.
351
@pre The diagnostics area is assigned or disabled. It can not be empty
352
-- we assume that every SQL statement or COM_* command
353
generates OK, ERROR, or EOF status.
355
@post The status information is encoded to protocol format and sent to the
358
@return We conventionally return void, since the only type of error
359
that can happen here is a NET (transport) error, and that one
360
will become visible when we attempt to read from the NET the
362
Diagnostics_area::is_sent is set for debugging purposes only.
365
void net_end_statement(Session *session)
367
assert(! session->main_da.is_sent);
369
/* Can not be true, but do not take chances in production. */
370
if (session->main_da.is_sent)
373
switch (session->main_da.status()) {
374
case Diagnostics_area::DA_ERROR:
375
/* The query failed, send error to log and abort bootstrap. */
376
net_send_error(session,
377
session->main_da.sql_errno(),
378
session->main_da.message());
380
case Diagnostics_area::DA_EOF:
381
net_send_eof(session,
382
session->main_da.server_status(),
383
session->main_da.total_warn_count());
385
case Diagnostics_area::DA_OK:
387
session->main_da.server_status(),
388
session->main_da.total_warn_count(),
389
session->main_da.affected_rows(),
390
session->main_da.last_insert_id(),
391
session->main_da.message());
393
case Diagnostics_area::DA_DISABLED:
395
case Diagnostics_area::DA_EMPTY:
397
//TODO: Something is being masked here by commenting this out
399
net_send_ok(session, session->server_status, session->total_warn_count,
403
session->main_da.is_sent= true;
407
/****************************************************************************
408
Functions used by the protocol functions (like net_send_ok) to store
409
strings and numbers in the header result packet.
410
****************************************************************************/
412
/* The following will only be used for short strings < 65K */
414
unsigned char *net_store_data(unsigned char *to, const unsigned char *from, size_t length)
416
to=net_store_length_fast(to,length);
417
memcpy(to,from,length);
421
unsigned char *net_store_data(unsigned char *to,int32_t from)
424
uint32_t length=(uint) (int10_to_str(from,buff,10)-buff);
425
to=net_store_length_fast(to,length);
426
memcpy(to,buff,length);
430
unsigned char *net_store_data(unsigned char *to,int64_t from)
433
uint32_t length=(uint) (int64_t10_to_str(from,buff,10)-buff);
434
to=net_store_length_fast(to,length);
435
memcpy(to,buff,length);
440
/*****************************************************************************
441
Default Protocol functions
442
*****************************************************************************/
444
void Protocol::init(Session *session_arg)
447
packet= &session->packet;
448
convert= &session->convert_buffer;
452
Finish the result set with EOF packet, as is expected by the client,
453
if there is an error evaluating the next row and a continue handler
457
void Protocol::end_partial_result_set(Session *session)
459
net_send_eof(session, session->server_status, 0 /* no warnings, we're inside SP */);
463
bool Protocol::flush()
465
return net_flush(&session->net);
427
470
Send name and type of result to client.
429
472
Sum fields has table name empty and field_name.
431
@param Session Thread data object
432
@param list List of items to send to client
433
@param flag Bit mask with the following functions:
474
@param Session Thread data object
475
@param list List of items to send to client
476
@param flag Bit mask with the following functions:
434
477
- 1 send number of rows
435
478
- 2 send default values
436
479
- 4 don't write eof packet
441
1 Error (Note that in this case the error is not sent to the
484
1 Error (Note that in this case the error is not sent to the
444
bool ClientDrizzleProtocol::sendFields(List<Item> *list)
487
bool Protocol::send_fields(List<Item> *list, uint32_t flags)
446
489
List_iterator_fast<Item> it(*list);
448
491
unsigned char buff[80];
449
492
String tmp((char*) buff,sizeof(buff),&my_charset_bin);
493
Protocol_text prot(session);
494
String *local_packet= prot.storage_packet();
495
const CHARSET_INFO * const session_charset= default_charset_info;
451
unsigned char *row_pos= drizzleclient_net_store_length(buff, list->elements);
452
(void) drizzleclient_net_write(&net, buff, (size_t) (row_pos-buff));
497
if (flags & SEND_NUM_ROWS)
498
{ // Packet with number of elements
499
unsigned char *pos= net_store_length(buff, list->elements);
500
(void) my_net_write(&session->net, buff, (size_t) (pos-buff));
454
503
while ((item=it++))
506
const CHARSET_INFO * const cs= system_charset_info;
458
508
item->make_field(&field);
462
if (store(STRING_WITH_LEN("def")) ||
463
store(field.db_name) ||
464
store(field.table_name) ||
465
store(field.org_table_name) ||
466
store(field.col_name) ||
467
store(field.org_col_name) ||
468
packet.realloc(packet.length()+12))
510
prot.prepare_for_resend();
513
if (prot.store(STRING_WITH_LEN("def"), cs, session_charset) ||
514
prot.store(field.db_name, (uint) strlen(field.db_name),
515
cs, session_charset) ||
516
prot.store(field.table_name, (uint) strlen(field.table_name),
517
cs, session_charset) ||
518
prot.store(field.org_table_name, (uint) strlen(field.org_table_name),
519
cs, session_charset) ||
520
prot.store(field.col_name, (uint) strlen(field.col_name),
521
cs, session_charset) ||
522
prot.store(field.org_col_name, (uint) strlen(field.org_col_name),
523
cs, session_charset) ||
524
local_packet->realloc(local_packet->length()+12))
471
527
/* Store fixed length fields */
472
pos= (char*) packet.ptr()+packet.length();
473
*pos++= 12; // Length of packed fields
475
int2store(pos, field.charsetnr);
476
int4store(pos+2, field.length);
478
if (using_mysql41_protocol)
528
pos= (char*) local_packet->ptr()+local_packet->length();
529
*pos++= 12; // Length of packed fields
530
if (item->collation.collation == &my_charset_bin || session_charset == NULL)
480
/* Switch to MySQL field numbering. */
483
case DRIZZLE_TYPE_LONG:
487
case DRIZZLE_TYPE_DOUBLE:
491
case DRIZZLE_TYPE_NULL:
495
case DRIZZLE_TYPE_TIMESTAMP:
499
case DRIZZLE_TYPE_LONGLONG:
503
case DRIZZLE_TYPE_DATETIME:
507
case DRIZZLE_TYPE_DATE:
511
case DRIZZLE_TYPE_VARCHAR:
515
case DRIZZLE_TYPE_DECIMAL:
519
case DRIZZLE_TYPE_ENUM:
523
case DRIZZLE_TYPE_BLOB:
533
int2store(pos, field.charsetnr);
534
int4store(pos+2, field.length);
530
/* Add one to compensate for tinyint removal from enum. */
531
pos[6]= field.type + 1;
538
/* With conversion */
539
uint32_t max_char_len;
540
int2store(pos, session_charset->number);
542
For TEXT/BLOB columns, field_length describes the maximum data
543
length in bytes. There is no limit to the number of characters
544
that a TEXT column can store, as long as the data fits into
545
the designated space.
546
For the rest of textual columns, field_length is evaluated as
547
char_count * mbmaxlen, where character count is taken from the
548
definition of the column. In other words, the maximum number
549
of characters here is limited by the column definition.
551
max_char_len= field.length / item->collation.collation->mbmaxlen;
552
int4store(pos+2, max_char_len * session_charset->mbmaxlen);
534
555
int2store(pos+7,field.flags);
535
556
pos[9]= (char) field.decimals;
536
pos[10]= 0; // For the future
537
pos[11]= 0; // For the future
557
pos[10]= 0; // For the future
558
pos[11]= 0; // For the future
540
packet.length((uint32_t) (pos - packet.ptr()));
561
local_packet->length((uint) (pos - local_packet->ptr()));
562
if (flags & SEND_DEFAULTS)
563
item->send(&prot, &tmp); // Send default value
565
break; /* purecov: inspected */
546
Mark the end of meta-data result set, and store session->server_status,
547
to show that there is no cursor.
548
Send no warning information, as it will be sent at statement end.
550
writeEOFPacket(session->server_status, session->total_warn_count);
568
if (flags & SEND_EOF)
571
Mark the end of meta-data result set, and store session->server_status,
572
to show that there is no cursor.
573
Send no warning information, as it will be sent at statement end.
575
write_eof_packet(session, &session->net, session->server_status, session->total_warn_count);
577
return(prepare_for_send(list));
554
580
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES),
559
bool ClientDrizzleProtocol::store(Field *from)
563
char buff[MAX_FIELD_WIDTH];
564
String str(buff,sizeof(buff), &my_charset_bin);
568
return netStoreData((const unsigned char *)str.ptr(), str.length());
571
bool ClientDrizzleProtocol::store(void)
581
MYF(0)); /* purecov: inspected */
582
return(1); /* purecov: inspected */
586
bool Protocol::write()
588
return(my_net_write(&session->net, (unsigned char*) packet->ptr(),
594
Send \\0 end terminated string.
596
@param from NULL or \\0 terminated string
599
In most cases one should use store(from, length) instead of this function
607
bool Protocol::store(const char *from, const CHARSET_INFO * const cs)
611
uint32_t length= strlen(from);
612
return store(from, length, cs);
617
Send a set of strings as one long string with ',' in between.
620
bool Protocol::store(I_List<i_string>* str_list)
623
String tmp(buf, sizeof(buf), &my_charset_bin);
625
I_List_iterator<i_string> it(*str_list);
634
if ((len= tmp.length()))
635
len--; // Remove last ','
636
return store((char*) tmp.ptr(), len, tmp.charset());
640
bool Protocol::store(String *str)
642
return store((char*) str->ptr(), str->length(), str->charset());
645
void Protocol::free()
651
/****************************************************************************
652
Functions to handle the simple (default) protocol where everything is
653
This protocol is the one that is used by default between the MySQL server
654
and client when you are not using prepared statements.
656
All data are sent as 'packed-string-length' followed by 'string-data'
657
****************************************************************************/
659
void Protocol_text::prepare_for_resend()
664
bool Protocol_text::store_null()
574
667
buff[0]= (char)251;
575
return packet.append(buff, sizeof(buff), PACKET_BUFFER_EXTRA_ALLOC);
578
bool ClientDrizzleProtocol::store(int32_t from)
581
return netStoreData((unsigned char*) buff,
582
(size_t) (internal::int10_to_str(from, buff, -10) - buff));
585
bool ClientDrizzleProtocol::store(uint32_t from)
588
return netStoreData((unsigned char*) buff,
589
(size_t) (internal::int10_to_str(from, buff, 10) - buff));
592
bool ClientDrizzleProtocol::store(int64_t from)
668
return packet->append(buff, sizeof(buff), PACKET_BUFFER_EXTRA_ALLOC);
673
Auxilary function to convert string to the given character set
674
and store in network buffer.
677
bool Protocol::store_string_aux(const char *from, size_t length,
678
const CHARSET_INFO * const fromcs,
679
const CHARSET_INFO * const tocs)
681
/* 'tocs' is set 0 when client issues SET character_set_results=NULL */
682
if (tocs && !my_charset_same(fromcs, tocs) &&
683
fromcs != &my_charset_bin &&
684
tocs != &my_charset_bin)
686
/* Store with conversion */
687
return net_store_data((unsigned char*) from, length, fromcs, tocs);
689
/* Store without conversion */
690
return net_store_data((unsigned char*) from, length);
694
bool Protocol_text::store(const char *from, size_t length,
695
const CHARSET_INFO * const fromcs,
696
const CHARSET_INFO * const tocs)
698
return store_string_aux(from, length, fromcs, tocs);
702
bool Protocol_text::store(const char *from, size_t length,
703
const CHARSET_INFO * const fromcs)
705
const CHARSET_INFO * const tocs= default_charset_info;
706
return store_string_aux(from, length, fromcs, tocs);
710
bool Protocol_text::store_tiny(int64_t from)
713
return net_store_data((unsigned char*) buff,
714
(size_t) (int10_to_str((int) from, buff, -10) - buff));
718
bool Protocol_text::store_short(int64_t from)
721
return net_store_data((unsigned char*) buff,
722
(size_t) (int10_to_str((int) from, buff, -10) -
727
bool Protocol_text::store_long(int64_t from)
730
return net_store_data((unsigned char*) buff,
731
(size_t) (int10_to_str((long int)from, buff,
732
(from <0)?-10:10)-buff));
736
bool Protocol_text::store_int64_t(int64_t from, bool unsigned_flag)
595
return netStoreData((unsigned char*) buff,
596
(size_t) (internal::int64_t10_to_str(from, buff, -10) - buff));
599
bool ClientDrizzleProtocol::store(uint64_t from)
602
return netStoreData((unsigned char*) buff,
603
(size_t) (internal::int64_t10_to_str(from, buff, 10) - buff));
606
bool ClientDrizzleProtocol::store(double from, uint32_t decimals, String *buffer)
739
return net_store_data((unsigned char*) buff,
740
(size_t) (int64_t10_to_str(from,buff,
741
unsigned_flag ? 10 : -10)-
746
bool Protocol_text::store_decimal(const my_decimal *d)
748
char buff[DECIMAL_MAX_STR_LENGTH];
749
String str(buff, sizeof(buff), &my_charset_bin);
750
(void) my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str);
751
return net_store_data((unsigned char*) str.ptr(), str.length());
755
bool Protocol_text::store(float from, uint32_t decimals, String *buffer)
757
buffer->set_real((double) from, decimals, session->charset());
758
return net_store_data((unsigned char*) buffer->ptr(), buffer->length());
762
bool Protocol_text::store(double from, uint32_t decimals, String *buffer)
608
764
buffer->set_real(from, decimals, session->charset());
609
return netStoreData((unsigned char*) buffer->ptr(), buffer->length());
612
bool ClientDrizzleProtocol::store(const char *from, size_t length)
614
return netStoreData((const unsigned char *)from, length);
617
bool ClientDrizzleProtocol::wasAborted(void)
619
return net.error && net.vio != 0;
622
bool ClientDrizzleProtocol::haveMoreData(void)
624
return drizzleclient_net_more_data(&net);
627
bool ClientDrizzleProtocol::haveError(void)
629
return net.error || net.vio == 0;
632
bool ClientDrizzleProtocol::checkConnection(void)
642
if (drizzleclient_net_peer_addr(&net, ip, &peer_port, NI_MAXHOST))
644
my_error(ER_BAD_HOST_ERROR, MYF(0), session->getSecurityContext().getIp().c_str());
648
session->getSecurityContext().setIp(ip);
650
drizzleclient_net_keepalive(&net, true);
652
uint32_t server_capabilites;
654
/* buff[] needs to big enough to hold the server_version variable */
655
char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH + 64];
657
server_capabilites= CLIENT_BASIC_FLAGS;
659
if (using_mysql41_protocol)
660
server_capabilites|= CLIENT_PROTOCOL_MYSQL41;
663
server_capabilites|= CLIENT_COMPRESS;
664
#endif /* HAVE_COMPRESS */
666
end= buff + strlen(VERSION);
667
if ((end - buff) >= SERVER_VERSION_LENGTH)
668
end= buff + (SERVER_VERSION_LENGTH - 1);
669
memcpy(buff, VERSION, end - buff);
673
int4store((unsigned char*) end, global_thread_id);
676
/* We don't use scramble anymore. */
677
memset(end, 'X', SCRAMBLE_LENGTH_323);
678
end+= SCRAMBLE_LENGTH_323;
679
*end++= 0; /* an empty byte for some reason */
681
int2store(end, server_capabilites);
682
/* write server characteristics: up to 16 bytes allowed */
683
end[2]=(char) default_charset_info->number;
684
int2store(end+3, session->server_status);
685
memset(end+5, 0, 13);
688
/* Write scramble tail. */
689
memset(end, 'X', SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323);
690
end+= (SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323);
691
*end++= 0; /* an empty byte for some reason */
693
/* At this point we write connection message and read reply */
694
if (drizzleclient_net_write_command(&net
695
, (unsigned char) PROTOCOL_VERSION
696
, (unsigned char*) ""
698
, (unsigned char*) buff
699
, (size_t) (end-buff))
700
|| (pkt_len= drizzleclient_net_read(&net)) == packet_error
701
|| pkt_len < MIN_HANDSHAKE_SIZE)
703
my_error(ER_HANDSHAKE_ERROR, MYF(0), session->getSecurityContext().getIp().c_str());
707
if (packet.alloc(buffer_length))
708
return false; /* The error is set by alloc(). */
710
client_capabilities= uint2korr(net.read_pos);
713
client_capabilities|= ((uint32_t) uint2korr(net.read_pos + 2)) << 16;
714
session->max_client_packet_length= uint4korr(net.read_pos + 4);
715
end= (char*) net.read_pos + 32;
718
Disable those bits which are not supported by the server.
719
This is a precautionary measure, if the client lies. See Bug#27944.
721
client_capabilities&= server_capabilites;
723
if (end >= (char*) net.read_pos + pkt_len + 2)
725
my_error(ER_HANDSHAKE_ERROR, MYF(0), session->getSecurityContext().getIp().c_str());
729
net.return_status= &session->server_status;
732
char *passwd= strchr(user, '\0')+1;
733
uint32_t user_len= passwd - user - 1;
737
Old clients send null-terminated string as password; new clients send
738
the size (1 byte) + string (not null-terminated). Hence in case of empty
739
password both send '\0'.
741
This strlen() can't be easily deleted without changing client.
743
Cast *passwd to an unsigned char, so that it doesn't extend the sign for
744
*passwd > 127 and become 2**32-127+ after casting to uint.
746
uint32_t passwd_len= client_capabilities & CLIENT_SECURE_CONNECTION ?
747
(unsigned char)(*passwd++) : strlen(passwd);
748
l_db= client_capabilities & CLIENT_CONNECT_WITH_DB ? l_db + passwd_len + 1 : 0;
750
/* strlen() can't be easily deleted without changing client */
751
uint32_t db_len= l_db ? strlen(l_db) : 0;
753
if (passwd + passwd_len + db_len > (char *) net.read_pos + pkt_len)
755
my_error(ER_HANDSHAKE_ERROR, MYF(0), session->getSecurityContext().getIp().c_str());
759
/* If username starts and ends in "'", chop them off */
760
if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
767
session->getSecurityContext().setUser(user);
769
return session->checkUser(passwd, passwd_len, l_db);
772
bool ClientDrizzleProtocol::netStoreData(const unsigned char *from, size_t length)
774
size_t packet_length= packet.length();
776
The +9 comes from that strings of length longer than 16M require
777
9 bytes to be stored (see drizzleclient_net_store_length).
779
if (packet_length+9+length > packet.alloced_length() &&
780
packet.realloc(packet_length+9+length))
782
unsigned char *to= drizzleclient_net_store_length((unsigned char*) packet.ptr()+packet_length, length);
783
memcpy(to,from,length);
784
packet.length((size_t) (to+length-(unsigned char*) packet.ptr()));
789
Format EOF packet according to the current client and
790
write it to the network output buffer.
793
void ClientDrizzleProtocol::writeEOFPacket(uint32_t server_status,
794
uint32_t total_warn_count)
796
unsigned char buff[5];
798
Don't send warn count during SP execution, as the warn_list
799
is cleared between substatements, and mysqltest gets confused
801
uint32_t tmp= min(total_warn_count, (uint32_t)65535);
802
buff[0]= DRIZZLE_PROTOCOL_NO_MORE_DATA;
803
int2store(buff+1, tmp);
805
The following test should never be true, but it's better to do it
806
because if 'is_fatal_error' is set the server is not going to execute
807
other queries (see the if test in dispatch_command / COM_QUERY)
809
if (session->is_fatal_error)
810
server_status&= ~SERVER_MORE_RESULTS_EXISTS;
811
int2store(buff + 3, server_status);
812
drizzleclient_net_write(&net, buff, 5);
815
static ListenDrizzleProtocol *listen_obj= NULL;
817
static int init(plugin::Context &context)
819
listen_obj= new ListenDrizzleProtocol("drizzle_protocol", false);
820
context.add(listen_obj);
824
static DRIZZLE_SYSVAR_UINT(port, port, PLUGIN_VAR_RQCMDARG,
825
N_("Port number to use for connection or 0 for "
826
"default to, in order of "
827
"preference, drizzle.cnf, $DRIZZLE_TCP_PORT, "
828
"built-in default (4427)."),
829
NULL, NULL, 0, 0, 65535, 0);
830
static DRIZZLE_SYSVAR_UINT(connect_timeout, connect_timeout,
831
PLUGIN_VAR_RQCMDARG, N_("Connect Timeout."),
832
NULL, NULL, 10, 1, 300, 0);
833
static DRIZZLE_SYSVAR_UINT(read_timeout, read_timeout, PLUGIN_VAR_RQCMDARG,
834
N_("Read Timeout."), NULL, NULL, 30, 1, 300, 0);
835
static DRIZZLE_SYSVAR_UINT(write_timeout, write_timeout, PLUGIN_VAR_RQCMDARG,
836
N_("Write Timeout."), NULL, NULL, 60, 1, 300, 0);
837
static DRIZZLE_SYSVAR_UINT(retry_count, retry_count, PLUGIN_VAR_RQCMDARG,
838
N_("Retry Count."), NULL, NULL, 10, 1, 100, 0);
839
static DRIZZLE_SYSVAR_UINT(buffer_length, buffer_length, PLUGIN_VAR_RQCMDARG,
840
N_("Buffer length."), NULL, NULL, 16384, 1024,
842
static DRIZZLE_SYSVAR_STR(bind_address, bind_address, PLUGIN_VAR_READONLY,
843
N_("Address to bind to."), NULL, NULL, NULL);
845
static drizzle_sys_var* sys_variables[]= {
846
DRIZZLE_SYSVAR(port),
847
DRIZZLE_SYSVAR(connect_timeout),
848
DRIZZLE_SYSVAR(read_timeout),
849
DRIZZLE_SYSVAR(write_timeout),
850
DRIZZLE_SYSVAR(retry_count),
851
DRIZZLE_SYSVAR(buffer_length),
852
DRIZZLE_SYSVAR(bind_address),
856
} /* namespace drizzle_protocol */
858
DRIZZLE_PLUGIN(drizzle_protocol::init, drizzle_protocol::sys_variables);
765
return net_store_data((unsigned char*) buffer->ptr(), buffer->length());
769
bool Protocol_text::store(Field *field)
771
if (field->is_null())
773
char buff[MAX_FIELD_WIDTH];
774
String str(buff,sizeof(buff), &my_charset_bin);
775
const CHARSET_INFO * const tocs= default_charset_info;
777
field->val_str(&str);
779
return store_string_aux(str.ptr(), str.length(), str.charset(), tocs);
785
Second_part format ("%06") needs to change when
786
we support 0-6 decimals for time.
789
bool Protocol_text::store(DRIZZLE_TIME *tm)
793
length= sprintf(buff, "%04d-%02d-%02d %02d:%02d:%02d",
801
length+= sprintf(buff+length, ".%06d",
802
(int)tm->second_part);
803
return net_store_data((unsigned char*) buff, length);
807
bool Protocol_text::store_date(DRIZZLE_TIME *tm)
809
char buff[MAX_DATE_STRING_REP_LENGTH];
810
size_t length= my_date_to_str(tm, buff);
811
return net_store_data((unsigned char*) buff, length);
817
Second_part format ("%06") needs to change when
818
we support 0-6 decimals for time.
821
bool Protocol_text::store_time(DRIZZLE_TIME *tm)
825
uint32_t day= (tm->year || tm->month) ? 0 : tm->day;
826
length= sprintf(buff, "%s%02ld:%02d:%02d",
828
(long) day*24L+(long) tm->hour,
832
length+= sprintf(buff+length, ".%06d", (int)tm->second_part);
833
return net_store_data((unsigned char*) buff, length);