00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021
00022 #include <boost/program_options.hpp>
00023
00024 #include <algorithm>
00025 #include <climits>
00026
00027 #include <drizzled/gettext.h>
00028 #include <drizzled/error.h>
00029 #include <drizzled/error/sql_state.h>
00030 #include <drizzled/session.h>
00031 #include <drizzled/internal/m_string.h>
00032 #include <drizzled/module/option_map.h>
00033 #include <drizzled/util/tokenize.h>
00034 #include <plugin/mysql_protocol/errmsg.h>
00035 #include <plugin/mysql_protocol/mysql_protocol.h>
00036 #include <plugin/mysql_protocol/mysql_password.h>
00037 #include <plugin/mysql_protocol/options.h>
00038 #include <drizzled/identifier.h>
00039 #include <drizzled/plugin/function.h>
00040 #include <drizzled/diagnostics_area.h>
00041 #include <drizzled/system_variables.h>
00042 #include <libdrizzle-2.0/constants.h>
00043
00044 #define MIN_HANDSHAKE_SIZE 6
00045 #define PROTOCOL_VERSION 10
00046
00047 namespace po= boost::program_options;
00048 using namespace std;
00049 using namespace drizzled;
00050
00051 namespace drizzle_plugin {
00052
00053 static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
00054
00055 static port_constraint port;
00056 static timeout_constraint connect_timeout;
00057 static timeout_constraint read_timeout;
00058 static timeout_constraint write_timeout;
00059 static retry_constraint retry_count;
00060 static buffer_constraint buffer_length;
00061
00062 static uint32_t random_seed1;
00063 static uint32_t random_seed2;
00064 static const uint32_t random_max= 0x3FFFFFFF;
00065 static const double random_max_double= (double)0x3FFFFFFF;
00066
00067 ProtocolCounters ListenMySQLProtocol::mysql_counters;
00068
00069 void ListenMySQLProtocol::addCountersToTable()
00070 {
00071 counters.push_back(new drizzled::plugin::ListenCounter(new std::string("connection_count"), &getCounters().connectionCount));
00072 counters.push_back(new drizzled::plugin::ListenCounter(new std::string("connected"), &getCounters().connected));
00073 counters.push_back(new drizzled::plugin::ListenCounter(new std::string("failed_connections"), &getCounters().failedConnections));
00074 }
00075
00076 const std::string ListenMySQLProtocol::getHost() const
00077 {
00078 return _hostname;
00079 }
00080
00081 in_port_t ListenMySQLProtocol::getPort() const
00082 {
00083 return port.get();
00084 }
00085
00086 plugin::Client *ListenMySQLProtocol::getClient(int fd)
00087 {
00088 int new_fd= acceptTcp(fd);
00089 return new_fd == -1 ? NULL : new ClientMySQLProtocol(new_fd, getCounters());
00090 }
00091
00092 ClientMySQLProtocol::ClientMySQLProtocol(int fd, ProtocolCounters& set_counters) :
00093 _is_interactive(false),
00094 counters(set_counters)
00095 {
00096 net.vio= 0;
00097
00098 if (fd == -1)
00099 return;
00100
00101 net.init(fd, buffer_length.get());
00102 net.set_read_timeout(read_timeout.get());
00103 net.set_write_timeout(write_timeout.get());
00104 net.retry_count=retry_count.get();
00105 }
00106
00107 ClientMySQLProtocol::~ClientMySQLProtocol()
00108 {
00109 if (net.vio)
00110 net.vio->close();
00111 }
00112
00113 int ClientMySQLProtocol::getFileDescriptor()
00114 {
00115 return net.get_sd();
00116 }
00117
00118 bool ClientMySQLProtocol::isConnected()
00119 {
00120 return net.vio != 0;
00121 }
00122
00123 bool ClientMySQLProtocol::flush()
00124 {
00125 if (net.vio == NULL)
00126 return false;
00127 bool ret= net.write(packet.ptr(), packet.length());
00128 packet.length(0);
00129 return ret;
00130 }
00131
00132 void ClientMySQLProtocol::close()
00133 {
00134 if (net.vio)
00135 {
00136 net.close();
00137 net.end();
00138 counters.connected.decrement();
00139 }
00140 }
00141
00142 bool ClientMySQLProtocol::authenticate()
00143 {
00144 counters.connectionCount.increment();
00145 counters.connected.increment();
00146
00147
00148 net.set_read_timeout(connect_timeout.get());
00149 net.set_write_timeout(connect_timeout.get());
00150
00151 if (checkConnection())
00152 {
00153 if (counters.connected > counters.max_connections)
00154 {
00155 std::string errmsg(ER(ER_CON_COUNT_ERROR));
00156 sendError(ER_CON_COUNT_ERROR, errmsg.c_str());
00157 counters.failedConnections.increment();
00158 }
00159 else
00160 {
00161 sendOK();
00162 }
00163 }
00164 else
00165 {
00166 sendError(session->main_da().sql_errno(), session->main_da().message());
00167 counters.failedConnections.increment();
00168 return false;
00169 }
00170
00171
00172 net.set_read_timeout(read_timeout.get());
00173 net.set_write_timeout(write_timeout.get());
00174 return true;
00175 }
00176
00177 bool ClientMySQLProtocol::readCommand(char **l_packet, uint32_t& packet_length)
00178 {
00179
00180
00181
00182
00183
00184
00185 #ifdef NEVER
00186
00187
00188 drizzleclient_net_set_read_timeout(&net,
00189 session->variables.net_wait_timeout);
00190 #endif
00191
00192 net.pkt_nr=0;
00193 packet_length= net.read();
00194 if (packet_length == packet_error)
00195 {
00196
00197
00198 if(net.last_errno== ER_NET_PACKET_TOO_LARGE)
00199 my_error(ER_NET_PACKET_TOO_LARGE, MYF(0));
00200 if (session->main_da().status() == Diagnostics_area::DA_ERROR)
00201 sendError(session->main_da().sql_errno(), session->main_da().message());
00202 else
00203 sendOK();
00204
00205 if (net.error_ != 3)
00206 return false;
00207
00208 net.error_= 0;
00209 }
00210
00211 *l_packet= (char*) net.read_pos;
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 if (packet_length == 0)
00223 {
00224
00225 (*l_packet)[0]= COM_SLEEP;
00226 packet_length= 1;
00227 }
00228 else
00229 {
00230
00231 switch ((*l_packet)[0])
00232 {
00233 case 0:
00234 case 1:
00235 case 2:
00236 case 3:
00237 break;
00238
00239 case 8:
00240 (*l_packet)[0]= COM_SHUTDOWN;
00241 break;
00242
00243 case 12:
00244 (*l_packet)[0]= COM_KILL;
00245 break;
00246
00247 case 14:
00248 (*l_packet)[0]= COM_PING;
00249 break;
00250
00251 default:
00252
00253 (*l_packet)[0]= COM_END;
00254 packet_length= 1;
00255 }
00256 }
00257
00258
00259 (*l_packet)[packet_length]= '\0';
00260
00261 #ifdef NEVER
00262
00263
00264 drizzleclient_net_set_read_timeout(&net, session->variables.net_read_timeout);
00265 #endif
00266
00267 return true;
00268 }
00269
00291 void ClientMySQLProtocol::sendOK()
00292 {
00293 unsigned char buff[DRIZZLE_ERRMSG_SIZE+10],*pos;
00294 const char *message= NULL;
00295 uint32_t tmp;
00296
00297 if (!net.vio)
00298 {
00299 return;
00300 }
00301
00302 buff[0]=0;
00303 if (session->main_da().status() == Diagnostics_area::DA_OK)
00304 {
00305 if (client_capabilities & CLIENT_FOUND_ROWS && session->main_da().found_rows())
00306 pos=storeLength(buff+1,session->main_da().found_rows());
00307 else
00308 pos=storeLength(buff+1,session->main_da().affected_rows());
00309 pos=storeLength(pos, session->main_da().last_insert_id());
00310 int2store(pos, session->main_da().server_status());
00311 pos+=2;
00312 tmp= min(session->main_da().total_warn_count(), (uint32_t)65535);
00313 message= session->main_da().message();
00314 }
00315 else
00316 {
00317 pos=storeLength(buff+1,0);
00318 pos=storeLength(pos, 0);
00319 int2store(pos, session->server_status);
00320 pos+=2;
00321 tmp= min(session->total_warn_count, (uint32_t)65535);
00322 }
00323
00324
00325 int2store(pos, tmp);
00326 pos+= 2;
00327
00328 session->main_da().can_overwrite_status= true;
00329
00330 if (message && message[0])
00331 {
00332 size_t length= strlen(message);
00333 pos=storeLength(pos,length);
00334 memcpy(pos,(unsigned char*) message,length);
00335 pos+=length;
00336 }
00337 net.write(buff, pos - buff);
00338 net.flush();
00339
00340 session->main_da().can_overwrite_status= false;
00341 }
00342
00358 void ClientMySQLProtocol::sendEOF()
00359 {
00360
00361 if (net.vio)
00362 {
00363 session->main_da().can_overwrite_status= true;
00364 writeEOFPacket(session->main_da().server_status(), session->main_da().total_warn_count());
00365 net.flush();
00366 session->main_da().can_overwrite_status= false;
00367 }
00368 packet.shrink(buffer_length.get());
00369 }
00370
00371
00372 void ClientMySQLProtocol::sendError(drizzled::error_t sql_errno, const char *err)
00373 {
00374
00375 unsigned char buff[2 + 1 + SQLSTATE_LENGTH + DRIZZLE_ERRMSG_SIZE];
00376
00377 assert(sql_errno != EE_OK);
00378 assert(err && err[0]);
00379
00380
00381
00382
00383
00384 session->main_da().can_overwrite_status= true;
00385
00386
00387 session->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
00388
00397 if (net.vio == 0)
00398 {
00399 return;
00400 }
00401
00402 int2store(buff, static_cast<uint16_t>(sql_errno));
00403
00404
00405 buff[2]= '#';
00406 unsigned char* pos= (unsigned char*) strcpy((char*) buff+3, error::convert_to_sqlstate(sql_errno));
00407 pos+= strlen(error::convert_to_sqlstate(sql_errno));
00408
00409 char *tmp= strncpy((char*)pos, err, DRIZZLE_ERRMSG_SIZE-1);
00410 tmp+= strlen((char*)pos);
00411 tmp[0]= '\0';
00412 net.write_command(255, data_ref(), data_ref(buff, tmp));
00413 net.flush();
00414 session->main_da().can_overwrite_status= false;
00415 }
00416
00435 void ClientMySQLProtocol::sendFields(List<Item>& list)
00436 {
00437 List<Item>::iterator it(list.begin());
00438 unsigned char buff[80];
00439 String tmp((char*) buff,sizeof(buff),&my_charset_bin);
00440
00441 unsigned char *row_pos= storeLength(buff, list.size());
00442 (void) net.write(buff, row_pos - buff);
00443
00444 while (Item* item=it++)
00445 {
00446 SendField field;
00447 item->make_field(&field);
00448
00449 packet.length(0);
00450
00451 store(STRING_WITH_LEN("def"));
00452 store(field.db_name);
00453 store(field.table_name);
00454 store(field.org_table_name);
00455 store(field.col_name);
00456 store(field.org_col_name);
00457 packet.realloc(packet.length()+12);
00458
00459
00460 char* pos= (char*) packet.ptr()+packet.length();
00461 *pos++= 12;
00462
00463 int2store(pos, field.charsetnr);
00464 int4store(pos+2, field.length);
00465
00466 if (true)
00467 {
00468
00469 switch (field.type)
00470 {
00471 case DRIZZLE_TYPE_LONG:
00472 pos[6]= DRIZZLE_COLUMN_TYPE_LONG;
00473 break;
00474
00475 case DRIZZLE_TYPE_DOUBLE:
00476 pos[6]= DRIZZLE_COLUMN_TYPE_DOUBLE;
00477 break;
00478
00479 case DRIZZLE_TYPE_NULL:
00480 pos[6]= DRIZZLE_COLUMN_TYPE_NULL;
00481 break;
00482
00483 case DRIZZLE_TYPE_TIMESTAMP:
00484 pos[6]= DRIZZLE_COLUMN_TYPE_TIMESTAMP;
00485 break;
00486
00487 case DRIZZLE_TYPE_LONGLONG:
00488 pos[6]= DRIZZLE_COLUMN_TYPE_LONGLONG;
00489 break;
00490
00491 case DRIZZLE_TYPE_DATETIME:
00492 pos[6]= DRIZZLE_COLUMN_TYPE_DATETIME;
00493 break;
00494
00495 case DRIZZLE_TYPE_TIME:
00496 pos[6]= DRIZZLE_COLUMN_TYPE_TIME;
00497 break;
00498
00499 case DRIZZLE_TYPE_DATE:
00500 pos[6]= DRIZZLE_COLUMN_TYPE_DATE;
00501 break;
00502
00503 case DRIZZLE_TYPE_VARCHAR:
00504 pos[6]= DRIZZLE_COLUMN_TYPE_VARCHAR;
00505 break;
00506
00507 case DRIZZLE_TYPE_MICROTIME:
00508 pos[6]= DRIZZLE_COLUMN_TYPE_VARCHAR;
00509 break;
00510
00511 case DRIZZLE_TYPE_UUID:
00512 pos[6]= DRIZZLE_COLUMN_TYPE_VARCHAR;
00513 break;
00514
00515 case DRIZZLE_TYPE_IPV6:
00516 pos[6]= DRIZZLE_COLUMN_TYPE_VARCHAR;
00517 break;
00518
00519 case DRIZZLE_TYPE_BOOLEAN:
00520 pos[6]= DRIZZLE_COLUMN_TYPE_TINY;
00521 break;
00522
00523 case DRIZZLE_TYPE_DECIMAL:
00524 pos[6]= (char)DRIZZLE_COLUMN_TYPE_NEWDECIMAL;
00525 break;
00526
00527 case DRIZZLE_TYPE_ENUM:
00528 pos[6]= (char)DRIZZLE_COLUMN_TYPE_ENUM;
00529 break;
00530
00531 case DRIZZLE_TYPE_BLOB:
00532 pos[6]= (char)DRIZZLE_COLUMN_TYPE_BLOB;
00533 break;
00534 }
00535 }
00536 else
00537 {
00538
00539 pos[6]= field.type + 1;
00540 }
00541
00542 int2store(pos+7,field.flags);
00543 pos[9]= (char) field.decimals;
00544 pos[10]= 0;
00545 pos[11]= 0;
00546 pos+= 12;
00547
00548 packet.length((uint32_t) (pos - packet.ptr()));
00549 if (flush())
00550 break;
00551 }
00552
00553
00554
00555
00556
00557
00558 writeEOFPacket(session->server_status, session->total_warn_count);
00559 }
00560
00561 void ClientMySQLProtocol::store(Field *from)
00562 {
00563 if (from->is_null())
00564 return store();
00565 if (from->type() == DRIZZLE_TYPE_BOOLEAN)
00566 {
00567 return store(from->val_int());
00568 }
00569
00570 char buff[MAX_FIELD_WIDTH];
00571 String str(buff,sizeof(buff), &my_charset_bin);
00572
00573 from->val_str_internal(&str);
00574
00575 netStoreData(str.ptr(), str.length());
00576 }
00577
00578 void ClientMySQLProtocol::store()
00579 {
00580 char buff[1];
00581 buff[0]= (char)251;
00582 packet.append(buff, sizeof(buff), PACKET_BUFFER_EXTRA_ALLOC);
00583 }
00584
00585 void ClientMySQLProtocol::store(int32_t from)
00586 {
00587 char buff[12];
00588 netStoreData(buff, internal::int10_to_str(from, buff, -10) - buff);
00589 }
00590
00591 void ClientMySQLProtocol::store(uint32_t from)
00592 {
00593 char buff[11];
00594 netStoreData(buff, internal::int10_to_str(from, buff, 10) - buff);
00595 }
00596
00597 void ClientMySQLProtocol::store(int64_t from)
00598 {
00599 char buff[22];
00600 netStoreData(buff, internal::int64_t10_to_str(from, buff, -10) - buff);
00601 }
00602
00603 void ClientMySQLProtocol::store(uint64_t from)
00604 {
00605 char buff[21];
00606 netStoreData(buff, internal::int64_t10_to_str(from, buff, 10) - buff);
00607 }
00608
00609 void ClientMySQLProtocol::store(double from, uint32_t decimals, String *buffer)
00610 {
00611 buffer->set_real(from, decimals, session->charset());
00612 netStoreData(buffer->ptr(), buffer->length());
00613 }
00614
00615 void ClientMySQLProtocol::store(const char *from, size_t length)
00616 {
00617 netStoreData(from, length);
00618 }
00619
00620 bool ClientMySQLProtocol::wasAborted()
00621 {
00622 return net.error_ && net.vio != 0;
00623 }
00624
00625 bool ClientMySQLProtocol::haveError()
00626 {
00627 return net.error_ || net.vio == 0;
00628 }
00629
00630 bool ClientMySQLProtocol::checkConnection()
00631 {
00632 char scramble[SCRAMBLE_LENGTH];
00633 identifier::user::mptr user_identifier= identifier::User::make_shared();
00634
00635 makeScramble(scramble);
00636
00637
00638 {
00639 char ip[NI_MAXHOST];
00640 uint16_t peer_port;
00641
00642 if (net.peer_addr(ip, NI_MAXHOST, peer_port))
00643 {
00644 my_error(ER_BAD_HOST_ERROR, MYF(0), ip);
00645 return false;
00646 }
00647
00648 user_identifier->setAddress(ip);
00649 }
00650 net.keepalive(true);
00651
00652 char* end;
00653 uint32_t pkt_len= 0;
00654 uint32_t server_capabilites;
00655 {
00656
00657 char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH + 64];
00658
00659 server_capabilites= CLIENT_BASIC_FLAGS | CLIENT_PROTOCOL_MYSQL41;
00660
00661 #ifdef HAVE_COMPRESS
00662 server_capabilites|= CLIENT_COMPRESS;
00663 #endif
00664
00665 end= buff + strlen(PANDORA_RELEASE_VERSION);
00666 if ((end - buff) >= SERVER_VERSION_LENGTH)
00667 end= buff + (SERVER_VERSION_LENGTH - 1);
00668 memcpy(buff, PANDORA_RELEASE_VERSION, end - buff);
00669 *end= 0;
00670 end++;
00671
00672 int4store((unsigned char*) end, session->variables.pseudo_thread_id);
00673 end+= 4;
00674
00675
00676 memcpy(end, scramble, SCRAMBLE_LENGTH_323);
00677 end+= SCRAMBLE_LENGTH_323;
00678 *end++= 0;
00679
00680 int2store(end, server_capabilites);
00681
00682 end[2]=(char) default_charset_info->number;
00683 int2store(end+3, session->server_status);
00684 memset(end+5, 0, 13);
00685 end+= 18;
00686
00687
00688 memcpy(end, scramble + SCRAMBLE_LENGTH_323, SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323);
00689 end+= (SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323);
00690 *end++= 0;
00691
00692
00693 if (net.write_command(PROTOCOL_VERSION, data_ref(), data_ref(buff, end))
00694 || (pkt_len= net.read()) == packet_error
00695 || pkt_len < MIN_HANDSHAKE_SIZE)
00696 {
00697 my_error(ER_HANDSHAKE_ERROR, MYF(0), user_identifier->address().c_str());
00698 return false;
00699 }
00700 }
00701 packet.alloc(buffer_length.get());
00702
00703 client_capabilities= uint2korr(net.read_pos);
00704 if (not (client_capabilities & CLIENT_PROTOCOL_MYSQL41))
00705 {
00706 my_error(ER_HANDSHAKE_ERROR, MYF(0), user_identifier->address().c_str());
00707 return false;
00708 }
00709
00710 client_capabilities|= ((uint32_t) uint2korr(net.read_pos + 2)) << 16;
00711
00712 end= (char*) net.read_pos + 32;
00713
00714
00715
00716
00717
00718 client_capabilities&= server_capabilites;
00719
00720 if (end >= (char*) net.read_pos + pkt_len + 2)
00721 {
00722 my_error(ER_HANDSHAKE_ERROR, MYF(0), user_identifier->address().c_str());
00723 return false;
00724 }
00725
00726 char *user= end;
00727 char *passwd= strchr(user, '\0')+1;
00728 uint32_t user_len= passwd - user - 1;
00729 char *l_db= passwd;
00730
00731
00732
00733
00734
00735
00736
00737 uint32_t passwd_len;
00738 if (client_capabilities & CLIENT_SECURE_CONNECTION &&
00739 passwd < (char *) net.read_pos + pkt_len)
00740 {
00741 passwd_len= (unsigned char)(*passwd++);
00742 if (passwd_len > 0 and client_capabilities & CLIENT_CAPABILITIES_PLUGIN_AUTH)
00743 {
00744 user_identifier->setPasswordType(identifier::User::PLAIN_TEXT);
00745 }
00746 else if (passwd_len > 0)
00747 {
00748 user_identifier->setPasswordType(identifier::User::MYSQL_HASH);
00749 user_identifier->setPasswordContext(scramble, SCRAMBLE_LENGTH);
00750 }
00751 }
00752 else
00753 {
00754 passwd_len= 0;
00755 }
00756
00757 if (client_capabilities & CLIENT_CONNECT_WITH_DB &&
00758 passwd < (char *) net.read_pos + pkt_len)
00759 {
00760 l_db= l_db + passwd_len + 1;
00761 }
00762 else
00763 {
00764 l_db= NULL;
00765 }
00766
00767
00768 uint32_t db_len= l_db ? strlen(l_db) : 0;
00769
00770 if (passwd + passwd_len + db_len > (char *) net.read_pos + pkt_len)
00771 {
00772 my_error(ER_HANDSHAKE_ERROR, MYF(0), user_identifier->address().c_str());
00773 return false;
00774 }
00775
00776
00777 if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
00778 {
00779 user[user_len-1]= 0;
00780 user++;
00781 user_len-= 2;
00782 }
00783
00784 if (client_capabilities & CLIENT_INTERACTIVE)
00785 {
00786 _is_interactive= true;
00787 }
00788
00789 if (client_capabilities & CLIENT_CAPABILITIES_PLUGIN_AUTH)
00790 {
00791 passwd_len= strlen(passwd);
00792 }
00793
00794 user_identifier->setUser(user);
00795 session->setUser(user_identifier);
00796
00797 return session->checkUser(string(passwd, passwd_len), string(l_db ? l_db : ""));
00798
00799 }
00800
00801 void ClientMySQLProtocol::netStoreData(const void* from, size_t length)
00802 {
00803 size_t packet_length= packet.length();
00804
00805
00806
00807
00808 if (packet_length+9+length > packet.alloced_length())
00809 packet.realloc(packet_length+9+length);
00810 unsigned char *to= storeLength((unsigned char*) packet.ptr()+packet_length, length);
00811 memcpy(to,from,length);
00812 packet.length((size_t) (to+length-(unsigned char*) packet.ptr()));
00813 }
00814
00820 void ClientMySQLProtocol::writeEOFPacket(uint32_t server_status, uint32_t total_warn_count)
00821 {
00822 unsigned char buff[5];
00823
00824
00825
00826
00827 uint32_t tmp= min(total_warn_count, (uint32_t)65535);
00828 buff[0]= DRIZZLE_PROTOCOL_NO_MORE_DATA;
00829 int2store(buff+1, tmp);
00830
00831
00832
00833
00834
00835 if (session->is_fatal_error)
00836 server_status&= ~SERVER_MORE_RESULTS_EXISTS;
00837 int2store(buff + 3, server_status);
00838 net.write(buff, 5);
00839 }
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854 unsigned char *ClientMySQLProtocol::storeLength(unsigned char *buffer, uint64_t length)
00855 {
00856 if (length < 251)
00857 {
00858 *buffer= (unsigned char) length;
00859 return buffer+1;
00860 }
00861
00862 if (length < 65536)
00863 {
00864 *buffer++= 252;
00865 int2store(buffer, (uint32_t) length);
00866 return buffer+2;
00867 }
00868 if (length < 16777216)
00869 {
00870 *buffer++=253;
00871 int3store(buffer, (uint32_t) length);
00872 return buffer+3;
00873 }
00874 *buffer++=254;
00875 int8store(buffer, length);
00876 return buffer+8;
00877 }
00878
00879 void ClientMySQLProtocol::makeScramble(char *scramble)
00880 {
00881
00882 random_seed1= (random_seed1 * 3 + random_seed2) % random_max;
00883 random_seed2= (random_seed1 + random_seed2 + 33) % random_max;
00884 uint32_t seed= static_cast<uint32_t>((static_cast<double>(random_seed1) / random_max_double) * 0xffffffff);
00885
00886 void *pointer= this;
00887 uint32_t pointer_seed;
00888 memcpy(&pointer_seed, &pointer, 4);
00889 uint32_t random1= (seed + pointer_seed) % random_max;
00890 uint32_t random2= (seed + session->variables.pseudo_thread_id + net.vio->get_fd()) % random_max;
00891
00892 for (char *end= scramble + SCRAMBLE_LENGTH; scramble != end; scramble++)
00893 {
00894 random1= (random1 * 3 + random2) % random_max;
00895 random2= (random1 + random2 + 33) % random_max;
00896 *scramble= static_cast<char>((static_cast<double>(random1) / random_max_double) * 94 + 33);
00897 }
00898 }
00899
00900 static int init(drizzled::module::Context &context)
00901 {
00902
00903 time_t seed_time= time(NULL);
00904 random_seed1= seed_time % random_max;
00905 random_seed2= (seed_time / 2) % random_max;
00906
00907 const module::option_map &vm= context.getOptions();
00908
00909 context.add(new plugin::Create_function<MySQLPassword>(MySQLPasswordName));
00910
00911 ListenMySQLProtocol* listen_obj= new ListenMySQLProtocol("mysql_protocol", vm["bind-address"].as<std::string>());
00912 listen_obj->addCountersToTable();
00913 context.add(listen_obj);
00914 context.registerVariable(new sys_var_constrained_value_readonly<in_port_t>("port", port));
00915 context.registerVariable(new sys_var_constrained_value<uint32_t>("connect_timeout", connect_timeout));
00916 context.registerVariable(new sys_var_constrained_value<uint32_t>("read_timeout", read_timeout));
00917 context.registerVariable(new sys_var_constrained_value<uint32_t>("write_timeout", write_timeout));
00918 context.registerVariable(new sys_var_constrained_value<uint32_t>("retry_count", retry_count));
00919 context.registerVariable(new sys_var_constrained_value<uint32_t>("buffer_length", buffer_length));
00920 context.registerVariable(new sys_var_const_string_val("bind_address", vm["bind-address"].as<std::string>()));
00921 context.registerVariable(new sys_var_uint32_t_ptr("max-connections", &ListenMySQLProtocol::mysql_counters.max_connections));
00922
00923 return 0;
00924 }
00925
00926 static void init_options(drizzled::module::option_context &context)
00927 {
00928 context("port",
00929 po::value<port_constraint>(&port)->default_value(3306),
00930 _("Port number to use for connection or 0 for default to with MySQL "
00931 "protocol."));
00932 context("connect-timeout",
00933 po::value<timeout_constraint>(&connect_timeout)->default_value(10),
00934 _("Connect Timeout."));
00935 context("read-timeout",
00936 po::value<timeout_constraint>(&read_timeout)->default_value(30),
00937 _("Read Timeout."));
00938 context("write-timeout",
00939 po::value<timeout_constraint>(&write_timeout)->default_value(60),
00940 _("Write Timeout."));
00941 context("retry-count",
00942 po::value<retry_constraint>(&retry_count)->default_value(10),
00943 _("Retry Count."));
00944 context("buffer-length",
00945 po::value<buffer_constraint>(&buffer_length)->default_value(16384),
00946 _("Buffer length."));
00947 context("bind-address",
00948 po::value<string>()->default_value("localhost"),
00949 _("Address to bind to."));
00950 context("max-connections",
00951 po::value<uint32_t>(&ListenMySQLProtocol::mysql_counters.max_connections)->default_value(1000),
00952 _("Maximum simultaneous connections."));
00953 }
00954
00955 }
00956
00957 DRIZZLE_DECLARE_PLUGIN
00958 {
00959 DRIZZLE_VERSION_ID,
00960 "mysql-protocol",
00961 "0.1",
00962 "Eric Day",
00963 "MySQL Protocol Module",
00964 PLUGIN_LICENSE_GPL,
00965 drizzle_plugin::init,
00966 NULL,
00967 drizzle_plugin::init_options
00968 }
00969 DRIZZLE_DECLARE_PLUGIN_END;