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
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
22
20
#include <drizzled/server_includes.h>
21
#include <drizzled/gettext.h>
23
22
#include <drizzled/error.h>
23
#include <drizzled/query_id.h>
24
24
#include <drizzled/sql_state.h>
25
#include <libdrizzle/pack.h>
25
#include <drizzled/session.h>
28
#include "oldlibdrizzle.h"
29
#include "libdrizzle.h"
34
using namespace drizzled;
36
#define PROTOCOL_VERSION 10
38
extern uint32_t drizzled_tcp_port;
27
40
static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
28
/* Declared non-static only because of the embedded library. */
29
static void net_send_error_packet(Session *session, uint32_t sql_errno, const char *err);
41
static uint32_t connect_timeout;
42
static uint32_t read_timeout;
43
static uint32_t write_timeout;
44
static uint32_t retry_count;
46
in_port_t ListenOldLibdrizzle::getPort(void) const
48
return (in_port_t) drizzled_tcp_port;
51
plugin::Client *ListenOldLibdrizzle::getClient(int fd)
54
return new (nothrow) ClientOldLibdrizzle(-1);
57
new_fd= acceptTcp(fd);
61
return new (nothrow) ClientOldLibdrizzle(new_fd);
30
64
static void write_eof_packet(Session *session, NET *net,
31
65
uint32_t server_status, uint32_t total_warn_count);
33
bool Protocol::net_store_data(const unsigned char *from, size_t length)
35
ulong packet_length=packet->length();
67
bool ClientOldLibdrizzle::isConnected()
72
void ClientOldLibdrizzle::setError(char error)
77
bool ClientOldLibdrizzle::haveError(void)
79
return net.error || net.vio == 0;
82
bool ClientOldLibdrizzle::wasAborted(void)
84
return net.error && net.vio != 0;
87
bool ClientOldLibdrizzle::haveMoreData(void)
89
return drizzleclient_net_more_data(&net);
92
bool ClientOldLibdrizzle::isReading(void)
94
return net.reading_or_writing == 1;
97
bool ClientOldLibdrizzle::isWriting(void)
99
return net.reading_or_writing == 2;
102
bool ClientOldLibdrizzle::netStoreData(const unsigned char *from, size_t length)
104
size_t packet_length= packet->length();
37
106
The +9 comes from that strings of length longer than 16M require
38
9 bytes to be stored (see net_store_length).
107
9 bytes to be stored (see drizzleclient_net_store_length).
40
109
if (packet_length+9+length > packet->alloced_length() &&
41
110
packet->realloc(packet_length+9+length))
43
unsigned char *to= net_store_length((unsigned char*) packet->ptr()+packet_length, length);
112
unsigned char *to= drizzleclient_net_store_length((unsigned char*) packet->ptr()+packet_length, length);
44
113
memcpy(to,from,length);
45
packet->length((uint) (to+length-(unsigned char*) packet->ptr()));
53
net_store_data() - extended version with character set conversion.
55
It is optimized for short strings whose length after
56
conversion is garanteed to be less than 251, which accupies
57
exactly one byte to store length. It allows not to use
58
the "convert" member as a temporary buffer, conversion
59
is done directly to the "packet" member.
60
The limit 251 is good enough to optimize send_fields()
61
because column, table, database names fit into this limit.
64
bool Protocol::net_store_data(const unsigned char *from, size_t length,
65
const CHARSET_INFO * const from_cs,
66
const CHARSET_INFO * const to_cs)
68
uint32_t dummy_errors;
69
/* Calculate maxumum possible result length */
70
uint32_t conv_length= to_cs->mbmaxlen * length / from_cs->mbminlen;
71
if (conv_length > 250)
74
For strings with conv_length greater than 250 bytes
75
we don't know how many bytes we will need to store length: one or two,
76
because we don't know result length until conversion is done.
77
For example, when converting from utf8 (mbmaxlen=3) to latin1,
78
conv_length=300 means that the result length can vary between 100 to 300.
79
length=100 needs one byte, length=300 needs to bytes.
81
Thus conversion directly to "packet" is not worthy.
82
Let's use "convert" as a temporary buffer.
84
return (convert->copy((const char*) from, length, from_cs,
85
to_cs, &dummy_errors) ||
86
net_store_data((const unsigned char*) convert->ptr(), convert->length()));
89
ulong packet_length= packet->length();
90
ulong new_length= packet_length + conv_length + 1;
92
if (new_length > packet->alloced_length() && packet->realloc(new_length))
95
char *length_pos= (char*) packet->ptr() + packet_length;
96
char *to= length_pos + 1;
98
to+= copy_and_convert(to, conv_length, to_cs,
99
(const char*) from, length, from_cs, &dummy_errors);
101
net_store_length((unsigned char*) length_pos, to - length_pos - 1);
102
packet->length((uint) (to - packet->ptr()));
108
Send a error string to client.
111
net_printf_error and net_send_error are low-level functions
112
that shall be used only when a new connection is being
113
established or at server startup.
115
For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's
116
critical that every error that can be intercepted is issued in one
117
place only, my_message_sql.
119
void net_send_error(Session *session, uint32_t sql_errno, const char *err)
122
assert(err && err[0]);
125
It's one case when we can push an error even though there
126
is an OK or EOF already.
128
session->main_da.can_overwrite_status= true;
130
/* Abort multi-result sets */
131
session->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
133
net_send_error_packet(session, sql_errno, err);
135
session->main_da.can_overwrite_status= false;
114
packet->length((size_t) (to+length-(unsigned char*) packet->ptr()));
139
120
Return ok to the client.
141
122
The ok packet has the following structure:
143
124
- 0 : Marker (1 byte)
144
- affected_rows : Stored in 1-9 bytes
145
- id : Stored in 1-9 bytes
146
- server_status : Copy of session->server_status; Can be used by client
125
- affected_rows : Stored in 1-9 bytes
126
- id : Stored in 1-9 bytes
127
- server_status : Copy of session->server_status; Can be used by client
147
128
to check if we are inside an transaction.
149
- warning_count : Stored in 2 bytes; New in 4.1 protocol
150
- message : Stored as packed length (1-9 bytes) + message.
130
- warning_count : Stored in 2 bytes; New in 4.1 client
131
- message : Stored as packed length (1-9 bytes) + message.
151
132
Is not stored if no message.
153
@param session Thread handler
154
@param affected_rows Number of rows changed by statement
155
@param id Auto_increment id for first row (if used)
156
@param message Message to send to the client (Used by mysql_status)
134
@param session Thread handler
135
@param affected_rows Number of rows changed by statement
136
@param id Auto_increment id for first row (if used)
137
@param message Message to send to the client (Used by mysql_status)
160
net_send_ok(Session *session,
161
uint32_t server_status, uint32_t total_warn_count,
162
ha_rows affected_rows, uint64_t id, const char *message)
140
void ClientOldLibdrizzle::sendOK()
164
NET *net= &session->net;
165
142
unsigned char buff[DRIZZLE_ERRMSG_SIZE+10],*pos;
143
const char *message= NULL;
167
if (! net->vio) // hack for re-parsing queries
146
if (!net.vio) // hack for re-parsing queries
172
buff[0]=0; // No fields
173
pos=net_store_length(buff+1,affected_rows);
174
pos=net_store_length(pos, id);
176
int2store(pos, server_status);
151
buff[0]=0; // No fields
152
if (session->main_da.status() == Diagnostics_area::DA_OK)
154
if (client_capabilities & CLIENT_FOUND_ROWS && session->main_da.found_rows())
155
pos=drizzleclient_net_store_length(buff+1,session->main_da.found_rows());
157
pos=drizzleclient_net_store_length(buff+1,session->main_da.affected_rows());
158
pos=drizzleclient_net_store_length(pos, session->main_da.last_insert_id());
159
int2store(pos, session->main_da.server_status());
161
tmp= min(session->main_da.total_warn_count(), (uint32_t)65535);
162
message= session->main_da.message();
166
pos=drizzleclient_net_store_length(buff+1,0);
167
pos=drizzleclient_net_store_length(pos, 0);
168
int2store(pos, session->server_status);
170
tmp= min(session->total_warn_count, (uint32_t)65535);
179
173
/* We can only return up to 65535 warnings in two bytes */
180
uint32_t tmp= cmin(total_warn_count, (uint)65535);
181
174
int2store(pos, tmp);
184
177
session->main_da.can_overwrite_status= true;
186
179
if (message && message[0])
187
pos= net_store_data(pos, (unsigned char*) message, strlen(message));
188
my_net_write(net, buff, (size_t) (pos-buff));
181
size_t length= strlen(message);
182
pos=drizzleclient_net_store_length(pos,length);
183
memcpy(pos,(unsigned char*) message,length);
186
drizzleclient_net_write(&net, buff, (size_t) (pos-buff));
187
drizzleclient_net_flush(&net);
191
189
session->main_da.can_overwrite_status= false;
270
282
int2store(buff,sql_errno);
273
/* The first # is to make the protocol backward compatible */
285
/* The first # is to make the client backward compatible */
275
pos= (unsigned char*) my_stpcpy((char*) buff+3, drizzle_errno_to_sqlstate(sql_errno));
287
pos= (unsigned char*) strcpy((char*) buff+3, drizzle_errno_to_sqlstate(sql_errno));
288
pos+= strlen(drizzle_errno_to_sqlstate(sql_errno));
277
length= (uint) (strmake((char*) pos, err, DRIZZLE_ERRMSG_SIZE-1) -
290
char *tmp= strncpy((char*)pos, err, DRIZZLE_ERRMSG_SIZE-1);
291
tmp+= strlen((char*)pos);
293
length= (uint32_t)(tmp-(char*)buff);
279
294
err= (char*) buff;
281
net_write_command(net,(unsigned char) 255, (unsigned char*) "", 0, (unsigned char*) err, length);
287
Faster net_store_length when we know that length is less than 65536.
288
We keep a separate version for that range because it's widely used in
291
uint32_t is used as agrument type because of MySQL type conventions:
292
- uint32_t for 0..65536
293
- ulong for 0..4294967296
294
- uint64_t for bigger numbers.
297
static unsigned char *net_store_length_fast(unsigned char *packet, uint32_t length)
301
*packet=(unsigned char) length;
305
int2store(packet,(uint) length);
310
Send the status of the current statement execution over network.
312
@param session in fact, carries two parameters, NET for the transport and
313
Diagnostics_area as the source of status information.
315
In MySQL, there are two types of SQL statements: those that return
316
a result set and those that return status information only.
318
If a statement returns a result set, it consists of 3 parts:
319
- result set meta-data
320
- variable number of result set rows (can be 0)
321
- followed and terminated by EOF or ERROR packet
323
Once the client has seen the meta-data information, it always
324
expects an EOF or ERROR to terminate the result set. If ERROR is
325
received, the result set rows are normally discarded (this is up
326
to the client implementation, libmysql at least does discard them).
327
EOF, on the contrary, means "successfully evaluated the entire
328
result set". Since we don't know how many rows belong to a result
329
set until it's evaluated, EOF/ERROR is the indicator of the end
330
of the row stream. Note, that we can not buffer result set rows
331
on the server -- there may be an arbitrary number of rows. But
332
we do buffer the last packet (EOF/ERROR) in the Diagnostics_area and
333
delay sending it till the very end of execution (here), to be able to
334
change EOF to an ERROR if commit failed or some other error occurred
335
during the last cleanup steps taken after execution.
337
A statement that does not return a result set doesn't send result
338
set meta-data either. Instead it returns one of:
341
Similarly to the EOF/ERROR of the previous statement type, OK/ERROR
342
packet is "buffered" in the diagnostics area and sent to the client
343
in the end of statement.
345
@pre The diagnostics area is assigned or disabled. It can not be empty
346
-- we assume that every SQL statement or COM_* command
347
generates OK, ERROR, or EOF status.
349
@post The status information is encoded to protocol format and sent to the
352
@return We conventionally return void, since the only type of error
353
that can happen here is a NET (transport) error, and that one
354
will become visible when we attempt to read from the NET the
356
Diagnostics_area::is_sent is set for debugging purposes only.
359
void net_end_statement(Session *session)
361
assert(! session->main_da.is_sent);
363
/* Can not be true, but do not take chances in production. */
364
if (session->main_da.is_sent)
296
drizzleclient_net_write_command(&net,(unsigned char) 255, (unsigned char*) "", 0, (unsigned char*) err, length);
298
session->main_da.can_overwrite_status= false;
302
ClientOldLibdrizzle::ClientOldLibdrizzle(int fd)
367
switch (session->main_da.status()) {
368
case Diagnostics_area::DA_ERROR:
369
/* The query failed, send error to log and abort bootstrap. */
370
net_send_error(session,
371
session->main_da.sql_errno(),
372
session->main_da.message());
374
case Diagnostics_area::DA_EOF:
375
net_send_eof(session,
376
session->main_da.server_status(),
377
session->main_da.total_warn_count());
379
case Diagnostics_area::DA_OK:
381
session->main_da.server_status(),
382
session->main_da.total_warn_count(),
383
session->main_da.affected_rows(),
384
session->main_da.last_insert_id(),
385
session->main_da.message());
387
case Diagnostics_area::DA_DISABLED:
389
case Diagnostics_area::DA_EMPTY:
392
net_send_ok(session, session->server_status, session->total_warn_count,
396
session->main_da.is_sent= true;
400
/****************************************************************************
401
Functions used by the protocol functions (like net_send_ok) to store
402
strings and numbers in the header result packet.
403
****************************************************************************/
405
/* The following will only be used for short strings < 65K */
407
unsigned char *net_store_data(unsigned char *to, const unsigned char *from, size_t length)
409
to=net_store_length_fast(to,length);
410
memcpy(to,from,length);
414
unsigned char *net_store_data(unsigned char *to,int32_t from)
417
uint32_t length=(uint) (int10_to_str(from,buff,10)-buff);
418
to=net_store_length_fast(to,length);
419
memcpy(to,buff,length);
423
unsigned char *net_store_data(unsigned char *to,int64_t from)
426
uint32_t length=(uint) (int64_t10_to_str(from,buff,10)-buff);
427
to=net_store_length_fast(to,length);
428
memcpy(to,buff,length);
433
/*****************************************************************************
434
Default Protocol functions
435
*****************************************************************************/
437
void Protocol::init(Session *session_arg)
310
if (drizzleclient_net_init_sock(&net, fd, 0))
313
drizzleclient_net_set_read_timeout(&net, read_timeout);
314
drizzleclient_net_set_write_timeout(&net, write_timeout);
315
net.retry_count=retry_count;
318
ClientOldLibdrizzle::~ClientOldLibdrizzle()
321
drizzleclient_vio_close(net.vio);
324
void ClientOldLibdrizzle::setSession(Session *session_arg)
326
session= session_arg;
440
327
packet= &session->packet;
441
328
convert= &session->convert_buffer;
445
Finish the result set with EOF packet, as is expected by the client,
446
if there is an error evaluating the next row and a continue handler
450
void Protocol::end_partial_result_set(Session *session)
452
net_send_eof(session, session->server_status, 0 /* no warnings, we're inside SP */);
456
bool Protocol::flush()
458
return net_flush(&session->net);
465
336
Sum fields has table name empty and field_name.
467
@param Session Thread data object
468
@param list List of items to send to client
469
@param flag Bit mask with the following functions:
338
@param Session Thread data object
339
@param list List of items to send to client
340
@param flag Bit mask with the following functions:
470
341
- 1 send number of rows
471
342
- 2 send default values
472
343
- 4 don't write eof packet
477
1 Error (Note that in this case the error is not sent to the
348
1 Error (Note that in this case the error is not sent to the
480
bool Protocol::send_fields(List<Item> *list, uint32_t flags)
351
bool ClientOldLibdrizzle::sendFields(List<Item> *list)
482
353
List_iterator_fast<Item> it(*list);
484
355
unsigned char buff[80];
485
356
String tmp((char*) buff,sizeof(buff),&my_charset_bin);
486
Protocol_text prot(session);
487
String *local_packet= prot.storage_packet();
488
const CHARSET_INFO * const session_charset= session->variables.character_set_results;
490
if (flags & SEND_NUM_ROWS)
491
{ // Packet with number of elements
492
unsigned char *pos= net_store_length(buff, list->elements);
493
(void) my_net_write(&session->net, buff, (size_t) (pos-buff));
358
unsigned char *row_pos= drizzleclient_net_store_length(buff, list->elements);
359
(void) drizzleclient_net_write(&net, buff, (size_t) (row_pos-buff));
496
361
while ((item=it++))
499
const CHARSET_INFO * const cs= system_charset_info;
501
365
item->make_field(&field);
503
prot.prepare_for_resend();
506
if (prot.store(STRING_WITH_LEN("def"), cs, session_charset) ||
507
prot.store(field.db_name, (uint) strlen(field.db_name),
508
cs, session_charset) ||
509
prot.store(field.table_name, (uint) strlen(field.table_name),
510
cs, session_charset) ||
511
prot.store(field.org_table_name, (uint) strlen(field.org_table_name),
512
cs, session_charset) ||
513
prot.store(field.col_name, (uint) strlen(field.col_name),
514
cs, session_charset) ||
515
prot.store(field.org_col_name, (uint) strlen(field.org_col_name),
516
cs, session_charset) ||
517
local_packet->realloc(local_packet->length()+12))
369
if (store(STRING_WITH_LEN("def")) ||
370
store(field.db_name) ||
371
store(field.table_name) ||
372
store(field.org_table_name) ||
373
store(field.col_name) ||
374
store(field.org_col_name) ||
375
packet->realloc(packet->length()+12))
520
378
/* Store fixed length fields */
521
pos= (char*) local_packet->ptr()+local_packet->length();
522
*pos++= 12; // Length of packed fields
523
if (item->collation.collation == &my_charset_bin || session_charset == NULL)
526
int2store(pos, field.charsetnr);
527
int4store(pos+2, field.length);
531
/* With conversion */
532
uint32_t max_char_len;
533
int2store(pos, session_charset->number);
535
For TEXT/BLOB columns, field_length describes the maximum data
536
length in bytes. There is no limit to the number of characters
537
that a TEXT column can store, as long as the data fits into
538
the designated space.
539
For the rest of textual columns, field_length is evaluated as
540
char_count * mbmaxlen, where character count is taken from the
541
definition of the column. In other words, the maximum number
542
of characters here is limited by the column definition.
544
max_char_len= field.length / item->collation.collation->mbmaxlen;
545
int4store(pos+2, max_char_len * session_charset->mbmaxlen);
379
pos= (char*) packet->ptr()+packet->length();
380
*pos++= 12; // Length of packed fields
382
int2store(pos, field.charsetnr);
383
int4store(pos+2, field.length);
547
384
pos[6]= field.type;
548
385
int2store(pos+7,field.flags);
549
386
pos[9]= (char) field.decimals;
550
pos[10]= 0; // For the future
551
pos[11]= 0; // For the future
387
pos[10]= 0; // For the future
388
pos[11]= 0; // For the future
554
local_packet->length((uint) (pos - local_packet->ptr()));
555
if (flags & SEND_DEFAULTS)
556
item->send(&prot, &tmp); // Send default value
558
break; /* purecov: inspected */
561
if (flags & SEND_EOF)
564
Mark the end of meta-data result set, and store session->server_status,
565
to show that there is no cursor.
566
Send no warning information, as it will be sent at statement end.
568
write_eof_packet(session, &session->net, session->server_status, session->total_warn_count);
570
return(prepare_for_send(list));
391
packet->length((uint32_t) (pos - packet->ptr()));
397
Mark the end of meta-data result set, and store session->server_status,
398
to show that there is no cursor.
399
Send no warning information, as it will be sent at statement end.
401
write_eof_packet(session, &net, session->server_status,
402
session->total_warn_count);
404
field_count= list->elements;
573
408
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES),
574
MYF(0)); /* purecov: inspected */
575
return(1); /* purecov: inspected */
579
bool Protocol::write()
581
return(my_net_write(&session->net, (unsigned char*) packet->ptr(),
587
Send \\0 end terminated string.
589
@param from NULL or \\0 terminated string
592
In most cases one should use store(from, length) instead of this function
600
bool Protocol::store(const char *from, const CHARSET_INFO * const cs)
604
uint32_t length= strlen(from);
605
return store(from, length, cs);
610
Send a set of strings as one long string with ',' in between.
613
bool Protocol::store(I_List<i_string>* str_list)
616
String tmp(buf, sizeof(buf), &my_charset_bin);
618
I_List_iterator<i_string> it(*str_list);
627
if ((len= tmp.length()))
628
len--; // Remove last ','
629
return store((char*) tmp.ptr(), len, tmp.charset());
633
/****************************************************************************
634
Functions to handle the simple (default) protocol where everything is
635
This protocol is the one that is used by default between the MySQL server
636
and client when you are not using prepared statements.
638
All data are sent as 'packed-string-length' followed by 'string-data'
639
****************************************************************************/
641
void Protocol_text::prepare_for_resend()
414
bool ClientOldLibdrizzle::flush()
418
bool ret= drizzleclient_net_write(&net, (unsigned char*) packet->ptr(),
424
void ClientOldLibdrizzle::free()
429
int ClientOldLibdrizzle::getFileDescriptor(void)
431
return drizzleclient_net_get_sd(&net);
434
bool ClientOldLibdrizzle::authenticate()
436
bool connection_is_valid;
438
/* Use "connect_timeout" value during connection phase */
439
drizzleclient_net_set_read_timeout(&net, connect_timeout);
440
drizzleclient_net_set_write_timeout(&net, connect_timeout);
442
connection_is_valid= checkConnection();
444
if (connection_is_valid)
448
sendError(session->main_da.sql_errno(), session->main_da.message());
452
/* Connect completed, set read/write timeouts back to default */
453
drizzleclient_net_set_read_timeout(&net, read_timeout);
454
drizzleclient_net_set_write_timeout(&net, write_timeout);
458
bool ClientOldLibdrizzle::readCommand(char **l_packet, uint32_t *packet_length)
461
This thread will do a blocking read from the client which
462
will be interrupted when the next command is received from
463
the client, the connection is closed or "net_wait_timeout"
464
number of seconds has passed
467
/* We can do this much more efficiently with poll timeouts or watcher thread,
468
disabling for now, which means net_wait_timeout == read_timeout. */
469
drizzleclient_net_set_read_timeout(&net,
470
session->variables.net_wait_timeout);
475
*packet_length= drizzleclient_net_read(&net);
476
if (*packet_length == packet_error)
478
/* Check if we can continue without closing the connection */
480
if(net.last_errno== CR_NET_PACKET_TOO_LARGE)
481
my_error(ER_NET_PACKET_TOO_LARGE, MYF(0));
482
if (session->main_da.status() == Diagnostics_area::DA_ERROR)
483
sendError(session->main_da.sql_errno(), session->main_da.message());
488
return false; // We have to close it.
495
*l_packet= (char*) net.read_pos;
498
'packet_length' contains length of data, as it was stored in packet
499
header. In case of malformed header, drizzleclient_net_read returns zero.
500
If packet_length is not zero, drizzleclient_net_read ensures that the returned
501
number of bytes was actually read from network.
502
There is also an extra safety measure in drizzleclient_net_read:
503
it sets packet[packet_length]= 0, but only for non-zero packets.
506
if (*packet_length == 0) /* safety */
508
/* Initialize with COM_SLEEP packet */
509
(*l_packet)[0]= (unsigned char) COM_SLEEP;
512
/* Do not rely on drizzleclient_net_read, extra safety against programming errors. */
513
(*l_packet)[*packet_length]= '\0'; /* safety */
516
/* See comment above. */
517
/* Restore read timeout value */
518
drizzleclient_net_set_read_timeout(&net,
519
session->variables.net_read_timeout);
525
void ClientOldLibdrizzle::close(void)
529
drizzleclient_net_close(&net);
530
drizzleclient_net_end(&net);
534
void ClientOldLibdrizzle::forceClose(void)
537
drizzleclient_vio_close(net.vio);
540
void ClientOldLibdrizzle::prepareForResend()
643
542
packet->length(0);
646
bool Protocol_text::store_null()
545
bool ClientOldLibdrizzle::store(void)
649
548
buff[0]= (char)251;
655
Auxilary function to convert string to the given character set
656
and store in network buffer.
659
bool Protocol::store_string_aux(const char *from, size_t length,
660
const CHARSET_INFO * const fromcs,
661
const CHARSET_INFO * const tocs)
663
/* 'tocs' is set 0 when client issues SET character_set_results=NULL */
664
if (tocs && !my_charset_same(fromcs, tocs) &&
665
fromcs != &my_charset_bin &&
666
tocs != &my_charset_bin)
668
/* Store with conversion */
669
return net_store_data((unsigned char*) from, length, fromcs, tocs);
671
/* Store without conversion */
672
return net_store_data((unsigned char*) from, length);
676
bool Protocol_text::store(const char *from, size_t length,
677
const CHARSET_INFO * const fromcs,
678
const CHARSET_INFO * const tocs)
680
return store_string_aux(from, length, fromcs, tocs);
684
bool Protocol_text::store(const char *from, size_t length,
685
const CHARSET_INFO * const fromcs)
687
const CHARSET_INFO * const tocs= this->session->variables.character_set_results;
688
return store_string_aux(from, length, fromcs, tocs);
692
bool Protocol_text::store_tiny(int64_t from)
695
return net_store_data((unsigned char*) buff,
696
(size_t) (int10_to_str((int) from, buff, -10) - buff));
700
bool Protocol_text::store_short(int64_t from)
703
return net_store_data((unsigned char*) buff,
704
(size_t) (int10_to_str((int) from, buff, -10) -
709
bool Protocol_text::store_long(int64_t from)
712
return net_store_data((unsigned char*) buff,
713
(size_t) (int10_to_str((long int)from, buff,
714
(from <0)?-10:10)-buff));
718
bool Protocol_text::store_int64_t(int64_t from, bool unsigned_flag)
553
bool ClientOldLibdrizzle::store(const char *from, size_t length)
555
return netStoreData((const unsigned char *)from, length);
559
bool ClientOldLibdrizzle::store(int32_t from)
562
return netStoreData((unsigned char*) buff,
563
(size_t) (int10_to_str(from, buff, -10) - buff));
566
bool ClientOldLibdrizzle::store(uint32_t from)
569
return netStoreData((unsigned char*) buff,
570
(size_t) (int10_to_str(from, buff, 10) - buff));
573
bool ClientOldLibdrizzle::store(int64_t from)
721
return net_store_data((unsigned char*) buff,
722
(size_t) (int64_t10_to_str(from,buff,
723
unsigned_flag ? 10 : -10)-
728
bool Protocol_text::store_decimal(const my_decimal *d)
730
char buff[DECIMAL_MAX_STR_LENGTH];
731
String str(buff, sizeof(buff), &my_charset_bin);
732
(void) my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str);
733
return net_store_data((unsigned char*) str.ptr(), str.length());
737
bool Protocol_text::store(float from, uint32_t decimals, String *buffer)
739
buffer->set_real((double) from, decimals, session->charset());
740
return net_store_data((unsigned char*) buffer->ptr(), buffer->length());
744
bool Protocol_text::store(double from, uint32_t decimals, String *buffer)
576
return netStoreData((unsigned char*) buff,
577
(size_t) (int64_t10_to_str(from, buff, -10) - buff));
580
bool ClientOldLibdrizzle::store(uint64_t from)
583
return netStoreData((unsigned char*) buff,
584
(size_t) (int64_t10_to_str(from, buff, 10) - buff));
588
bool ClientOldLibdrizzle::store(double from, uint32_t decimals, String *buffer)
746
590
buffer->set_real(from, decimals, session->charset());
747
return net_store_data((unsigned char*) buffer->ptr(), buffer->length());
591
return netStoreData((unsigned char*) buffer->ptr(), buffer->length());
751
bool Protocol_text::store(Field *field)
595
bool ClientOldLibdrizzle::store(Field *from)
753
if (field->is_null())
755
599
char buff[MAX_FIELD_WIDTH];
756
600
String str(buff,sizeof(buff), &my_charset_bin);
757
const CHARSET_INFO * const tocs= this->session->variables.character_set_results;
759
field->val_str(&str);
761
return store_string_aux(str.ptr(), str.length(), str.charset(), tocs);
604
return netStoreData((const unsigned char *)str.ptr(), str.length());
767
Second_part format ("%06") needs to change when
768
we support 0-6 decimals for time.
771
bool Protocol_text::store(DRIZZLE_TIME *tm)
775
length= sprintf(buff, "%04d-%02d-%02d %02d:%02d:%02d",
783
length+= sprintf(buff+length, ".%06d",
784
(int)tm->second_part);
785
return net_store_data((unsigned char*) buff, length);
789
bool Protocol_text::store_date(DRIZZLE_TIME *tm)
791
char buff[MAX_DATE_STRING_REP_LENGTH];
792
size_t length= my_date_to_str(tm, buff);
793
return net_store_data((unsigned char*) buff, length);
799
Second_part format ("%06") needs to change when
800
we support 0-6 decimals for time.
803
bool Protocol_text::store_time(DRIZZLE_TIME *tm)
807
uint32_t day= (tm->year || tm->month) ? 0 : tm->day;
808
length= sprintf(buff, "%s%02ld:%02d:%02d",
810
(long) day*24L+(long) tm->hour,
814
length+= sprintf(buff+length, ".%06d", (int)tm->second_part);
815
return net_store_data((unsigned char*) buff, length);
610
Second_part format ("%06") needs to change when
611
we support 0-6 decimals for time.
614
bool ClientOldLibdrizzle::store(const DRIZZLE_TIME *tm)
620
switch (tm->time_type)
622
case DRIZZLE_TIMESTAMP_DATETIME:
623
length= sprintf(buff, "%04d-%02d-%02d %02d:%02d:%02d",
631
length+= sprintf(buff+length, ".%06d", (int)tm->second_part);
634
case DRIZZLE_TIMESTAMP_DATE:
635
length= sprintf(buff, "%04d-%02d-%02d",
641
case DRIZZLE_TIMESTAMP_TIME:
642
day= (tm->year || tm->month) ? 0 : tm->day;
643
length= sprintf(buff, "%s%02ld:%02d:%02d", tm->neg ? "-" : "",
644
(long) day*24L+(long) tm->hour, (int) tm->minute,
647
length+= sprintf(buff+length, ".%06d", (int)tm->second_part);
650
case DRIZZLE_TIMESTAMP_NONE:
651
case DRIZZLE_TIMESTAMP_ERROR:
657
return netStoreData((unsigned char*) buff, length);
660
bool ClientOldLibdrizzle::checkConnection(void)
665
const Query_id& local_query_id= Query_id::get_query_id();
666
struct rand_struct rand;
673
if (drizzleclient_net_peer_addr(&net, ip, &port, NI_MAXHOST))
675
my_error(ER_BAD_HOST_ERROR, MYF(0), session->security_ctx.ip.c_str());
679
session->security_ctx.ip.assign(ip);
681
drizzleclient_net_keepalive(&net, true);
683
uint32_t server_capabilites;
685
/* buff[] needs to big enough to hold the server_version variable */
686
char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH + 64];
688
server_capabilites= CLIENT_BASIC_FLAGS;
691
server_capabilites|= CLIENT_COMPRESS;
692
#endif /* HAVE_COMPRESS */
694
end= buff + strlen(VERSION);
695
if ((end - buff) >= SERVER_VERSION_LENGTH)
696
end= buff + (SERVER_VERSION_LENGTH - 1);
697
memcpy(buff, VERSION, end - buff);
701
int4store((unsigned char*) end, global_thread_id);
704
So as _checkConnection is the only entry point to authorization
705
procedure, scramble is set here. This gives us new scramble for
709
drizzleclient_randominit(&rand, rnd_tmp + (uint64_t) &session,
710
rnd_tmp + (uint64_t)local_query_id.value());
711
drizzleclient_create_random_string(scramble, SCRAMBLE_LENGTH, &rand);
713
Old clients does not understand long scrambles, but can ignore packet
714
tail: that's why first part of the scramble is placed here, and second
715
part at the end of packet.
717
end= strncpy(end, scramble, SCRAMBLE_LENGTH_323);
718
end+= SCRAMBLE_LENGTH_323;
720
*end++= 0; /* an empty byte for some reason */
722
int2store(end, server_capabilites);
723
/* write server characteristics: up to 16 bytes allowed */
724
end[2]=(char) default_charset_info->number;
725
int2store(end+3, session->server_status);
726
memset(end+5, 0, 13);
728
/* write scramble tail */
729
size_t scramble_len= SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323;
730
end= strncpy(end, scramble + SCRAMBLE_LENGTH_323, scramble_len);
733
*end++= 0; /* an empty byte for some reason */
735
/* At this point we write connection message and read reply */
736
if (drizzleclient_net_write_command(&net
737
, (unsigned char) PROTOCOL_VERSION
738
, (unsigned char*) ""
740
, (unsigned char*) buff
741
, (size_t) (end-buff))
742
|| (pkt_len= drizzleclient_net_read(&net)) == packet_error
743
|| pkt_len < MIN_HANDSHAKE_SIZE)
745
my_error(ER_HANDSHAKE_ERROR, MYF(0), session->security_ctx.ip.c_str());
749
if (session->packet.alloc(session->variables.net_buffer_length))
750
return false; /* The error is set by alloc(). */
752
client_capabilities= uint2korr(net.read_pos);
755
client_capabilities|= ((uint32_t) uint2korr(net.read_pos + 2)) << 16;
756
session->max_client_packet_length= uint4korr(net.read_pos + 4);
757
end= (char*) net.read_pos + 32;
760
Disable those bits which are not supported by the server.
761
This is a precautionary measure, if the client lies. See Bug#27944.
763
client_capabilities&= server_capabilites;
765
if (end >= (char*) net.read_pos + pkt_len + 2)
767
my_error(ER_HANDSHAKE_ERROR, MYF(0), session->security_ctx.ip.c_str());
771
net.return_status= &session->server_status;
774
char *passwd= strchr(user, '\0')+1;
775
uint32_t user_len= passwd - user - 1;
779
Old clients send null-terminated string as password; new clients send
780
the size (1 byte) + string (not null-terminated). Hence in case of empty
781
password both send '\0'.
783
This strlen() can't be easily deleted without changing client.
785
Cast *passwd to an unsigned char, so that it doesn't extend the sign for
786
*passwd > 127 and become 2**32-127+ after casting to uint.
788
uint32_t passwd_len= client_capabilities & CLIENT_SECURE_CONNECTION ?
789
(unsigned char)(*passwd++) : strlen(passwd);
790
l_db= client_capabilities & CLIENT_CONNECT_WITH_DB ? l_db + passwd_len + 1 : 0;
792
/* strlen() can't be easily deleted without changing client */
793
uint32_t db_len= l_db ? strlen(l_db) : 0;
795
if (passwd + passwd_len + db_len > (char *) net.read_pos + pkt_len)
797
my_error(ER_HANDSHAKE_ERROR, MYF(0), session->security_ctx.ip.c_str());
801
/* If username starts and ends in "'", chop them off */
802
if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
809
session->security_ctx.user.assign(user);
811
return session->checkUser(passwd, passwd_len, l_db);
814
static ListenOldLibdrizzle *listen_obj= NULL;
816
static int init(drizzled::plugin::Registry ®istry)
818
listen_obj= new ListenOldLibdrizzle("oldlibdrizzle");
819
registry.add(listen_obj);
823
static int deinit(drizzled::plugin::Registry ®istry)
825
registry.remove(listen_obj);
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);
840
static struct st_mysql_sys_var* system_variables[]= {
841
DRIZZLE_SYSVAR(connect_timeout),
842
DRIZZLE_SYSVAR(read_timeout),
843
DRIZZLE_SYSVAR(write_timeout),
844
DRIZZLE_SYSVAR(retry_count),
848
drizzle_declare_plugin(oldlibdrizzle)
853
"Old libdrizzle Client",
855
init, /* Plugin Init */
856
deinit, /* Plugin Deinit */
857
NULL, /* status variables */
858
system_variables, /* system variables */
859
NULL /* config options */
861
drizzle_declare_plugin_end;