SQL Client with VodafoneUSBModem

Fork of MySQLClient by Donatien Garnier

Committer:
loc_tran17
Date:
Fri Nov 22 09:15:53 2013 +0000
Revision:
6:e8f34b496ab0
Child:
8:cdb6d1236f37
change to TCP Socket for VodafoneUSBModem

Who changed what in which revision?

UserRevisionLine numberNew contents of line
loc_tran17 6:e8f34b496ab0 1
loc_tran17 6:e8f34b496ab0 2
loc_tran17 6:e8f34b496ab0 3 /*
loc_tran17 6:e8f34b496ab0 4 Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
loc_tran17 6:e8f34b496ab0 5
loc_tran17 6:e8f34b496ab0 6 Permission is hereby granted, free of charge, to any person obtaining a copy
loc_tran17 6:e8f34b496ab0 7 of this software and associated documentation files (the "Software"), to deal
loc_tran17 6:e8f34b496ab0 8 in the Software without restriction, including without limitation the rights
loc_tran17 6:e8f34b496ab0 9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
loc_tran17 6:e8f34b496ab0 10 copies of the Software, and to permit persons to whom the Software is
loc_tran17 6:e8f34b496ab0 11 furnished to do so, subject to the following conditions:
loc_tran17 6:e8f34b496ab0 12
loc_tran17 6:e8f34b496ab0 13 The above copyright notice and this permission notice shall be included in
loc_tran17 6:e8f34b496ab0 14 all copies or substantial portions of the Software.
loc_tran17 6:e8f34b496ab0 15
loc_tran17 6:e8f34b496ab0 16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
loc_tran17 6:e8f34b496ab0 17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
loc_tran17 6:e8f34b496ab0 18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
loc_tran17 6:e8f34b496ab0 19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
loc_tran17 6:e8f34b496ab0 20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
loc_tran17 6:e8f34b496ab0 21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
loc_tran17 6:e8f34b496ab0 22 THE SOFTWARE.
loc_tran17 6:e8f34b496ab0 23 */
loc_tran17 6:e8f34b496ab0 24
loc_tran17 6:e8f34b496ab0 25 #include "mycrypt.h"
loc_tran17 6:e8f34b496ab0 26 #include "sha1.h"
loc_tran17 6:e8f34b496ab0 27 #include "MySQLClient.h"
loc_tran17 6:e8f34b496ab0 28
loc_tran17 6:e8f34b496ab0 29 //#define __DEBUG
loc_tran17 6:e8f34b496ab0 30
loc_tran17 6:e8f34b496ab0 31
loc_tran17 6:e8f34b496ab0 32 #define MYSQL_TIMEOUT_MS 45000
loc_tran17 6:e8f34b496ab0 33 #define MYSQL_PORT 3306
loc_tran17 6:e8f34b496ab0 34
loc_tran17 6:e8f34b496ab0 35 #define BUF_SIZE 256
loc_tran17 6:e8f34b496ab0 36
loc_tran17 6:e8f34b496ab0 37 #define CLIENT_LONG_PASSWORD 1
loc_tran17 6:e8f34b496ab0 38 #define CLIENT_CONNECT_WITH_DB 8
loc_tran17 6:e8f34b496ab0 39 #define CLIENT_PROTOCOL_41 512
loc_tran17 6:e8f34b496ab0 40 #define CLIENT_INTERACTIVE 1024
loc_tran17 6:e8f34b496ab0 41 #define CLIENT_SECURE_CONNECTION 32768
loc_tran17 6:e8f34b496ab0 42
loc_tran17 6:e8f34b496ab0 43 #define MIN(a,b) ((a)<(b)?(a):(b))
loc_tran17 6:e8f34b496ab0 44 #define ABS(a) (((a)>0)?(a):0)
loc_tran17 6:e8f34b496ab0 45
loc_tran17 6:e8f34b496ab0 46 //MySQL commands
loc_tran17 6:e8f34b496ab0 47 #define COM_QUIT 0x01 //Exit
loc_tran17 6:e8f34b496ab0 48 #define COM_QUERY 0x03 //Execute an SQL query
loc_tran17 6:e8f34b496ab0 49
loc_tran17 6:e8f34b496ab0 50 //#define htons( x ) ( (( x << 8 ) & 0xFF00) | (( x >> 8 ) & 0x00FF) )
loc_tran17 6:e8f34b496ab0 51 #define ntohs( x ) (htons(x))
loc_tran17 6:e8f34b496ab0 52
loc_tran17 6:e8f34b496ab0 53 /*#define htonl( x ) ( (( x << 24 ) & 0xFF000000) \
loc_tran17 6:e8f34b496ab0 54 | (( x << 8 ) & 0x00FF0000) \
loc_tran17 6:e8f34b496ab0 55 | (( x >> 8 ) & 0x0000FF00) \
loc_tran17 6:e8f34b496ab0 56 | (( x >> 24 ) & 0x000000FF) )*/
loc_tran17 6:e8f34b496ab0 57 #define htonl( x ) (x)
loc_tran17 6:e8f34b496ab0 58 #define ntohl( x ) (htonl(x))
loc_tran17 6:e8f34b496ab0 59
loc_tran17 6:e8f34b496ab0 60 MySQLClient::MySQLClient() : m_pCbItem(NULL), m_pCbMeth(NULL), m_pCb(NULL),
loc_tran17 6:e8f34b496ab0 61 m_pTCPSocket(NULL), m_watchdog(), m_timeout(MYSQL_TIMEOUT_MS*1000), m_closed(true),
loc_tran17 6:e8f34b496ab0 62 m_user(), m_password(), m_db(), m_state(MYSQL_CLOSED)
loc_tran17 6:e8f34b496ab0 63 {
loc_tran17 6:e8f34b496ab0 64 m_buf = new byte[BUF_SIZE];
loc_tran17 6:e8f34b496ab0 65 m_pPos = m_buf;
loc_tran17 6:e8f34b496ab0 66 m_len = 0;
loc_tran17 6:e8f34b496ab0 67 m_size = BUF_SIZE;
loc_tran17 6:e8f34b496ab0 68 }
loc_tran17 6:e8f34b496ab0 69
loc_tran17 6:e8f34b496ab0 70 MySQLClient::~MySQLClient()
loc_tran17 6:e8f34b496ab0 71 {
loc_tran17 6:e8f34b496ab0 72 close();
loc_tran17 6:e8f34b496ab0 73 delete[] m_buf;
loc_tran17 6:e8f34b496ab0 74 }
loc_tran17 6:e8f34b496ab0 75
loc_tran17 6:e8f34b496ab0 76 //High Level setup functions
loc_tran17 6:e8f34b496ab0 77 MySQLResult MySQLClient::open(const string& host, int port, const string& user, const string& password, const string& db, void (*pMethod)(MySQLResult)) //Non blocking
loc_tran17 6:e8f34b496ab0 78 {
loc_tran17 6:e8f34b496ab0 79 setOnResult(pMethod);
loc_tran17 6:e8f34b496ab0 80 setup(host, port, user, password, db);
loc_tran17 6:e8f34b496ab0 81 return MYSQL_PROCESSING;
loc_tran17 6:e8f34b496ab0 82 }
loc_tran17 6:e8f34b496ab0 83
loc_tran17 6:e8f34b496ab0 84 MySQLResult MySQLClient::sql(string& sqlCommand)
loc_tran17 6:e8f34b496ab0 85 {
loc_tran17 6:e8f34b496ab0 86 if(m_state!=MYSQL_COMMANDS)
loc_tran17 6:e8f34b496ab0 87 return MYSQL_SETUP;
loc_tran17 6:e8f34b496ab0 88 sendCommand(COM_QUERY, (byte*)sqlCommand.data(), sqlCommand.length());
loc_tran17 6:e8f34b496ab0 89 return MYSQL_PROCESSING;
loc_tran17 6:e8f34b496ab0 90 }
loc_tran17 6:e8f34b496ab0 91
loc_tran17 6:e8f34b496ab0 92 MySQLResult MySQLClient::exit()
loc_tran17 6:e8f34b496ab0 93 {
loc_tran17 6:e8f34b496ab0 94 sendCommand(COM_QUIT, NULL, 0);
loc_tran17 6:e8f34b496ab0 95 close();
loc_tran17 6:e8f34b496ab0 96 return MYSQL_OK;
loc_tran17 6:e8f34b496ab0 97 }
loc_tran17 6:e8f34b496ab0 98
loc_tran17 6:e8f34b496ab0 99 void MySQLClient::setOnResult( void (*pMethod)(MySQLResult) )
loc_tran17 6:e8f34b496ab0 100 {
loc_tran17 6:e8f34b496ab0 101 m_pCb = pMethod;
loc_tran17 6:e8f34b496ab0 102 m_pCbItem = NULL;
loc_tran17 6:e8f34b496ab0 103 m_pCbMeth = NULL;
loc_tran17 6:e8f34b496ab0 104 }
loc_tran17 6:e8f34b496ab0 105
loc_tran17 6:e8f34b496ab0 106 #if 0 //Ref only
loc_tran17 6:e8f34b496ab0 107 template<class T>
loc_tran17 6:e8f34b496ab0 108 void MySQLClient::setOnResult( T* pItem, void (T::*pMethod)(MySQLResult) )
loc_tran17 6:e8f34b496ab0 109 {
loc_tran17 6:e8f34b496ab0 110 m_pCb = NULL;
loc_tran17 6:e8f34b496ab0 111 m_pCbItem = (CDummy*) pItem;
loc_tran17 6:e8f34b496ab0 112 m_pCbMeth = (void (CDummy::*)(MySQLResult)) pMethod;
loc_tran17 6:e8f34b496ab0 113 }
loc_tran17 6:e8f34b496ab0 114 #endif
loc_tran17 6:e8f34b496ab0 115
loc_tran17 6:e8f34b496ab0 116 void MySQLClient::setTimeout(int ms)
loc_tran17 6:e8f34b496ab0 117 {
loc_tran17 6:e8f34b496ab0 118 m_timeout = 1000*ms;
loc_tran17 6:e8f34b496ab0 119 }
loc_tran17 6:e8f34b496ab0 120
loc_tran17 6:e8f34b496ab0 121 void MySQLClient::poll() //Called by NetServices
loc_tran17 6:e8f34b496ab0 122 {
loc_tran17 6:e8f34b496ab0 123 if(m_closed)
loc_tran17 6:e8f34b496ab0 124 {
loc_tran17 6:e8f34b496ab0 125 return;
loc_tran17 6:e8f34b496ab0 126 }
loc_tran17 6:e8f34b496ab0 127 if(m_watchdog.read_us()>m_timeout)
loc_tran17 6:e8f34b496ab0 128 {
loc_tran17 6:e8f34b496ab0 129 onTimeout();
loc_tran17 6:e8f34b496ab0 130 }
loc_tran17 6:e8f34b496ab0 131 }
loc_tran17 6:e8f34b496ab0 132
loc_tran17 6:e8f34b496ab0 133 void MySQLClient::resetTimeout()
loc_tran17 6:e8f34b496ab0 134 {
loc_tran17 6:e8f34b496ab0 135 m_watchdog.reset();
loc_tran17 6:e8f34b496ab0 136 m_watchdog.start();
loc_tran17 6:e8f34b496ab0 137 }
loc_tran17 6:e8f34b496ab0 138
loc_tran17 6:e8f34b496ab0 139 void MySQLClient::init()
loc_tran17 6:e8f34b496ab0 140 {
loc_tran17 6:e8f34b496ab0 141 close(); //Remove previous elements
loc_tran17 6:e8f34b496ab0 142 if(!m_closed) //Already opened
loc_tran17 6:e8f34b496ab0 143 return;
loc_tran17 6:e8f34b496ab0 144 m_state = MYSQL_HANDSHAKE;
loc_tran17 6:e8f34b496ab0 145 m_pTCPSocket = new TCPSocketConnection;
loc_tran17 6:e8f34b496ab0 146 #if 0
loc_tran17 6:e8f34b496ab0 147 m_pTCPSocket->setOnEvent(this, &MySQLClient::onTCPSocketEvent);
loc_tran17 6:e8f34b496ab0 148 #endif
loc_tran17 6:e8f34b496ab0 149 m_closed = false;
loc_tran17 6:e8f34b496ab0 150 }
loc_tran17 6:e8f34b496ab0 151
loc_tran17 6:e8f34b496ab0 152 void MySQLClient::close()
loc_tran17 6:e8f34b496ab0 153 {
loc_tran17 6:e8f34b496ab0 154 if(m_closed)
loc_tran17 6:e8f34b496ab0 155 return;
loc_tran17 6:e8f34b496ab0 156 m_state = MYSQL_CLOSED;
loc_tran17 6:e8f34b496ab0 157 m_closed = true; //Prevent recursive calling or calling on an object being destructed by someone else
loc_tran17 6:e8f34b496ab0 158 m_watchdog.stop(); //Stop timeout
loc_tran17 6:e8f34b496ab0 159 m_watchdog.reset();
loc_tran17 6:e8f34b496ab0 160 #if 0
loc_tran17 6:e8f34b496ab0 161 m_pTCPSocket->resetOnEvent();
loc_tran17 6:e8f34b496ab0 162 #endif
loc_tran17 6:e8f34b496ab0 163 m_pTCPSocket->close();
loc_tran17 6:e8f34b496ab0 164 delete m_pTCPSocket;
loc_tran17 6:e8f34b496ab0 165 m_pTCPSocket = NULL;
loc_tran17 6:e8f34b496ab0 166 #if 0
loc_tran17 6:e8f34b496ab0 167 if( m_pDnsReq )
loc_tran17 6:e8f34b496ab0 168 {
loc_tran17 6:e8f34b496ab0 169 m_pDnsReq->close();
loc_tran17 6:e8f34b496ab0 170 delete m_pDnsReq;
loc_tran17 6:e8f34b496ab0 171 m_pDnsReq = NULL;
loc_tran17 6:e8f34b496ab0 172 }
loc_tran17 6:e8f34b496ab0 173 #endif
loc_tran17 6:e8f34b496ab0 174 }
loc_tran17 6:e8f34b496ab0 175
loc_tran17 6:e8f34b496ab0 176 void MySQLClient::setup(const string& host, int port, const string& user, const string& password, const string& db) //Setup connection, make DNS Req if necessary
loc_tran17 6:e8f34b496ab0 177 {
loc_tran17 6:e8f34b496ab0 178 init(); //Initialize client in known state, create socket
loc_tran17 6:e8f34b496ab0 179 resetTimeout();
loc_tran17 6:e8f34b496ab0 180 #if 0
loc_tran17 6:e8f34b496ab0 181 m_host = host;
loc_tran17 6:e8f34b496ab0 182 if(!host.getPort())
loc_tran17 6:e8f34b496ab0 183 host.setPort( MYSQL_PORT ); //Default port
loc_tran17 6:e8f34b496ab0 184 #endif
loc_tran17 6:e8f34b496ab0 185
loc_tran17 6:e8f34b496ab0 186 m_host = host;
loc_tran17 6:e8f34b496ab0 187 m_port = port;
loc_tran17 6:e8f34b496ab0 188 m_user = user;
loc_tran17 6:e8f34b496ab0 189 m_password = password;
loc_tran17 6:e8f34b496ab0 190
loc_tran17 6:e8f34b496ab0 191 m_db = db;
loc_tran17 6:e8f34b496ab0 192
loc_tran17 6:e8f34b496ab0 193 #if 0
loc_tran17 6:e8f34b496ab0 194 if( !host.getIp().isNull() )
loc_tran17 6:e8f34b496ab0 195 {
loc_tran17 6:e8f34b496ab0 196 connect();
loc_tran17 6:e8f34b496ab0 197 }
loc_tran17 6:e8f34b496ab0 198 else //Need to do a DNS Query...
loc_tran17 6:e8f34b496ab0 199 {
loc_tran17 6:e8f34b496ab0 200 printf("DNS Query...\n");
loc_tran17 6:e8f34b496ab0 201 m_pDnsReq = new DNSRequest();
loc_tran17 6:e8f34b496ab0 202 m_pDnsReq->setOnReply(this, &MySQLClient::onDNSReply);
loc_tran17 6:e8f34b496ab0 203 m_pDnsReq->resolve(&m_host);
loc_tran17 6:e8f34b496ab0 204 printf("MySQLClient : DNSRequest %p\n", m_pDnsReq);
loc_tran17 6:e8f34b496ab0 205 }
loc_tran17 6:e8f34b496ab0 206 #endif
loc_tran17 6:e8f34b496ab0 207 connect();
loc_tran17 6:e8f34b496ab0 208 }
loc_tran17 6:e8f34b496ab0 209
loc_tran17 6:e8f34b496ab0 210 void MySQLClient::connect() //Start Connection
loc_tran17 6:e8f34b496ab0 211 {
loc_tran17 6:e8f34b496ab0 212 char host[128];
loc_tran17 6:e8f34b496ab0 213
loc_tran17 6:e8f34b496ab0 214 resetTimeout();
loc_tran17 6:e8f34b496ab0 215 printf("Connecting...");
loc_tran17 6:e8f34b496ab0 216
loc_tran17 6:e8f34b496ab0 217 strcpy(host, m_host.c_str());
loc_tran17 6:e8f34b496ab0 218 m_pTCPSocket->connect(host, m_port);
loc_tran17 6:e8f34b496ab0 219
loc_tran17 6:e8f34b496ab0 220 printf("OK \n");
loc_tran17 6:e8f34b496ab0 221 m_packetId = 0;
loc_tran17 6:e8f34b496ab0 222 }
loc_tran17 6:e8f34b496ab0 223
loc_tran17 6:e8f34b496ab0 224 void MySQLClient::handleHandshake()
loc_tran17 6:e8f34b496ab0 225 {
loc_tran17 6:e8f34b496ab0 226 readData();
loc_tran17 6:e8f34b496ab0 227 if( ! (( m_len > 1 ) && ( memchr( m_buf + 1, 0, m_len ) != NULL )) )
loc_tran17 6:e8f34b496ab0 228 {
loc_tran17 6:e8f34b496ab0 229 printf("Connected but could not find pcsz...\n");
loc_tran17 6:e8f34b496ab0 230 onResult(MYSQL_PRTCL);
loc_tran17 6:e8f34b496ab0 231 return;
loc_tran17 6:e8f34b496ab0 232 }
loc_tran17 6:e8f34b496ab0 233
loc_tran17 6:e8f34b496ab0 234 printf("Connected to server: %d bytes read ; Protocol version %d, mysql-%s.\n", m_len, m_buf[0], &m_buf[1]);
loc_tran17 6:e8f34b496ab0 235
loc_tran17 6:e8f34b496ab0 236 m_pPos = (byte*) memchr( (char*)(m_buf + 1), 0, m_len ) + 1;
loc_tran17 6:e8f34b496ab0 237
loc_tran17 6:e8f34b496ab0 238 sendAuth();
loc_tran17 6:e8f34b496ab0 239 }
loc_tran17 6:e8f34b496ab0 240
loc_tran17 6:e8f34b496ab0 241 void MySQLClient::sendAuth()
loc_tran17 6:e8f34b496ab0 242 {
loc_tran17 6:e8f34b496ab0 243 if( m_len - (m_pPos - m_buf) != 44)
loc_tran17 6:e8f34b496ab0 244 {
loc_tran17 6:e8f34b496ab0 245 //We only support protocol >= mysql-4.1
loc_tran17 6:e8f34b496ab0 246 printf("Message after pcsz has wrong len (%d != 44)...\n", m_len - (m_pPos - m_buf));
loc_tran17 6:e8f34b496ab0 247 onResult(MYSQL_PRTCL);
loc_tran17 6:e8f34b496ab0 248 return;
loc_tran17 6:e8f34b496ab0 249 }
loc_tran17 6:e8f34b496ab0 250
loc_tran17 6:e8f34b496ab0 251 uint16_t serverFlags = *((uint16_t*)&m_pPos[13]);
loc_tran17 6:e8f34b496ab0 252 printf("Server capabilities are %04X.\n", serverFlags);
loc_tran17 6:e8f34b496ab0 253
loc_tran17 6:e8f34b496ab0 254 uint32_t clientFlags = CLIENT_CONNECT_WITH_DB | CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION | CLIENT_INTERACTIVE;;
loc_tran17 6:e8f34b496ab0 255
loc_tran17 6:e8f34b496ab0 256 //if(serverFlags & CLIENT_LONG_PASSWORD)
loc_tran17 6:e8f34b496ab0 257
loc_tran17 6:e8f34b496ab0 258 printf("Using auth 4.1+\n");
loc_tran17 6:e8f34b496ab0 259 //Encrypt pw using scramble
loc_tran17 6:e8f34b496ab0 260 byte scramble[20+20]={0};
loc_tran17 6:e8f34b496ab0 261 memcpy(scramble, m_pPos+4, 8);
loc_tran17 6:e8f34b496ab0 262 memcpy(scramble+8, m_pPos+31, 12); // *(m_pPos+43) == 0 (zero-terminated char*)
loc_tran17 6:e8f34b496ab0 263
loc_tran17 6:e8f34b496ab0 264 byte stage1_hash[20] = {0};
loc_tran17 6:e8f34b496ab0 265 sha1( (byte*)m_password.data(), m_password.length(), stage1_hash );
loc_tran17 6:e8f34b496ab0 266
loc_tran17 6:e8f34b496ab0 267 sha1( stage1_hash, 20, ((byte*)scramble + 20) );
loc_tran17 6:e8f34b496ab0 268
loc_tran17 6:e8f34b496ab0 269 byte token[20] = {0};
loc_tran17 6:e8f34b496ab0 270 sha1( scramble, 40, token );
loc_tran17 6:e8f34b496ab0 271
loc_tran17 6:e8f34b496ab0 272 for(int i=0;i<20;i++)
loc_tran17 6:e8f34b496ab0 273 token[i] = token[i] ^ stage1_hash[i];
loc_tran17 6:e8f34b496ab0 274
loc_tran17 6:e8f34b496ab0 275 clientFlags |= CLIENT_LONG_PASSWORD;
loc_tran17 6:e8f34b496ab0 276
loc_tran17 6:e8f34b496ab0 277 printf("Building response\n");
loc_tran17 6:e8f34b496ab0 278 //Build response
loc_tran17 6:e8f34b496ab0 279
loc_tran17 6:e8f34b496ab0 280 //BE
loc_tran17 6:e8f34b496ab0 281 *((uint32_t*)&m_buf[0]) = htonl(clientFlags);
loc_tran17 6:e8f34b496ab0 282 *((uint32_t*)&m_buf[4]) = BUF_SIZE; //Max packets size
loc_tran17 6:e8f34b496ab0 283 m_buf[8] = 8; //latin1 charset
loc_tran17 6:e8f34b496ab0 284 memset((char*)(m_buf+9),0,23);
loc_tran17 6:e8f34b496ab0 285 strcpy((char*)(m_buf+32),m_user.c_str());
loc_tran17 6:e8f34b496ab0 286 m_pPos = m_buf + 32 + m_user.length() + 1;
loc_tran17 6:e8f34b496ab0 287 m_pPos[0] = 20;
loc_tran17 6:e8f34b496ab0 288 memcpy((char*)&m_pPos[1],token,20);
loc_tran17 6:e8f34b496ab0 289 strcpy((char*)(m_pPos+21),m_db.c_str());
loc_tran17 6:e8f34b496ab0 290 m_len = 32 + m_user.length() + 1 + 21 + m_db.length() + 1;
loc_tran17 6:e8f34b496ab0 291
loc_tran17 6:e8f34b496ab0 292 //Save first part of scramble in case we need it again
loc_tran17 6:e8f34b496ab0 293 memcpy(&m_buf[BUF_SIZE-8], scramble, 8);
loc_tran17 6:e8f34b496ab0 294
loc_tran17 6:e8f34b496ab0 295 m_state = MYSQL_AUTH;
loc_tran17 6:e8f34b496ab0 296
loc_tran17 6:e8f34b496ab0 297 printf("Writing data\n");
loc_tran17 6:e8f34b496ab0 298 writeData();
loc_tran17 6:e8f34b496ab0 299 }
loc_tran17 6:e8f34b496ab0 300
loc_tran17 6:e8f34b496ab0 301 void MySQLClient::handleAuthResult()
loc_tran17 6:e8f34b496ab0 302 {
loc_tran17 6:e8f34b496ab0 303 readData();
loc_tran17 6:e8f34b496ab0 304 if(m_len==1 && *m_buf==0xfe)
loc_tran17 6:e8f34b496ab0 305 {
loc_tran17 6:e8f34b496ab0 306 //Re-send auth using 4.0- auth
loc_tran17 6:e8f34b496ab0 307 sendAuth323();
loc_tran17 6:e8f34b496ab0 308 return;
loc_tran17 6:e8f34b496ab0 309 }
loc_tran17 6:e8f34b496ab0 310 m_watchdog.stop(); //Stop timeout
loc_tran17 6:e8f34b496ab0 311 m_watchdog.reset();
loc_tran17 6:e8f34b496ab0 312 if(m_len<2)
loc_tran17 6:e8f34b496ab0 313 {
loc_tran17 6:e8f34b496ab0 314 printf("Response too short..\n");
loc_tran17 6:e8f34b496ab0 315 onResult(MYSQL_PRTCL);
loc_tran17 6:e8f34b496ab0 316 return;
loc_tran17 6:e8f34b496ab0 317 }
loc_tran17 6:e8f34b496ab0 318 printf("RC=%d ",m_buf[0]);
loc_tran17 6:e8f34b496ab0 319 if(m_buf[0]==0)
loc_tran17 6:e8f34b496ab0 320 {
loc_tran17 6:e8f34b496ab0 321 m_buf[m_len] = 0;
loc_tran17 6:e8f34b496ab0 322 m_pPos = m_buf + 1;
loc_tran17 6:e8f34b496ab0 323 m_pPos += m_buf[1] +1;
loc_tran17 6:e8f34b496ab0 324 m_pPos += m_pPos[0];
loc_tran17 6:e8f34b496ab0 325 m_pPos += 1;
loc_tran17 6:e8f34b496ab0 326 printf("(OK) : Server status %d, Message : %s\n", *((uint16_t*)&m_pPos[0]), m_pPos+4);
loc_tran17 6:e8f34b496ab0 327 onResult(MYSQL_OK);
loc_tran17 6:e8f34b496ab0 328 }
loc_tran17 6:e8f34b496ab0 329 else
loc_tran17 6:e8f34b496ab0 330 {
loc_tran17 6:e8f34b496ab0 331 m_buf[m_len] = 0;
loc_tran17 6:e8f34b496ab0 332 printf("(Error %d) : %s\n", *((uint16_t*)&m_buf[1]), &m_buf[9]); //LE
loc_tran17 6:e8f34b496ab0 333 onResult(MYSQL_AUTHFAILED);
loc_tran17 6:e8f34b496ab0 334 return;
loc_tran17 6:e8f34b496ab0 335 }
loc_tran17 6:e8f34b496ab0 336 m_state = MYSQL_COMMANDS;
loc_tran17 6:e8f34b496ab0 337 }
loc_tran17 6:e8f34b496ab0 338
loc_tran17 6:e8f34b496ab0 339 void MySQLClient::sendAuth323()
loc_tran17 6:e8f34b496ab0 340 {
loc_tran17 6:e8f34b496ab0 341 printf("Using auth 4.0-\n");
loc_tran17 6:e8f34b496ab0 342 byte scramble[8]={0};
loc_tran17 6:e8f34b496ab0 343
loc_tran17 6:e8f34b496ab0 344 memcpy(scramble, &m_buf[BUF_SIZE-8], 8); //Recover scramble
loc_tran17 6:e8f34b496ab0 345
loc_tran17 6:e8f34b496ab0 346 //memcpy(scramble+8, m_pPos+31, 12); // *(m_pPos+43) == 0 (zero-terminated char*)
loc_tran17 6:e8f34b496ab0 347
loc_tran17 6:e8f34b496ab0 348 byte token[9]={0};
loc_tran17 6:e8f34b496ab0 349
loc_tran17 6:e8f34b496ab0 350 scramble_323((char*)token, (const char*)scramble, m_password.c_str());
loc_tran17 6:e8f34b496ab0 351
loc_tran17 6:e8f34b496ab0 352 printf("Building response\n");
loc_tran17 6:e8f34b496ab0 353 //Build response
loc_tran17 6:e8f34b496ab0 354
loc_tran17 6:e8f34b496ab0 355 memcpy((char*)m_buf,token,9);
loc_tran17 6:e8f34b496ab0 356 m_len = 9;
loc_tran17 6:e8f34b496ab0 357
loc_tran17 6:e8f34b496ab0 358 #if 0
loc_tran17 6:e8f34b496ab0 359 *((uint32_t*)&m_buf[0]) = htonl(clientFlags);
loc_tran17 6:e8f34b496ab0 360 *((uint32_t*)&m_buf[4]) = BUF_SIZE; //Max packets size
loc_tran17 6:e8f34b496ab0 361 m_buf[8] = 8; //latin1 charset
loc_tran17 6:e8f34b496ab0 362 memset((char*)(m_buf+9),0,23);
loc_tran17 6:e8f34b496ab0 363 strcpy((char*)(m_buf+32),m_user.c_str());
loc_tran17 6:e8f34b496ab0 364 m_pPos = m_buf + 32 + m_user.length() + 1;
loc_tran17 6:e8f34b496ab0 365 m_pPos[0] = 8;
loc_tran17 6:e8f34b496ab0 366 memcpy((char*)&m_pPos[1],token+1,8);
loc_tran17 6:e8f34b496ab0 367 strcpy((char*)(m_pPos+9),m_db.c_str());
loc_tran17 6:e8f34b496ab0 368 m_len = 32 + m_user.length() + 1 + 9 + m_db.length() + 1;
loc_tran17 6:e8f34b496ab0 369 #endif
loc_tran17 6:e8f34b496ab0 370
loc_tran17 6:e8f34b496ab0 371 printf("Writing data\n");
loc_tran17 6:e8f34b496ab0 372 writeData();
loc_tran17 6:e8f34b496ab0 373 }
loc_tran17 6:e8f34b496ab0 374
loc_tran17 6:e8f34b496ab0 375 void MySQLClient::sendCommand(byte command, byte* arg, int len)
loc_tran17 6:e8f34b496ab0 376 {
loc_tran17 6:e8f34b496ab0 377 printf("Sending command %d, payload of len %d\n", command, len);
loc_tran17 6:e8f34b496ab0 378 m_packetId=0;//Reset packet ID (New sequence)
loc_tran17 6:e8f34b496ab0 379 m_buf[0] = command;
loc_tran17 6:e8f34b496ab0 380 memcpy(&m_buf[1], arg, len);
loc_tran17 6:e8f34b496ab0 381 m_len = 1 + len;
loc_tran17 6:e8f34b496ab0 382 writeData();
loc_tran17 6:e8f34b496ab0 383 m_watchdog.start();
loc_tran17 6:e8f34b496ab0 384 }
loc_tran17 6:e8f34b496ab0 385
loc_tran17 6:e8f34b496ab0 386 void MySQLClient::handleCommandResult()
loc_tran17 6:e8f34b496ab0 387 {
loc_tran17 6:e8f34b496ab0 388 readData();
loc_tran17 6:e8f34b496ab0 389 m_watchdog.stop(); //Stop timeout
loc_tran17 6:e8f34b496ab0 390 m_watchdog.reset();
loc_tran17 6:e8f34b496ab0 391 if(m_len<2)
loc_tran17 6:e8f34b496ab0 392 {
loc_tran17 6:e8f34b496ab0 393 printf("Response too short..\n");
loc_tran17 6:e8f34b496ab0 394 onResult(MYSQL_PRTCL);
loc_tran17 6:e8f34b496ab0 395 return;
loc_tran17 6:e8f34b496ab0 396 }
loc_tran17 6:e8f34b496ab0 397 printf("RC=%d ",m_buf[0]);
loc_tran17 6:e8f34b496ab0 398 if(m_buf[0]==0)
loc_tran17 6:e8f34b496ab0 399 {
loc_tran17 6:e8f34b496ab0 400 printf("(OK)\n");
loc_tran17 6:e8f34b496ab0 401 onResult(MYSQL_OK);
loc_tran17 6:e8f34b496ab0 402 }
loc_tran17 6:e8f34b496ab0 403 else
loc_tran17 6:e8f34b496ab0 404 {
loc_tran17 6:e8f34b496ab0 405 m_buf[m_len] = 0;
loc_tran17 6:e8f34b496ab0 406 printf("(SQL Error %d) : %s\n", *((uint16_t*)&m_buf[1]), &m_buf[9]); //LE
loc_tran17 6:e8f34b496ab0 407 onResult(MYSQL_SQL);
loc_tran17 6:e8f34b496ab0 408 return;
loc_tran17 6:e8f34b496ab0 409 }
loc_tran17 6:e8f34b496ab0 410 }
loc_tran17 6:e8f34b496ab0 411
loc_tran17 6:e8f34b496ab0 412 void MySQLClient::readData() //Copy to buf
loc_tran17 6:e8f34b496ab0 413 {
loc_tran17 6:e8f34b496ab0 414 byte head[4];
loc_tran17 6:e8f34b496ab0 415 int ret = m_pTCPSocket->receive((char*)head, 4); //Packet header
loc_tran17 6:e8f34b496ab0 416 m_len = *((uint16_t*)&head[0]);
loc_tran17 6:e8f34b496ab0 417 m_packetId = head[3];
loc_tran17 6:e8f34b496ab0 418 printf("Packet Id %d of length %d\n", head[3], m_len);
loc_tran17 6:e8f34b496ab0 419 m_packetId++;
loc_tran17 6:e8f34b496ab0 420 if(ret>0)
loc_tran17 6:e8f34b496ab0 421 ret = m_pTCPSocket->receive((char*)m_buf, m_len);
loc_tran17 6:e8f34b496ab0 422 if(ret < 0)//Error
loc_tran17 6:e8f34b496ab0 423 {
loc_tran17 6:e8f34b496ab0 424 onResult(MYSQL_CONN);
loc_tran17 6:e8f34b496ab0 425 return;
loc_tran17 6:e8f34b496ab0 426 }
loc_tran17 6:e8f34b496ab0 427 if(ret < m_len)
loc_tran17 6:e8f34b496ab0 428 {
loc_tran17 6:e8f34b496ab0 429 printf("WARN: Incomplete packet\n");
loc_tran17 6:e8f34b496ab0 430 }
loc_tran17 6:e8f34b496ab0 431 m_len = ret;
loc_tran17 6:e8f34b496ab0 432 }
loc_tran17 6:e8f34b496ab0 433
loc_tran17 6:e8f34b496ab0 434 void MySQLClient::writeData() //Copy from buf
loc_tran17 6:e8f34b496ab0 435 {
loc_tran17 6:e8f34b496ab0 436 byte head[4] = { 0 };
loc_tran17 6:e8f34b496ab0 437 *((uint16_t*)&head[0]) = m_len;
loc_tran17 6:e8f34b496ab0 438 head[3] = m_packetId;
loc_tran17 6:e8f34b496ab0 439 printf("Packet Id %d\n", head[3]);
loc_tran17 6:e8f34b496ab0 440 m_packetId++;
loc_tran17 6:e8f34b496ab0 441 int ret = m_pTCPSocket->send((char*)head, 4); //Packet header
loc_tran17 6:e8f34b496ab0 442 if(ret>0)
loc_tran17 6:e8f34b496ab0 443 ret = m_pTCPSocket->send((char*)m_buf, m_len);
loc_tran17 6:e8f34b496ab0 444 if(ret < 0)//Error
loc_tran17 6:e8f34b496ab0 445 {
loc_tran17 6:e8f34b496ab0 446 onResult(MYSQL_CONN);
loc_tran17 6:e8f34b496ab0 447 return;
loc_tran17 6:e8f34b496ab0 448 }
loc_tran17 6:e8f34b496ab0 449 m_len = 0;//FIXME... incomplete packets handling
loc_tran17 6:e8f34b496ab0 450 }
loc_tran17 6:e8f34b496ab0 451
loc_tran17 6:e8f34b496ab0 452 #if 0
loc_tran17 6:e8f34b496ab0 453 void MySQLClient::onTCPSocketEvent(TCPSocketEvent e)
loc_tran17 6:e8f34b496ab0 454 {
loc_tran17 6:e8f34b496ab0 455 printf("Event %d in MySQLClient::onTCPSocketEvent()\n", e);
loc_tran17 6:e8f34b496ab0 456
loc_tran17 6:e8f34b496ab0 457 if(m_closed)
loc_tran17 6:e8f34b496ab0 458 {
loc_tran17 6:e8f34b496ab0 459 printf("WARN: Discarded\n");
loc_tran17 6:e8f34b496ab0 460 return;
loc_tran17 6:e8f34b496ab0 461 }
loc_tran17 6:e8f34b496ab0 462
loc_tran17 6:e8f34b496ab0 463 switch(e)
loc_tran17 6:e8f34b496ab0 464 {
loc_tran17 6:e8f34b496ab0 465 case TCPSOCKET_READABLE: //Incoming data
loc_tran17 6:e8f34b496ab0 466 resetTimeout();
loc_tran17 6:e8f34b496ab0 467 if(m_state == MYSQL_HANDSHAKE)
loc_tran17 6:e8f34b496ab0 468 handleHandshake();
loc_tran17 6:e8f34b496ab0 469 else if(m_state == MYSQL_AUTH)
loc_tran17 6:e8f34b496ab0 470 handleAuthResult();
loc_tran17 6:e8f34b496ab0 471 else if(m_state == MYSQL_COMMANDS)
loc_tran17 6:e8f34b496ab0 472 handleCommandResult();
loc_tran17 6:e8f34b496ab0 473 break;
loc_tran17 6:e8f34b496ab0 474 case TCPSOCKET_WRITEABLE: //We can send data
loc_tran17 6:e8f34b496ab0 475 resetTimeout();
loc_tran17 6:e8f34b496ab0 476 break;
loc_tran17 6:e8f34b496ab0 477 case TCPSOCKET_CONNECTED: //Connected, wait for handshake packet
loc_tran17 6:e8f34b496ab0 478 resetTimeout();
loc_tran17 6:e8f34b496ab0 479 break;
loc_tran17 6:e8f34b496ab0 480 case TCPSOCKET_CONTIMEOUT:
loc_tran17 6:e8f34b496ab0 481 case TCPSOCKET_CONRST:
loc_tran17 6:e8f34b496ab0 482 case TCPSOCKET_CONABRT:
loc_tran17 6:e8f34b496ab0 483 case TCPSOCKET_ERROR:
loc_tran17 6:e8f34b496ab0 484 printf("Connection error.\n");
loc_tran17 6:e8f34b496ab0 485 onResult(MYSQL_CONN);
loc_tran17 6:e8f34b496ab0 486 case TCPSOCKET_DISCONNECTED:
loc_tran17 6:e8f34b496ab0 487 //There might still be some data available for reading
loc_tran17 6:e8f34b496ab0 488 //So if we are in a reading state, do not close the socket yet
loc_tran17 6:e8f34b496ab0 489 if(m_state != MYSQL_CLOSED)
loc_tran17 6:e8f34b496ab0 490 {
loc_tran17 6:e8f34b496ab0 491 onResult(MYSQL_CONN);
loc_tran17 6:e8f34b496ab0 492 }
loc_tran17 6:e8f34b496ab0 493 printf("Connection closed by remote host.\n");
loc_tran17 6:e8f34b496ab0 494 break;
loc_tran17 6:e8f34b496ab0 495 }
loc_tran17 6:e8f34b496ab0 496 }
loc_tran17 6:e8f34b496ab0 497
loc_tran17 6:e8f34b496ab0 498 void MySQLClient::onDNSReply(DNSReply r)
loc_tran17 6:e8f34b496ab0 499 {
loc_tran17 6:e8f34b496ab0 500 if(m_closed)
loc_tran17 6:e8f34b496ab0 501 {
loc_tran17 6:e8f34b496ab0 502 printf("WARN: Discarded\n");
loc_tran17 6:e8f34b496ab0 503 return;
loc_tran17 6:e8f34b496ab0 504 }
loc_tran17 6:e8f34b496ab0 505
loc_tran17 6:e8f34b496ab0 506 if( r != DNS_FOUND )
loc_tran17 6:e8f34b496ab0 507 {
loc_tran17 6:e8f34b496ab0 508 printf("Could not resolve hostname.\n");
loc_tran17 6:e8f34b496ab0 509 onResult(MYSQL_DNS);
loc_tran17 6:e8f34b496ab0 510 return;
loc_tran17 6:e8f34b496ab0 511 }
loc_tran17 6:e8f34b496ab0 512
loc_tran17 6:e8f34b496ab0 513 printf("DNS Resolved to %d.%d.%d.%d.\n",m_host.getIp()[0],m_host.getIp()[1],m_host.getIp()[2],m_host.getIp()[3]);
loc_tran17 6:e8f34b496ab0 514 //If no error, m_host has been updated by m_pDnsReq so we're set to go !
loc_tran17 6:e8f34b496ab0 515 m_pDnsReq->close();
loc_tran17 6:e8f34b496ab0 516 delete m_pDnsReq;
loc_tran17 6:e8f34b496ab0 517 m_pDnsReq = NULL;
loc_tran17 6:e8f34b496ab0 518 connect();
loc_tran17 6:e8f34b496ab0 519 }
loc_tran17 6:e8f34b496ab0 520 #endif
loc_tran17 6:e8f34b496ab0 521
loc_tran17 6:e8f34b496ab0 522 void MySQLClient::onResult(MySQLResult r) //Called when exchange completed or on failure
loc_tran17 6:e8f34b496ab0 523 {
loc_tran17 6:e8f34b496ab0 524 if(m_pCbItem && m_pCbMeth)
loc_tran17 6:e8f34b496ab0 525 (m_pCbItem->*m_pCbMeth)(r);
loc_tran17 6:e8f34b496ab0 526 else if(m_pCb)
loc_tran17 6:e8f34b496ab0 527 m_pCb(r);
loc_tran17 6:e8f34b496ab0 528
loc_tran17 6:e8f34b496ab0 529 if( (r==MYSQL_DNS) || (r==MYSQL_PRTCL) || (r==MYSQL_AUTHFAILED) || (r==MYSQL_TIMEOUT) || (r==MYSQL_CONN) ) //Fatal error, close connection
loc_tran17 6:e8f34b496ab0 530 close();
loc_tran17 6:e8f34b496ab0 531 }
loc_tran17 6:e8f34b496ab0 532
loc_tran17 6:e8f34b496ab0 533 void MySQLClient::onTimeout() //Connection has timed out
loc_tran17 6:e8f34b496ab0 534 {
loc_tran17 6:e8f34b496ab0 535 printf("Timed out.\n");
loc_tran17 6:e8f34b496ab0 536 onResult(MYSQL_TIMEOUT);
loc_tran17 6:e8f34b496ab0 537 close();
loc_tran17 6:e8f34b496ab0 538 }
loc_tran17 6:e8f34b496ab0 539
loc_tran17 6:e8f34b496ab0 540
loc_tran17 6:e8f34b496ab0 541
loc_tran17 6:e8f34b496ab0 542