private static ByteBufferWriter CreateCapabilitiesPayload(ProtocolCapabilities serverCapabilities, ConnectionSettings cs, bool useCompression, CharacterSet characterSet, ProtocolCapabilities additionalCapabilities = 0) { var writer = new ByteBufferWriter(); writer.Write((int)( ProtocolCapabilities.Protocol41 | (cs.InteractiveSession ? (serverCapabilities & ProtocolCapabilities.Interactive) : 0) | ProtocolCapabilities.LongPassword | (serverCapabilities & ProtocolCapabilities.Transactions) | ProtocolCapabilities.SecureConnection | (serverCapabilities & ProtocolCapabilities.PluginAuth) | (serverCapabilities & ProtocolCapabilities.PluginAuthLengthEncodedClientData) | ProtocolCapabilities.MultiStatements | ProtocolCapabilities.MultiResults | ProtocolCapabilities.LocalFiles | (string.IsNullOrWhiteSpace(cs.Database) ? 0 : ProtocolCapabilities.ConnectWithDatabase) | (cs.UseAffectedRows ? 0 : ProtocolCapabilities.FoundRows) | (useCompression ? ProtocolCapabilities.Compress : ProtocolCapabilities.None) | (serverCapabilities & ProtocolCapabilities.ConnectionAttributes) | (serverCapabilities & ProtocolCapabilities.SessionTrack) | (serverCapabilities & ProtocolCapabilities.DeprecateEof) | additionalCapabilities)); writer.Write(0x4000_0000); writer.Write((byte)characterSet); writer.Write(s_padding); return(writer); }
public bool WriteQueryCommand(ref CommandListPosition commandListPosition, IDictionary <string, CachedProcedure?> cachedProcedures, ByteBufferWriter writer) { writer.Write((byte)CommandKind.Multi); bool?firstResult = default; bool wroteCommand; do { // save room for command length var position = writer.Position; writer.Write(Padding); wroteCommand = SingleCommandPayloadCreator.Instance.WriteQueryCommand(ref commandListPosition, cachedProcedures, writer); if (firstResult is null) { firstResult = wroteCommand; } // write command length var commandLength = writer.Position - position - Padding.Length; var span = writer.ArraySegment.AsSpan().Slice(position); span[0] = 0xFE; BinaryPrimitives.WriteUInt64LittleEndian(span.Slice(1), (ulong)commandLength); } while (wroteCommand); // remove the padding that was saved for the final command (which wasn't written) writer.TrimEnd(Padding.Length); return(firstResult.Value); }
private static void WritePreparedStatement(IMySqlCommand command, PreparedStatement preparedStatement, ByteBufferWriter writer) { var parameterCollection = command.RawParameters; if (Log.IsDebugEnabled()) { Log.Debug("Session{0} Preparing command payload; CommandId: {1}; CommandText: {2}", command.Connection !.Session.Id, preparedStatement.StatementId, command.CommandText); } writer.Write(preparedStatement.StatementId); writer.Write((byte)0); writer.Write(1); if (preparedStatement.Parameters?.Length > 0) { // TODO: How to handle incorrect number of parameters? // build subset of parameters for this statement var parameters = new MySqlParameter[preparedStatement.Statement.ParameterNames.Count]; for (var i = 0; i < preparedStatement.Statement.ParameterNames.Count; i++) { var parameterName = preparedStatement.Statement.ParameterNames[i]; var parameterIndex = parameterName is object?(parameterCollection?.NormalizedIndexOf(parameterName) ?? -1) : preparedStatement.Statement.ParameterIndexes[i]; if (parameterIndex == -1 && parameterName is object) { throw new MySqlException("Parameter '{0}' must be defined.".FormatInvariant(parameterName)); } else if (parameterIndex < 0 || parameterIndex >= (parameterCollection?.Count ?? 0)) { throw new MySqlException("Parameter index {0} is invalid when only {1} parameter{2} defined.".FormatInvariant(parameterIndex, parameterCollection?.Count ?? 0, parameterCollection?.Count == 1 ? " is" : "s are")); } parameters[i] = parameterCollection ![parameterIndex];
public static PayloadData Create(string databaseName) { var writer = new ByteBufferWriter(); writer.Write((byte)CommandKind.InitDatabase); writer.Write(databaseName); return(writer.ToPayloadData()); }
public static PayloadData Create(string filename) { var writer = new ByteBufferWriter(); var position = 4; var flags = (ushort)BinlogFlags.NonBlock; var serverId = 10; writer.Write((byte)CommandKind.BinlogDump); writer.Write(position); writer.Write(flags); writer.Write(serverId); writer.Write(filename); return(writer.ToPayloadData()); }
private PayloadData CreateQueryPayload(PreparedStatement preparedStatement, MySqlParameterCollection parameterCollection, MySqlGuidFormat guidFormat) { var writer = new ByteBufferWriter(); writer.Write((byte)CommandKind.StatementExecute); writer.Write(preparedStatement.StatementId); writer.Write((byte)0); writer.Write(1); if (preparedStatement.Parameters?.Length > 0) { // TODO: How to handle incorrect number of parameters? // build subset of parameters for this statement var parameters = new MySqlParameter[preparedStatement.Statement.ParameterNames.Count]; for (var i = 0; i < preparedStatement.Statement.ParameterNames.Count; i++) { var parameterName = preparedStatement.Statement.ParameterNames[i]; var parameterIndex = parameterName != null?parameterCollection.NormalizedIndexOf(parameterName) : preparedStatement.Statement.ParameterIndexes[i]; parameters[i] = parameterCollection[parameterIndex]; } // write null bitmap byte nullBitmap = 0; for (var i = 0; i < parameters.Length; i++) { var parameter = parameters[i]; if (parameter.Value == null || parameter.Value == DBNull.Value) { if (i > 0 && i % 8 == 0) { writer.Write(nullBitmap); nullBitmap = 0; } nullBitmap |= (byte)(1 << (i % 8)); } } writer.Write(nullBitmap); // write "new parameters bound" flag writer.Write((byte)1); foreach (var parameter in parameters) { writer.Write(TypeMapper.ConvertToColumnTypeAndFlags(parameter.MySqlDbType, guidFormat)); } var options = m_command.CreateStatementPreparerOptions(); foreach (var parameter in parameters) { parameter.AppendBinary(writer, options); } } return(writer.ToPayloadData()); }
public void can_continue_on_a_partial_write() { var buffer = new byte[] { 1, 2, 3, 4, 5, 6, 7 }; var mgr = new BufferManager(100, 10); var context = new WriterContext(mgr); context.BytesLeftToEnqueue = 4; var sut = new ByteBufferWriter(buffer, 0, buffer.Length); context.BytesLeftToEnqueue = 4; sut.Write(context); context.BytesLeftToEnqueue = 10; var actual = sut.Write(context); actual.Should().BeTrue(); var packet = context.GetPackets()[1]; packet.Buffer[packet.Offset + 2].Should().Be(7); }
public void ParseAndBindParameters(ByteBufferWriter writer) { if (!string.IsNullOrWhiteSpace(m_commandText)) { writer.Write((byte)CommandKind.Query); var parser = new ParameterSqlParser(this, writer); parser.Parse(m_commandText); } }
private static ByteBufferWriter CreateCapabilitiesPayload(ProtocolCapabilities serverCapabilities, ConnectionSettings cs, bool useCompression, CharacterSet characterSet, ProtocolCapabilities additionalCapabilities = 0) { var writer = new ByteBufferWriter(); writer.Write((int)( ProtocolCapabilities.Protocol41 | (cs.InteractiveSession ? (serverCapabilities & ProtocolCapabilities.Interactive) : 0) | (serverCapabilities & ProtocolCapabilities.LongPassword) | (serverCapabilities & ProtocolCapabilities.Transactions) | ProtocolCapabilities.SecureConnection | (serverCapabilities & ProtocolCapabilities.PluginAuth) | (serverCapabilities & ProtocolCapabilities.PluginAuthLengthEncodedClientData) | ProtocolCapabilities.MultiStatements | ProtocolCapabilities.MultiResults | (cs.AllowLoadLocalInfile ? ProtocolCapabilities.LocalFiles : 0) | (string.IsNullOrWhiteSpace(cs.Database) ? 0 : ProtocolCapabilities.ConnectWithDatabase) | (cs.UseAffectedRows ? 0 : ProtocolCapabilities.FoundRows) | (useCompression ? ProtocolCapabilities.Compress : ProtocolCapabilities.None) | (serverCapabilities & ProtocolCapabilities.ConnectionAttributes) | (serverCapabilities & ProtocolCapabilities.SessionTrack) | (serverCapabilities & ProtocolCapabilities.DeprecateEof) | additionalCapabilities)); writer.Write(0x4000_0000); writer.Write((byte)characterSet); // NOTE: not new byte[19]; see https://github.com/dotnet/roslyn/issues/33088 ReadOnlySpan <byte> padding = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; writer.Write(padding); if ((serverCapabilities & ProtocolCapabilities.LongPassword) == 0) { // MariaDB writes extended capabilities at the end of the padding writer.Write((int)(((long)(serverCapabilities & ProtocolCapabilities.MariaDbComMulti)) >> 32)); } else { writer.Write(0u); } return(writer); }
public void can_write_to_our_context() { var buffer = new byte[] {1, 2, 3, 4, 5, 6, 7}; var mgr = new BufferManager(100, 10); var context = new WriterContext(mgr); var sut = new ByteBufferWriter(buffer, 0, buffer.Length); sut.Write(context); context.GetPackets()[0].Buffer.Should().BeSubsetOf(buffer); }
public void can_do_partial_write() { var buffer = new byte[] { 1, 2, 3, 4, 5, 6, 7 }; var mgr = new BufferManager(100, 10); var context = new WriterContext(mgr); context.BytesLeftToEnqueue = 4; var sut = new ByteBufferWriter(buffer, 0, buffer.Length); var actual = sut.Write(context); actual.Should().BeFalse(); }
public void can_write_to_our_context() { var buffer = new byte[] { 1, 2, 3, 4, 5, 6, 7 }; var mgr = new BufferManager(100, 10); var context = new WriterContext(mgr); var sut = new ByteBufferWriter(buffer, 0, buffer.Length); sut.Write(context); context.GetPackets()[0].Buffer.Should().BeSubsetOf(buffer); }
public void partial_bytes_are_copied() { var buffer = new byte[] { 1, 2, 3, 4, 5, 6, 7 }; var mgr = new BufferManager(100, 10); var context = new WriterContext(mgr); context.BytesLeftToEnqueue = 4; var sut = new ByteBufferWriter(buffer, 0, buffer.Length); sut.Write(context); context.GetPackets()[0].Buffer[3].Should().Be(4); }
public ArraySegment <byte> ParseAndBindParameters() { var writer = new ByteBufferWriter(m_commandText.Length + 1); writer.Write((byte)CommandKind.Query); if (!string.IsNullOrWhiteSpace(m_commandText)) { var parser = new ParameterSqlParser(this, writer); parser.Parse(m_commandText); } return(writer.ArraySegment); }
public bool WriteQueryCommand(ref CommandListPosition commandListPosition, IDictionary <string, CachedProcedure?> cachedProcedures, ByteBufferWriter writer) { if (commandListPosition.CommandIndex == commandListPosition.Commands.Count) { return(false); } var command = commandListPosition.Commands[commandListPosition.CommandIndex]; var preparedStatements = command.TryGetPreparedStatements(); if (preparedStatements is null) { if (Log.IsDebugEnabled()) { Log.Debug("Session{0} Preparing command payload; CommandText: {1}", command.Connection !.Session.Id, command.CommandText); } writer.Write((byte)CommandKind.Query); WriteQueryPayload(command, cachedProcedures, writer); commandListPosition.CommandIndex++; } else { writer.Write((byte)CommandKind.StatementExecute); WritePreparedStatement(command, preparedStatements.Statements[commandListPosition.PreparedStatementIndex], writer); // advance to next prepared statement or next command if (++commandListPosition.PreparedStatementIndex == preparedStatements.Statements.Count) { commandListPosition.CommandIndex++; commandListPosition.PreparedStatementIndex = 0; } } return(true); }
public void WriteString(int length) { var expected = new byte[length * 3]; for (var i = 0; i < length; i++) { expected[i * 3] = 0xEE; expected[i * 3 + 1] = 0x80; expected[i * 3 + 2] = 0x81; } var writer = new ByteBufferWriter(); var input = char.ConvertFromUtf32(0xE001); for (var i = 0; i < length; i++) { writer.Write(input); } Assert.Equal(expected, writer.ArraySegment); }
public bool WriteQueryCommand(ref CommandListPosition commandListPosition, IDictionary <string, CachedProcedure?> cachedProcedures, ByteBufferWriter writer) { if (commandListPosition.CommandIndex == commandListPosition.Commands.Count) { return(false); } writer.Write((byte)CommandKind.Query); bool isComplete; do { var command = commandListPosition.Commands[commandListPosition.CommandIndex]; if (Log.IsTraceEnabled()) { Log.Trace("Session{0} Preparing command payload; CommandText: {1}", command.Connection !.Session.Id, command.CommandText); } isComplete = SingleCommandPayloadCreator.WriteQueryPayload(command, cachedProcedures, writer); commandListPosition.CommandIndex++; }while (commandListPosition.CommandIndex < commandListPosition.Commands.Count && isComplete); return(true); }
public static PayloadData Create(string user, ReadOnlySpan <byte> authResponse, string?schemaName, CharacterSet characterSet, byte[]?connectionAttributes) { var writer = new ByteBufferWriter(); writer.Write((byte)CommandKind.ChangeUser); writer.WriteNullTerminatedString(user); writer.Write(checked ((byte)authResponse.Length)); writer.Write(authResponse); writer.WriteNullTerminatedString(schemaName ?? ""); writer.Write((byte)characterSet); writer.Write((byte)0); writer.WriteNullTerminatedString("mysql_native_password"); if (connectionAttributes is not null) { writer.Write(connectionAttributes); } return(writer.ToPayloadData()); }
public static PayloadData Create(string user, byte[] authResponse, string schemaName, byte[] connectionAttributes) { var writer = new ByteBufferWriter(); writer.Write((byte)CommandKind.ChangeUser); writer.WriteNullTerminatedString(user); writer.Write(checked ((byte)authResponse.Length)); writer.Write(authResponse); writer.WriteNullTerminatedString(schemaName ?? ""); writer.Write((byte)CharacterSet.Utf8Mb4Binary); writer.Write((byte)0); writer.WriteNullTerminatedString("mysql_native_password"); if (connectionAttributes != null) { writer.Write(connectionAttributes); } return(writer.ToPayloadData()); }
private void WritePreparedStatement(IMySqlCommand command, PreparedStatement preparedStatement, ByteBufferWriter writer) { var parameterCollection = command.Parameters; if (Log.IsDebugEnabled()) { Log.Debug("Session{0} Preparing command payload; CommandId: {1}; CommandText: {2}", command.Connection.Session.Id, preparedStatement.StatementId, command.CommandText); } writer.Write((byte)CommandKind.StatementExecute); writer.Write(preparedStatement.StatementId); writer.Write((byte)0); writer.Write(1); if (preparedStatement.Parameters?.Length > 0) { // TODO: How to handle incorrect number of parameters? // build subset of parameters for this statement var parameters = new MySqlParameter[preparedStatement.Statement.ParameterNames.Count]; for (var i = 0; i < preparedStatement.Statement.ParameterNames.Count; i++) { var parameterName = preparedStatement.Statement.ParameterNames[i]; var parameterIndex = parameterName != null ? (parameterCollection?.NormalizedIndexOf(parameterName) ?? -1) : preparedStatement.Statement.ParameterIndexes[i]; if (parameterIndex == -1 && parameterName != null) { throw new MySqlException("Parameter '{0}' must be defined.".FormatInvariant(parameterName)); } else if (parameterIndex < 0 || parameterIndex >= (parameterCollection?.Count ?? 0)) { throw new MySqlException("Parameter index {0} is invalid when only {1} parameter{2} defined.".FormatInvariant(parameterIndex, parameterCollection?.Count ?? 0, parameterCollection?.Count == 1 ? " is" : "s are")); } parameters[i] = parameterCollection[parameterIndex]; } // write null bitmap byte nullBitmap = 0; for (var i = 0; i < parameters.Length; i++) { var parameter = parameters[i]; if (parameter.Value is null || parameter.Value == DBNull.Value) { nullBitmap |= (byte)(1 << (i % 8)); } if (i % 8 == 7) { writer.Write(nullBitmap); nullBitmap = 0; } } if (parameters.Length % 8 != 0) { writer.Write(nullBitmap); } // write "new parameters bound" flag writer.Write((byte)1); foreach (var parameter in parameters) { writer.Write(TypeMapper.ConvertToColumnTypeAndFlags(parameter.MySqlDbType, command.Connection.GuidFormat)); } var options = command.CreateStatementPreparerOptions(); foreach (var parameter in parameters) { parameter.AppendBinary(writer, options); } } }
private PayloadData CreateQueryPayload(PreparedStatement preparedStatement, MySqlParameterCollection parameterCollection, MySqlGuidFormat guidFormat) { var writer = new ByteBufferWriter(); writer.Write((byte)CommandKind.StatementExecute); writer.Write(preparedStatement.StatementId); writer.Write((byte)0); writer.Write(1); if (preparedStatement.Parameters?.Length > 0) { // TODO: How to handle incorrect number of parameters? // build subset of parameters for this statement var parameters = new MySqlParameter[preparedStatement.Statement.ParameterNames.Count]; for (var i = 0; i < preparedStatement.Statement.ParameterNames.Count; i++) { var parameterName = preparedStatement.Statement.ParameterNames[i]; var parameterIndex = parameterName != null ? (parameterCollection?.NormalizedIndexOf(parameterName) ?? -1) : preparedStatement.Statement.ParameterIndexes[i]; if (parameterIndex == -1 && parameterName != null) { throw new MySqlException("Parameter '{0}' must be defined.".FormatInvariant(parameterName)); } else if (parameterIndex < 0 || parameterIndex >= (parameterCollection?.Count ?? 0)) { throw new MySqlException("Parameter index {0} is invalid when only {1} parameter{2} defined.".FormatInvariant(parameterIndex, parameterCollection?.Count ?? 0, parameterCollection?.Count == 1 ? " is" : "s are")); } parameters[i] = parameterCollection[parameterIndex]; } // write null bitmap byte nullBitmap = 0; for (var i = 0; i < parameters.Length; i++) { var parameter = parameters[i]; if (parameter.Value == null || parameter.Value == DBNull.Value) { if (i > 0 && i % 8 == 0) { writer.Write(nullBitmap); nullBitmap = 0; } nullBitmap |= (byte)(1 << (i % 8)); } } writer.Write(nullBitmap); // write "new parameters bound" flag writer.Write((byte)1); foreach (var parameter in parameters) { writer.Write(TypeMapper.ConvertToColumnTypeAndFlags(parameter.MySqlDbType, guidFormat)); } var options = m_command.CreateStatementPreparerOptions(); foreach (var parameter in parameters) { parameter.AppendBinary(writer, options); } } return(writer.ToPayloadData()); }