~drizzle-trunk/drizzle/development

520.6.3 by Monty Taylor
Moved scheduler.h out of common_includes.
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 *
4
 *  Copyright (C) 2008 Sun Microsystems
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; version 2 of the License.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License
16
 *  along with this program; if not, write to the Free Software
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 */
1 by brian
clean slate
19
20
21
/*
22
  Functions to autenticate and handle reqests for a connection
23
*/
243.1.17 by Jay Pipes
FINAL PHASE removal of mysql_priv.h (Bye, bye my friend.)
24
#include <drizzled/server_includes.h>
575.4.7 by Monty Taylor
More header cleanup.
25
#include <netdb.h>
26
259 by Brian Aker
First pass on PAM auth
27
#include <drizzled/authentication.h>
575.4.6 by Monty Taylor
Removed my_getwd.
28
#include <drizzled/db.h>
549 by Monty Taylor
Took gettext.h out of header files.
29
#include <drizzled/error.h>
575.4.7 by Monty Taylor
More header cleanup.
30
#include <drizzled/sql_parse.h>
1 by brian
clean slate
31
520.6.3 by Monty Taylor
Moved scheduler.h out of common_includes.
32
extern scheduler_functions thread_scheduler;
33
1 by brian
clean slate
34
#define MIN_HANDSHAKE_SIZE      6
35
36
/*
37
  Get structure for logging connection data for the current user
38
*/
39
40
char *ip_to_hostname(struct sockaddr_storage *in, int addrLen)
41
{
42
  char *name;
43
44
  int gxi_error;
45
  char hostname_buff[NI_MAXHOST];
46
47
  /* Historical comparison for 127.0.0.1 */
48
  gxi_error= getnameinfo((struct sockaddr *)in, addrLen,
49
                         hostname_buff, NI_MAXHOST,
50
                         NULL, 0, NI_NUMERICHOST);
51
  if (gxi_error)
52
  {
53
    return NULL;
54
  }
55
56
  if (!(name= my_strdup(hostname_buff, MYF(0))))
57
  {
58
    return NULL;
59
  }
60
61
  return NULL;
62
}
63
64
/**
65
  Check if user exist and password supplied is correct.
66
520.1.22 by Brian Aker
Second pass of thd cleanup
67
  @param  session         thread handle, session->security_ctx->{host,user,ip} are used
1 by brian
clean slate
68
  @param  command     originator of the check: now check_user is called
69
                      during connect and change user procedures; used for
70
                      logging.
71
  @param  passwd      scrambled password received from client
72
  @param  passwd_len  length of scrambled password
73
  @param  db          database name to connect to, may be NULL
51.1.50 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
74
  @param  check_count true if establishing a new connection. In this case
1 by brian
clean slate
75
                      check that we have not exceeded the global
76
                      max_connections limist
77
78
  @note Host, user and passwd may point to communication buffer.
79
  Current implementation does not depend on that, but future changes
520.1.22 by Brian Aker
Second pass of thd cleanup
80
  should be done with this in mind; 'session' is INOUT, all other params
1 by brian
clean slate
81
  are 'IN'.
82
265 by brian
First pass through cleaning up security context.
83
  @retval  0  OK
1 by brian
clean slate
84
  @retval  1  error, e.g. access denied or handshake error, not sent to
85
              the client. A message is pushed into the error stack.
86
*/
87
88
int
520.1.22 by Brian Aker
Second pass of thd cleanup
89
check_user(Session *session, const char *passwd,
482 by Brian Aker
Remove uint.
90
           uint32_t passwd_len, const char *db,
77.1.45 by Monty Taylor
Warning fixes.
91
           bool check_count)
1 by brian
clean slate
92
{
93
  LEX_STRING db_str= { (char *) db, db ? strlen(db) : 0 };
259 by Brian Aker
First pass on PAM auth
94
  bool is_authenticated;
1 by brian
clean slate
95
96
  /*
520.1.22 by Brian Aker
Second pass of thd cleanup
97
    Clear session->db as it points to something, that will be freed when
1 by brian
clean slate
98
    connection is closed. We don't want to accidentally free a wrong
99
    pointer if connect failed. Also in case of 'CHANGE USER' failure,
100
    current database will be switched to 'no database selected'.
101
  */
520.1.22 by Brian Aker
Second pass of thd cleanup
102
  session->reset_db(NULL, 0);
1 by brian
clean slate
103
259 by Brian Aker
First pass on PAM auth
104
  if (passwd_len != 0 && passwd_len != SCRAMBLE_LENGTH)
1 by brian
clean slate
105
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
106
    my_error(ER_HANDSHAKE_ERROR, MYF(0), session->main_security_ctx.ip);
51.1.50 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
107
    return(1);
1 by brian
clean slate
108
  }
109
520.1.22 by Brian Aker
Second pass of thd cleanup
110
  is_authenticated= authenticate_user(session, passwd);
259 by Brian Aker
First pass on PAM auth
111
112
  if (is_authenticated != true)
113
  {
114
    my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
520.1.22 by Brian Aker
Second pass of thd cleanup
115
             session->main_security_ctx.user,
116
             session->main_security_ctx.ip,
259 by Brian Aker
First pass on PAM auth
117
             passwd_len ? ER(ER_YES) : ER(ER_NO));
118
119
    return 1;
120
  }
121
122
1 by brian
clean slate
123
  USER_RESOURCES ur;
520.1.22 by Brian Aker
Second pass of thd cleanup
124
  session->security_ctx->skip_grants();
1 by brian
clean slate
125
  memset(&ur, 0, sizeof(USER_RESOURCES));
126
127
  if (check_count)
128
  {
129
    pthread_mutex_lock(&LOCK_connection_count);
130
    bool count_ok= connection_count <= max_connections;
398.1.10 by Monty Taylor
Actually removed VOID() this time.
131
    pthread_mutex_unlock(&LOCK_connection_count);
1 by brian
clean slate
132
133
    if (!count_ok)
134
    {                                         // too many connections
135
      my_error(ER_CON_COUNT_ERROR, MYF(0));
51.1.50 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
136
      return(1);
1 by brian
clean slate
137
    }
138
  }
139
140
  /* Change database if necessary */
141
  if (db && db[0])
142
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
143
    if (mysql_change_db(session, &db_str, false))
1 by brian
clean slate
144
    {
145
      /* mysql_change_db() has pushed the error message. */
51.1.50 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
146
      return(1);
1 by brian
clean slate
147
    }
148
  }
520.1.22 by Brian Aker
Second pass of thd cleanup
149
  my_ok(session);
150
  session->password= test(passwd_len);          // remember for error messages 
1 by brian
clean slate
151
  /* Ready to handle queries */
51.1.50 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
152
  return(0);
1 by brian
clean slate
153
}
154
155
156
/*
157
  Check for maximum allowable user connections, if the mysqld server is
158
  started with corresponding variable that is greater then 0.
159
*/
160
481 by Brian Aker
Remove all of uchar.
161
extern "C" unsigned char *get_key_conn(user_conn *buff, size_t *length,
199 by Brian Aker
my_bool...
162
                               bool not_used __attribute__((unused)))
1 by brian
clean slate
163
{
164
  *length= buff->len;
481 by Brian Aker
Remove all of uchar.
165
  return (unsigned char*) buff->user;
1 by brian
clean slate
166
}
167
168
169
extern "C" void free_user(struct user_conn *uc)
170
{
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
171
  free((char*) uc);
1 by brian
clean slate
172
}
173
520.1.22 by Brian Aker
Second pass of thd cleanup
174
void session_init_client_charset(Session *session, uint32_t cs_number)
1 by brian
clean slate
175
{
176
  /*
177
   Use server character set and collation if
178
   - opt_character_set_client_handshake is not set
179
   - client has not specified a character set
180
   - client character set is the same as the servers
181
   - client character set doesn't exists in server
182
  */
183
  if (!opt_character_set_client_handshake ||
520.1.22 by Brian Aker
Second pass of thd cleanup
184
      !(session->variables.character_set_client= get_charset(cs_number, MYF(0))) ||
383.1.12 by Brian Aker
Much closer toward UTF8 being around all the time...
185
      !my_strcasecmp(&my_charset_utf8_general_ci,
1 by brian
clean slate
186
                     global_system_variables.character_set_client->name,
520.1.22 by Brian Aker
Second pass of thd cleanup
187
                     session->variables.character_set_client->name))
1 by brian
clean slate
188
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
189
    session->variables.character_set_client=
1 by brian
clean slate
190
      global_system_variables.character_set_client;
520.1.22 by Brian Aker
Second pass of thd cleanup
191
    session->variables.collation_connection=
1 by brian
clean slate
192
      global_system_variables.collation_connection;
520.1.22 by Brian Aker
Second pass of thd cleanup
193
    session->variables.character_set_results=
1 by brian
clean slate
194
      global_system_variables.character_set_results;
195
  }
196
  else
197
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
198
    session->variables.character_set_results=
199
      session->variables.collation_connection= 
200
      session->variables.character_set_client;
1 by brian
clean slate
201
  }
202
}
203
204
205
/*
206
  Initialize connection threads
207
*/
208
209
bool init_new_connection_handler_thread()
210
{
211
  pthread_detach_this_thread();
212
  /* Win32 calls this in pthread_create */
213
  if (my_thread_init())
214
    return 1;
215
  return 0;
216
}
217
218
/*
520.1.22 by Brian Aker
Second pass of thd cleanup
219
  Perform handshake, authorize client and update session ACL variables.
1 by brian
clean slate
220
221
  SYNOPSIS
222
    check_connection()
520.1.22 by Brian Aker
Second pass of thd cleanup
223
    session  thread handle
1 by brian
clean slate
224
225
  RETURN
520.1.22 by Brian Aker
Second pass of thd cleanup
226
     0  success, OK is sent to user, session is updated.
1 by brian
clean slate
227
    -1  error, which is sent to user
228
   > 0  error code (not sent to user)
229
*/
230
520.1.22 by Brian Aker
Second pass of thd cleanup
231
static int check_connection(Session *session)
1 by brian
clean slate
232
{
520.1.22 by Brian Aker
Second pass of thd cleanup
233
  NET *net= &session->net;
307 by Brian Aker
Minor cleanups around ulong in kernel.
234
  uint32_t pkt_len= 0;
1 by brian
clean slate
235
  char *end;
236
265 by brian
First pass through cleaning up security context.
237
  // TCP/IP connection
1 by brian
clean slate
238
  {
239
    char ip[NI_MAXHOST];
240
520.1.22 by Brian Aker
Second pass of thd cleanup
241
    if (net_peer_addr(net, ip, &session->peer_port, NI_MAXHOST))
1 by brian
clean slate
242
    {
520.1.22 by Brian Aker
Second pass of thd cleanup
243
      my_error(ER_BAD_HOST_ERROR, MYF(0), session->main_security_ctx.ip);
1 by brian
clean slate
244
      return 1;
245
    }
520.1.22 by Brian Aker
Second pass of thd cleanup
246
    if (!(session->main_security_ctx.ip= my_strdup(ip,MYF(MY_WME))))
1 by brian
clean slate
247
      return 1; /* The error is set by my_strdup(). */
248
  }
383.1.54 by Monty Taylor
More violite refactoring/removal.
249
  net_keepalive(net, true);
1 by brian
clean slate
250
  
307 by Brian Aker
Minor cleanups around ulong in kernel.
251
  uint32_t server_capabilites;
1 by brian
clean slate
252
  {
253
    /* buff[] needs to big enough to hold the server_version variable */
254
    char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH + 64];
255
    server_capabilites= CLIENT_BASIC_FLAGS;
256
257
    if (opt_using_transactions)
258
      server_capabilites|= CLIENT_TRANSACTIONS;
259
#ifdef HAVE_COMPRESS
260
    server_capabilites|= CLIENT_COMPRESS;
261
#endif /* HAVE_COMPRESS */
262
411.1.1 by Brian Aker
Work on removing GNU specific calls.
263
    end= my_stpncpy(buff, server_version, SERVER_VERSION_LENGTH) + 1;
520.1.22 by Brian Aker
Second pass of thd cleanup
264
    int4store((unsigned char*) end, session->thread_id);
1 by brian
clean slate
265
    end+= 4;
266
    /*
267
      So as check_connection is the only entry point to authorization
268
      procedure, scramble is set here. This gives us new scramble for
269
      each handshake.
270
    */
520.1.22 by Brian Aker
Second pass of thd cleanup
271
    create_random_string(session->scramble, SCRAMBLE_LENGTH, &session->rand);
1 by brian
clean slate
272
    /*
273
      Old clients does not understand long scrambles, but can ignore packet
274
      tail: that's why first part of the scramble is placed here, and second
275
      part at the end of packet.
276
    */
520.1.22 by Brian Aker
Second pass of thd cleanup
277
    end= strmake(end, session->scramble, SCRAMBLE_LENGTH_323) + 1;
1 by brian
clean slate
278
   
279
    int2store(end, server_capabilites);
280
    /* write server characteristics: up to 16 bytes allowed */
281
    end[2]=(char) default_charset_info->number;
520.1.22 by Brian Aker
Second pass of thd cleanup
282
    int2store(end+3, session->server_status);
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
283
    memset(end+5, 0, 13);
1 by brian
clean slate
284
    end+= 18;
285
    /* write scramble tail */
520.1.22 by Brian Aker
Second pass of thd cleanup
286
    end= strmake(end, session->scramble + SCRAMBLE_LENGTH_323, 
1 by brian
clean slate
287
                 SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323) + 1;
288
289
    /* At this point we write connection message and read reply */
481 by Brian Aker
Remove all of uchar.
290
    if (net_write_command(net, (unsigned char) protocol_version, (unsigned char*) "", 0,
291
                          (unsigned char*) buff, (size_t) (end-buff)) ||
1 by brian
clean slate
292
	(pkt_len= my_net_read(net)) == packet_error ||
293
	pkt_len < MIN_HANDSHAKE_SIZE)
294
    {
295
      my_error(ER_HANDSHAKE_ERROR, MYF(0),
520.1.22 by Brian Aker
Second pass of thd cleanup
296
               session->main_security_ctx.ip);
1 by brian
clean slate
297
      return 1;
298
    }
299
  }
520.1.22 by Brian Aker
Second pass of thd cleanup
300
  if (session->packet.alloc(session->variables.net_buffer_length))
1 by brian
clean slate
301
    return 1; /* The error is set by alloc(). */
302
520.1.22 by Brian Aker
Second pass of thd cleanup
303
  session->client_capabilities= uint2korr(net->read_pos);
304
305
306
  session->client_capabilities|= ((uint32_t) uint2korr(net->read_pos+2)) << 16;
307
  session->max_client_packet_length= uint4korr(net->read_pos+4);
308
  session_init_client_charset(session, (uint) net->read_pos[8]);
309
  session->update_charset();
264.2.4 by Andrey Hristov
Remove support for the old, pre-4.1, protocol
310
  end= (char*) net->read_pos+32;
311
1 by brian
clean slate
312
  /*
313
    Disable those bits which are not supported by the server.
314
    This is a precautionary measure, if the client lies. See Bug#27944.
315
  */
520.1.22 by Brian Aker
Second pass of thd cleanup
316
  session->client_capabilities&= server_capabilites;
1 by brian
clean slate
317
318
  if (end >= (char*) net->read_pos+ pkt_len +2)
319
  {
320
520.1.22 by Brian Aker
Second pass of thd cleanup
321
    my_error(ER_HANDSHAKE_ERROR, MYF(0), session->main_security_ctx.ip);
1 by brian
clean slate
322
    return 1;
323
  }
324
520.1.22 by Brian Aker
Second pass of thd cleanup
325
  if (session->client_capabilities & CLIENT_INTERACTIVE)
326
    session->variables.net_wait_timeout= session->variables.net_interactive_timeout;
327
  if ((session->client_capabilities & CLIENT_TRANSACTIONS) &&
1 by brian
clean slate
328
      opt_using_transactions)
520.1.22 by Brian Aker
Second pass of thd cleanup
329
    net->return_status= &session->server_status;
1 by brian
clean slate
330
331
  char *user= end;
376 by Brian Aker
strend remove
332
  char *passwd= strchr(user, '\0')+1;
482 by Brian Aker
Remove uint.
333
  uint32_t user_len= passwd - user - 1;
1 by brian
clean slate
334
  char *db= passwd;
335
  char db_buff[NAME_LEN + 1];           // buffer to store db in utf8
336
  char user_buff[USERNAME_LENGTH + 1];	// buffer to store user in utf8
482 by Brian Aker
Remove uint.
337
  uint32_t dummy_errors;
1 by brian
clean slate
338
339
  /*
340
    Old clients send null-terminated string as password; new clients send
341
    the size (1 byte) + string (not null-terminated). Hence in case of empty
342
    password both send '\0'.
343
344
    This strlen() can't be easily deleted without changing protocol.
345
346
    Cast *passwd to an unsigned char, so that it doesn't extend the sign for
347
    *passwd > 127 and become 2**32-127+ after casting to uint.
348
  */
520.1.22 by Brian Aker
Second pass of thd cleanup
349
  uint32_t passwd_len= session->client_capabilities & CLIENT_SECURE_CONNECTION ?
481 by Brian Aker
Remove all of uchar.
350
    (unsigned char)(*passwd++) : strlen(passwd);
520.1.22 by Brian Aker
Second pass of thd cleanup
351
  db= session->client_capabilities & CLIENT_CONNECT_WITH_DB ?
1 by brian
clean slate
352
    db + passwd_len + 1 : 0;
353
  /* strlen() can't be easily deleted without changing protocol */
482 by Brian Aker
Remove uint.
354
  uint32_t db_len= db ? strlen(db) : 0;
1 by brian
clean slate
355
356
  if (passwd + passwd_len + db_len > (char *)net->read_pos + pkt_len)
357
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
358
    my_error(ER_HANDSHAKE_ERROR, MYF(0), session->main_security_ctx.ip);
1 by brian
clean slate
359
    return 1;
360
  }
361
362
  /* Since 4.1 all database names are stored in utf8 */
363
  if (db)
364
  {
365
    db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1,
366
                             system_charset_info,
367
                             db, db_len,
520.1.22 by Brian Aker
Second pass of thd cleanup
368
                             session->charset(), &dummy_errors)]= 0;
1 by brian
clean slate
369
    db= db_buff;
370
  }
371
372
  user_buff[user_len= copy_and_convert(user_buff, sizeof(user_buff)-1,
373
                                       system_charset_info, user, user_len,
520.1.22 by Brian Aker
Second pass of thd cleanup
374
                                       session->charset(), &dummy_errors)]= '\0';
1 by brian
clean slate
375
  user= user_buff;
376
377
  /* If username starts and ends in "'", chop them off */
378
  if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
379
  {
380
    user[user_len-1]= 0;
381
    user++;
382
    user_len-= 2;
383
  }
384
520.1.22 by Brian Aker
Second pass of thd cleanup
385
  if (session->main_security_ctx.user)
386
    if (session->main_security_ctx.user)
387
      free(session->main_security_ctx.user);
388
  if (!(session->main_security_ctx.user= my_strdup(user, MYF(MY_WME))))
1 by brian
clean slate
389
    return 1; /* The error is set by my_strdup(). */
520.1.22 by Brian Aker
Second pass of thd cleanup
390
  return check_user(session, passwd, passwd_len, db, true);
1 by brian
clean slate
391
}
392
393
394
/*
395
  Setup thread to be used with the current thread
396
397
  SYNOPSIS
398
    bool setup_connection_thread_globals()
520.1.22 by Brian Aker
Second pass of thd cleanup
399
    session    Thread/connection handler
1 by brian
clean slate
400
401
  RETURN
402
    0   ok
403
    1   Error (out of memory)
404
        In this case we will close the connection and increment status
405
*/
406
520.1.22 by Brian Aker
Second pass of thd cleanup
407
bool setup_connection_thread_globals(Session *session)
1 by brian
clean slate
408
{
520.1.22 by Brian Aker
Second pass of thd cleanup
409
  if (session->store_globals())
1 by brian
clean slate
410
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
411
    close_connection(session, ER_OUT_OF_RESOURCES, 1);
1 by brian
clean slate
412
    statistic_increment(aborted_connects,&LOCK_status);
520.1.22 by Brian Aker
Second pass of thd cleanup
413
    thread_scheduler.end_thread(session, 0);
1 by brian
clean slate
414
    return 1;                                   // Error
415
  }
416
  return 0;
417
}
418
419
420
/*
421
  Autenticate user, with error reporting
422
423
  SYNOPSIS
424
   login_connection()
520.1.22 by Brian Aker
Second pass of thd cleanup
425
   session        Thread handler
1 by brian
clean slate
426
427
  NOTES
428
    Connection is not closed in case of errors
429
430
  RETURN
431
    0    ok
432
    1    error
433
*/
434
435
520.1.22 by Brian Aker
Second pass of thd cleanup
436
bool login_connection(Session *session)
1 by brian
clean slate
437
{
520.1.22 by Brian Aker
Second pass of thd cleanup
438
  NET *net= &session->net;
1 by brian
clean slate
439
  int error;
440
441
  /* Use "connect_timeout" value during connection phase */
442
  my_net_set_read_timeout(net, connect_timeout);
443
  my_net_set_write_timeout(net, connect_timeout);
444
  
520.1.22 by Brian Aker
Second pass of thd cleanup
445
  lex_start(session);
1 by brian
clean slate
446
520.1.22 by Brian Aker
Second pass of thd cleanup
447
  error= check_connection(session);
448
  net_end_statement(session);
1 by brian
clean slate
449
450
  if (error)
451
  {						// Wrong permissions
452
    statistic_increment(aborted_connects,&LOCK_status);
51.1.50 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
453
    return(1);
1 by brian
clean slate
454
  }
455
  /* Connect completed, set read/write timeouts back to default */
520.1.22 by Brian Aker
Second pass of thd cleanup
456
  my_net_set_read_timeout(net, session->variables.net_read_timeout);
457
  my_net_set_write_timeout(net, session->variables.net_write_timeout);
51.1.50 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
458
  return(0);
1 by brian
clean slate
459
}
460
461
462
/*
463
  Close an established connection
464
465
  NOTES
466
    This mainly updates status variables
467
*/
468
520.1.22 by Brian Aker
Second pass of thd cleanup
469
void end_connection(Session *session)
1 by brian
clean slate
470
{
520.1.22 by Brian Aker
Second pass of thd cleanup
471
  NET *net= &session->net;
472
  plugin_sessionvar_cleanup(session);
1 by brian
clean slate
473
520.1.22 by Brian Aker
Second pass of thd cleanup
474
  if (session->killed || (net->error && net->vio != 0))
1 by brian
clean slate
475
  {
476
    statistic_increment(aborted_threads,&LOCK_status);
477
  }
478
479
  if (net->error && net->vio != 0)
480
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
481
    if (!session->killed && session->variables.log_warnings > 1)
1 by brian
clean slate
482
    {
520.1.22 by Brian Aker
Second pass of thd cleanup
483
      Security_context *sctx= session->security_ctx;
1 by brian
clean slate
484
485
      sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION),
520.1.22 by Brian Aker
Second pass of thd cleanup
486
                        session->thread_id,(session->db ? session->db : "unconnected"),
1 by brian
clean slate
487
                        sctx->user ? sctx->user : "unauthenticated",
265 by brian
First pass through cleaning up security context.
488
                        sctx->ip,
520.1.22 by Brian Aker
Second pass of thd cleanup
489
                        (session->main_da.is_error() ? session->main_da.message() :
1 by brian
clean slate
490
                         ER(ER_UNKNOWN_ERROR)));
491
    }
492
  }
493
}
494
495
496
/*
520.1.21 by Brian Aker
THD -> Session rename
497
  Initialize Session to handle queries
1 by brian
clean slate
498
*/
499
520.1.22 by Brian Aker
Second pass of thd cleanup
500
void prepare_new_connection_state(Session* session)
1 by brian
clean slate
501
{
520.1.22 by Brian Aker
Second pass of thd cleanup
502
  Security_context *sctx= session->security_ctx;
1 by brian
clean slate
503
520.1.22 by Brian Aker
Second pass of thd cleanup
504
  if (session->variables.max_join_size == HA_POS_ERROR)
505
    session->options |= OPTION_BIG_SELECTS;
506
  if (session->client_capabilities & CLIENT_COMPRESS)
507
    session->net.compress=1;				// Use compression
1 by brian
clean slate
508
509
  /*
520.1.22 by Brian Aker
Second pass of thd cleanup
510
    Much of this is duplicated in create_embedded_session() for the
1 by brian
clean slate
511
    embedded server library.
512
    TODO: refactor this to avoid code duplication there
513
  */
520.1.22 by Brian Aker
Second pass of thd cleanup
514
  session->version= refresh_version;
515
  session->set_proc_info(0);
516
  session->command= COM_SLEEP;
517
  session->set_time();
518
  session->init_for_queries();
1 by brian
clean slate
519
520
  /* In the past this would only run of the user did not have SUPER_ACL */
521
  if (sys_init_connect.value_length)
522
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
523
    execute_init_command(session, &sys_init_connect, &LOCK_sys_init_connect);
524
    if (session->is_error())
1 by brian
clean slate
525
    {
520.1.22 by Brian Aker
Second pass of thd cleanup
526
      session->killed= Session::KILL_CONNECTION;
1 by brian
clean slate
527
      sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION),
520.1.22 by Brian Aker
Second pass of thd cleanup
528
                        session->thread_id,(session->db ? session->db : "unconnected"),
1 by brian
clean slate
529
                        sctx->user ? sctx->user : "unauthenticated",
265 by brian
First pass through cleaning up security context.
530
                        sctx->ip, "init_connect command failed");
520.1.22 by Brian Aker
Second pass of thd cleanup
531
      sql_print_warning("%s", session->main_da.message());
1 by brian
clean slate
532
    }
520.1.22 by Brian Aker
Second pass of thd cleanup
533
    session->set_proc_info(0);
534
    session->set_time();
535
    session->init_for_queries();
1 by brian
clean slate
536
  }
537
}
538
539
540
/*
541
  Thread handler for a connection
542
543
  SYNOPSIS
544
    handle_one_connection()
520.1.21 by Brian Aker
THD -> Session rename
545
    arg		Connection object (Session)
1 by brian
clean slate
546
547
  IMPLEMENTATION
548
    This function (normally) does the following:
549
    - Initialize thread
520.1.21 by Brian Aker
THD -> Session rename
550
    - Initialize Session to be used with this thread
1 by brian
clean slate
551
    - Authenticate user
552
    - Execute all queries sent on the connection
553
    - Take connection down
554
    - End thread  / Handle next connection using thread from thread cache
555
*/
556
557
pthread_handler_t handle_one_connection(void *arg)
558
{
520.1.22 by Brian Aker
Second pass of thd cleanup
559
  Session *session= (Session*) arg;
560
  uint32_t launch_time= (uint32_t) ((session->thr_create_utime= my_micro_time()) -
561
                              session->connect_utime);
1 by brian
clean slate
562
563
  if (thread_scheduler.init_new_connection_thread())
564
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
565
    close_connection(session, ER_OUT_OF_RESOURCES, 1);
1 by brian
clean slate
566
    statistic_increment(aborted_connects,&LOCK_status);
520.1.22 by Brian Aker
Second pass of thd cleanup
567
    thread_scheduler.end_thread(session,0);
1 by brian
clean slate
568
    return 0;
569
  }
570
  if (launch_time >= slow_launch_time*1000000L)
571
    statistic_increment(slow_launch_threads,&LOCK_status);
572
573
  /*
574
    handle_one_connection() is normally the only way a thread would
575
    start and would always be on the very high end of the stack ,
576
    therefore, the thread stack always starts at the address of the
520.1.22 by Brian Aker
Second pass of thd cleanup
577
    first local variable of handle_one_connection, which is session. We
1 by brian
clean slate
578
    need to know the start of the stack so that we could check for
579
    stack overruns.
580
  */
520.1.22 by Brian Aker
Second pass of thd cleanup
581
  session->thread_stack= (char*) &session;
582
  if (setup_connection_thread_globals(session))
1 by brian
clean slate
583
    return 0;
584
585
  for (;;)
586
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
587
    NET *net= &session->net;
1 by brian
clean slate
588
520.1.22 by Brian Aker
Second pass of thd cleanup
589
    if (login_connection(session))
1 by brian
clean slate
590
      goto end_thread;
591
520.1.22 by Brian Aker
Second pass of thd cleanup
592
    prepare_new_connection_state(session);
1 by brian
clean slate
593
594
    while (!net->error && net->vio != 0 &&
520.1.22 by Brian Aker
Second pass of thd cleanup
595
           !(session->killed == Session::KILL_CONNECTION))
1 by brian
clean slate
596
    {
520.1.22 by Brian Aker
Second pass of thd cleanup
597
      if (do_command(session))
1 by brian
clean slate
598
	break;
599
    }
520.1.22 by Brian Aker
Second pass of thd cleanup
600
    end_connection(session);
1 by brian
clean slate
601
   
602
end_thread:
520.1.22 by Brian Aker
Second pass of thd cleanup
603
    close_connection(session, 0, 1);
604
    if (thread_scheduler.end_thread(session,1))
1 by brian
clean slate
605
      return 0;                                 // Probably no-threads
606
607
    /*
608
      If end_thread() returns, we are either running with
609
      thread-handler=no-threads or this thread has been schedule to
610
      handle the next connection.
611
    */
520.1.22 by Brian Aker
Second pass of thd cleanup
612
    session= current_session;
613
    session->thread_stack= (char*) &session;
1 by brian
clean slate
614
  }
615
}