~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/protocol.cc

  • Committer: Brian Aker
  • Date: 2009-04-05 19:53:29 UTC
  • mfrom: (971.3.11 eday-dev)
  • Revision ID: brian@tangent.org-20090405195329-k2vpiwhlri9oaedq
MergeĀ fromĀ Eric.

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>
26
27
#include <drizzled/protocol.h>
27
28
#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
}
28
50
 
29
51
static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
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);
 
52
 
32
53
static void write_eof_packet(Session *session, NET *net,
33
54
                             uint32_t server_status, uint32_t total_warn_count);
34
55
 
 
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
 
35
132
bool Protocol::net_store_data(const unsigned char *from, size_t length)
36
133
{
37
134
  size_t packet_length= packet->length();
107
204
 
108
205
 
109
206
/**
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
 
/**
141
207
  Return ok to the client.
142
208
 
143
209
  The ok packet has the following structure:
159
225
*/
160
226
 
161
227
static void
162
 
net_send_ok(Session *session,
 
228
net_send_ok(Session *session, NET *net,
163
229
            uint32_t server_status, uint32_t total_warn_count,
164
230
            ha_rows affected_rows, uint64_t id, const char *message)
165
231
{
166
 
  NET *net= &session->net;
167
232
  unsigned char buff[DRIZZLE_ERRMSG_SIZE+10],*pos;
168
233
 
169
 
  if (! net->vio)       // hack for re-parsing queries
 
234
  if (!net->vio)        // hack for re-parsing queries
170
235
  {
171
236
    return;
172
237
  }
186
251
  session->main_da.can_overwrite_status= true;
187
252
 
188
253
  if (message && message[0])
189
 
    pos= net_store_data(pos, (unsigned char*) message, strlen(message));
 
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
  }
190
260
  drizzleclient_net_write(net, buff, (size_t) (pos-buff));
191
261
  drizzleclient_net_flush(net);
192
262
 
213
283
*/
214
284
 
215
285
static void
216
 
net_send_eof(Session *session, uint32_t server_status, uint32_t total_warn_count)
 
286
net_send_eof(Session *session, NET *net, uint32_t server_status, uint32_t total_warn_count)
217
287
{
218
 
  NET *net= &session->net;
219
288
  /* Set to true if no active vio, to work well in case of --init-file */
220
289
  if (net->vio != 0)
221
290
  {
255
324
  drizzleclient_net_write(net, buff, 5);
256
325
}
257
326
 
258
 
void net_send_error_packet(Session *session, uint32_t sql_errno, const char *err)
 
327
void Protocol_text::send_error_packet(uint32_t sql_errno, const char *err)
259
328
{
260
 
  NET *net= &session->net;
261
329
  uint32_t length;
262
330
  /*
263
331
    buff[]: sql_errno:2 + ('#':1 + SQLSTATE_LENGTH:5) + DRIZZLE_ERRMSG_SIZE:512
264
332
  */
265
333
  unsigned char buff[2+1+SQLSTATE_LENGTH+DRIZZLE_ERRMSG_SIZE], *pos;
266
334
 
267
 
  if (net->vio == 0)
 
335
  if (net.vio == 0)
268
336
  {
269
337
    return;
270
338
  }
274
342
 
275
343
  /* The first # is to make the protocol backward compatible */
276
344
  buff[2]= '#';
277
 
  pos= (unsigned char*) strcpy((char*) buff+3, drizzleclient_errno_to_sqlstate(sql_errno));
278
 
  pos+= strlen(drizzleclient_errno_to_sqlstate(sql_errno));
 
345
  pos= (unsigned char*) strcpy((char*) buff+3, drizzle_errno_to_sqlstate(sql_errno));
 
346
  pos+= strlen(drizzle_errno_to_sqlstate(sql_errno));
279
347
 
280
348
  char *tmp= strncpy((char*)pos, err, DRIZZLE_ERRMSG_SIZE-1);
281
349
  tmp+= strlen((char*)pos);
283
351
  length= (uint32_t)(tmp-(char*)buff);
284
352
  err= (char*) buff;
285
353
 
286
 
  drizzleclient_net_write_command(net,(unsigned char) 255, (unsigned char*) "", 0, (unsigned char*) err, length);
 
354
  drizzleclient_net_write_command(&net,(unsigned char) 255, (unsigned char*) "", 0, (unsigned char*) err, length);
287
355
  return;
288
356
}
289
357
 
290
 
 
291
358
/**
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.
 
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.
300
369
*/
301
 
 
302
 
static unsigned char *drizzleclient_net_store_length_fast(unsigned char *packet, uint32_t length)
 
370
void Protocol_text::send_error(uint32_t sql_errno, const char *err)
303
371
{
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;
 
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;
313
387
}
314
388
 
 
389
 
315
390
/**
316
391
  Send the status of the current statement execution over network.
317
392
 
362
437
          Diagnostics_area::is_sent is set for debugging purposes only.
363
438
*/
364
439
 
365
 
void drizzleclient_net_end_statement(Session *session)
 
440
void Protocol::end_statement()
366
441
{
367
442
  assert(! session->main_da.is_sent);
368
443
 
373
448
  switch (session->main_da.status()) {
374
449
  case Diagnostics_area::DA_ERROR:
375
450
    /* The query failed, send error to log and abort bootstrap. */
376
 
    net_send_error(session,
377
 
                   session->main_da.sql_errno(),
378
 
                   session->main_da.message());
 
451
    send_error(session->main_da.sql_errno(),
 
452
               session->main_da.message());
379
453
    break;
380
454
  case Diagnostics_area::DA_EOF:
381
 
    net_send_eof(session,
 
455
    net_send_eof(session, &net,
382
456
                 session->main_da.server_status(),
383
457
                 session->main_da.total_warn_count());
384
458
    break;
385
459
  case Diagnostics_area::DA_OK:
386
 
    net_send_ok(session,
 
460
    net_send_ok(session, &net,
387
461
                session->main_da.server_status(),
388
462
                session->main_da.total_warn_count(),
389
463
                session->main_da.affected_rows(),
396
470
  default:
397
471
    //TODO: Something is being masked here by commenting this out
398
472
    //  assert(0);
399
 
    net_send_ok(session, session->server_status, session->total_warn_count,
 
473
    net_send_ok(session, &net, session->server_status, session->total_warn_count,
400
474
                0, 0, NULL);
401
475
    break;
402
476
  }
404
478
}
405
479
 
406
480
 
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
 
 
440
481
/*****************************************************************************
441
482
  Default Protocol functions
442
483
*****************************************************************************/
446
487
  session=session_arg;
447
488
  packet= &session->packet;
448
489
  convert= &session->convert_buffer;
 
490
  net.vio= 0;
449
491
}
450
492
 
451
493
 
452
494
bool Protocol::flush()
453
495
{
454
 
  return drizzleclient_net_flush(&session->net);
 
496
  return drizzleclient_net_flush(&net);
455
497
}
456
498
 
457
499
 
479
521
  Item *item;
480
522
  unsigned char buff[80];
481
523
  String tmp((char*) buff,sizeof(buff),&my_charset_bin);
482
 
  Protocol_text prot(session);
483
 
  String *local_packet= prot.storage_packet();
 
524
  String *local_packet= storage_packet();
484
525
  const CHARSET_INFO * const session_charset= default_charset_info;
485
526
 
486
527
  if (flags & SEND_NUM_ROWS)
487
528
  {                             // Packet with number of elements
488
529
    unsigned char *pos= drizzleclient_net_store_length(buff, list->elements);
489
 
    (void) drizzleclient_net_write(&session->net, buff, (size_t) (pos-buff));
 
530
    (void) drizzleclient_net_write(&net, buff, (size_t) (pos-buff));
490
531
  }
491
532
 
492
533
  while ((item=it++))
496
537
    Send_field field;
497
538
    item->make_field(&field);
498
539
 
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),
 
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),
512
553
                   cs, session_charset) ||
513
554
        local_packet->realloc(local_packet->length()+12))
514
555
      goto err;
549
590
 
550
591
    local_packet->length((uint32_t) (pos - local_packet->ptr()));
551
592
    if (flags & SEND_DEFAULTS)
552
 
      item->send(&prot, &tmp);                  // Send default value
553
 
    if (prot.write())
 
593
      item->send(this, &tmp);                   // Send default value
 
594
    if (write())
554
595
      break;                                    /* purecov: inspected */
555
596
  }
556
597
 
561
602
      to show that there is no cursor.
562
603
      Send no warning information, as it will be sent at statement end.
563
604
    */
564
 
    write_eof_packet(session, &session->net, session->server_status, session->total_warn_count);
 
605
    write_eof_packet(session, &net, session->server_status, session->total_warn_count);
565
606
  }
566
607
  return(prepare_for_send(list));
567
608
 
574
615
 
575
616
bool Protocol::write()
576
617
{
577
 
  return(drizzleclient_net_write(&session->net, (unsigned char*) packet->ptr(),
 
618
  return(drizzleclient_net_write(&net, (unsigned char*) packet->ptr(),
578
619
                           packet->length()));
579
620
}
580
621
 
645
686
  All data are sent as 'packed-string-length' followed by 'string-data'
646
687
****************************************************************************/
647
688
 
 
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
 
648
804
void Protocol_text::prepare_for_resend()
649
805
{
650
806
  packet->length(0);
822
978
  return net_store_data((unsigned char*) buff, length);
823
979
}
824
980
 
 
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
}