~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/protocol.cc

  • Committer: Stewart Smith
  • Date: 2009-03-26 04:18:57 UTC
  • mto: This revision was merged to the branch mainline in revision 966.
  • Revision ID: stewart@flamingspork.com-20090326041857-uiron9bpwzocma2l
fix innodb_autoextend_increment for sparc

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
#include <drizzled/error.h>
24
24
#include <drizzled/sql_state.h>
25
25
#include <libdrizzleclient/pack.h>
26
 
#include <libdrizzleclient/errmsg.h>
27
26
#include <drizzled/protocol.h>
28
27
#include <drizzled/session.h>
29
 
#include <drizzled/data_home.h>
30
 
 
31
 
/*
32
 
  Function called by drizzleclient_net_init() to set some check variables
33
 
*/
34
 
 
35
 
extern "C" {
36
 
  void drizzleclient_net_local_init(NET *net)
37
 
  {
38
 
    net->max_packet= (uint32_t) global_system_variables.net_buffer_length;
39
 
 
40
 
    drizzleclient_net_set_read_timeout(net,
41
 
                            (uint32_t)global_system_variables.net_read_timeout);
42
 
    drizzleclient_net_set_write_timeout(net,
43
 
                           (uint32_t)global_system_variables.net_write_timeout);
44
 
 
45
 
    net->retry_count=  (uint32_t) global_system_variables.net_retry_count;
46
 
    net->max_packet_size= cmax(global_system_variables.net_buffer_length,
47
 
                               global_system_variables.max_allowed_packet);
48
 
  }
49
 
}
50
28
 
51
29
static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
52
 
 
 
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);
53
32
static void write_eof_packet(Session *session, NET *net,
54
33
                             uint32_t server_status, uint32_t total_warn_count);
55
34
 
56
 
bool Protocol::io_ok()
57
 
{
58
 
  return net.vio != 0;
59
 
}
60
 
 
61
 
void Protocol::set_read_timeout(uint32_t timeout)
62
 
{
63
 
  drizzleclient_net_set_read_timeout(&net, timeout);
64
 
}
65
 
 
66
 
void Protocol::set_write_timeout(uint32_t timeout)
67
 
{
68
 
  drizzleclient_net_set_write_timeout(&net, timeout);
69
 
}
70
 
 
71
 
void Protocol::set_retry_count(uint32_t count)
72
 
{
73
 
  net.retry_count=count;
74
 
}
75
 
 
76
 
void Protocol::set_error(char error)
77
 
{
78
 
  net.error= error;
79
 
}
80
 
 
81
 
bool Protocol::have_error(void)
82
 
{
83
 
  return net.error || net.vio == 0;
84
 
}
85
 
 
86
 
bool Protocol::was_aborted(void)
87
 
{
88
 
  return net.error && net.vio != 0;
89
 
}
90
 
 
91
 
bool Protocol::have_more_data(void)
92
 
{
93
 
  return drizzleclient_net_more_data(&net);
94
 
}
95
 
 
96
 
bool Protocol::have_compression(void)
97
 
{
98
 
  return net.compress;
99
 
}
100
 
 
101
 
void Protocol::enable_compression(void)
102
 
{
103
 
  net.compress= true;
104
 
}
105
 
 
106
 
bool Protocol::is_reading(void)
107
 
{
108
 
  return net.reading_or_writing == 1;
109
 
}
110
 
 
111
 
bool Protocol::is_writing(void)
112
 
{
113
 
  return net.reading_or_writing == 2;
114
 
}
115
 
 
116
 
/*
117
 
 * To disable results we set net.vio to 0.
118
 
 */
119
 
 
120
 
void Protocol::disable_results(void)
121
 
{
122
 
  save_vio= net.vio;
123
 
  net.vio= 0;
124
 
}
125
 
 
126
 
void Protocol::enable_results(void)
127
 
{
128
 
  net.vio= save_vio;
129
 
}
130
 
 
131
 
 
132
35
bool Protocol::net_store_data(const unsigned char *from, size_t length)
133
36
{
134
37
  size_t packet_length= packet->length();
204
107
 
205
108
 
206
109
/**
 
110
  Send a error string to client.
 
111
 
 
112
  Design note:
 
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.
 
116
 
 
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.
 
120
*/
 
121
void net_send_error(Session *session, uint32_t sql_errno, const char *err)
 
122
{
 
123
  assert(sql_errno);
 
124
  assert(err && err[0]);
 
125
 
 
126
  /*
 
127
    It's one case when we can push an error even though there
 
128
    is an OK or EOF already.
 
129
  */
 
130
  session->main_da.can_overwrite_status= true;
 
131
 
 
132
  /* Abort multi-result sets */
 
133
  session->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
 
134
 
 
135
  net_send_error_packet(session, sql_errno, err);
 
136
 
 
137
  session->main_da.can_overwrite_status= false;
 
138
}
 
139
 
 
140
/**
207
141
  Return ok to the client.
208
142
 
209
143
  The ok packet has the following structure:
225
159
*/
226
160
 
227
161
static void
228
 
net_send_ok(Session *session, NET *net,
 
162
net_send_ok(Session *session,
229
163
            uint32_t server_status, uint32_t total_warn_count,
230
164
            ha_rows affected_rows, uint64_t id, const char *message)
231
165
{
 
166
  NET *net= &session->net;
232
167
  unsigned char buff[DRIZZLE_ERRMSG_SIZE+10],*pos;
233
168
 
234
 
  if (!net->vio)        // hack for re-parsing queries
 
169
  if (! net->vio)       // hack for re-parsing queries
235
170
  {
236
171
    return;
237
172
  }
251
186
  session->main_da.can_overwrite_status= true;
252
187
 
253
188
  if (message && message[0])
254
 
  {
255
 
    size_t length= strlen(message);
256
 
    pos=drizzleclient_net_store_length(pos,length);
257
 
    memcpy(pos,(unsigned char*) message,length);
258
 
    pos+=length;
259
 
  }
 
189
    pos= net_store_data(pos, (unsigned char*) message, strlen(message));
260
190
  drizzleclient_net_write(net, buff, (size_t) (pos-buff));
261
191
  drizzleclient_net_flush(net);
262
192
 
283
213
*/
284
214
 
285
215
static void
286
 
net_send_eof(Session *session, NET *net, uint32_t server_status, uint32_t total_warn_count)
 
216
net_send_eof(Session *session, uint32_t server_status, uint32_t total_warn_count)
287
217
{
 
218
  NET *net= &session->net;
288
219
  /* Set to true if no active vio, to work well in case of --init-file */
289
220
  if (net->vio != 0)
290
221
  {
324
255
  drizzleclient_net_write(net, buff, 5);
325
256
}
326
257
 
327
 
void Protocol_text::send_error_packet(uint32_t sql_errno, const char *err)
 
258
void net_send_error_packet(Session *session, uint32_t sql_errno, const char *err)
328
259
{
 
260
  NET *net= &session->net;
329
261
  uint32_t length;
330
262
  /*
331
263
    buff[]: sql_errno:2 + ('#':1 + SQLSTATE_LENGTH:5) + DRIZZLE_ERRMSG_SIZE:512
332
264
  */
333
265
  unsigned char buff[2+1+SQLSTATE_LENGTH+DRIZZLE_ERRMSG_SIZE], *pos;
334
266
 
335
 
  if (net.vio == 0)
 
267
  if (net->vio == 0)
336
268
  {
337
269
    return;
338
270
  }
342
274
 
343
275
  /* The first # is to make the protocol backward compatible */
344
276
  buff[2]= '#';
345
 
  pos= (unsigned char*) strcpy((char*) buff+3, drizzle_errno_to_sqlstate(sql_errno));
346
 
  pos+= strlen(drizzle_errno_to_sqlstate(sql_errno));
 
277
  pos= (unsigned char*) strcpy((char*) buff+3, drizzleclient_errno_to_sqlstate(sql_errno));
 
278
  pos+= strlen(drizzleclient_errno_to_sqlstate(sql_errno));
347
279
 
348
280
  char *tmp= strncpy((char*)pos, err, DRIZZLE_ERRMSG_SIZE-1);
349
281
  tmp+= strlen((char*)pos);
351
283
  length= (uint32_t)(tmp-(char*)buff);
352
284
  err= (char*) buff;
353
285
 
354
 
  drizzleclient_net_write_command(&net,(unsigned char) 255, (unsigned char*) "", 0, (unsigned char*) err, length);
 
286
  drizzleclient_net_write_command(net,(unsigned char) 255, (unsigned char*) "", 0, (unsigned char*) err, length);
355
287
  return;
356
288
}
357
289
 
 
290
 
358
291
/**
359
 
  Send a error string to client.
360
 
 
361
 
  Design note:
362
 
  net_printf_error and net_send_error are low-level functions
363
 
  that shall be used only when a new connection is being
364
 
  established or at server startup.
365
 
 
366
 
  For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's
367
 
  critical that every error that can be intercepted is issued in one
368
 
  place only, my_message_sql.
 
292
  Faster drizzleclient_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
 
294
  libmysql.
 
295
 
 
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.
369
300
*/
370
 
void Protocol_text::send_error(uint32_t sql_errno, const char *err)
 
301
 
 
302
static unsigned char *drizzleclient_net_store_length_fast(unsigned char *packet, uint32_t length)
371
303
{
372
 
  assert(sql_errno);
373
 
  assert(err && err[0]);
374
 
 
375
 
  /*
376
 
    It's one case when we can push an error even though there
377
 
    is an OK or EOF already.
378
 
  */
379
 
  session->main_da.can_overwrite_status= true;
380
 
 
381
 
  /* Abort multi-result sets */
382
 
  session->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
383
 
 
384
 
  send_error_packet(sql_errno, err);
385
 
 
386
 
  session->main_da.can_overwrite_status= false;
 
304
  if (length < 251)
 
305
  {
 
306
    *packet=(unsigned char) length;
 
307
    return packet+1;
 
308
  }
 
309
  *packet++=252;
 
310
  int2store(packet,(uint32_t) length);
 
311
 
 
312
  return packet+2;
387
313
}
388
314
 
389
 
 
390
315
/**
391
316
  Send the status of the current statement execution over network.
392
317
 
437
362
          Diagnostics_area::is_sent is set for debugging purposes only.
438
363
*/
439
364
 
440
 
void Protocol::end_statement()
 
365
void drizzleclient_net_end_statement(Session *session)
441
366
{
442
367
  assert(! session->main_da.is_sent);
443
368
 
448
373
  switch (session->main_da.status()) {
449
374
  case Diagnostics_area::DA_ERROR:
450
375
    /* The query failed, send error to log and abort bootstrap. */
451
 
    send_error(session->main_da.sql_errno(),
452
 
               session->main_da.message());
 
376
    net_send_error(session,
 
377
                   session->main_da.sql_errno(),
 
378
                   session->main_da.message());
453
379
    break;
454
380
  case Diagnostics_area::DA_EOF:
455
 
    net_send_eof(session, &net,
 
381
    net_send_eof(session,
456
382
                 session->main_da.server_status(),
457
383
                 session->main_da.total_warn_count());
458
384
    break;
459
385
  case Diagnostics_area::DA_OK:
460
 
    net_send_ok(session, &net,
 
386
    net_send_ok(session,
461
387
                session->main_da.server_status(),
462
388
                session->main_da.total_warn_count(),
463
389
                session->main_da.affected_rows(),
470
396
  default:
471
397
    //TODO: Something is being masked here by commenting this out
472
398
    //  assert(0);
473
 
    net_send_ok(session, &net, session->server_status, session->total_warn_count,
 
399
    net_send_ok(session, session->server_status, session->total_warn_count,
474
400
                0, 0, NULL);
475
401
    break;
476
402
  }
478
404
}
479
405
 
480
406
 
 
407
/****************************************************************************
 
408
  Functions used by the protocol functions (like net_send_ok) to store
 
409
  strings and numbers in the header result packet.
 
410
****************************************************************************/
 
411
 
 
412
/* The following will only be used for short strings < 65K */
 
413
 
 
414
unsigned char *net_store_data(unsigned char *to, const unsigned char *from, size_t length)
 
415
{
 
416
  to=drizzleclient_net_store_length_fast(to,length);
 
417
  memcpy(to,from,length);
 
418
  return to+length;
 
419
}
 
420
 
 
421
unsigned char *net_store_data(unsigned char *to,int32_t from)
 
422
{
 
423
  char buff[20];
 
424
  uint32_t length=(uint32_t) (int10_to_str(from,buff,10)-buff);
 
425
  to=drizzleclient_net_store_length_fast(to,length);
 
426
  memcpy(to,buff,length);
 
427
  return to+length;
 
428
}
 
429
 
 
430
unsigned char *net_store_data(unsigned char *to,int64_t from)
 
431
{
 
432
  char buff[22];
 
433
  uint32_t length=(uint32_t) (int64_t10_to_str(from,buff,10)-buff);
 
434
  to=drizzleclient_net_store_length_fast(to,length);
 
435
  memcpy(to,buff,length);
 
436
  return to+length;
 
437
}
 
438
 
 
439
 
481
440
/*****************************************************************************
482
441
  Default Protocol functions
483
442
*****************************************************************************/
487
446
  session=session_arg;
488
447
  packet= &session->packet;
489
448
  convert= &session->convert_buffer;
490
 
  net.vio= 0;
491
449
}
492
450
 
493
451
 
494
452
bool Protocol::flush()
495
453
{
496
 
  return drizzleclient_net_flush(&net);
 
454
  return drizzleclient_net_flush(&session->net);
497
455
}
498
456
 
499
457
 
521
479
  Item *item;
522
480
  unsigned char buff[80];
523
481
  String tmp((char*) buff,sizeof(buff),&my_charset_bin);
524
 
  String *local_packet= storage_packet();
 
482
  Protocol_text prot(session);
 
483
  String *local_packet= prot.storage_packet();
525
484
  const CHARSET_INFO * const session_charset= default_charset_info;
526
485
 
527
486
  if (flags & SEND_NUM_ROWS)
528
487
  {                             // Packet with number of elements
529
488
    unsigned char *pos= drizzleclient_net_store_length(buff, list->elements);
530
 
    (void) drizzleclient_net_write(&net, buff, (size_t) (pos-buff));
 
489
    (void) drizzleclient_net_write(&session->net, buff, (size_t) (pos-buff));
531
490
  }
532
491
 
533
492
  while ((item=it++))
537
496
    Send_field field;
538
497
    item->make_field(&field);
539
498
 
540
 
    prepare_for_resend();
541
 
 
542
 
 
543
 
    if (store(STRING_WITH_LEN("def"), cs, session_charset) ||
544
 
        store(field.db_name, (uint32_t) strlen(field.db_name),
545
 
                   cs, session_charset) ||
546
 
        store(field.table_name, (uint32_t) strlen(field.table_name),
547
 
                   cs, session_charset) ||
548
 
        store(field.org_table_name, (uint32_t) strlen(field.org_table_name),
549
 
                   cs, session_charset) ||
550
 
        store(field.col_name, (uint32_t) strlen(field.col_name),
551
 
                   cs, session_charset) ||
552
 
        store(field.org_col_name, (uint32_t) strlen(field.org_col_name),
 
499
    prot.prepare_for_resend();
 
500
 
 
501
 
 
502
    if (prot.store(STRING_WITH_LEN("def"), cs, session_charset) ||
 
503
        prot.store(field.db_name, (uint32_t) strlen(field.db_name),
 
504
                   cs, session_charset) ||
 
505
        prot.store(field.table_name, (uint32_t) strlen(field.table_name),
 
506
                   cs, session_charset) ||
 
507
        prot.store(field.org_table_name, (uint32_t) strlen(field.org_table_name),
 
508
                   cs, session_charset) ||
 
509
        prot.store(field.col_name, (uint32_t) strlen(field.col_name),
 
510
                   cs, session_charset) ||
 
511
        prot.store(field.org_col_name, (uint32_t) strlen(field.org_col_name),
553
512
                   cs, session_charset) ||
554
513
        local_packet->realloc(local_packet->length()+12))
555
514
      goto err;
590
549
 
591
550
    local_packet->length((uint32_t) (pos - local_packet->ptr()));
592
551
    if (flags & SEND_DEFAULTS)
593
 
      item->send(this, &tmp);                   // Send default value
594
 
    if (write())
 
552
      item->send(&prot, &tmp);                  // Send default value
 
553
    if (prot.write())
595
554
      break;                                    /* purecov: inspected */
596
555
  }
597
556
 
602
561
      to show that there is no cursor.
603
562
      Send no warning information, as it will be sent at statement end.
604
563
    */
605
 
    write_eof_packet(session, &net, session->server_status, session->total_warn_count);
 
564
    write_eof_packet(session, &session->net, session->server_status, session->total_warn_count);
606
565
  }
607
566
  return(prepare_for_send(list));
608
567
 
615
574
 
616
575
bool Protocol::write()
617
576
{
618
 
  return(drizzleclient_net_write(&net, (unsigned char*) packet->ptr(),
 
577
  return(drizzleclient_net_write(&session->net, (unsigned char*) packet->ptr(),
619
578
                           packet->length()));
620
579
}
621
580
 
686
645
  All data are sent as 'packed-string-length' followed by 'string-data'
687
646
****************************************************************************/
688
647
 
689
 
void Protocol_text::init_random(uint64_t seed1, uint64_t seed2)
690
 
{
691
 
  drizzleclient_randominit(&_rand, seed1, seed2);
692
 
}
693
 
 
694
 
bool Protocol_text::init_file_descriptor(int fd)
695
 
{
696
 
  if (drizzleclient_net_init_sock(&net, fd, 0))
697
 
    return true;
698
 
  return false;
699
 
}
700
 
 
701
 
int Protocol_text::file_descriptor(void)
702
 
{
703
 
  return drizzleclient_net_get_sd(&net);
704
 
}
705
 
 
706
 
bool Protocol_text::authenticate()
707
 
{
708
 
  bool connection_is_valid;
709
 
 
710
 
  /* Use "connect_timeout" value during connection phase */
711
 
  drizzleclient_net_set_read_timeout(&net, connect_timeout);
712
 
  drizzleclient_net_set_write_timeout(&net, connect_timeout);
713
 
 
714
 
  connection_is_valid= _check_connection();
715
 
  end_statement();
716
 
 
717
 
  if (!connection_is_valid)
718
 
    return false;
719
 
 
720
 
  /* Connect completed, set read/write timeouts back to default */
721
 
  drizzleclient_net_set_read_timeout(&net,
722
 
                                     session->variables.net_read_timeout);
723
 
  drizzleclient_net_set_write_timeout(&net,
724
 
                                      session->variables.net_write_timeout);
725
 
  return true;
726
 
}
727
 
 
728
 
bool Protocol_text::read_command(char **l_packet, uint32_t *packet_length)
729
 
{
730
 
  /*
731
 
    This thread will do a blocking read from the client which
732
 
    will be interrupted when the next command is received from
733
 
    the client, the connection is closed or "net_wait_timeout"
734
 
    number of seconds has passed
735
 
  */
736
 
  drizzleclient_net_set_read_timeout(&net,
737
 
                                     session->variables.net_wait_timeout);
738
 
 
739
 
  /*
740
 
    XXX: this code is here only to clear possible errors of init_connect.
741
 
    Consider moving to init_connect() instead.
742
 
  */
743
 
  session->clear_error();                    // Clear error message
744
 
  session->main_da.reset_diagnostics_area();
745
 
 
746
 
  net.pkt_nr=0;
747
 
 
748
 
  *packet_length= drizzleclient_net_read(&net);
749
 
  if (*packet_length == packet_error)
750
 
  {
751
 
    /* Check if we can continue without closing the connection */
752
 
 
753
 
    if(net.last_errno== CR_NET_PACKET_TOO_LARGE)
754
 
      my_error(ER_NET_PACKET_TOO_LARGE, MYF(0));
755
 
    /* Assert is invalid for dirty connection shutdown
756
 
     *     assert(session->is_error());
757
 
     */
758
 
    end_statement();
759
 
 
760
 
    if (net.error != 3)
761
 
      return false;                       // We have to close it.
762
 
 
763
 
    net.error= 0;
764
 
    *packet_length= 0;
765
 
    return true;
766
 
  }
767
 
 
768
 
  *l_packet= (char*) net.read_pos;
769
 
 
770
 
  /*
771
 
    'packet_length' contains length of data, as it was stored in packet
772
 
    header. In case of malformed header, drizzleclient_net_read returns zero.
773
 
    If packet_length is not zero, drizzleclient_net_read ensures that the returned
774
 
    number of bytes was actually read from network.
775
 
    There is also an extra safety measure in drizzleclient_net_read:
776
 
    it sets packet[packet_length]= 0, but only for non-zero packets.
777
 
  */
778
 
 
779
 
  if (*packet_length == 0)                       /* safety */
780
 
  {
781
 
    /* Initialize with COM_SLEEP packet */
782
 
    (*l_packet)[0]= (unsigned char) COM_SLEEP;
783
 
    *packet_length= 1;
784
 
  }
785
 
  /* Do not rely on drizzleclient_net_read, extra safety against programming errors. */
786
 
  (*l_packet)[*packet_length]= '\0';                  /* safety */
787
 
 
788
 
  /* Restore read timeout value */
789
 
  drizzleclient_net_set_read_timeout(&net,
790
 
                                     session->variables.net_read_timeout);
791
 
 
792
 
  return true;
793
 
}
794
 
 
795
 
void Protocol_text::close(void)
796
 
{
797
 
  if (net.vio)
798
 
  { 
799
 
    drizzleclient_net_close(&net);
800
 
    drizzleclient_net_end(&net);
801
 
  }
802
 
}
803
 
 
804
648
void Protocol_text::prepare_for_resend()
805
649
{
806
650
  packet->length(0);
978
822
  return net_store_data((unsigned char*) buff, length);
979
823
}
980
824
 
981
 
bool Protocol_text::_check_connection(void)
982
 
{
983
 
  uint32_t pkt_len= 0;
984
 
  char *end;
985
 
 
986
 
  // TCP/IP connection
987
 
  {
988
 
    char ip[NI_MAXHOST];
989
 
 
990
 
    if (drizzleclient_net_peer_addr(&net, ip, &session->peer_port, NI_MAXHOST))
991
 
    {
992
 
      my_error(ER_BAD_HOST_ERROR, MYF(0), session->security_ctx.ip.c_str());
993
 
      return false;
994
 
    }
995
 
 
996
 
    session->security_ctx.ip.assign(ip);
997
 
  }
998
 
  drizzleclient_net_keepalive(&net, true);
999
 
 
1000
 
  uint32_t server_capabilites;
1001
 
  {
1002
 
    /* buff[] needs to big enough to hold the server_version variable */
1003
 
    char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH + 64];
1004
 
 
1005
 
    server_capabilites= CLIENT_BASIC_FLAGS;
1006
 
 
1007
 
#ifdef HAVE_COMPRESS
1008
 
    server_capabilites|= CLIENT_COMPRESS;
1009
 
#endif /* HAVE_COMPRESS */
1010
 
 
1011
 
    end= buff + strlen(server_version);
1012
 
    if ((end - buff) >= SERVER_VERSION_LENGTH)
1013
 
      end= buff + (SERVER_VERSION_LENGTH - 1);
1014
 
    memcpy(buff, server_version, end - buff);
1015
 
    *end= 0;
1016
 
    end++;
1017
 
 
1018
 
    int4store((unsigned char*) end, thread_id);
1019
 
    end+= 4;
1020
 
    /*
1021
 
      So as _checkConnection is the only entry point to authorization
1022
 
      procedure, scramble is set here. This gives us new scramble for
1023
 
      each handshake.
1024
 
    */
1025
 
    drizzleclient_create_random_string(_scramble, SCRAMBLE_LENGTH, &_rand);
1026
 
    /*
1027
 
      Old clients does not understand long scrambles, but can ignore packet
1028
 
      tail: that's why first part of the scramble is placed here, and second
1029
 
      part at the end of packet.
1030
 
    */
1031
 
    end= strncpy(end, _scramble, SCRAMBLE_LENGTH_323);
1032
 
    end+= SCRAMBLE_LENGTH_323;
1033
 
 
1034
 
    *end++= 0; /* an empty byte for some reason */
1035
 
 
1036
 
    int2store(end, server_capabilites);
1037
 
    /* write server characteristics: up to 16 bytes allowed */
1038
 
    end[2]=(char) default_charset_info->number;
1039
 
    int2store(end+3, session->server_status);
1040
 
    memset(end+5, 0, 13);
1041
 
    end+= 18;
1042
 
    /* write scramble tail */
1043
 
    size_t scramble_len= SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323;
1044
 
    end= strncpy(end, _scramble + SCRAMBLE_LENGTH_323, scramble_len);
1045
 
    end+= scramble_len;
1046
 
 
1047
 
    *end++= 0; /* an empty byte for some reason */
1048
 
 
1049
 
    /* At this point we write connection message and read reply */
1050
 
    if (drizzleclient_net_write_command(&net
1051
 
          , (unsigned char) protocol_version
1052
 
          , (unsigned char*) ""
1053
 
          , 0
1054
 
          , (unsigned char*) buff
1055
 
          , (size_t) (end-buff)) 
1056
 
        ||      (pkt_len= drizzleclient_net_read(&net)) == packet_error 
1057
 
        || pkt_len < MIN_HANDSHAKE_SIZE)
1058
 
    {
1059
 
      my_error(ER_HANDSHAKE_ERROR, MYF(0), session->security_ctx.ip.c_str());
1060
 
      return false;
1061
 
    }
1062
 
  }
1063
 
  if (session->packet.alloc(session->variables.net_buffer_length))
1064
 
    return false; /* The error is set by alloc(). */
1065
 
 
1066
 
  session->client_capabilities= uint2korr(net.read_pos);
1067
 
 
1068
 
 
1069
 
  session->client_capabilities|= ((uint32_t) uint2korr(net.read_pos + 2)) << 16;
1070
 
  session->max_client_packet_length= uint4korr(net.read_pos + 4);
1071
 
  session->update_charset();
1072
 
  end= (char*) net.read_pos + 32;
1073
 
 
1074
 
  /*
1075
 
    Disable those bits which are not supported by the server.
1076
 
    This is a precautionary measure, if the client lies. See Bug#27944.
1077
 
  */
1078
 
  session->client_capabilities&= server_capabilites;
1079
 
 
1080
 
  if (end >= (char*) net.read_pos + pkt_len + 2)
1081
 
  {
1082
 
    my_error(ER_HANDSHAKE_ERROR, MYF(0), session->security_ctx.ip.c_str());
1083
 
    return false;
1084
 
  }
1085
 
 
1086
 
  net.return_status= &session->server_status;
1087
 
 
1088
 
  char *user= end;
1089
 
  char *passwd= strchr(user, '\0')+1;
1090
 
  uint32_t user_len= passwd - user - 1;
1091
 
  char *l_db= passwd;
1092
 
  char db_buff[NAME_LEN + 1];           // buffer to store db in utf8
1093
 
  char user_buff[USERNAME_LENGTH + 1];  // buffer to store user in utf8
1094
 
  uint32_t dummy_errors;
1095
 
 
1096
 
  /*
1097
 
    Old clients send null-terminated string as password; new clients send
1098
 
    the size (1 byte) + string (not null-terminated). Hence in case of empty
1099
 
    password both send '\0'.
1100
 
 
1101
 
    This strlen() can't be easily deleted without changing protocol.
1102
 
 
1103
 
    Cast *passwd to an unsigned char, so that it doesn't extend the sign for
1104
 
    *passwd > 127 and become 2**32-127+ after casting to uint.
1105
 
  */
1106
 
  uint32_t passwd_len= session->client_capabilities & CLIENT_SECURE_CONNECTION ?
1107
 
    (unsigned char)(*passwd++) : strlen(passwd);
1108
 
  l_db= session->client_capabilities & CLIENT_CONNECT_WITH_DB ? l_db + passwd_len + 1 : 0;
1109
 
 
1110
 
  /* strlen() can't be easily deleted without changing protocol */
1111
 
  uint32_t db_len= l_db ? strlen(l_db) : 0;
1112
 
 
1113
 
  if (passwd + passwd_len + db_len > (char *) net.read_pos + pkt_len)
1114
 
  {
1115
 
    my_error(ER_HANDSHAKE_ERROR, MYF(0), session->security_ctx.ip.c_str());
1116
 
    return false;
1117
 
  }
1118
 
 
1119
 
  /* Since 4.1 all database names are stored in utf8 */
1120
 
  if (l_db)
1121
 
  {
1122
 
    db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1,
1123
 
                             system_charset_info,
1124
 
                             l_db, db_len,
1125
 
                             session->charset(), &dummy_errors)]= 0;
1126
 
    l_db= db_buff;
1127
 
  }
1128
 
 
1129
 
  user_buff[user_len= copy_and_convert(user_buff, sizeof(user_buff)-1,
1130
 
                                       system_charset_info, user, user_len,
1131
 
                                       session->charset(), &dummy_errors)]= '\0';
1132
 
  user= user_buff;
1133
 
 
1134
 
  /* If username starts and ends in "'", chop them off */
1135
 
  if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
1136
 
  {
1137
 
    user[user_len-1]= 0;
1138
 
    user++;
1139
 
    user_len-= 2;
1140
 
  }
1141
 
 
1142
 
  session->security_ctx.user.assign(user);
1143
 
 
1144
 
  return session->checkUser(passwd, passwd_len, l_db);
1145
 
}