~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/oldlibdrizzle/oldlibdrizzle.cc

  • Committer: Monty Taylor
  • Date: 2009-04-14 19:16:51 UTC
  • mto: (997.2.5 mordred)
  • mto: This revision was merged to the branch mainline in revision 994.
  • Revision ID: mordred@inaugust.com-20090414191651-ltbww6hpqks8k7qk
Clarified instructions in README.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
18
 */
19
19
 
20
 
#include "config.h"
21
 
#include <drizzled/gettext.h>
 
20
/**
 
21
  @file
 
22
 
 
23
  Low level functions for storing data to be send to the MySQL client.
 
24
  The actual communction is handled by the net_xxx functions in net_serv.cc
 
25
*/
 
26
 
 
27
#include <drizzled/server_includes.h>
22
28
#include <drizzled/error.h>
23
 
#include <drizzled/query_id.h>
24
29
#include <drizzled/sql_state.h>
 
30
#include <drizzled/protocol.h>
25
31
#include <drizzled/session.h>
26
 
#include "drizzled/internal/my_sys.h"
27
 
#include "drizzled/internal/m_string.h"
28
 
#include <algorithm>
29
 
 
 
32
#include <drizzled/data_home.h>
30
33
#include "pack.h"
31
34
#include "errmsg.h"
32
 
#include "drizzle_protocol.h"
33
 
#include "options.h"
34
 
 
35
 
#define PROTOCOL_VERSION 10
36
 
 
37
 
namespace drizzled
38
 
{
39
 
extern uint32_t global_thread_id;
40
 
}
41
 
 
42
 
using namespace drizzled;
43
 
using namespace std;
44
 
 
45
 
namespace drizzle_protocol
46
 
{
47
 
 
48
 
 
49
 
static const uint32_t DRIZZLE_TCP_PORT= 4427;
 
35
#include "oldlibdrizzle.h"
 
36
 
 
37
/*
 
38
  Function called by drizzleclient_net_init() to set some check variables
 
39
*/
 
40
 
50
41
static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
51
 
static uint32_t port;
52
 
static uint32_t connect_timeout;
53
 
static uint32_t read_timeout;
54
 
static uint32_t write_timeout;
55
 
static uint32_t retry_count;
56
 
static uint32_t buffer_length;
57
 
static char* bind_address;
58
 
 
59
 
const char* ListenDrizzleProtocol::getHost(void) const
60
 
{
61
 
  return bind_address;
62
 
}
63
 
 
64
 
in_port_t ListenDrizzleProtocol::getPort(void) const
65
 
{
66
 
  char *env;
67
 
 
68
 
  if (port == 0)
69
 
  {
70
 
    port= DRIZZLE_TCP_PORT;
71
 
 
72
 
    if ((env = getenv("DRIZZLE_TCP_PORT")))
73
 
      port= (uint32_t) atoi(env);
74
 
 
75
 
    assert(port != 0);
76
 
  }
77
 
 
78
 
  return (in_port_t) port;
79
 
}
80
 
 
81
 
plugin::Client *ListenDrizzleProtocol::getClient(int fd)
82
 
{
83
 
  int new_fd;
84
 
  new_fd= acceptTcp(fd);
85
 
  if (new_fd == -1)
86
 
    return NULL;
87
 
 
88
 
  return new (nothrow) ClientDrizzleProtocol(new_fd, using_mysql41_protocol);
89
 
}
90
 
 
91
 
ClientDrizzleProtocol::ClientDrizzleProtocol(int fd, bool using_mysql41_protocol_arg):
92
 
  using_mysql41_protocol(using_mysql41_protocol_arg)
93
 
{
94
 
  net.vio= 0;
95
 
 
96
 
  if (fd == -1)
97
 
    return;
98
 
 
99
 
  if (drizzleclient_net_init_sock(&net, fd, 0, buffer_length))
100
 
    throw bad_alloc();
101
 
 
102
 
  drizzleclient_net_set_read_timeout(&net, read_timeout);
103
 
  drizzleclient_net_set_write_timeout(&net, write_timeout);
104
 
  net.retry_count=retry_count;
105
 
}
106
 
 
107
 
ClientDrizzleProtocol::~ClientDrizzleProtocol()
108
 
{
109
 
  if (net.vio)
110
 
    drizzleclient_vio_close(net.vio);
111
 
}
112
 
 
113
 
int ClientDrizzleProtocol::getFileDescriptor(void)
114
 
{
115
 
  return drizzleclient_net_get_sd(&net);
116
 
}
117
 
 
118
 
bool ClientDrizzleProtocol::isConnected()
 
42
 
 
43
static void write_eof_packet(Session *session, NET *net,
 
44
                             uint32_t server_status, uint32_t total_warn_count);
 
45
 
 
46
bool ProtocolOldLibdrizzle::isConnected()
119
47
{
120
48
  return net.vio != 0;
121
49
}
122
50
 
123
 
bool ClientDrizzleProtocol::isReading(void)
 
51
void ProtocolOldLibdrizzle::setReadTimeout(uint32_t timeout)
 
52
{
 
53
  drizzleclient_net_set_read_timeout(&net, timeout);
 
54
}
 
55
 
 
56
void ProtocolOldLibdrizzle::setWriteTimeout(uint32_t timeout)
 
57
{
 
58
  drizzleclient_net_set_write_timeout(&net, timeout);
 
59
}
 
60
 
 
61
void ProtocolOldLibdrizzle::setRetryCount(uint32_t count)
 
62
{
 
63
  net.retry_count=count;
 
64
}
 
65
 
 
66
void ProtocolOldLibdrizzle::setError(char error)
 
67
{
 
68
  net.error= error;
 
69
}
 
70
 
 
71
bool ProtocolOldLibdrizzle::haveError(void)
 
72
{
 
73
  return net.error || net.vio == 0;
 
74
}
 
75
 
 
76
bool ProtocolOldLibdrizzle::wasAborted(void)
 
77
{
 
78
  return net.error && net.vio != 0;
 
79
}
 
80
 
 
81
bool ProtocolOldLibdrizzle::haveMoreData(void)
 
82
{
 
83
  return drizzleclient_net_more_data(&net);
 
84
}
 
85
 
 
86
void ProtocolOldLibdrizzle::enableCompression(void)
 
87
{
 
88
  net.compress= true;
 
89
}
 
90
 
 
91
bool ProtocolOldLibdrizzle::isReading(void)
124
92
{
125
93
  return net.reading_or_writing == 1;
126
94
}
127
95
 
128
 
bool ClientDrizzleProtocol::isWriting(void)
 
96
bool ProtocolOldLibdrizzle::isWriting(void)
129
97
{
130
98
  return net.reading_or_writing == 2;
131
99
}
132
100
 
133
 
bool ClientDrizzleProtocol::flush()
134
 
{
135
 
  if (net.vio == NULL)
136
 
    return false;
137
 
  bool ret= drizzleclient_net_write(&net, (unsigned char*) packet.ptr(),
138
 
                           packet.length());
139
 
  packet.length(0);
140
 
  return ret;
141
 
}
142
 
 
143
 
void ClientDrizzleProtocol::close(void)
144
 
{
145
 
  if (net.vio)
146
 
  { 
147
 
    drizzleclient_net_close(&net);
148
 
    drizzleclient_net_end(&net);
149
 
  }
150
 
}
151
 
 
152
 
bool ClientDrizzleProtocol::authenticate()
153
 
{
154
 
  bool connection_is_valid;
155
 
 
156
 
  /* Use "connect_timeout" value during connection phase */
157
 
  drizzleclient_net_set_read_timeout(&net, connect_timeout);
158
 
  drizzleclient_net_set_write_timeout(&net, connect_timeout);
159
 
 
160
 
  connection_is_valid= checkConnection();
161
 
 
162
 
  if (connection_is_valid)
163
 
    sendOK();
164
 
  else
165
 
  {
166
 
    sendError(session->main_da.sql_errno(), session->main_da.message());
167
 
    return false;
168
 
  }
169
 
 
170
 
  /* Connect completed, set read/write timeouts back to default */
171
 
  drizzleclient_net_set_read_timeout(&net, read_timeout);
172
 
  drizzleclient_net_set_write_timeout(&net, write_timeout);
173
 
  return true;
174
 
}
175
 
 
176
 
bool ClientDrizzleProtocol::readCommand(char **l_packet, uint32_t *packet_length)
177
 
{
178
 
  /*
179
 
    This thread will do a blocking read from the client which
180
 
    will be interrupted when the next command is received from
181
 
    the client, the connection is closed or "net_wait_timeout"
182
 
    number of seconds has passed
183
 
  */
184
 
#ifdef NEVER
185
 
  /* We can do this much more efficiently with poll timeouts or watcher thread,
186
 
     disabling for now, which means net_wait_timeout == read_timeout. */
187
 
  drizzleclient_net_set_read_timeout(&net,
188
 
                                     session->variables.net_wait_timeout);
189
 
#endif
190
 
 
191
 
  net.pkt_nr=0;
192
 
 
193
 
  *packet_length= drizzleclient_net_read(&net);
194
 
  if (*packet_length == packet_error)
195
 
  {
196
 
    /* Check if we can continue without closing the connection */
197
 
 
198
 
    if(net.last_errno== CR_NET_PACKET_TOO_LARGE)
199
 
      my_error(ER_NET_PACKET_TOO_LARGE, MYF(0));
200
 
    if (session->main_da.status() == Diagnostics_area::DA_ERROR)
201
 
      sendError(session->main_da.sql_errno(), session->main_da.message());
202
 
    else
203
 
      sendOK();
204
 
 
205
 
    if (net.error != 3)
206
 
      return false;                       // We have to close it.
207
 
 
208
 
    net.error= 0;
209
 
    *packet_length= 0;
210
 
    return true;
211
 
  }
212
 
 
213
 
  *l_packet= (char*) net.read_pos;
214
 
 
215
 
  /*
216
 
    'packet_length' contains length of data, as it was stored in packet
217
 
    header. In case of malformed header, drizzleclient_net_read returns zero.
218
 
    If packet_length is not zero, drizzleclient_net_read ensures that the returned
219
 
    number of bytes was actually read from network.
220
 
    There is also an extra safety measure in drizzleclient_net_read:
221
 
    it sets packet[packet_length]= 0, but only for non-zero packets.
222
 
  */
223
 
 
224
 
  if (*packet_length == 0)                       /* safety */
225
 
  {
226
 
    /* Initialize with COM_SLEEP packet */
227
 
    (*l_packet)[0]= (unsigned char) COM_SLEEP;
228
 
    *packet_length= 1;
229
 
  }
230
 
  else if (using_mysql41_protocol)
231
 
  {
232
 
    /* Map from MySQL commands to Drizzle commands. */
233
 
    switch ((int)(*l_packet)[0])
234
 
    {
235
 
    case 0: /* SLEEP */
236
 
    case 1: /* QUIT */
237
 
    case 2: /* INIT_DB */
238
 
    case 3: /* QUERY */
239
 
      break;
240
 
 
241
 
    case 8: /* SHUTDOWN */
242
 
      (*l_packet)[0]= (unsigned char) COM_SHUTDOWN;
243
 
      break;
244
 
 
245
 
    case 14: /* PING */
246
 
      (*l_packet)[0]= (unsigned char) COM_SHUTDOWN;
247
 
      break;
248
 
 
249
 
 
250
 
    default:
251
 
      /* Just drop connection for MySQL commands we don't support. */
252
 
      (*l_packet)[0]= (unsigned char) COM_QUIT;
253
 
      *packet_length= 1;
254
 
      break;
255
 
    }
256
 
  }
257
 
 
258
 
  /* Do not rely on drizzleclient_net_read, extra safety against programming errors. */
259
 
  (*l_packet)[*packet_length]= '\0';                  /* safety */
260
 
 
261
 
#ifdef NEVER
262
 
  /* See comment above. */
263
 
  /* Restore read timeout value */
264
 
  drizzleclient_net_set_read_timeout(&net,
265
 
                                     session->variables.net_read_timeout);
266
 
#endif
267
 
 
268
 
  return true;
269
 
}
 
101
bool ProtocolOldLibdrizzle::netStoreData(const unsigned char *from, size_t length)
 
102
{
 
103
  size_t packet_length= packet->length();
 
104
  /*
 
105
     The +9 comes from that strings of length longer than 16M require
 
106
     9 bytes to be stored (see drizzleclient_net_store_length).
 
107
  */
 
108
  if (packet_length+9+length > packet->alloced_length() &&
 
109
      packet->realloc(packet_length+9+length))
 
110
    return 1;
 
111
  unsigned char *to= drizzleclient_net_store_length((unsigned char*) packet->ptr()+packet_length, length);
 
112
  memcpy(to,from,length);
 
113
  packet->length((size_t) (to+length-(unsigned char*) packet->ptr()));
 
114
  return 0;
 
115
}
 
116
 
 
117
 
 
118
/*
 
119
  netStoreData() - extended version with character set conversion.
 
120
 
 
121
  It is optimized for short strings whose length after
 
122
  conversion is garanteed to be less than 251, which accupies
 
123
  exactly one byte to store length. It allows not to use
 
124
  the "convert" member as a temporary buffer, conversion
 
125
  is done directly to the "packet" member.
 
126
  The limit 251 is good enough to optimize send_fields()
 
127
  because column, table, database names fit into this limit.
 
128
*/
 
129
 
 
130
bool ProtocolOldLibdrizzle::netStoreData(const unsigned char *from, size_t length,
 
131
                              const CHARSET_INFO * const from_cs,
 
132
                              const CHARSET_INFO * const to_cs)
 
133
{
 
134
  uint32_t dummy_errors;
 
135
  /* Calculate maxumum possible result length */
 
136
  uint32_t conv_length= to_cs->mbmaxlen * length / from_cs->mbminlen;
 
137
  if (conv_length > 250)
 
138
  {
 
139
    /*
 
140
      For strings with conv_length greater than 250 bytes
 
141
      we don't know how many bytes we will need to store length: one or two,
 
142
      because we don't know result length until conversion is done.
 
143
      For example, when converting from utf8 (mbmaxlen=3) to latin1,
 
144
      conv_length=300 means that the result length can vary between 100 to 300.
 
145
      length=100 needs one byte, length=300 needs to bytes.
 
146
 
 
147
      Thus conversion directly to "packet" is not worthy.
 
148
      Let's use "convert" as a temporary buffer.
 
149
    */
 
150
    return (convert->copy((const char*) from, length, from_cs,
 
151
                          to_cs, &dummy_errors) ||
 
152
            netStoreData((const unsigned char*) convert->ptr(), convert->length()));
 
153
  }
 
154
 
 
155
  size_t packet_length= packet->length();
 
156
  size_t new_length= packet_length + conv_length + 1;
 
157
 
 
158
  if (new_length > packet->alloced_length() && packet->realloc(new_length))
 
159
    return 1;
 
160
 
 
161
  char *length_pos= (char*) packet->ptr() + packet_length;
 
162
  char *to= length_pos + 1;
 
163
 
 
164
  to+= copy_and_convert(to, conv_length, to_cs,
 
165
                        (const char*) from, length, from_cs, &dummy_errors);
 
166
 
 
167
  drizzleclient_net_store_length((unsigned char*) length_pos, to - length_pos - 1);
 
168
  packet->length((uint32_t) (to - packet->ptr()));
 
169
  return 0;
 
170
}
 
171
 
270
172
 
271
173
/**
272
174
  Return ok to the client.
278
180
  - id        : Stored in 1-9 bytes
279
181
  - server_status    : Copy of session->server_status;  Can be used by client
280
182
  to check if we are inside an transaction.
281
 
  New in 4.0 client
282
 
  - warning_count    : Stored in 2 bytes; New in 4.1 client
 
183
  New in 4.0 protocol
 
184
  - warning_count    : Stored in 2 bytes; New in 4.1 protocol
283
185
  - message        : Stored as packed length (1-9 bytes) + message.
284
186
  Is not stored if no message.
285
187
 
289
191
  @param message       Message to send to the client (Used by mysql_status)
290
192
*/
291
193
 
292
 
void ClientDrizzleProtocol::sendOK()
 
194
void ProtocolOldLibdrizzle::sendOK()
293
195
{
294
196
  unsigned char buff[DRIZZLE_ERRMSG_SIZE+10],*pos;
295
197
  const char *message= NULL;
303
205
  buff[0]=0;                    // No fields
304
206
  if (session->main_da.status() == Diagnostics_area::DA_OK)
305
207
  {
306
 
    if (client_capabilities & CLIENT_FOUND_ROWS && session->main_da.found_rows())
307
 
      pos=drizzleclient_net_store_length(buff+1,session->main_da.found_rows());
308
 
    else
309
 
      pos=drizzleclient_net_store_length(buff+1,session->main_da.affected_rows());
 
208
    pos=drizzleclient_net_store_length(buff+1,session->main_da.affected_rows());
310
209
    pos=drizzleclient_net_store_length(pos, session->main_da.last_insert_id());
311
210
    int2store(pos, session->main_da.server_status());
312
211
    pos+=2;
313
 
    tmp= min(session->main_da.total_warn_count(), (uint32_t)65535);
 
212
    tmp= cmin(session->main_da.total_warn_count(), (uint32_t)65535);
314
213
    message= session->main_da.message();
315
214
  }
316
215
  else
319
218
    pos=drizzleclient_net_store_length(pos, 0);
320
219
    int2store(pos, session->server_status);
321
220
    pos+=2;
322
 
    tmp= min(session->total_warn_count, (uint32_t)65535);
 
221
    tmp= cmin(session->total_warn_count, (uint32_t)65535);
323
222
  }
324
223
 
325
224
  /* We can only return up to 65535 warnings in two bytes */
347
246
  The eof packet has the following structure:
348
247
 
349
248
  - 254    (DRIZZLE_PROTOCOL_NO_MORE_DATA)    : Marker (1 byte)
350
 
  - warning_count    : Stored in 2 bytes; New in 4.1 client
 
249
  - warning_count    : Stored in 2 bytes; New in 4.1 protocol
351
250
  - status_flag    : Stored in 2 bytes;
352
251
  For flags like SERVER_MORE_RESULTS_EXISTS.
353
252
 
356
255
  client.
357
256
*/
358
257
 
359
 
void ClientDrizzleProtocol::sendEOF()
 
258
void ProtocolOldLibdrizzle::sendEOF()
360
259
{
361
260
  /* Set to true if no active vio, to work well in case of --init-file */
362
261
  if (net.vio != 0)
363
262
  {
364
263
    session->main_da.can_overwrite_status= true;
365
 
    writeEOFPacket(session->main_da.server_status(),
366
 
                   session->main_da.total_warn_count());
 
264
    write_eof_packet(session, &net, session->main_da.server_status(),
 
265
                     session->main_da.total_warn_count());
367
266
    drizzleclient_net_flush(&net);
368
267
    session->main_da.can_overwrite_status= false;
369
268
  }
370
 
  packet.shrink(buffer_length);
371
 
}
372
 
 
373
 
 
374
 
void ClientDrizzleProtocol::sendError(uint32_t sql_errno, const char *err)
 
269
}
 
270
 
 
271
 
 
272
/**
 
273
  Format EOF packet according to the current protocol and
 
274
  write it to the network output buffer.
 
275
*/
 
276
 
 
277
static void write_eof_packet(Session *session, NET *net,
 
278
                             uint32_t server_status,
 
279
                             uint32_t total_warn_count)
 
280
{
 
281
  unsigned char buff[5];
 
282
  /*
 
283
    Don't send warn count during SP execution, as the warn_list
 
284
    is cleared between substatements, and mysqltest gets confused
 
285
  */
 
286
  uint32_t tmp= cmin(total_warn_count, (uint32_t)65535);
 
287
  buff[0]= DRIZZLE_PROTOCOL_NO_MORE_DATA;
 
288
  int2store(buff+1, tmp);
 
289
  /*
 
290
    The following test should never be true, but it's better to do it
 
291
    because if 'is_fatal_error' is set the server is not going to execute
 
292
    other queries (see the if test in dispatch_command / COM_QUERY)
 
293
  */
 
294
  if (session->is_fatal_error)
 
295
    server_status&= ~SERVER_MORE_RESULTS_EXISTS;
 
296
  int2store(buff + 3, server_status);
 
297
  drizzleclient_net_write(net, buff, 5);
 
298
}
 
299
 
 
300
void ProtocolOldLibdrizzle::sendError(uint32_t sql_errno, const char *err)
375
301
{
376
302
  uint32_t length;
377
303
  /*
407
333
  int2store(buff,sql_errno);
408
334
  pos= buff+2;
409
335
 
410
 
  /* The first # is to make the client backward compatible */
 
336
  /* The first # is to make the protocol backward compatible */
411
337
  buff[2]= '#';
412
338
  pos= (unsigned char*) strcpy((char*) buff+3, drizzle_errno_to_sqlstate(sql_errno));
413
339
  pos+= strlen(drizzle_errno_to_sqlstate(sql_errno));
423
349
  session->main_da.can_overwrite_status= false;
424
350
}
425
351
 
 
352
 
 
353
ProtocolOldLibdrizzle::ProtocolOldLibdrizzle()
 
354
{
 
355
  scramble[0]= 0;
 
356
  net.vio= 0;
 
357
}
 
358
 
 
359
void ProtocolOldLibdrizzle::setSession(Session *session_arg)
 
360
{
 
361
  session= session_arg;
 
362
  packet= &session->packet;
 
363
  convert= &session->convert_buffer;
 
364
}
 
365
 
 
366
 
426
367
/**
427
368
  Send name and type of result to client.
428
369
 
441
382
    1    Error  (Note that in this case the error is not sent to the
442
383
    client)
443
384
*/
444
 
bool ClientDrizzleProtocol::sendFields(List<Item> *list)
 
385
bool ProtocolOldLibdrizzle::sendFields(List<Item> *list, uint32_t flags)
445
386
{
446
387
  List_iterator_fast<Item> it(*list);
447
388
  Item *item;
448
389
  unsigned char buff[80];
449
390
  String tmp((char*) buff,sizeof(buff),&my_charset_bin);
450
391
 
451
 
  unsigned char *row_pos= drizzleclient_net_store_length(buff, list->elements);
452
 
  (void) drizzleclient_net_write(&net, buff, (size_t) (row_pos-buff));
 
392
  if (flags & SEND_NUM_ROWS)
 
393
  {                // Packet with number of elements
 
394
    unsigned char *pos= drizzleclient_net_store_length(buff, list->elements);
 
395
    (void) drizzleclient_net_write(&net, buff, (size_t) (pos-buff));
 
396
  }
453
397
 
454
398
  while ((item=it++))
455
399
  {
456
400
    char *pos;
457
 
    SendField field;
 
401
    const CHARSET_INFO * const cs= system_charset_info;
 
402
    Send_field field;
458
403
    item->make_field(&field);
459
404
 
460
 
    packet.length(0);
 
405
    prepareForResend();
461
406
 
462
 
    if (store(STRING_WITH_LEN("def")) ||
463
 
        store(field.db_name) ||
464
 
        store(field.table_name) ||
465
 
        store(field.org_table_name) ||
466
 
        store(field.col_name) ||
467
 
        store(field.org_col_name) ||
468
 
        packet.realloc(packet.length()+12))
 
407
    if (store(STRING_WITH_LEN("def"), cs) ||
 
408
        store(field.db_name, cs) ||
 
409
        store(field.table_name, cs) ||
 
410
        store(field.org_table_name, cs) ||
 
411
        store(field.col_name, cs) ||
 
412
        store(field.org_col_name, cs) ||
 
413
        packet->realloc(packet->length()+12))
469
414
      goto err;
470
415
 
471
416
    /* Store fixed length fields */
472
 
    pos= (char*) packet.ptr()+packet.length();
 
417
    pos= (char*) packet->ptr()+packet->length();
473
418
    *pos++= 12;                // Length of packed fields
474
 
    /* No conversion */
475
 
    int2store(pos, field.charsetnr);
476
 
    int4store(pos+2, field.length);
477
 
 
478
 
    if (using_mysql41_protocol)
 
419
    if (item->collation.collation == &my_charset_bin)
479
420
    {
480
 
      /* Switch to MySQL field numbering. */
481
 
      switch (field.type)
482
 
      {
483
 
      case DRIZZLE_TYPE_LONG:
484
 
        pos[6]= 3;
485
 
        break;
486
 
 
487
 
      case DRIZZLE_TYPE_DOUBLE:
488
 
        pos[6]= 5;
489
 
        break;
490
 
 
491
 
      case DRIZZLE_TYPE_NULL:
492
 
        pos[6]= 6;
493
 
        break;
494
 
 
495
 
      case DRIZZLE_TYPE_TIMESTAMP:
496
 
        pos[6]= 7;
497
 
        break;
498
 
 
499
 
      case DRIZZLE_TYPE_LONGLONG:
500
 
        pos[6]= 8;
501
 
        break;
502
 
 
503
 
      case DRIZZLE_TYPE_DATETIME:
504
 
        pos[6]= 12;
505
 
        break;
506
 
 
507
 
      case DRIZZLE_TYPE_DATE:
508
 
        pos[6]= 14;
509
 
        break;
510
 
 
511
 
      case DRIZZLE_TYPE_VARCHAR:
512
 
        pos[6]= 15;
513
 
        break;
514
 
 
515
 
      case DRIZZLE_TYPE_DECIMAL:
516
 
        pos[6]= (char)246;
517
 
        break;
518
 
 
519
 
      case DRIZZLE_TYPE_ENUM:
520
 
        pos[6]= (char)247;
521
 
        break;
522
 
 
523
 
      case DRIZZLE_TYPE_BLOB:
524
 
        pos[6]= (char)252;
525
 
        break;
526
 
      }
 
421
      /* No conversion */
 
422
      int2store(pos, field.charsetnr);
 
423
      int4store(pos+2, field.length);
527
424
    }
528
425
    else
529
426
    {
530
 
      /* Add one to compensate for tinyint removal from enum. */
531
 
      pos[6]= field.type + 1;
 
427
      /* With conversion */
 
428
      uint32_t max_char_len;
 
429
      int2store(pos, cs->number);
 
430
      /*
 
431
        For TEXT/BLOB columns, field_length describes the maximum data
 
432
        length in bytes. There is no limit to the number of characters
 
433
        that a TEXT column can store, as long as the data fits into
 
434
        the designated space.
 
435
        For the rest of textual columns, field_length is evaluated as
 
436
        char_count * mbmaxlen, where character count is taken from the
 
437
        definition of the column. In other words, the maximum number
 
438
        of characters here is limited by the column definition.
 
439
      */
 
440
      max_char_len= field.length / item->collation.collation->mbmaxlen;
 
441
      int4store(pos+2, max_char_len * cs->mbmaxlen);
532
442
    }
533
 
 
 
443
    pos[6]= field.type;
534
444
    int2store(pos+7,field.flags);
535
445
    pos[9]= (char) field.decimals;
536
446
    pos[10]= 0;                // For the future
537
447
    pos[11]= 0;                // For the future
538
448
    pos+= 12;
539
449
 
540
 
    packet.length((uint32_t) (pos - packet.ptr()));
541
 
    if (flush())
542
 
      break;
543
 
  }
544
 
 
545
 
  /*
546
 
    Mark the end of meta-data result set, and store session->server_status,
547
 
    to show that there is no cursor.
548
 
    Send no warning information, as it will be sent at statement end.
549
 
  */
550
 
  writeEOFPacket(session->server_status, session->total_warn_count);
 
450
    packet->length((uint32_t) (pos - packet->ptr()));
 
451
    if (flags & SEND_DEFAULTS)
 
452
      item->send(this, &tmp);            // Send default value
 
453
    if (write())
 
454
      break;                    /* purecov: inspected */
 
455
  }
 
456
 
 
457
  if (flags & SEND_EOF)
 
458
  {
 
459
    /*
 
460
      Mark the end of meta-data result set, and store session->server_status,
 
461
      to show that there is no cursor.
 
462
      Send no warning information, as it will be sent at statement end.
 
463
    */
 
464
    write_eof_packet(session, &net, session->server_status, session->total_warn_count);
 
465
  }
 
466
 
 
467
  field_count= list->elements;
551
468
  return 0;
552
469
 
553
470
err:
554
471
  my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES),
555
 
             MYF(0));
556
 
  return 1;
557
 
}
558
 
 
559
 
bool ClientDrizzleProtocol::store(Field *from)
560
 
{
561
 
  if (from->is_null())
562
 
    return store();
563
 
  char buff[MAX_FIELD_WIDTH];
564
 
  String str(buff,sizeof(buff), &my_charset_bin);
565
 
 
566
 
  from->val_str(&str);
567
 
 
568
 
  return netStoreData((const unsigned char *)str.ptr(), str.length());
569
 
}
570
 
 
571
 
bool ClientDrizzleProtocol::store(void)
 
472
             MYF(0));    /* purecov: inspected */
 
473
  return 1;                /* purecov: inspected */
 
474
}
 
475
 
 
476
 
 
477
bool ProtocolOldLibdrizzle::write()
 
478
{
 
479
  return(drizzleclient_net_write(&net, (unsigned char*) packet->ptr(),
 
480
                           packet->length()));
 
481
}
 
482
 
 
483
void ProtocolOldLibdrizzle::free()
 
484
{
 
485
  packet->free();
 
486
}
 
487
 
 
488
 
 
489
void ProtocolOldLibdrizzle::setRandom(uint64_t seed1, uint64_t seed2)
 
490
{
 
491
  drizzleclient_randominit(&rand, seed1, seed2);
 
492
}
 
493
 
 
494
bool ProtocolOldLibdrizzle::setFileDescriptor(int fd)
 
495
{
 
496
  if (drizzleclient_net_init_sock(&net, fd, 0))
 
497
    return true;
 
498
  return false;
 
499
}
 
500
 
 
501
int ProtocolOldLibdrizzle::fileDescriptor(void)
 
502
{
 
503
  return drizzleclient_net_get_sd(&net);
 
504
}
 
505
 
 
506
bool ProtocolOldLibdrizzle::authenticate()
 
507
{
 
508
  bool connection_is_valid;
 
509
 
 
510
  /* Use "connect_timeout" value during connection phase */
 
511
  drizzleclient_net_set_read_timeout(&net, connect_timeout);
 
512
  drizzleclient_net_set_write_timeout(&net, connect_timeout);
 
513
 
 
514
  connection_is_valid= checkConnection();
 
515
 
 
516
  if (connection_is_valid)
 
517
    sendOK();
 
518
  else
 
519
  {
 
520
    sendError(session->main_da.sql_errno(), session->main_da.message());
 
521
    return false;
 
522
  }
 
523
 
 
524
  /* Connect completed, set read/write timeouts back to default */
 
525
  drizzleclient_net_set_read_timeout(&net,
 
526
                                     session->variables.net_read_timeout);
 
527
  drizzleclient_net_set_write_timeout(&net,
 
528
                                      session->variables.net_write_timeout);
 
529
  return true;
 
530
}
 
531
 
 
532
bool ProtocolOldLibdrizzle::readCommand(char **l_packet, uint32_t *packet_length)
 
533
{
 
534
  /*
 
535
    This thread will do a blocking read from the client which
 
536
    will be interrupted when the next command is received from
 
537
    the client, the connection is closed or "net_wait_timeout"
 
538
    number of seconds has passed
 
539
  */
 
540
#ifdef NEVER
 
541
  /* We can do this much more efficiently with poll timeouts or watcher thread,
 
542
     disabling for now, which means net_wait_timeout == read_timeout. */
 
543
  drizzleclient_net_set_read_timeout(&net,
 
544
                                     session->variables.net_wait_timeout);
 
545
#endif
 
546
 
 
547
  session->clear_error();
 
548
  session->main_da.reset_diagnostics_area();
 
549
 
 
550
  net.pkt_nr=0;
 
551
 
 
552
  *packet_length= drizzleclient_net_read(&net);
 
553
  if (*packet_length == packet_error)
 
554
  {
 
555
    /* Check if we can continue without closing the connection */
 
556
 
 
557
    if(net.last_errno== CR_NET_PACKET_TOO_LARGE)
 
558
      my_error(ER_NET_PACKET_TOO_LARGE, MYF(0));
 
559
    if (session->main_da.status() == Diagnostics_area::DA_ERROR)
 
560
      sendError(session->main_da.sql_errno(), session->main_da.message());
 
561
    else
 
562
      session->protocol->sendOK();
 
563
 
 
564
    if (net.error != 3)
 
565
      return false;                       // We have to close it.
 
566
 
 
567
    net.error= 0;
 
568
    *packet_length= 0;
 
569
    return true;
 
570
  }
 
571
 
 
572
  *l_packet= (char*) net.read_pos;
 
573
 
 
574
  /*
 
575
    'packet_length' contains length of data, as it was stored in packet
 
576
    header. In case of malformed header, drizzleclient_net_read returns zero.
 
577
    If packet_length is not zero, drizzleclient_net_read ensures that the returned
 
578
    number of bytes was actually read from network.
 
579
    There is also an extra safety measure in drizzleclient_net_read:
 
580
    it sets packet[packet_length]= 0, but only for non-zero packets.
 
581
  */
 
582
 
 
583
  if (*packet_length == 0)                       /* safety */
 
584
  {
 
585
    /* Initialize with COM_SLEEP packet */
 
586
    (*l_packet)[0]= (unsigned char) COM_SLEEP;
 
587
    *packet_length= 1;
 
588
  }
 
589
  /* Do not rely on drizzleclient_net_read, extra safety against programming errors. */
 
590
  (*l_packet)[*packet_length]= '\0';                  /* safety */
 
591
 
 
592
#ifdef NEVER
 
593
  /* See comment above. */
 
594
  /* Restore read timeout value */
 
595
  drizzleclient_net_set_read_timeout(&net,
 
596
                                     session->variables.net_read_timeout);
 
597
#endif
 
598
 
 
599
  return true;
 
600
}
 
601
 
 
602
void ProtocolOldLibdrizzle::close(void)
 
603
{
 
604
  if (net.vio)
 
605
  { 
 
606
    drizzleclient_net_close(&net);
 
607
    drizzleclient_net_end(&net);
 
608
  }
 
609
}
 
610
 
 
611
void ProtocolOldLibdrizzle::forceClose(void)
 
612
{
 
613
  if (net.vio)
 
614
    drizzleclient_vio_close(net.vio);
 
615
}
 
616
 
 
617
void ProtocolOldLibdrizzle::prepareForResend()
 
618
{
 
619
  packet->length(0);
 
620
}
 
621
 
 
622
bool ProtocolOldLibdrizzle::store(void)
572
623
{
573
624
  char buff[1];
574
625
  buff[0]= (char)251;
575
 
  return packet.append(buff, sizeof(buff), PACKET_BUFFER_EXTRA_ALLOC);
576
 
}
577
 
 
578
 
bool ClientDrizzleProtocol::store(int32_t from)
 
626
  return packet->append(buff, sizeof(buff), PACKET_BUFFER_EXTRA_ALLOC);
 
627
}
 
628
 
 
629
 
 
630
/**
 
631
  Auxilary function to convert string to the given character set
 
632
  and store in network buffer.
 
633
*/
 
634
 
 
635
bool ProtocolOldLibdrizzle::storeString(const char *from, size_t length,
 
636
                                        const CHARSET_INFO * const fromcs,
 
637
                                        const CHARSET_INFO * const tocs)
 
638
{
 
639
  /* 'tocs' is set 0 when client issues SET character_set_results=NULL */
 
640
  if (tocs && !my_charset_same(fromcs, tocs) &&
 
641
      fromcs != &my_charset_bin &&
 
642
      tocs != &my_charset_bin)
 
643
  {
 
644
    /* Store with conversion */
 
645
    return netStoreData((unsigned char*) from, length, fromcs, tocs);
 
646
  }
 
647
  /* Store without conversion */
 
648
  return netStoreData((unsigned char*) from, length);
 
649
}
 
650
 
 
651
 
 
652
bool ProtocolOldLibdrizzle::store(const char *from, size_t length,
 
653
                          const CHARSET_INFO * const fromcs)
 
654
{
 
655
  const CHARSET_INFO * const tocs= default_charset_info;
 
656
  return storeString(from, length, fromcs, tocs);
 
657
}
 
658
 
 
659
 
 
660
bool ProtocolOldLibdrizzle::store(int32_t from)
579
661
{
580
662
  char buff[12];
581
663
  return netStoreData((unsigned char*) buff,
582
 
                      (size_t) (internal::int10_to_str(from, buff, -10) - buff));
 
664
                      (size_t) (int10_to_str(from, buff, -10) - buff));
583
665
}
584
666
 
585
 
bool ClientDrizzleProtocol::store(uint32_t from)
 
667
bool ProtocolOldLibdrizzle::store(uint32_t from)
586
668
{
587
669
  char buff[11];
588
670
  return netStoreData((unsigned char*) buff,
589
 
                      (size_t) (internal::int10_to_str(from, buff, 10) - buff));
 
671
                      (size_t) (int10_to_str(from, buff, 10) - buff));
590
672
}
591
673
 
592
 
bool ClientDrizzleProtocol::store(int64_t from)
 
674
bool ProtocolOldLibdrizzle::store(int64_t from)
593
675
{
594
676
  char buff[22];
595
677
  return netStoreData((unsigned char*) buff,
596
 
                      (size_t) (internal::int64_t10_to_str(from, buff, -10) - buff));
 
678
                      (size_t) (int64_t10_to_str(from, buff, -10) - buff));
597
679
}
598
680
 
599
 
bool ClientDrizzleProtocol::store(uint64_t from)
 
681
bool ProtocolOldLibdrizzle::store(uint64_t from)
600
682
{
601
683
  char buff[21];
602
684
  return netStoreData((unsigned char*) buff,
603
 
                      (size_t) (internal::int64_t10_to_str(from, buff, 10) - buff));
 
685
                      (size_t) (int64_t10_to_str(from, buff, 10) - buff));
604
686
}
605
687
 
606
 
bool ClientDrizzleProtocol::store(double from, uint32_t decimals, String *buffer)
 
688
 
 
689
bool ProtocolOldLibdrizzle::store(double from, uint32_t decimals, String *buffer)
607
690
{
608
691
  buffer->set_real(from, decimals, session->charset());
609
692
  return netStoreData((unsigned char*) buffer->ptr(), buffer->length());
610
693
}
611
694
 
612
 
bool ClientDrizzleProtocol::store(const char *from, size_t length)
613
 
{
614
 
  return netStoreData((const unsigned char *)from, length);
615
 
}
616
 
 
617
 
bool ClientDrizzleProtocol::wasAborted(void)
618
 
{
619
 
  return net.error && net.vio != 0;
620
 
}
621
 
 
622
 
bool ClientDrizzleProtocol::haveMoreData(void)
623
 
{
624
 
  return drizzleclient_net_more_data(&net);
625
 
}
626
 
 
627
 
bool ClientDrizzleProtocol::haveError(void)
628
 
{
629
 
  return net.error || net.vio == 0;
630
 
}
631
 
 
632
 
bool ClientDrizzleProtocol::checkConnection(void)
 
695
 
 
696
bool ProtocolOldLibdrizzle::store(Field *from)
 
697
{
 
698
  if (from->is_null())
 
699
    return store();
 
700
  char buff[MAX_FIELD_WIDTH];
 
701
  String str(buff,sizeof(buff), &my_charset_bin);
 
702
  const CHARSET_INFO * const tocs= default_charset_info;
 
703
 
 
704
  from->val_str(&str);
 
705
 
 
706
  return storeString(str.ptr(), str.length(), str.charset(), tocs);
 
707
}
 
708
 
 
709
 
 
710
/**
 
711
  @todo
 
712
    Second_part format ("%06") needs to change when
 
713
    we support 0-6 decimals for time.
 
714
*/
 
715
 
 
716
bool ProtocolOldLibdrizzle::store(const DRIZZLE_TIME *tm)
 
717
{
 
718
  char buff[40];
 
719
  uint32_t length;
 
720
  uint32_t day;
 
721
 
 
722
  switch (tm->time_type)
 
723
  {
 
724
  case DRIZZLE_TIMESTAMP_DATETIME:
 
725
    length= sprintf(buff, "%04d-%02d-%02d %02d:%02d:%02d",
 
726
                    (int) tm->year,
 
727
                    (int) tm->month,
 
728
                    (int) tm->day,
 
729
                    (int) tm->hour,
 
730
                    (int) tm->minute,
 
731
                    (int) tm->second);
 
732
    if (tm->second_part)
 
733
      length+= sprintf(buff+length, ".%06d", (int)tm->second_part);
 
734
    break;
 
735
 
 
736
  case DRIZZLE_TIMESTAMP_DATE:
 
737
    length= sprintf(buff, "%04d-%02d-%02d",
 
738
                    (int) tm->year,
 
739
                    (int) tm->month,
 
740
                    (int) tm->day);
 
741
    break;
 
742
 
 
743
  case DRIZZLE_TIMESTAMP_TIME:
 
744
    day= (tm->year || tm->month) ? 0 : tm->day;
 
745
    length= sprintf(buff, "%s%02ld:%02d:%02d", tm->neg ? "-" : "",
 
746
                    (long) day*24L+(long) tm->hour, (int) tm->minute,
 
747
                    (int) tm->second);
 
748
    if (tm->second_part)
 
749
      length+= sprintf(buff+length, ".%06d", (int)tm->second_part);
 
750
    break;
 
751
 
 
752
  case DRIZZLE_TIMESTAMP_NONE:
 
753
  case DRIZZLE_TIMESTAMP_ERROR:
 
754
  default:
 
755
    assert(0);
 
756
    return false;
 
757
  }
 
758
 
 
759
  return netStoreData((unsigned char*) buff, length);
 
760
}
 
761
 
 
762
bool ProtocolOldLibdrizzle::checkConnection(void)
633
763
{
634
764
  uint32_t pkt_len= 0;
635
765
  char *end;
637
767
  // TCP/IP connection
638
768
  {
639
769
    char ip[NI_MAXHOST];
640
 
    uint16_t peer_port;
641
770
 
642
 
    if (drizzleclient_net_peer_addr(&net, ip, &peer_port, NI_MAXHOST))
 
771
    if (drizzleclient_net_peer_addr(&net, ip, &session->peer_port, NI_MAXHOST))
643
772
    {
644
 
      my_error(ER_BAD_HOST_ERROR, MYF(0), session->getSecurityContext().getIp().c_str());
 
773
      my_error(ER_BAD_HOST_ERROR, MYF(0), session->security_ctx.ip.c_str());
645
774
      return false;
646
775
    }
647
776
 
648
 
    session->getSecurityContext().setIp(ip);
 
777
    session->security_ctx.ip.assign(ip);
649
778
  }
650
779
  drizzleclient_net_keepalive(&net, true);
651
780
 
656
785
 
657
786
    server_capabilites= CLIENT_BASIC_FLAGS;
658
787
 
659
 
    if (using_mysql41_protocol)
660
 
      server_capabilites|= CLIENT_PROTOCOL_MYSQL41;
661
 
 
662
788
#ifdef HAVE_COMPRESS
663
789
    server_capabilites|= CLIENT_COMPRESS;
664
790
#endif /* HAVE_COMPRESS */
665
791
 
666
 
    end= buff + strlen(VERSION);
 
792
    end= buff + strlen(server_version);
667
793
    if ((end - buff) >= SERVER_VERSION_LENGTH)
668
794
      end= buff + (SERVER_VERSION_LENGTH - 1);
669
 
    memcpy(buff, VERSION, end - buff);
 
795
    memcpy(buff, server_version, end - buff);
670
796
    *end= 0;
671
797
    end++;
672
798
 
673
 
    int4store((unsigned char*) end, global_thread_id);
 
799
    int4store((unsigned char*) end, thread_id);
674
800
    end+= 4;
675
 
 
676
 
    /* We don't use scramble anymore. */
677
 
    memset(end, 'X', SCRAMBLE_LENGTH_323);
 
801
    /*
 
802
      So as _checkConnection is the only entry point to authorization
 
803
      procedure, scramble is set here. This gives us new scramble for
 
804
      each handshake.
 
805
    */
 
806
    drizzleclient_create_random_string(scramble, SCRAMBLE_LENGTH, &rand);
 
807
    /*
 
808
      Old clients does not understand long scrambles, but can ignore packet
 
809
      tail: that's why first part of the scramble is placed here, and second
 
810
      part at the end of packet.
 
811
    */
 
812
    end= strncpy(end, scramble, SCRAMBLE_LENGTH_323);
678
813
    end+= SCRAMBLE_LENGTH_323;
 
814
 
679
815
    *end++= 0; /* an empty byte for some reason */
680
816
 
681
817
    int2store(end, server_capabilites);
684
820
    int2store(end+3, session->server_status);
685
821
    memset(end+5, 0, 13);
686
822
    end+= 18;
 
823
    /* write scramble tail */
 
824
    size_t scramble_len= SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323;
 
825
    end= strncpy(end, scramble + SCRAMBLE_LENGTH_323, scramble_len);
 
826
    end+= scramble_len;
687
827
 
688
 
    /* Write scramble tail. */
689
 
    memset(end, 'X', SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323);
690
 
    end+= (SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323);
691
828
    *end++= 0; /* an empty byte for some reason */
692
829
 
693
830
    /* At this point we write connection message and read reply */
694
831
    if (drizzleclient_net_write_command(&net
695
 
          , (unsigned char) PROTOCOL_VERSION
 
832
          , (unsigned char) protocol_version
696
833
          , (unsigned char*) ""
697
834
          , 0
698
835
          , (unsigned char*) buff
700
837
        ||    (pkt_len= drizzleclient_net_read(&net)) == packet_error 
701
838
        || pkt_len < MIN_HANDSHAKE_SIZE)
702
839
    {
703
 
      my_error(ER_HANDSHAKE_ERROR, MYF(0), session->getSecurityContext().getIp().c_str());
 
840
      my_error(ER_HANDSHAKE_ERROR, MYF(0), session->security_ctx.ip.c_str());
704
841
      return false;
705
842
    }
706
843
  }
707
 
  if (packet.alloc(buffer_length))
 
844
  if (session->packet.alloc(session->variables.net_buffer_length))
708
845
    return false; /* The error is set by alloc(). */
709
846
 
710
 
  client_capabilities= uint2korr(net.read_pos);
711
 
 
712
 
 
713
 
  client_capabilities|= ((uint32_t) uint2korr(net.read_pos + 2)) << 16;
 
847
  session->client_capabilities= uint2korr(net.read_pos);
 
848
 
 
849
 
 
850
  session->client_capabilities|= ((uint32_t) uint2korr(net.read_pos + 2)) << 16;
714
851
  session->max_client_packet_length= uint4korr(net.read_pos + 4);
 
852
  session->update_charset();
715
853
  end= (char*) net.read_pos + 32;
716
854
 
717
855
  /*
718
856
    Disable those bits which are not supported by the server.
719
857
    This is a precautionary measure, if the client lies. See Bug#27944.
720
858
  */
721
 
  client_capabilities&= server_capabilites;
 
859
  session->client_capabilities&= server_capabilites;
722
860
 
723
861
  if (end >= (char*) net.read_pos + pkt_len + 2)
724
862
  {
725
 
    my_error(ER_HANDSHAKE_ERROR, MYF(0), session->getSecurityContext().getIp().c_str());
 
863
    my_error(ER_HANDSHAKE_ERROR, MYF(0), session->security_ctx.ip.c_str());
726
864
    return false;
727
865
  }
728
866
 
732
870
  char *passwd= strchr(user, '\0')+1;
733
871
  uint32_t user_len= passwd - user - 1;
734
872
  char *l_db= passwd;
 
873
  char db_buff[NAME_LEN + 1];           // buffer to store db in utf8
 
874
  char user_buff[USERNAME_LENGTH + 1];    // buffer to store user in utf8
 
875
  uint32_t dummy_errors;
735
876
 
736
877
  /*
737
878
    Old clients send null-terminated string as password; new clients send
738
879
    the size (1 byte) + string (not null-terminated). Hence in case of empty
739
880
    password both send '\0'.
740
881
 
741
 
    This strlen() can't be easily deleted without changing client.
 
882
    This strlen() can't be easily deleted without changing protocol.
742
883
 
743
884
    Cast *passwd to an unsigned char, so that it doesn't extend the sign for
744
885
    *passwd > 127 and become 2**32-127+ after casting to uint.
745
886
  */
746
 
  uint32_t passwd_len= client_capabilities & CLIENT_SECURE_CONNECTION ?
 
887
  uint32_t passwd_len= session->client_capabilities & CLIENT_SECURE_CONNECTION ?
747
888
    (unsigned char)(*passwd++) : strlen(passwd);
748
 
  l_db= client_capabilities & CLIENT_CONNECT_WITH_DB ? l_db + passwd_len + 1 : 0;
 
889
  l_db= session->client_capabilities & CLIENT_CONNECT_WITH_DB ? l_db + passwd_len + 1 : 0;
749
890
 
750
 
  /* strlen() can't be easily deleted without changing client */
 
891
  /* strlen() can't be easily deleted without changing protocol */
751
892
  uint32_t db_len= l_db ? strlen(l_db) : 0;
752
893
 
753
894
  if (passwd + passwd_len + db_len > (char *) net.read_pos + pkt_len)
754
895
  {
755
 
    my_error(ER_HANDSHAKE_ERROR, MYF(0), session->getSecurityContext().getIp().c_str());
 
896
    my_error(ER_HANDSHAKE_ERROR, MYF(0), session->security_ctx.ip.c_str());
756
897
    return false;
757
898
  }
758
899
 
 
900
  /* Since 4.1 all database names are stored in utf8 */
 
901
  if (l_db)
 
902
  {
 
903
    db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1,
 
904
                             system_charset_info,
 
905
                             l_db, db_len,
 
906
                             session->charset(), &dummy_errors)]= 0;
 
907
    l_db= db_buff;
 
908
  }
 
909
 
 
910
  user_buff[user_len= copy_and_convert(user_buff, sizeof(user_buff)-1,
 
911
                                       system_charset_info, user, user_len,
 
912
                                       session->charset(), &dummy_errors)]= '\0';
 
913
  user= user_buff;
 
914
 
759
915
  /* If username starts and ends in "'", chop them off */
760
916
  if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
761
917
  {
764
920
    user_len-= 2;
765
921
  }
766
922
 
767
 
  session->getSecurityContext().setUser(user);
 
923
  session->security_ctx.user.assign(user);
768
924
 
769
925
  return session->checkUser(passwd, passwd_len, l_db);
770
926
}
771
927
 
772
 
bool ClientDrizzleProtocol::netStoreData(const unsigned char *from, size_t length)
773
 
{
774
 
  size_t packet_length= packet.length();
775
 
  /*
776
 
     The +9 comes from that strings of length longer than 16M require
777
 
     9 bytes to be stored (see drizzleclient_net_store_length).
778
 
  */
779
 
  if (packet_length+9+length > packet.alloced_length() &&
780
 
      packet.realloc(packet_length+9+length))
781
 
    return 1;
782
 
  unsigned char *to= drizzleclient_net_store_length((unsigned char*) packet.ptr()+packet_length, length);
783
 
  memcpy(to,from,length);
784
 
  packet.length((size_t) (to+length-(unsigned char*) packet.ptr()));
785
 
  return 0;
786
 
}
787
 
 
788
 
/**
789
 
  Format EOF packet according to the current client and
790
 
  write it to the network output buffer.
791
 
*/
792
 
 
793
 
void ClientDrizzleProtocol::writeEOFPacket(uint32_t server_status,
794
 
                                         uint32_t total_warn_count)
795
 
{
796
 
  unsigned char buff[5];
797
 
  /*
798
 
    Don't send warn count during SP execution, as the warn_list
799
 
    is cleared between substatements, and mysqltest gets confused
800
 
  */
801
 
  uint32_t tmp= min(total_warn_count, (uint32_t)65535);
802
 
  buff[0]= DRIZZLE_PROTOCOL_NO_MORE_DATA;
803
 
  int2store(buff+1, tmp);
804
 
  /*
805
 
    The following test should never be true, but it's better to do it
806
 
    because if 'is_fatal_error' is set the server is not going to execute
807
 
    other queries (see the if test in dispatch_command / COM_QUERY)
808
 
  */
809
 
  if (session->is_fatal_error)
810
 
    server_status&= ~SERVER_MORE_RESULTS_EXISTS;
811
 
  int2store(buff + 3, server_status);
812
 
  drizzleclient_net_write(&net, buff, 5);
813
 
}
814
 
 
815
 
static ListenDrizzleProtocol *listen_obj= NULL;
816
 
 
817
 
static int init(plugin::Context &context)
818
 
{
819
 
  listen_obj= new ListenDrizzleProtocol("drizzle_protocol", false);
820
 
  context.add(listen_obj); 
821
 
  return 0;
822
 
}
823
 
 
824
 
static DRIZZLE_SYSVAR_UINT(port, port, PLUGIN_VAR_RQCMDARG,
825
 
                           N_("Port number to use for connection or 0 for "
826
 
                              "default to, in order of "
827
 
                              "preference, drizzle.cnf, $DRIZZLE_TCP_PORT, "
828
 
                              "built-in default (4427)."),
829
 
                           NULL, NULL, 0, 0, 65535, 0);
830
 
static DRIZZLE_SYSVAR_UINT(connect_timeout, connect_timeout,
831
 
                           PLUGIN_VAR_RQCMDARG, N_("Connect Timeout."),
832
 
                           NULL, NULL, 10, 1, 300, 0);
833
 
static DRIZZLE_SYSVAR_UINT(read_timeout, read_timeout, PLUGIN_VAR_RQCMDARG,
834
 
                           N_("Read Timeout."), NULL, NULL, 30, 1, 300, 0);
835
 
static DRIZZLE_SYSVAR_UINT(write_timeout, write_timeout, PLUGIN_VAR_RQCMDARG,
836
 
                           N_("Write Timeout."), NULL, NULL, 60, 1, 300, 0);
837
 
static DRIZZLE_SYSVAR_UINT(retry_count, retry_count, PLUGIN_VAR_RQCMDARG,
838
 
                           N_("Retry Count."), NULL, NULL, 10, 1, 100, 0);
839
 
static DRIZZLE_SYSVAR_UINT(buffer_length, buffer_length, PLUGIN_VAR_RQCMDARG,
840
 
                           N_("Buffer length."), NULL, NULL, 16384, 1024,
841
 
                           1024*1024, 0);
842
 
static DRIZZLE_SYSVAR_STR(bind_address, bind_address, PLUGIN_VAR_READONLY,
843
 
                          N_("Address to bind to."), NULL, NULL, NULL);
844
 
 
845
 
static drizzle_sys_var* sys_variables[]= {
846
 
  DRIZZLE_SYSVAR(port),
847
 
  DRIZZLE_SYSVAR(connect_timeout),
848
 
  DRIZZLE_SYSVAR(read_timeout),
849
 
  DRIZZLE_SYSVAR(write_timeout),
850
 
  DRIZZLE_SYSVAR(retry_count),
851
 
  DRIZZLE_SYSVAR(buffer_length),
852
 
  DRIZZLE_SYSVAR(bind_address),
853
 
  NULL
854
 
};
855
 
 
856
 
} /* namespace drizzle_protocol */
857
 
 
858
 
DRIZZLE_PLUGIN(drizzle_protocol::init, drizzle_protocol::sys_variables);
 
928
static ProtocolFactoryOldLibdrizzle *factory= NULL;
 
929
 
 
930
static int init(PluginRegistry &registry)
 
931
{
 
932
  factory= new ProtocolFactoryOldLibdrizzle;
 
933
  registry.add(factory); 
 
934
  return 0;
 
935
}
 
936
 
 
937
static int deinit(PluginRegistry &registry)
 
938
{
 
939
  if (factory)
 
940
  {
 
941
    registry.remove(factory);
 
942
    delete factory;
 
943
  }
 
944
  return 0;
 
945
}
 
946
 
 
947
drizzle_declare_plugin(oldlibdrizzle)
 
948
{
 
949
  "oldlibdrizzle",
 
950
  "0.1",
 
951
  "Eric Day",
 
952
  "Old libdrizzle Protocol",
 
953
  PLUGIN_LICENSE_GPL,
 
954
  init,   /* Plugin Init */
 
955
  deinit, /* Plugin Deinit */
 
956
  NULL,   /* status variables */
 
957
  NULL,   /* system variables */
 
958
  NULL    /* config options */
 
959
}
 
960
drizzle_declare_plugin_end;