19
23
Low level functions for storing data to be send to the MySQL client.
20
24
The actual communction is handled by the net_xxx functions in net_serv.cc
22
27
#include <drizzled/server_includes.h>
23
#include <drizzled/drizzled_error_messages.h>
28
#include <drizzled/error.h>
24
29
#include <drizzled/sql_state.h>
30
#include <drizzled/protocol.h>
31
#include <drizzled/session.h>
32
#include <drizzled/data_home.h>
35
#include "oldlibdrizzle.h"
38
Function called by drizzleclient_net_init() to set some check variables
26
41
static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
27
/* Declared non-static only because of the embedded library. */
28
static void net_send_error_packet(THD *thd, uint32_t sql_errno, const char *err);
29
static void write_eof_packet(THD *thd, NET *net,
43
static void write_eof_packet(Session *session, NET *net,
30
44
uint32_t server_status, uint32_t total_warn_count);
32
bool Protocol::net_store_data(const unsigned char *from, size_t length)
34
ulong packet_length=packet->length();
46
bool ProtocolOldLibdrizzle::isConnected()
51
void ProtocolOldLibdrizzle::setReadTimeout(uint32_t timeout)
53
drizzleclient_net_set_read_timeout(&net, timeout);
56
void ProtocolOldLibdrizzle::setWriteTimeout(uint32_t timeout)
58
drizzleclient_net_set_write_timeout(&net, timeout);
61
void ProtocolOldLibdrizzle::setRetryCount(uint32_t count)
63
net.retry_count=count;
66
void ProtocolOldLibdrizzle::setError(char error)
71
bool ProtocolOldLibdrizzle::haveError(void)
73
return net.error || net.vio == 0;
76
bool ProtocolOldLibdrizzle::wasAborted(void)
78
return net.error && net.vio != 0;
81
bool ProtocolOldLibdrizzle::haveMoreData(void)
83
return drizzleclient_net_more_data(&net);
86
void ProtocolOldLibdrizzle::enableCompression(void)
91
bool ProtocolOldLibdrizzle::isReading(void)
93
return net.reading_or_writing == 1;
96
bool ProtocolOldLibdrizzle::isWriting(void)
98
return net.reading_or_writing == 2;
101
bool ProtocolOldLibdrizzle::netStoreData(const unsigned char *from, size_t length)
103
size_t packet_length= packet->length();
36
105
The +9 comes from that strings of length longer than 16M require
37
9 bytes to be stored (see net_store_length).
106
9 bytes to be stored (see drizzleclient_net_store_length).
39
108
if (packet_length+9+length > packet->alloced_length() &&
40
109
packet->realloc(packet_length+9+length))
42
unsigned char *to= net_store_length((unsigned char*) packet->ptr()+packet_length, length);
111
unsigned char *to= drizzleclient_net_store_length((unsigned char*) packet->ptr()+packet_length, length);
43
112
memcpy(to,from,length);
44
packet->length((uint) (to+length-(unsigned char*) packet->ptr()));
52
net_store_data() - extended version with character set conversion.
54
It is optimized for short strings whose length after
55
conversion is garanteed to be less than 251, which accupies
56
exactly one byte to store length. It allows not to use
57
the "convert" member as a temporary buffer, conversion
58
is done directly to the "packet" member.
59
The limit 251 is good enough to optimize send_fields()
60
because column, table, database names fit into this limit.
63
bool Protocol::net_store_data(const unsigned char *from, size_t length,
64
const CHARSET_INFO * const from_cs,
65
const CHARSET_INFO * const to_cs)
67
uint32_t dummy_errors;
68
/* Calculate maxumum possible result length */
69
uint32_t conv_length= to_cs->mbmaxlen * length / from_cs->mbminlen;
70
if (conv_length > 250)
73
For strings with conv_length greater than 250 bytes
74
we don't know how many bytes we will need to store length: one or two,
75
because we don't know result length until conversion is done.
76
For example, when converting from utf8 (mbmaxlen=3) to latin1,
77
conv_length=300 means that the result length can vary between 100 to 300.
78
length=100 needs one byte, length=300 needs to bytes.
80
Thus conversion directly to "packet" is not worthy.
81
Let's use "convert" as a temporary buffer.
83
return (convert->copy((const char*) from, length, from_cs,
84
to_cs, &dummy_errors) ||
85
net_store_data((const unsigned char*) convert->ptr(), convert->length()));
88
ulong packet_length= packet->length();
89
ulong new_length= packet_length + conv_length + 1;
91
if (new_length > packet->alloced_length() && packet->realloc(new_length))
94
char *length_pos= (char*) packet->ptr() + packet_length;
95
char *to= length_pos + 1;
97
to+= copy_and_convert(to, conv_length, to_cs,
98
(const char*) from, length, from_cs, &dummy_errors);
100
net_store_length((unsigned char*) length_pos, to - length_pos - 1);
101
packet->length((uint) (to - packet->ptr()));
107
Send a error string to client.
110
net_printf_error and net_send_error are low-level functions
111
that shall be used only when a new connection is being
112
established or at server startup.
114
For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's
115
critical that every error that can be intercepted is issued in one
116
place only, my_message_sql.
118
void net_send_error(THD *thd, uint32_t sql_errno, const char *err)
121
assert(err && err[0]);
124
It's one case when we can push an error even though there
125
is an OK or EOF already.
127
thd->main_da.can_overwrite_status= true;
129
/* Abort multi-result sets */
130
thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
132
net_send_error_packet(thd, sql_errno, err);
134
thd->main_da.can_overwrite_status= false;
113
packet->length((size_t) (to+length-(unsigned char*) packet->ptr()));
138
119
Return ok to the client.
140
121
The ok packet has the following structure:
142
123
- 0 : Marker (1 byte)
143
- affected_rows : Stored in 1-9 bytes
144
- id : Stored in 1-9 bytes
145
- server_status : Copy of thd->server_status; Can be used by client
124
- affected_rows : Stored in 1-9 bytes
125
- id : Stored in 1-9 bytes
126
- server_status : Copy of session->server_status; Can be used by client
146
127
to check if we are inside an transaction.
147
128
New in 4.0 protocol
148
- warning_count : Stored in 2 bytes; New in 4.1 protocol
149
- message : Stored as packed length (1-9 bytes) + message.
129
- warning_count : Stored in 2 bytes; New in 4.1 protocol
130
- message : Stored as packed length (1-9 bytes) + message.
150
131
Is not stored if no message.
152
@param thd Thread handler
153
@param affected_rows Number of rows changed by statement
154
@param id Auto_increment id for first row (if used)
155
@param message Message to send to the client (Used by mysql_status)
133
@param session Thread handler
134
@param affected_rows Number of rows changed by statement
135
@param id Auto_increment id for first row (if used)
136
@param message Message to send to the client (Used by mysql_status)
159
net_send_ok(THD *thd,
160
uint32_t server_status, uint32_t total_warn_count,
161
ha_rows affected_rows, uint64_t id, const char *message)
139
void ProtocolOldLibdrizzle::sendOK()
164
141
unsigned char buff[DRIZZLE_ERRMSG_SIZE+10],*pos;
142
const char *message= NULL;
166
if (! net->vio) // hack for re-parsing queries
145
if (!net.vio) // hack for re-parsing queries
171
buff[0]=0; // No fields
172
pos=net_store_length(buff+1,affected_rows);
173
pos=net_store_length(pos, id);
175
int2store(pos, server_status);
150
buff[0]=0; // No fields
151
if (session->main_da.status() == Diagnostics_area::DA_OK)
153
pos=drizzleclient_net_store_length(buff+1,session->main_da.affected_rows());
154
pos=drizzleclient_net_store_length(pos, session->main_da.last_insert_id());
155
int2store(pos, session->main_da.server_status());
157
tmp= cmin(session->main_da.total_warn_count(), (uint32_t)65535);
158
message= session->main_da.message();
162
pos=drizzleclient_net_store_length(buff+1,0);
163
pos=drizzleclient_net_store_length(pos, 0);
164
int2store(pos, session->server_status);
166
tmp= cmin(session->total_warn_count, (uint32_t)65535);
178
169
/* We can only return up to 65535 warnings in two bytes */
179
uint32_t tmp= cmin(total_warn_count, (uint)65535);
180
170
int2store(pos, tmp);
183
thd->main_da.can_overwrite_status= true;
173
session->main_da.can_overwrite_status= true;
185
175
if (message && message[0])
186
pos= net_store_data(pos, (unsigned char*) message, strlen(message));
187
my_net_write(net, buff, (size_t) (pos-buff));
177
size_t length= strlen(message);
178
pos=drizzleclient_net_store_length(pos,length);
179
memcpy(pos,(unsigned char*) message,length);
182
drizzleclient_net_write(&net, buff, (size_t) (pos-buff));
183
drizzleclient_net_flush(&net);
190
thd->main_da.can_overwrite_status= false;
185
session->main_da.can_overwrite_status= false;
272
281
/* The first # is to make the protocol backward compatible */
274
pos= (unsigned char*) my_stpcpy((char*) buff+3, drizzle_errno_to_sqlstate(sql_errno));
283
pos= (unsigned char*) strcpy((char*) buff+3, drizzle_errno_to_sqlstate(sql_errno));
284
pos+= strlen(drizzle_errno_to_sqlstate(sql_errno));
276
length= (uint) (strmake((char*) pos, err, DRIZZLE_ERRMSG_SIZE-1) -
286
char *tmp= strncpy((char*)pos, err, DRIZZLE_ERRMSG_SIZE-1);
287
tmp+= strlen((char*)pos);
289
length= (uint32_t)(tmp-(char*)buff);
278
290
err= (char*) buff;
280
net_write_command(net,(unsigned char) 255, (unsigned char*) "", 0, (unsigned char*) err, length);
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
uint32_t is used as agrument type because of MySQL type conventions:
291
- uint32_t for 0..65536
292
- ulong for 0..4294967296
293
- uint64_t for bigger numbers.
296
static unsigned char *net_store_length_fast(unsigned char *packet, uint32_t length)
300
*packet=(unsigned char) 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
unsigned char *net_store_data(unsigned char *to, const unsigned char *from, size_t length)
408
to=net_store_length_fast(to,length);
409
memcpy(to,from,length);
413
unsigned char *net_store_data(unsigned char *to,int32_t from)
416
uint32_t length=(uint) (int10_to_str(from,buff,10)-buff);
417
to=net_store_length_fast(to,length);
418
memcpy(to,buff,length);
422
unsigned char *net_store_data(unsigned char *to,int64_t from)
425
uint32_t 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);
292
drizzleclient_net_write_command(&net,(unsigned char) 255, (unsigned char*) "", 0, (unsigned char*) err, length);
294
session->main_da.can_overwrite_status= false;
298
ProtocolOldLibdrizzle::ProtocolOldLibdrizzle()
304
void ProtocolOldLibdrizzle::setSession(Session *session_arg)
306
session= session_arg;
307
packet= &session->packet;
308
convert= &session->convert_buffer;
464
315
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:
317
@param Session Thread data object
318
@param list List of items to send to client
319
@param flag Bit mask with the following functions:
469
320
- 1 send number of rows
470
321
- 2 send default values
471
322
- 4 don't write eof packet
476
1 Error (Note that in this case the error is not sent to the
327
1 Error (Note that in this case the error is not sent to the
479
bool Protocol::send_fields(List<Item> *list, uint32_t flags)
330
bool ProtocolOldLibdrizzle::sendFields(List<Item> *list, uint32_t flags)
481
332
List_iterator_fast<Item> it(*list);
483
334
unsigned char buff[80];
484
335
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
337
if (flags & SEND_NUM_ROWS)
490
{ // Packet with number of elements
491
unsigned char *pos= net_store_length(buff, list->elements);
492
(void) my_net_write(&thd->net, buff, (size_t) (pos-buff));
338
{ // Packet with number of elements
339
unsigned char *pos= drizzleclient_net_store_length(buff, list->elements);
340
(void) drizzleclient_net_write(&net, buff, (size_t) (pos-buff));
495
343
while ((item=it++))
498
const CHARSET_INFO * const cs= system_charset_info;
499
346
Send_field field;
500
347
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))
351
if (store(STRING_WITH_LEN("def")) ||
352
store(field.db_name) ||
353
store(field.table_name) ||
354
store(field.org_table_name) ||
355
store(field.col_name) ||
356
store(field.org_col_name) ||
357
packet->realloc(packet->length()+12))
519
360
/* 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)
525
int2store(pos, field.charsetnr);
526
int4store(pos+2, field.length);
530
/* With conversion */
531
uint32_t max_char_len;
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);
361
pos= (char*) packet->ptr()+packet->length();
362
*pos++= 12; // Length of packed fields
364
int2store(pos, field.charsetnr);
365
int4store(pos+2, field.length);
546
366
pos[6]= field.type;
547
367
int2store(pos+7,field.flags);
548
368
pos[9]= (char) field.decimals;
549
pos[10]= 0; // For the future
550
pos[11]= 0; // For the future
369
pos[10]= 0; // For the future
370
pos[11]= 0; // For the future
553
local_packet->length((uint) (pos - local_packet->ptr()));
373
packet->length((uint32_t) (pos - packet->ptr()));
554
374
if (flags & SEND_DEFAULTS)
555
item->send(&prot, &tmp); // Send default value
557
break; /* purecov: inspected */
375
item->send(this, &tmp); // Send default value
377
break; /* purecov: inspected */
560
380
if (flags & SEND_EOF)
563
Mark the end of meta-data result set, and store thd->server_status,
383
Mark the end of meta-data result set, and store session->server_status,
564
384
to show that there is no cursor.
565
385
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);
387
write_eof_packet(session, &net, session->server_status, session->total_warn_count);
569
return(prepare_for_send(list));
390
field_count= list->elements;
572
394
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES),
573
MYF(0)); /* purecov: inspected */
574
return(1); /* purecov: inspected */
395
MYF(0)); /* purecov: inspected */
396
return 1; /* purecov: inspected */
578
bool Protocol::write()
400
bool ProtocolOldLibdrizzle::write()
580
return(my_net_write(&thd->net, (unsigned char*) packet->ptr(),
402
return(drizzleclient_net_write(&net, (unsigned char*) packet->ptr(),
581
403
packet->length()));
586
Send \\0 end terminated string.
588
@param from NULL 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
uint32_t 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()
406
void ProtocolOldLibdrizzle::free()
412
void ProtocolOldLibdrizzle::setRandom(uint64_t seed1, uint64_t seed2)
414
drizzleclient_randominit(&rand, seed1, seed2);
417
bool ProtocolOldLibdrizzle::setFileDescriptor(int fd)
419
if (drizzleclient_net_init_sock(&net, fd, 0))
424
int ProtocolOldLibdrizzle::fileDescriptor(void)
426
return drizzleclient_net_get_sd(&net);
429
bool ProtocolOldLibdrizzle::authenticate()
431
bool connection_is_valid;
433
/* Use "connect_timeout" value during connection phase */
434
drizzleclient_net_set_read_timeout(&net, connect_timeout);
435
drizzleclient_net_set_write_timeout(&net, connect_timeout);
437
connection_is_valid= checkConnection();
439
if (connection_is_valid)
443
sendError(session->main_da.sql_errno(), session->main_da.message());
447
/* Connect completed, set read/write timeouts back to default */
448
drizzleclient_net_set_read_timeout(&net,
449
session->variables.net_read_timeout);
450
drizzleclient_net_set_write_timeout(&net,
451
session->variables.net_write_timeout);
455
bool ProtocolOldLibdrizzle::readCommand(char **l_packet, uint32_t *packet_length)
458
This thread will do a blocking read from the client which
459
will be interrupted when the next command is received from
460
the client, the connection is closed or "net_wait_timeout"
461
number of seconds has passed
464
/* We can do this much more efficiently with poll timeouts or watcher thread,
465
disabling for now, which means net_wait_timeout == read_timeout. */
466
drizzleclient_net_set_read_timeout(&net,
467
session->variables.net_wait_timeout);
470
session->clear_error();
471
session->main_da.reset_diagnostics_area();
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());
485
session->protocol->sendOK();
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 ProtocolOldLibdrizzle::close(void)
529
drizzleclient_net_close(&net);
530
drizzleclient_net_end(&net);
534
void ProtocolOldLibdrizzle::forceClose(void)
537
drizzleclient_vio_close(net.vio);
540
void ProtocolOldLibdrizzle::prepareForResend()
642
542
packet->length(0);
645
bool Protocol_text::store_null()
545
bool ProtocolOldLibdrizzle::store(void)
648
548
buff[0]= (char)251;
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((unsigned char*) from, length, fromcs, tocs);
670
/* Store without conversion */
671
return net_store_data((unsigned char*) 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((unsigned char*) 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((unsigned char*) 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((unsigned char*) 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)
553
bool ProtocolOldLibdrizzle::store(const char *from, size_t length)
555
return netStoreData((const unsigned char *)from, length);
559
bool ProtocolOldLibdrizzle::store(int32_t from)
562
return netStoreData((unsigned char*) buff,
563
(size_t) (int10_to_str(from, buff, -10) - buff));
566
bool ProtocolOldLibdrizzle::store(uint32_t from)
569
return netStoreData((unsigned char*) buff,
570
(size_t) (int10_to_str(from, buff, 10) - buff));
573
bool ProtocolOldLibdrizzle::store(int64_t from)
720
return net_store_data((unsigned char*) 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((unsigned char*) 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((unsigned char*) 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((unsigned char*) buffer->ptr(), buffer->length());
750
bool Protocol_text::store(Field *field)
752
if (field->is_null())
576
return netStoreData((unsigned char*) buff,
577
(size_t) (int64_t10_to_str(from, buff, -10) - buff));
580
bool ProtocolOldLibdrizzle::store(uint64_t from)
583
return netStoreData((unsigned char*) buff,
584
(size_t) (int64_t10_to_str(from, buff, 10) - buff));
588
bool ProtocolOldLibdrizzle::store(double from, uint32_t decimals, String *buffer)
590
buffer->set_real(from, decimals, session->charset());
591
return netStoreData((unsigned char*) buffer->ptr(), buffer->length());
595
bool ProtocolOldLibdrizzle::store(Field *from)
754
599
char buff[MAX_FIELD_WIDTH];
755
600
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);
604
return netStoreData((const unsigned char *)str.ptr(), str.length());
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((unsigned char*) 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((unsigned char*) 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
uint32_t 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((unsigned char*) buff, length);
610
Second_part format ("%06") needs to change when
611
we support 0-6 decimals for time.
614
bool ProtocolOldLibdrizzle::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 ProtocolOldLibdrizzle::checkConnection(void)
669
if (drizzleclient_net_peer_addr(&net, ip, &session->peer_port, NI_MAXHOST))
671
my_error(ER_BAD_HOST_ERROR, MYF(0), session->security_ctx.ip.c_str());
675
session->security_ctx.ip.assign(ip);
677
drizzleclient_net_keepalive(&net, true);
679
uint32_t server_capabilites;
681
/* buff[] needs to big enough to hold the server_version variable */
682
char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH + 64];
684
server_capabilites= CLIENT_BASIC_FLAGS;
687
server_capabilites|= CLIENT_COMPRESS;
688
#endif /* HAVE_COMPRESS */
690
end= buff + strlen(server_version);
691
if ((end - buff) >= SERVER_VERSION_LENGTH)
692
end= buff + (SERVER_VERSION_LENGTH - 1);
693
memcpy(buff, server_version, end - buff);
697
int4store((unsigned char*) end, thread_id);
700
So as _checkConnection is the only entry point to authorization
701
procedure, scramble is set here. This gives us new scramble for
704
drizzleclient_create_random_string(scramble, SCRAMBLE_LENGTH, &rand);
706
Old clients does not understand long scrambles, but can ignore packet
707
tail: that's why first part of the scramble is placed here, and second
708
part at the end of packet.
710
end= strncpy(end, scramble, SCRAMBLE_LENGTH_323);
711
end+= SCRAMBLE_LENGTH_323;
713
*end++= 0; /* an empty byte for some reason */
715
int2store(end, server_capabilites);
716
/* write server characteristics: up to 16 bytes allowed */
717
end[2]=(char) default_charset_info->number;
718
int2store(end+3, session->server_status);
719
memset(end+5, 0, 13);
721
/* write scramble tail */
722
size_t scramble_len= SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323;
723
end= strncpy(end, scramble + SCRAMBLE_LENGTH_323, scramble_len);
726
*end++= 0; /* an empty byte for some reason */
728
/* At this point we write connection message and read reply */
729
if (drizzleclient_net_write_command(&net
730
, (unsigned char) protocol_version
731
, (unsigned char*) ""
733
, (unsigned char*) buff
734
, (size_t) (end-buff))
735
|| (pkt_len= drizzleclient_net_read(&net)) == packet_error
736
|| pkt_len < MIN_HANDSHAKE_SIZE)
738
my_error(ER_HANDSHAKE_ERROR, MYF(0), session->security_ctx.ip.c_str());
742
if (session->packet.alloc(session->variables.net_buffer_length))
743
return false; /* The error is set by alloc(). */
745
session->client_capabilities= uint2korr(net.read_pos);
748
session->client_capabilities|= ((uint32_t) uint2korr(net.read_pos + 2)) << 16;
749
session->max_client_packet_length= uint4korr(net.read_pos + 4);
750
session->update_charset();
751
end= (char*) net.read_pos + 32;
754
Disable those bits which are not supported by the server.
755
This is a precautionary measure, if the client lies. See Bug#27944.
757
session->client_capabilities&= server_capabilites;
759
if (end >= (char*) net.read_pos + pkt_len + 2)
761
my_error(ER_HANDSHAKE_ERROR, MYF(0), session->security_ctx.ip.c_str());
765
net.return_status= &session->server_status;
768
char *passwd= strchr(user, '\0')+1;
769
uint32_t user_len= passwd - user - 1;
771
char db_buff[NAME_LEN + 1]; // buffer to store db in utf8
772
char user_buff[USERNAME_LENGTH + 1]; // buffer to store user in utf8
773
uint32_t dummy_errors;
776
Old clients send null-terminated string as password; new clients send
777
the size (1 byte) + string (not null-terminated). Hence in case of empty
778
password both send '\0'.
780
This strlen() can't be easily deleted without changing protocol.
782
Cast *passwd to an unsigned char, so that it doesn't extend the sign for
783
*passwd > 127 and become 2**32-127+ after casting to uint.
785
uint32_t passwd_len= session->client_capabilities & CLIENT_SECURE_CONNECTION ?
786
(unsigned char)(*passwd++) : strlen(passwd);
787
l_db= session->client_capabilities & CLIENT_CONNECT_WITH_DB ? l_db + passwd_len + 1 : 0;
789
/* strlen() can't be easily deleted without changing protocol */
790
uint32_t db_len= l_db ? strlen(l_db) : 0;
792
if (passwd + passwd_len + db_len > (char *) net.read_pos + pkt_len)
794
my_error(ER_HANDSHAKE_ERROR, MYF(0), session->security_ctx.ip.c_str());
798
/* Since 4.1 all database names are stored in utf8 */
801
db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1,
804
session->charset(), &dummy_errors)]= 0;
808
user_buff[user_len= copy_and_convert(user_buff, sizeof(user_buff)-1,
809
system_charset_info, user, user_len,
810
session->charset(), &dummy_errors)]= '\0';
813
/* If username starts and ends in "'", chop them off */
814
if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
821
session->security_ctx.user.assign(user);
823
return session->checkUser(passwd, passwd_len, l_db);
826
static ProtocolFactoryOldLibdrizzle *factory= NULL;
828
static int init(PluginRegistry ®istry)
830
factory= new ProtocolFactoryOldLibdrizzle;
831
registry.add(factory);
835
static int deinit(PluginRegistry ®istry)
839
registry.remove(factory);
845
drizzle_declare_plugin(oldlibdrizzle)
850
"Old libdrizzle Protocol",
852
init, /* Plugin Init */
853
deinit, /* Plugin Deinit */
854
NULL, /* status variables */
855
NULL, /* system variables */
856
NULL /* config options */
858
drizzle_declare_plugin_end;