void ParseReceivePacket() { //TODO: review here, optimized buffer _receiveBuffer = new byte[DEFAULT_BUFFER_SIZE]; var socket = _conn.socket; int receive = socket.Receive(_receiveBuffer); if (receive == 0) { return; } //--------------------------------------------------- //TODO: review err handling _parser.LoadNewBuffer(_receiveBuffer, receive); switch (_receiveBuffer[4]) { case ERROR_CODE: LoadError = new ErrPacket(); LoadError.ParsePacket(_parser); break; case 0xfe: //0x00 or 0xfe the OK packet header case OK_CODE: OkPacket = new OkPacket(_conn.IsProtocol41); OkPacket.ParsePacket(_parser); break; default: ParseResultSet(); break; } }
bool Parse_Ok_Content(MySqlStreamReader reader) { if (!reader.Ensure(_currentHeader.ContentLength)) //check if length is enough to parse { return(_needMoreData = true); } if (this._currentMultResultSet != null) { //in multiple result set mode *** //see https://dev.mysql.com/doc/internals/en/multi-resultset.html // var okPacket = new OkPacket(_currentHeader, this._isProtocol41); okPacket.ParsePacketContent(reader); _parseResult = _currentMultResultSet; _parsingState = ResultPacketState.ShouldEnd; //* // _currentMultResultSet = null; //reset } else { var okPacket = new OkPacket(_currentHeader, this._isProtocol41); okPacket.ParsePacketContent(reader); _parseResult = new MySqlOkResult(okPacket); _parsingState = ResultPacketState.ShouldEnd; //* } return(true); }
public void Connect() { if (State == ConnectionState.Connected) { throw new NotSupportedException("already connected"); } var endpoint = new IPEndPoint(IPAddress.Parse(config.host), config.port); socket.Connect(endpoint); byte[] buffer = new byte[512]; int count = socket.Receive(buffer); if (count > 0) { _writer.Reset(); _parser.LoadNewBuffer(buffer, count); _handshake = new HandshakePacket(); _handshake.ParsePacket(_parser); threadId = _handshake.threadId; byte[] token = MakeToken(config.password, GetScrollbleBuffer(_handshake.scrambleBuff1, _handshake.scrambleBuff2)); _writer.IncrementPacketNumber(); //------------------------------------------ var authPacket = new ClientAuthenticationPacket(); authPacket.SetValues(config.user, token, config.database, _handshake.protocol41); authPacket.WritePacket(_writer); byte[] sendBuff = _writer.ToArray(); byte[] receiveBuff = new byte[512]; //------------------------------------------- //send data int sendNum = socket.Send(sendBuff); int receiveNum = socket.Receive(receiveBuff); _parser.LoadNewBuffer(receiveBuff, receiveNum); if (receiveBuff[4] == 255) { ErrPacket errPacket = new ErrPacket(); errPacket.ParsePacket(_parser); return; } else { OkPacket okPacket = new OkPacket(_handshake.protocol41); okPacket.ParsePacket(_parser); } _writer.Reset(); GetMaxAllowedPacket(); _writer.SetMaxAllowedPacket(_maxPacketSize); } }
void RecvPacket_A(Action whenRecv) { _recvComplete = false; bool isFirstRecv = true; //before start recv _conn.StartReceive(result => { if (result == null) { throw new NotSupportedException(); } else { switch (result.Kind) { default: throw new NotSupportedException(); //unknown case MySqlResultKind.Ok: { OkPacket = (result as MySqlOkResult).okpacket; RecvComplete(); } break; case MySqlResultKind.Error: { MySqlErrorResult error = result as MySqlErrorResult; Error = error.errPacket; RecvComplete(); if (_errorListener != null) { _errorListener(error); } else { //ERROR throw new MySqlExecException(error); } } break; case MySqlResultKind.PrepareResponse: { //The server will send a OK_Packet if the statement could be reset, a ERR_Packet if not. //on prepare MySqlPrepareResponseResult response = result as MySqlPrepareResponseResult; _prepareContext = new PreparedContext( response.okPacket.statement_id, _sqlStrTemplate, response.tableHeader); RecvComplete(); } break; case MySqlResultKind.TableResult: { //support partial table mode //last sub table is not partial table //and must notify reader first*** //before call RecvComplete(); //----------------------------------------- MySqlTableResult tableResult = result as MySqlTableResult; //*** _recvComplete = !tableResult.HasFollower; //the _tableResultListener may modifid by other state (Close) //if don't lock we need to store it to local var _tableResultListener?.Invoke(tableResult); //----------------------------------------- if (!tableResult.HasFollower) { RecvComplete(); } } break; case MySqlResultKind.MultiTableResult: { MySqlMultiTableResult multiTables = result as MySqlMultiTableResult; List <MySqlTableResult> subTables = multiTables.subTables; int j = subTables.Count; for (int i = 0; i < j; ++i) { MySqlTableResult table = subTables[i]; if (i < j - 1) { //not the last one //(the last one may complete or not complete) table.HasFollower = true; //the _tableResultListener may modifid by other state (Close) //if don't lock we need to store it to local var _tableResultListener?.Invoke(table); } else { //this is the last one in the series //support partial table mode //last sub table is not partial table //and must notify reader first*** //before call RecvComplete(); _recvComplete = !table.HasFollower; //the _tableResultListener may modifid by other state (Close) //if don't lock we need to store it to local var _tableResultListener?.Invoke(table); if (!table.HasFollower) { RecvComplete(); } } } } break; } } //----------------- //exec once if (isFirstRecv) { isFirstRecv = false; whenRecv(); whenRecv = null; } //----------------- }); }
public MySqlOkResult(OkPacket okpacket) { this.okpacket = okpacket; }
void RecvPacket_A(Action whenRecv) { _recvComplete = false; bool isFirstRecv = true; _conn.StartReceive(result => { if (result == null) { throw new NotSupportedException(); } else { switch (result.Kind) { default: throw new NotSupportedException();//unknown case MySqlResultKind.Ok: { MySqlOkResult ok = result as MySqlOkResult; OkPacket = ok.okpacket; RecvComplete(); } break; case MySqlResultKind.Error: { MySqlErrorResult error = result as MySqlErrorResult; LoadError = error.errPacket; RecvComplete(); } break; case MySqlResultKind.PrepareResponse: { //The server will send a OK_Packet if the statement could be reset, a ERR_Packet if not. //on prepare MySqlPrepareResponseResult response = result as MySqlPrepareResponseResult; _prepareContext = new PreparedContext( response.okPacket.statement_id, _sqlStrTemplate, response.tableHeader); RecvComplete(); } break; case MySqlResultKind.TableResult: { //support partial table mode //last sub table is not partial table //and must notify reader first*** //before call RecvComplete(); //----------------------------------------- MySqlTableResult tableResult = result as MySqlTableResult; //*** _recvComplete = !tableResult.HasFollower; if (_tableResultListener != null) { //the _tableResultListener may modifid by other state (Close) //if don't lock we need to store it to local var _tableResultListener(tableResult); } //----------------------------------------- if (!tableResult.HasFollower) { RecvComplete(); } } break; case MySqlResultKind.MultiTableResult: { MySqlMultiTableResult multiTables = result as MySqlMultiTableResult; List<MySqlTableResult> subTables = multiTables.subTables; int j = subTables.Count; for (int i = 0; i < j; ++i) { MySqlTableResult table = subTables[i]; if (i < j - 1) { //not the last one //(the last one may complete or not complete) table.HasFollower = true; if (_tableResultListener != null) { //the _tableResultListener may modifid by other state (Close) //if don't lock we need to store it to local var _tableResultListener(table); } } else { //this is the last one in the series //support partial table mode //last sub table is not partial table //and must notify reader first*** //before call RecvComplete(); _recvComplete = !table.HasFollower; if (_tableResultListener != null) { //the _tableResultListener may modifid by other state (Close) //if don't lock we need to store it to local var _tableResultListener(table); } if (!table.HasFollower) { RecvComplete(); } } } } break; } } //----------------- //exec once if (isFirstRecv) { isFirstRecv = false; whenRecv(); whenRecv = null; } //----------------- }); }
public void ConnectAsync(Action connHandler) { //1. socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); _saea.SetBuffer(_sockBuffer, 0, _sockBuffer.Length); //2. buffer _connSession = new MySqlConnectionSession(_saea, 1024, 1024); _saea.UserToken = _connSession; _saea.AcceptSocket = socket; var endPoint = new IPEndPoint(IPAddress.Parse(config.host), config.port); //first connect socket.Connect(endPoint); _connSession.StartReceive(recv => { //TODO: review here, don't copy, //we should use shared sockBuffer byte[] buffer = new byte[512]; int count = recv.BytesTransferred; recv.CopyTo(0, buffer, 0, recv.BytesTransferred); _parser.LoadNewBuffer(buffer, count); _handshake = new HandshakePacket(); _handshake.ParsePacket(_parser); this.threadId = _handshake.threadId; byte[] token = MakeToken(config.password, GetScrollbleBuffer(_handshake.scrambleBuff1, _handshake.scrambleBuff2)); _writer.Reset(); _writer.IncrementPacketNumber(); //------------------------------------------ var authPacket = new ClientAuthenticationPacket(); authPacket.SetValues(config.user, token, config.database, _handshake.protocol41); authPacket.WritePacket(_writer); //send //do authen //handle recv._recvAction = () => { byte[] sendBuff = _writer.ToArray(); byte[] receiveBuff = new byte[512]; //------------------------------------------- //send data int sendNum = socket.Send(sendBuff); int receiveNum = socket.Receive(receiveBuff); _parser.LoadNewBuffer(receiveBuff, receiveNum); if (receiveBuff[4] == 255) { ErrPacket errPacket = new ErrPacket(); errPacket.ParsePacket(_parser); } else { OkPacket okPacket = new OkPacket(_handshake.protocol41); okPacket.ParsePacket(_parser); } _writer.Reset(); GetMaxAllowedPacket(); if (_maxPacketSize > 0) { _writer.SetMaxAllowedPacket(_maxPacketSize); } if (connHandler != null) { connHandler(); } }; return(EndReceiveState.Complete); }); }
bool Parse_Ok_Content(MySqlStreamReader reader) { if (!reader.Ensure(_currentHeader.ContentLength)) //check if length is enough to parse { return _needMoreData = true; } if (this._currentMultResultSet != null) { //in multiple result set mode *** //see https://dev.mysql.com/doc/internals/en/multi-resultset.html // var okPacket = new OkPacket(_currentHeader, this._isProtocol41); okPacket.ParsePacketContent(reader); _parseResult = _currentMultResultSet; _parsingState = ResultPacketState.ShouldEnd; //* // _currentMultResultSet = null;//reset } else { var okPacket = new OkPacket(_currentHeader, this._isProtocol41); okPacket.ParsePacketContent(reader); _parseResult = new MySqlOkResult(okPacket); _parsingState = ResultPacketState.ShouldEnd; //* } return true; }