Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xdoc/plans2
-rwxr-xr-xdoc/sqlite2
-rw-r--r--man/mono.14
-rwxr-xr-xmcs/class/ByteFX.Data/AssemblyInfo.cs8
-rw-r--r--mcs/class/ByteFX.Data/ByteFX.Data.dll.sources1
-rwxr-xr-xmcs/class/ByteFX.Data/ChangeLog.txt36
-rw-r--r--mcs/class/ByteFX.Data/Common/DBConnectionString.cs8
-rw-r--r--mcs/class/ByteFX.Data/Common/DBParametersEditor.cs2
-rw-r--r--mcs/class/ByteFX.Data/Common/MultiHostStream.cs194
-rwxr-xr-xmcs/class/ByteFX.Data/Common/NamedPipeStream.cs2
-rw-r--r--mcs/class/ByteFX.Data/Common/Security.cs2
-rw-r--r--mcs/class/ByteFX.Data/Common/SqlCommandTextEditor.cs2
-rw-r--r--mcs/class/ByteFX.Data/Common/Version.cs2
-rwxr-xr-xmcs/class/ByteFX.Data/mysqlclient/CommandBuilder.cs15
-rwxr-xr-xmcs/class/ByteFX.Data/mysqlclient/Connection.cs22
-rw-r--r--mcs/class/ByteFX.Data/mysqlclient/ConnectionInternal.cs20
-rw-r--r--mcs/class/ByteFX.Data/mysqlclient/ConnectionString.cs2
-rwxr-xr-xmcs/class/ByteFX.Data/mysqlclient/Driver.cs117
-rwxr-xr-xmcs/class/ByteFX.Data/mysqlclient/Exception.cs17
-rwxr-xr-xmcs/class/ByteFX.Data/mysqlclient/Field.cs22
-rw-r--r--mcs/class/ByteFX.Data/mysqlclient/MySqlHelper.cs118
-rw-r--r--mcs/class/ByteFX.Data/mysqlclient/MySqlPool.cs93
-rw-r--r--mcs/class/ByteFX.Data/mysqlclient/MySqlPoolManager.cs4
-rw-r--r--mcs/class/ByteFX.Data/mysqlclient/MySqlStream.cs150
-rwxr-xr-xmcs/class/ByteFX.Data/mysqlclient/MysqlDefs.cs38
-rw-r--r--mcs/class/ByteFX.Data/mysqlclient/Packet.cs111
-rwxr-xr-xmcs/class/ByteFX.Data/mysqlclient/command.cs116
-rwxr-xr-xmcs/class/ByteFX.Data/mysqlclient/dataadapter.cs153
-rwxr-xr-xmcs/class/ByteFX.Data/mysqlclient/datareader.cs84
-rwxr-xr-xmcs/class/ByteFX.Data/mysqlclient/parameter.cs204
-rwxr-xr-xmcs/class/ByteFX.Data/mysqlclient/parameter_collection.cs107
-rwxr-xr-xmcs/class/ByteFX.Data/mysqlclient/transcaction.cs34
-rw-r--r--mcs/class/Microsoft.JScript/Microsoft.JScript/ChangeLog13
-rw-r--r--mcs/class/Microsoft.JScript/Microsoft.JScript/CodeGenerator.cs131
-rw-r--r--mcs/class/Microsoft.JScript/Microsoft.JScript/Literal.cs12
-rw-r--r--mcs/class/Microsoft.JScript/Microsoft.JScript/StringLiteral.cs5
-rwxr-xr-xmcs/class/Microsoft.JScript/Microsoft.JScript/expression.cs42
-rwxr-xr-xmcs/class/Mono.Security/Mono.Security.Cryptography/MD5SHA1CryptoServiceProvider.cs127
-rwxr-xr-xmcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsCompressionMethod.cs37
-rw-r--r--mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsNetworkStream.cs369
-rw-r--r--mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsProtocol.cs34
-rw-r--r--mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSession.cs265
-rw-r--r--mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSessionContext.cs289
-rw-r--r--mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSessionSettings.cs218
-rw-r--r--mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSocket.cs664
-rwxr-xr-xmcs/class/System.Data.ObjectSpaces/System.Data.ObjectSpaces/PersistenceErrorBehaviour.cs21
-rwxr-xr-xmcs/class/System.Data.ObjectSpaces/System.Data.ObjectSpaces/PersisteneceErrorType.cs23
-rw-r--r--mcs/class/System.Web/System.Web.UI/TODO42
-rw-r--r--mcs/class/System/Test/system_linux_test.args37
-rw-r--r--mcs/class/corlib/System.Reflection/common.src25
-rw-r--r--mono/metadata/ChangeLog4
-rw-r--r--mono/metadata/reflection.c3
-rw-r--r--mono/mini/cpu-g4.md5
-rw-r--r--mono/mini/inssel-ppc.brg18
-rw-r--r--mono/mini/mini-ppc.c23
-rw-r--r--runtime/Makefile.am2
-rwxr-xr-xweb/plans2
-rwxr-xr-xweb/sqlite2
58 files changed, 3523 insertions, 582 deletions
diff --git a/doc/plans b/doc/plans
index db6f6dde7c8..f53aecd4e95 100755
--- a/doc/plans
+++ b/doc/plans
@@ -8,7 +8,7 @@
Currently you can read our plans for <a
href="ado-net.html">ADO.NET</a>, <a
- href="asp-net">ASP.NET</a>, <a href="java.html">Java</a> and
+ href="asp-net.html">ASP.NET</a>, <a href="java.html">Java</a> and
<a href="winforms.html">WinForms</a>.
diff --git a/doc/sqlite b/doc/sqlite
index 35ee3056896..6730477202c 100755
--- a/doc/sqlite
+++ b/doc/sqlite
@@ -82,7 +82,7 @@
{
string connectionString = "URI=file:SqliteTest.db";
IDbConnection dbcon;
- dbcon = new MySQLConnection(connectionString);
+ dbcon = new SqliteConnection(connectionString);
dbcon.Open();
IDbCommand dbcmd = dbcon.CreateCommand();
// requires a table to be created named employee
diff --git a/man/mono.1 b/man/mono.1
index 3c680323dd3..b668b344a33 100644
--- a/man/mono.1
+++ b/man/mono.1
@@ -271,6 +271,8 @@ Visit http://mail.ximian.com/mailman/mono-list for details.
.SH WEB SITE
Visit: http://www.go-mono.com for details
.SH SEE ALSO
-.BR mcs(1), mint(1), monodis(1), mono-config(5)
+.BR mcs(1), mint(1), monodis(1), mono-config(5).
+.PP
+For ASP.NET-related documentation, see the xsp(1) manual page
diff --git a/mcs/class/ByteFX.Data/AssemblyInfo.cs b/mcs/class/ByteFX.Data/AssemblyInfo.cs
index 39aab33df80..07e3da27400 100755
--- a/mcs/class/ByteFX.Data/AssemblyInfo.cs
+++ b/mcs/class/ByteFX.Data/AssemblyInfo.cs
@@ -26,7 +26,7 @@ using System.Runtime.CompilerServices;
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
-[assembly: AssemblyVersion("0.7.2.*")]
+[assembly: AssemblyVersion("0.7.4.*")]
//
// In order to sign your assembly you must specify a key to use. Refer to the
@@ -53,6 +53,6 @@ using System.Runtime.CompilerServices;
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
// documentation for more information on this.
//
-//[assembly: AssemblyDelaySign(false)]
-//[assembly: AssemblyKeyFile("..\\..\\bytefx.snk")]
-//[assembly: AssemblyKeyName("")]
+[assembly: AssemblyDelaySign(false)]
+[assembly: AssemblyKeyFile("..\\..\\bytefx.snk")]
+[assembly: AssemblyKeyName("")]
diff --git a/mcs/class/ByteFX.Data/ByteFX.Data.dll.sources b/mcs/class/ByteFX.Data/ByteFX.Data.dll.sources
index 9d2af306d9c..305c1b42bad 100644
--- a/mcs/class/ByteFX.Data/ByteFX.Data.dll.sources
+++ b/mcs/class/ByteFX.Data/ByteFX.Data.dll.sources
@@ -10,6 +10,7 @@
./Common/SqlCommandTextEditor.cs
./Common/StringUtility.cs
./Common/Version.cs
+./Common/MultiHostStream.cs
./mysqlclient/CharSetMap.cs
./mysqlclient/CommandBuilder.cs
./mysqlclient/command.cs
diff --git a/mcs/class/ByteFX.Data/ChangeLog.txt b/mcs/class/ByteFX.Data/ChangeLog.txt
index acd157dbee2..3a805d686e1 100755
--- a/mcs/class/ByteFX.Data/ChangeLog.txt
+++ b/mcs/class/ByteFX.Data/ChangeLog.txt
@@ -1,3 +1,39 @@
+11/30/2003
+MySql - Fixed ConnectionSTring editor dialog (thanks marco p (pomarc))
+Common - UserId now supported in connection strings (thanks Jeff Neeley)
+MySql - Attempting to create a parameter that is not input throws an exception (thanks Ryan Gregg)
+
+11/29/2003
+MySql - Added much documentation
+
+11/26/2003
+MySql - checked in new MultiHostStream capability. Big thanks to Dan Guisinger for this. he originally submitted the code and idea of supporting multiple machines on the connect string.
+
+11/25/2003
+MySql - Added alot of documentation. Still alot to do.
+
+11/24/2003
+MySql - Fixed speed issue with 0.73
+
+11/14/2003
+MySql - changed to Thread.Sleep(0) in MySqlDataStream to help optimize the case where it doesn't need to wait (thanks Todd German)
+11/1/2003
+MySql - Prepopulating the idlepools to MinPoolSize
+
+10/31/2003
+MySql - Fixed MySqlPool deadlock condition as well as stupid bug where CreateNewPooledConnection
+ was not ever adding new connections to the pool.
+ Also fixed MySqlStream.ReadBytes and ReadByte to not use TicksPerSecond which does not appear
+ to always be right.
+ (thanks Matthew J. Peddlesden)
+MySql - Fix for precision and scale (thanks Matthew J. Peddlesden)
+
+10/28/2003
+MySql - Added Thread.Sleep(1) to stream reading methods to be more cpu friendly (thanks Sean McGinnis)
+
+10/24/2003
+MySql - Fixed problem where ExecuteReader would sometime return null (thanks Lloyd Dupont )
+
10/17/2003
MySql - Fixed major bug with null field handling (thanks Naucki)
diff --git a/mcs/class/ByteFX.Data/Common/DBConnectionString.cs b/mcs/class/ByteFX.Data/Common/DBConnectionString.cs
index 03943266449..2fe01655ad4 100644
--- a/mcs/class/ByteFX.Data/Common/DBConnectionString.cs
+++ b/mcs/class/ByteFX.Data/Common/DBConnectionString.cs
@@ -119,7 +119,10 @@ namespace ByteFX.Data.Common
!persistSecurityInfo) continue;
str.AppendFormat("{0}={1};", key, keyValues[key]);
}
- str.Remove( str.Length-1, 1 );
+
+ if (str.Length > 0)
+ str.Remove( str.Length-1, 1 );
+
return str.ToString();
}
@@ -138,6 +141,7 @@ namespace ByteFX.Data.Common
case "username":
case "user id":
case "user name":
+ case "userid":
username = value;
break;
@@ -216,6 +220,8 @@ namespace ByteFX.Data.Common
}
}
+ keyValues.Clear();
+
// now we run through our normalized key-values, splitting on equals
for (int y=0; y < x; y++)
{
diff --git a/mcs/class/ByteFX.Data/Common/DBParametersEditor.cs b/mcs/class/ByteFX.Data/Common/DBParametersEditor.cs
index 7e065fad4c7..0a555796100 100644
--- a/mcs/class/ByteFX.Data/Common/DBParametersEditor.cs
+++ b/mcs/class/ByteFX.Data/Common/DBParametersEditor.cs
@@ -24,7 +24,7 @@ namespace ByteFX.Data.Common
/// <summary>
/// Summary description for DBParametersEditor.
/// </summary>
- public class DBParametersEditor : CollectionEditor
+ internal class DBParametersEditor : CollectionEditor
{
public DBParametersEditor(Type t) : base(t)
{
diff --git a/mcs/class/ByteFX.Data/Common/MultiHostStream.cs b/mcs/class/ByteFX.Data/Common/MultiHostStream.cs
new file mode 100644
index 00000000000..56a2c8f9534
--- /dev/null
+++ b/mcs/class/ByteFX.Data/Common/MultiHostStream.cs
@@ -0,0 +1,194 @@
+using System;
+using System.Net;
+using System.IO;
+using System.Collections;
+using System.Threading;
+
+namespace ByteFX.Data.Common
+{
+ internal enum MultiHostStreamErrorType
+ {
+ Connecting,
+ Reading,
+ Writing
+ }
+
+ /// <summary>
+ /// Summary description for MultiHostStream.
+ /// </summary>
+ internal abstract class MultiHostStream : Stream
+ {
+ protected Stream stream;
+ protected int readTimeOut;
+ protected Exception baseException;
+
+ /// <summary>
+ /// Constructs a new MultiHostStream object with the given parameters
+ /// </summary>
+ /// <param name="hostList"></param>
+ /// <param name="port"></param>
+ /// <param name="readTimeOut"></param>
+ /// <param name="connectTimeOut"></param>
+ public MultiHostStream(string hostList, int port, int readTimeOut, int connectTimeOut)
+ {
+ this.readTimeOut = readTimeOut;
+ ProcessHosts( hostList, port, connectTimeOut );
+ }
+
+ protected abstract void TimeOut(MultiHostStreamErrorType error);
+ protected abstract void Error(string msg);
+ protected abstract bool CreateStream( IPAddress ip, string host, int port );
+ protected abstract bool DataAvailable
+ {
+ get;
+ }
+
+ private void ProcessHosts( string hostList, int port, int connectTimeOut )
+ {
+ int startTime = Environment.TickCount;
+
+ int toTicks = connectTimeOut * 1000;
+ //
+ // Host name can contain multiple hosts, seperated by &.
+ string [] dnsHosts = hostList.Split('&');
+ Hashtable ips = new Hashtable();
+
+ //
+ // Each host name specified may contain multiple IP addresses
+ // Lets look at the DNS entries for each host name
+ foreach(string h in dnsHosts)
+ {
+ IPHostEntry hostAddress = Dns.GetHostByName(h);
+ foreach (IPAddress addr in hostAddress.AddressList)
+ ips.Add( addr, hostAddress.HostName );
+ }
+ IPAddress[] keys = new IPAddress[ ips.Count ];
+ ips.Keys.CopyTo( keys, 0 );
+
+ if ((Environment.TickCount - startTime) > toTicks)
+ {
+ TimeOut(MultiHostStreamErrorType.Connecting);
+ return;
+ }
+
+ // make sure they gave us at least one host
+ if (ips.Count == 0)
+ {
+ Error("You must specify at least one host");
+ return;
+ }
+
+ int index = 0;
+ // now choose a random server if there are more than one
+ if (ips.Count > 1)
+ {
+ System.Random random = new Random((int)DateTime.Now.Ticks);
+ index = random.Next(ips.Count-1);
+ }
+
+ //
+ // Lets step through our hosts until we get a connection
+ for (int i=0; i < ips.Count; i++)
+ {
+ if ((Environment.TickCount - startTime) > toTicks)
+ {
+ TimeOut(MultiHostStreamErrorType.Connecting);
+ return;
+ }
+ if (CreateStream( (IPAddress)keys[i], (string)ips[keys[i]], port ))
+ return;
+ }
+ }
+
+ public override int ReadByte()
+ {
+ int start = Environment.TickCount;
+ int ticks = readTimeOut * 1000;
+
+ while ((Environment.TickCount - start) < ticks)
+ {
+ if (DataAvailable)
+ {
+ int b = stream.ReadByte();
+ return b;
+ }
+ else
+ Thread.Sleep(1);
+ }
+
+ TimeOut(MultiHostStreamErrorType.Reading);
+ return -1;
+ }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ int numToRead = count;
+ int start = Environment.TickCount;
+ int ticks = readTimeOut * 1000;
+
+ while (numToRead > 0 && (Environment.TickCount - start) < ticks)
+ {
+ if (DataAvailable)
+ {
+ int bytes_read = stream.Read( buffer, offset, numToRead);
+ if (bytes_read == 0)
+ return (count - numToRead);
+ offset += bytes_read;
+ numToRead -= bytes_read;
+ }
+ Thread.Sleep(1);
+ }
+
+ if (numToRead > 0)
+ TimeOut(MultiHostStreamErrorType.Reading);
+ return count;
+ }
+
+ public override bool CanRead
+ {
+ get { return stream.CanRead; }
+ }
+
+ public override bool CanWrite
+ {
+ get { return stream.CanWrite; }
+ }
+
+ public override bool CanSeek
+ {
+ get { return stream.CanSeek; }
+ }
+
+ public override long Length
+ {
+ get { return stream.Length; }
+ }
+
+ public override long Position
+ {
+ get { return stream.Position; }
+ set { stream.Position = value; }
+ }
+
+ public override void Flush()
+ {
+ stream.Flush();
+ }
+
+ public override void SetLength(long length)
+ {
+ stream.SetLength( length );
+ }
+
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ stream.Write( buffer, offset, count );
+ }
+
+ public override long Seek( long offset, SeekOrigin origin )
+ {
+ return stream.Seek( offset, origin );
+ }
+
+ }
+}
diff --git a/mcs/class/ByteFX.Data/Common/NamedPipeStream.cs b/mcs/class/ByteFX.Data/Common/NamedPipeStream.cs
index 1d38c253ab5..5ebc5755cb8 100755
--- a/mcs/class/ByteFX.Data/Common/NamedPipeStream.cs
+++ b/mcs/class/ByteFX.Data/Common/NamedPipeStream.cs
@@ -25,7 +25,7 @@ namespace ByteFX.Data.Common
/// <summary>
/// Summary description for API.
/// </summary>
- public class NamedPipeStream : Stream
+ internal class NamedPipeStream : Stream
{
[DllImport("kernel32.dll", EntryPoint="CreateFile", SetLastError=true)]
private static extern IntPtr CreateFile(String lpFileName,
diff --git a/mcs/class/ByteFX.Data/Common/Security.cs b/mcs/class/ByteFX.Data/Common/Security.cs
index 811f16c3f70..0547e2e1a1b 100644
--- a/mcs/class/ByteFX.Data/Common/Security.cs
+++ b/mcs/class/ByteFX.Data/Common/Security.cs
@@ -5,7 +5,7 @@ namespace ByteFX.Data.Common
/// <summary>
/// Summary description for Security.
/// </summary>
- public class Security
+ internal class Security
{
public Security()
{
diff --git a/mcs/class/ByteFX.Data/Common/SqlCommandTextEditor.cs b/mcs/class/ByteFX.Data/Common/SqlCommandTextEditor.cs
index 530bf20be70..7dfa9743518 100644
--- a/mcs/class/ByteFX.Data/Common/SqlCommandTextEditor.cs
+++ b/mcs/class/ByteFX.Data/Common/SqlCommandTextEditor.cs
@@ -25,7 +25,7 @@ namespace ByteFX.Data.Common
/// <summary>
/// Summary description for MySqlConnectionDesign.
/// </summary>
- public class SqlCommandTextEditor : UITypeEditor
+ internal class SqlCommandTextEditor : UITypeEditor
{
public override System.Drawing.Design.UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
{
diff --git a/mcs/class/ByteFX.Data/Common/Version.cs b/mcs/class/ByteFX.Data/Common/Version.cs
index eba74166ff2..03b72a6a985 100644
--- a/mcs/class/ByteFX.Data/Common/Version.cs
+++ b/mcs/class/ByteFX.Data/Common/Version.cs
@@ -5,7 +5,7 @@ namespace ByteFX.Data.Common
/// <summary>
/// Summary description for Version.
/// </summary>
- public struct Version
+ internal struct Version
{
private int major;
private int minor;
diff --git a/mcs/class/ByteFX.Data/mysqlclient/CommandBuilder.cs b/mcs/class/ByteFX.Data/mysqlclient/CommandBuilder.cs
index 5befb5d7ba0..7572a398e4b 100755
--- a/mcs/class/ByteFX.Data/mysqlclient/CommandBuilder.cs
+++ b/mcs/class/ByteFX.Data/mysqlclient/CommandBuilder.cs
@@ -23,8 +23,9 @@ using System.Text;
namespace ByteFX.Data.MySqlClient
{
/// <summary>
- /// Summary description for CommandBuilder.
+ /// Automatically generates single-table commands used to reconcile changes made to a DataSet with the associated MySQL database. This class cannot be inherited.
/// </summary>
+ /// <include file='docs/MySqlCommandBuilder.xml' path='MyDocs/MyMembers[@name="Class"]/*'/>
[ToolboxItem(false)]
[System.ComponentModel.DesignerCategory("Code")]
public sealed class MySqlCommandBuilder : Component
@@ -40,10 +41,16 @@ namespace ByteFX.Data.MySqlClient
private MySqlCommand _deleteCmd;
#region Constructors
+ /// <summary>
+ /// Overloaded. Initializes a new instance of the SqlCommandBuilder class.
+ /// </summary>
public MySqlCommandBuilder()
{
}
+ /// <summary>
+ /// Overloaded. Initializes a new instance of the SqlCommandBuilder class.
+ /// </summary>
public MySqlCommandBuilder( MySqlDataAdapter adapter )
{
_adapter = adapter;
@@ -90,6 +97,12 @@ namespace ByteFX.Data.MySqlClient
#endregion
#region Public Methods
+ /// <summary>
+ /// Retrieves parameter information from the stored procedure specified in the MySqlCommand and populates the Parameters collection of the specified MySqlCommand object.
+ /// This method is not currently supported since stored procedures are not available in MySql.
+ /// </summary>
+ /// <param name="command">The MySqlCommand referencing the stored procedure from which the parameter information is to be derived. The derived parameters are added to the Parameters collection of the MySqlCommand.</param>
+ /// <exception cref="InvalidOperationException">The command text is not a valid stored procedure name.</exception>
public static void DeriveParameters(MySqlCommand command)
{
throw new MySqlException("DeriveParameters is not supported (due to MySql not supporting SP)");
diff --git a/mcs/class/ByteFX.Data/mysqlclient/Connection.cs b/mcs/class/ByteFX.Data/mysqlclient/Connection.cs
index 6a634886061..47895e40d6e 100755
--- a/mcs/class/ByteFX.Data/mysqlclient/Connection.cs
+++ b/mcs/class/ByteFX.Data/mysqlclient/Connection.cs
@@ -37,9 +37,12 @@ namespace ByteFX.Data.MySqlClient
internal ConnectionState state;
private MySqlInternalConnection internalConnection;
private MySqlDataReader dataReader;
- private NumberFormatInfo numberFormat;
- private MySqlConnectionString settings;
+ private NumberFormatInfo numberFormat;
+ private MySqlConnectionString settings;
+ /// <summary>
+ /// Occurs when the state of the connection changes.
+ /// </summary>
public event StateChangeEventHandler StateChange;
@@ -149,17 +152,17 @@ namespace ByteFX.Data.MySqlClient
[Browsable(false)]
public string ServerVersion
{
- get { return ""; } //internalConnection.GetServerVersion(); }
+ get { return internalConnection.Driver.Version; }
}
internal Encoding Encoding
{
get
{
-//TODO if (encoding == null)
+ if (internalConnection == null)
return System.Text.Encoding.Default;
-// else
-// return encoding;
+ else
+ return internalConnection.Driver.Encoding;
}
}
@@ -167,6 +170,7 @@ namespace ByteFX.Data.MySqlClient
/// <summary>
/// Gets or sets the string used to connect to a MySQL Server database.
/// </summary>
+ /// <include file='docs/MySqlConnection.xml' path='MyDocs/MyMembers[@name="ConnectionString"]/*'/>
#if WINDOWS
[Editor(typeof(Designers.ConnectionStringEditor), typeof(System.Drawing.Design.UITypeEditor))]
#endif
@@ -340,7 +344,11 @@ namespace ByteFX.Data.MySqlClient
}
#region ICloneable
- public object Clone()
+ /// <summary>
+ /// Creates a new MySqlConnection object with the exact same ConnectionString value
+ /// </summary>
+ /// <returns>A cloned MySqlConnection object</returns>
+ object ICloneable.Clone()
{
MySqlConnection clone = new MySqlConnection();
clone.ConnectionString = this.ConnectionString;
diff --git a/mcs/class/ByteFX.Data/mysqlclient/ConnectionInternal.cs b/mcs/class/ByteFX.Data/mysqlclient/ConnectionInternal.cs
index 52b23ce06c1..cb51b1f1ae8 100644
--- a/mcs/class/ByteFX.Data/mysqlclient/ConnectionInternal.cs
+++ b/mcs/class/ByteFX.Data/mysqlclient/ConnectionInternal.cs
@@ -40,12 +40,13 @@ namespace ByteFX.Data.MySqlClient
Packet packet;
try
{
- packet = driver.SendSql( "show status like 'uptime'" );
+ byte[] bytes = driver.Encoding.GetBytes("show status like 'uptime'");
+ packet = driver.SendSql( bytes );
// we have to read for two last packets since MySql sends
// us a last packet after schema and again after rows
// I will likely change this later to have the driver just
// return schema in one very large packet.
- while (packet.Type != PacketType.Last)
+ while (! packet.IsLastPacket())
packet = driver.ReadPacket();
}
catch
@@ -74,10 +75,13 @@ namespace ByteFX.Data.MySqlClient
if (serverVariablesSet) return;
// retrieve the encoding that should be used for character data
- MySqlCommand cmd = new MySqlCommand("select @@max_allowed_packet", connection);
+ MySqlCommand cmd = new MySqlCommand("show variables like 'max_allowed_packet'", connection);
try
{
- driver.MaxPacketSize = Convert.ToInt64(cmd.ExecuteScalar());
+ MySqlDataReader reader = cmd.ExecuteReader();
+ reader.Read();
+ driver.MaxPacketSize = reader.GetInt64( 1 );
+ reader.Close();
}
catch
{
@@ -94,7 +98,10 @@ namespace ByteFX.Data.MySqlClient
driver.Encoding = CharSetMap.GetEncoding( reader.GetString(1) );
reader.Close();
}
- catch { }
+ catch
+ {
+ throw new MySqlException("Failure to initialize connection");
+ }
serverVariablesSet = true;
}
@@ -102,8 +109,7 @@ namespace ByteFX.Data.MySqlClient
public void Open()
{
driver = new Driver();
- driver.Open( settings.Host, settings.Port, settings.Username, settings.Password,
- settings.UseCompression, settings.ConnectTimeout );
+ driver.Open( settings );
createTime = DateTime.Now;
}
diff --git a/mcs/class/ByteFX.Data/mysqlclient/ConnectionString.cs b/mcs/class/ByteFX.Data/mysqlclient/ConnectionString.cs
index ac5dac837fa..f3a9567d794 100644
--- a/mcs/class/ByteFX.Data/mysqlclient/ConnectionString.cs
+++ b/mcs/class/ByteFX.Data/mysqlclient/ConnectionString.cs
@@ -8,7 +8,7 @@ namespace ByteFX.Data.MySqlClient
/// </summary>
internal sealed class MySqlConnectionString : DBConnectionString
{
- private bool useCompression;
+ private bool useCompression = false;
public MySqlConnectionString()
{
diff --git a/mcs/class/ByteFX.Data/mysqlclient/Driver.cs b/mcs/class/ByteFX.Data/mysqlclient/Driver.cs
index 6aa5404c56e..fec7dfea8bc 100755
--- a/mcs/class/ByteFX.Data/mysqlclient/Driver.cs
+++ b/mcs/class/ByteFX.Data/mysqlclient/Driver.cs
@@ -37,11 +37,11 @@ namespace ByteFX.Data.MySqlClient
protected MySqlStream stream;
protected Encoding encoding;
protected byte packetSeq;
- protected int timeOut;
protected long maxPacketSize;
protected Packet peekedPacket = null;
protected ByteFX.Data.Common.Version serverVersion;
protected bool isOpen;
+ protected string versionString;
int protocol;
uint threadID;
@@ -69,41 +69,33 @@ namespace ByteFX.Data.MySqlClient
set { maxPacketSize = value; }
}
- /// <summary>
- ///
- /// </summary>
- /// <param name="host"></param>
- /// <param name="port"></param>
- /// <param name="userid"></param>
- /// <param name="password"></param>
- public void Open( String host, int port, String userid, String password,
- bool UseCompression, int connectTimeout )
+ public string Version
+ {
+ get { return versionString; }
+ }
+
+ public void Open( MySqlConnectionString settings )
{
- timeOut = connectTimeout;
- stream = new MySqlStream( host, port, timeOut );
+ stream = new MySqlStream( settings.Host, settings.Port, 30, settings.ConnectTimeout );
Packet packet = ReadPacket();
// read off the protocol version
protocol = packet.ReadByte();
- serverVersion = ByteFX.Data.Common.Version.Parse( packet.ReadString() );
+ versionString = packet.ReadString();
+ serverVersion = ByteFX.Data.Common.Version.Parse( versionString );
threadID = (uint)packet.ReadInteger(4);
encryptionSeed = packet.ReadString();
// read in Server capabilities if they are provided
serverCaps = 0;
- if (packet.CanRead)
+ if (packet.HasMoreData)
serverCaps = (int)packet.ReadInteger(2);
- Authenticate( userid, password, UseCompression );
+ Authenticate( settings.Username, settings.Password, settings.UseCompression );
isOpen = true;
}
- /// <summary>
- ///
- /// </summary>
- /// <param name="userid"></param>
- /// <param name="password"></param>
private void Authenticate( String userid, String password, bool UseCompression )
{
ClientParam clientParam = ClientParam.CLIENT_FOUND_ROWS | ClientParam.CLIENT_LONG_FLAG;
@@ -156,7 +148,8 @@ namespace ByteFX.Data.MySqlClient
/// <summary>
/// AuthenticateSecurity implements the new 4.1 authentication scheme
/// </summary>
- /// <param name="password"></param>
+ /// <param name="packet">The in-progress packet we use to complete the authentication</param>
+ /// <param name="password">The password of the user to use</param>
private void AuthenticateSecurely( Packet packet, string password )
{
packet.WriteString("xxxxxxxx", encoding );
@@ -169,7 +162,7 @@ namespace ByteFX.Data.MySqlClient
SHA1 sha = new SHA1CryptoServiceProvider();
byte[] firstPassBytes = sha.ComputeHash( System.Text.Encoding.Default.GetBytes(newPass));
- byte[] salt = packet.GetBytes();
+ byte[] salt = packet.GetBuffer();
byte[] input = new byte[ firstPassBytes.Length + 4 ];
salt.CopyTo( input, 0 );
firstPassBytes.CopyTo( input, 4 );
@@ -183,11 +176,10 @@ namespace ByteFX.Data.MySqlClient
// send the packet
packet = new Packet();
- packet.WriteBytes( firstPassBytes, 0, 20 );
+ packet.Write( firstPassBytes, 0, 20 );
SendPacket(packet);
}
-
/// <summary>
///
/// </summary>
@@ -272,35 +264,15 @@ namespace ByteFX.Data.MySqlClient
Packet packet = ReadRawPacket();
- if (packet.Type == PacketType.Error)
+ // if this is an error packet, then throw the exception
+ if (packet[0] == 0xff)
{
+ packet.ReadByte();
int errorCode = (int)packet.ReadInteger(2);
string msg = packet.ReadString();
throw new MySqlException( msg, errorCode );
}
- else if (packet.Type != PacketType.UpdateOrOk)
- packet.Position = 0;
-
- return packet;
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="packet"></param>
- private Packet LoadSchemaIntoPacket( Packet packet, int count )
- {
- for (int i=0; i < count; i++)
- {
- Packet colPacket = ReadRawPacket();
- packet.AppendPacket( colPacket );
- }
- Packet lastPacket = ReadRawPacket();
- if (lastPacket.Type != PacketType.Last)
- throw new MySqlException("Last packet not received when expected");
- packet.Type = PacketType.ResultSchema;
- packet.Position = 0;
return packet;
}
@@ -338,7 +310,7 @@ namespace ByteFX.Data.MySqlClient
byte[] compressed_buffer = new byte[packet.Length * 2];
Deflater deflater = new Deflater();
- deflater.SetInput( packet.GetBytes(), 0, packet.Length );
+ deflater.SetInput( packet.GetBuffer(), 0, packet.Length );
deflater.Finish();
int comp_len = deflater.Deflate( compressed_buffer, 0, compressed_buffer.Length );
if (comp_len > packet.Length) return null;
@@ -368,7 +340,7 @@ namespace ByteFX.Data.MySqlClient
header.WriteInteger( packet.Length + HEADER_LEN, 3 );
header.WriteByte( packetSeq );
header.WriteInteger( 0, 3 );
- buffer = packet.GetBytes();
+ buffer = packet.GetBuffer();
}
// now write the internal header
header.WriteInteger( packet.Length, 3 );
@@ -376,16 +348,14 @@ namespace ByteFX.Data.MySqlClient
}
else
{
- header = new Packet();
- header.WriteInteger( packet.Length, 3 );
- header.WriteByte( packetSeq );
- buffer = packet.GetBytes();
+ buffer = packet.GetBytes( packetSeq );
}
packetSeq++;
// send the data to eth server
- stream.Write( header.GetBytes(), 0, header.Length );
- stream.Write( buffer, 0, buffer.Length );
+ int start = 0;
+ if (! useCompression) start = 3;
+ stream.Write( buffer, start, packet.Length - start );
stream.Flush();
}
@@ -412,7 +382,7 @@ namespace ByteFX.Data.MySqlClient
SendPacket(packet);
packet = ReadPacket();
- if (packet.Type != PacketType.UpdateOrOk)
+ if (packet[0] != 0)
throw new MySqlException("SendCommand failed for command " + text );
}
@@ -423,42 +393,28 @@ namespace ByteFX.Data.MySqlClient
/// <returns>A packet containing the bytes returned by the server</returns>
public Packet SendQuery( byte[] sql )
{
+ string s = encoding.GetString(sql);
+
Packet packet = new Packet();
packetSeq = 0;
packet.WriteByte( (byte)DBCmd.QUERY );
- packet.WriteBytes( sql, 0, sql.Length );
+ packet.Write( sql, 0, sql.Length );
SendPacket( packet );
return ReadPacket();
}
- public Packet SendSql( string sql )
- {
- byte[] bytes = encoding.GetBytes(sql);
+
+ public Packet SendSql( byte[] bytes )
+ {
Packet packet = new Packet();
packetSeq = 0;
packet.WriteByte( (byte)DBCmd.QUERY );
- packet.WriteBytes( bytes, 0, bytes.Length );
+ packet.Write( bytes, 0, bytes.Length );
SendPacket( packet );
packet = ReadPacket();
-
- switch (packet.Type)
- {
- case PacketType.LoadDataLocal:
- SendFileToServer();
- return null;
-
- case PacketType.Other:
- packet.Position = 0;
- int count = (int)packet.ReadLenInteger();
- if (count > 0)
- return LoadSchemaIntoPacket( packet, count );
- else
- return packet;
- }
-
return packet;
}
@@ -472,10 +428,11 @@ namespace ByteFX.Data.MySqlClient
}
/// <summary>
- ///
+ /// Encrypts a password using the MySql encryption scheme
/// </summary>
- /// <param name="password"></param>
- /// <param name="seed"></param>
+ /// <param name="password">The password to encrypt</param>
+ /// <param name="message">The encryption seed the server gave us</param>
+ /// <param name="new_ver">Indicates if we should use the old or new encryption scheme</param>
/// <returns></returns>
public static String EncryptPassword(String password, String message, bool new_ver)
{
diff --git a/mcs/class/ByteFX.Data/mysqlclient/Exception.cs b/mcs/class/ByteFX.Data/mysqlclient/Exception.cs
index 9e4b315f617..2e8efbc8820 100755
--- a/mcs/class/ByteFX.Data/mysqlclient/Exception.cs
+++ b/mcs/class/ByteFX.Data/mysqlclient/Exception.cs
@@ -21,25 +21,30 @@ using System.Runtime.Serialization;
namespace ByteFX.Data.MySqlClient
{
/// <summary>
- /// Summary description for MySqlException.
+ /// The exception that is thrown when MySQL returns an error. This class cannot be inherited.
/// </summary>
+ /// <include file='docs/MySqlException.xml' path='MyDocs/MyMembers[@name="Class"]/*'/>
[Serializable]
- public sealed class MySqlException : Exception
+ public sealed class MySqlException : SystemException
{
- public MySqlException(string msg) : base(msg)
+ internal MySqlException(string msg) : base(msg)
+ {
+ }
+
+ internal MySqlException( string msg, Exception ex ) : base(msg, ex)
{
}
- public MySqlException()
+ internal MySqlException()
{
}
- public MySqlException(string msg, int errno) : base(msg)
+ internal MySqlException(string msg, int errno) : base(msg)
{
}
- public MySqlException(SerializationInfo info,
+ internal MySqlException(SerializationInfo info,
StreamingContext context) : base(info, context)
{
}
diff --git a/mcs/class/ByteFX.Data/mysqlclient/Field.cs b/mcs/class/ByteFX.Data/mysqlclient/Field.cs
index 4e81e6a54c6..4e30648224c 100755
--- a/mcs/class/ByteFX.Data/mysqlclient/Field.cs
+++ b/mcs/class/ByteFX.Data/mysqlclient/Field.cs
@@ -81,14 +81,14 @@ namespace ByteFX.Data.MySqlClient
public int NumericPrecision()
{
if (colType == MySqlDbType.Decimal)
- return ((SqlDecimal)value).Precision;
+ return colLen;
return -1;
}
public int NumericScale()
{
if (colType == MySqlDbType.Decimal)
- return ((SqlDecimal)value).Scale;
+ return colDecimals;
return -1;
}
@@ -143,7 +143,7 @@ namespace ByteFX.Data.MySqlClient
// read in the data
byte[] data = new byte[ len ];
- p.ReadBytes( data, 0, len );
+ p.Read( data, 0, len );
// if it is a blob and binary, then GetBytes is the way to go
if ( IsBlob() && IsBinary() )
@@ -172,7 +172,7 @@ namespace ByteFX.Data.MySqlClient
value = Int16.Parse( sValue );
break;
- case MySqlDbType.Long :
+ case MySqlDbType.Int :
case MySqlDbType.Int24:
if (IsUnsigned())
value = UInt32.Parse( sValue );
@@ -180,7 +180,7 @@ namespace ByteFX.Data.MySqlClient
value = Int32.Parse( sValue );
break;
- case MySqlDbType.LongLong:
+ case MySqlDbType.BigInt:
if (IsUnsigned())
value = UInt64.Parse( sValue );
else
@@ -264,12 +264,12 @@ namespace ByteFX.Data.MySqlClient
case MySqlDbType.Decimal: return "DECIMAL";
case MySqlDbType.Byte: return "TINY";
case MySqlDbType.Short: return "SHORT";
- case MySqlDbType.Long: return "LONG";
+ case MySqlDbType.Int: return "INTEGER";
case MySqlDbType.Float: return "FLOAT";
case MySqlDbType.Double: return "DOUBLE";
case MySqlDbType.Null: return "NULL";
case MySqlDbType.Timestamp: return "TIMESTAMP";
- case MySqlDbType.LongLong: return "LONGLONG";
+ case MySqlDbType.BigInt: return "BIGINT";
case MySqlDbType.Int24: return "INT24";
case MySqlDbType.Date: return "DATE";
case MySqlDbType.Time: return "TIME";
@@ -297,10 +297,10 @@ namespace ByteFX.Data.MySqlClient
case MySqlDbType.Short: return IsUnsigned() ? typeof(System.UInt16) : typeof(System.Int16);
- case MySqlDbType.Long:
+ case MySqlDbType.Int:
case MySqlDbType.Int24: return IsUnsigned() ? typeof(System.UInt32) : typeof(System.Int32);
- case MySqlDbType.LongLong: return IsUnsigned() ? typeof(System.UInt64) : typeof(System.Int64);
+ case MySqlDbType.BigInt: return IsUnsigned() ? typeof(System.UInt64) : typeof(System.Int64);
case MySqlDbType.Float: return typeof(System.Single);
case MySqlDbType.Double: return typeof(System.Double);
@@ -343,7 +343,7 @@ namespace ByteFX.Data.MySqlClient
else
return DbType.Int16;
- case MySqlDbType.Long:
+ case MySqlDbType.Int:
if (IsUnsigned())
return DbType.UInt32;
else
@@ -353,7 +353,7 @@ namespace ByteFX.Data.MySqlClient
case MySqlDbType.Double: return DbType.Double;
case MySqlDbType.Null: return DbType.Object;
- case MySqlDbType.LongLong:
+ case MySqlDbType.BigInt:
if (IsUnsigned())
return DbType.UInt64;
else
diff --git a/mcs/class/ByteFX.Data/mysqlclient/MySqlHelper.cs b/mcs/class/ByteFX.Data/mysqlclient/MySqlHelper.cs
index ad07b89875a..c2b710821a3 100644
--- a/mcs/class/ByteFX.Data/mysqlclient/MySqlHelper.cs
+++ b/mcs/class/ByteFX.Data/mysqlclient/MySqlHelper.cs
@@ -5,7 +5,7 @@ using ByteFX.Data.MySqlClient;
namespace ByteFX.Data.MySqlClient
{
/// <summary>
- /// Summary description for MySqlHelper.
+ /// Helper class that makes it easier to work with the provider.
/// </summary>
public sealed class MySqlHelper
{
@@ -15,6 +15,15 @@ namespace ByteFX.Data.MySqlClient
}
#region ExecuteNonQuery
+
+ /// <summary>
+ /// Executes a single command against a MySQL database. The <see cref="MySqlConnection"/> is assumed to be
+ /// open when the method is called and remains open after the method completes.
+ /// </summary>
+ /// <param name="connection"><see cref="MySqlConnection"/> object to use</param>
+ /// <param name="commandText">SQL command to be executed</param>
+ /// <param name="commandParameters">Array of <see cref="MySqlParameter"/> objects to use with the command.</param>
+ /// <returns></returns>
public static int ExecuteNonQuery( MySqlConnection connection, string commandText, params MySqlParameter[] commandParameters )
{
//create a command and prepare it for execution
@@ -33,6 +42,14 @@ namespace ByteFX.Data.MySqlClient
return result;
}
+ /// <summary>
+ /// Executes a single command against a MySQL database. A new <see cref="MySqlConnection"/> is created
+ /// using the <see cref="MySqlConnection.ConnectionString"/> given.
+ /// </summary>
+ /// <param name="connectionString"><see cref="MySqlConnection.ConnectionString"/> to use</param>
+ /// <param name="commandText">SQL command to be executed</param>
+ /// <param name="parms">Array of <see cref="MySqlParameter"/> objects to use with the command.</param>
+ /// <returns></returns>
public static int ExecuteNonQuery( string connectionString, string commandText, params MySqlParameter[] parms )
{
//create & open a SqlConnection, and dispose of it after we are done.
@@ -47,6 +64,15 @@ namespace ByteFX.Data.MySqlClient
#endregion
#region ExecuteDataSet
+
+ /// <summary>
+ /// Executes a single SQL command and returns the first row of the resultset. A new MySqlConnection object
+ /// is created, opened, and closed during this method.
+ /// </summary>
+ /// <param name="connectionString">Settings to be used for the connection</param>
+ /// <param name="commandText">Command to execute</param>
+ /// <param name="parms">Parameters to use for the command</param>
+ /// <returns>DataRow containing the first row of the resultset</returns>
public static DataRow ExecuteDatarow( string connectionString, string commandText, params MySqlParameter[] parms )
{
DataSet ds = ExecuteDataset( connectionString, commandText, parms );
@@ -56,12 +82,27 @@ namespace ByteFX.Data.MySqlClient
return ds.Tables[0].Rows[0];
}
+ /// <summary>
+ /// Executes a single SQL command and returns the resultset in a <see cref="DataSet"/>.
+ /// A new MySqlConnection object is created, opened, and closed during this method.
+ /// </summary>
+ /// <param name="connectionString">Settings to be used for the connection</param>
+ /// <param name="commandText">Command to execute</param>
+ /// <returns><see cref="DataSet"/> containing the resultset</returns>
public static DataSet ExecuteDataset(string connectionString, string commandText)
{
//pass through the call providing null for the set of SqlParameters
return ExecuteDataset(connectionString, commandText, (MySqlParameter[])null);
}
+ /// <summary>
+ /// Executes a single SQL command and returns the resultset in a <see cref="DataSet"/>.
+ /// A new MySqlConnection object is created, opened, and closed during this method.
+ /// </summary>
+ /// <param name="connectionString">Settings to be used for the connection</param>
+ /// <param name="commandText">Command to execute</param>
+ /// <param name="commandParameters">Parameters to use for the command</param>
+ /// <returns><see cref="DataSet"/> containing the resultset</returns>
public static DataSet ExecuteDataset(string connectionString, string commandText, params MySqlParameter[] commandParameters)
{
//create & open a SqlConnection, and dispose of it after we are done.
@@ -74,13 +115,29 @@ namespace ByteFX.Data.MySqlClient
}
}
+ /// <summary>
+ /// Executes a single SQL command and returns the resultset in a <see cref="DataSet"/>.
+ /// The state of the <see cref="MySqlConnection"/> object remains unchanged after execution
+ /// of this method.
+ /// </summary>
+ /// <param name="connection"><see cref="MySqlConnection"/> object to use</param>
+ /// <param name="commandText">Command to execute</param>
+ /// <returns><see cref="DataSet"/> containing the resultset</returns>
public static DataSet ExecuteDataset(MySqlConnection connection, string commandText)
{
//pass through the call providing null for the set of SqlParameters
return ExecuteDataset(connection, commandText, (MySqlParameter[])null);
}
-
+ /// <summary>
+ /// Executes a single SQL command and returns the resultset in a <see cref="DataSet"/>.
+ /// The state of the <see cref="MySqlConnection"/> object remains unchanged after execution
+ /// of this method.
+ /// </summary>
+ /// <param name="connection"><see cref="MySqlConnection"/> object to use</param>
+ /// <param name="commandText">Command to execute</param>
+ /// <param name="commandParameters">Parameters to use for the command</param>
+ /// <returns><see cref="DataSet"/> containing the resultset</returns>
public static DataSet ExecuteDataset(MySqlConnection connection, string commandText, params MySqlParameter[] commandParameters)
{
//create a command and prepare it for execution
@@ -107,6 +164,13 @@ namespace ByteFX.Data.MySqlClient
return ds;
}
+ /// <summary>
+ /// Updates the given table with data from the given <see cref="DataSet"/>
+ /// </summary>
+ /// <param name="connectionString">Settings to use for the update</param>
+ /// <param name="commandText">Command text to use for the update</param>
+ /// <param name="ds"><see cref="DataSet"/> containing the new data to use in the update</param>
+ /// <param name="tablename">Tablename in the dataset to update</param>
public static void UpdateDataSet( string connectionString, string commandText, DataSet ds, string tablename )
{
MySqlConnection cn = new MySqlConnection( connectionString );
@@ -120,6 +184,16 @@ namespace ByteFX.Data.MySqlClient
#endregion
#region ExecuteDataReader
+
+ /// <summary>
+ /// Executes a single command against a MySQL database, possibly inside an existing transaction.
+ /// </summary>
+ /// <param name="connection"><see cref="MySqlConnection"/> object to use for the command</param>
+ /// <param name="transaction"><see cref="MySqlTransaction"/> object to use for the command</param>
+ /// <param name="commandText">Command text to use</param>
+ /// <param name="commandParameters">Array of <see cref="MySqlParameter"/> objects to use with the command</param>
+ /// <param name="ExternalConn">True if the connection should be preserved, false if not</param>
+ /// <returns><see cref="MySqlDataReader"/> object ready to read the results of the command</returns>
private static MySqlDataReader ExecuteReader(MySqlConnection connection, MySqlTransaction transaction, string commandText, MySqlParameter[] commandParameters, bool ExternalConn )
{
//create a command and prepare it for execution
@@ -152,12 +226,25 @@ namespace ByteFX.Data.MySqlClient
return dr;
}
+ /// <summary>
+ /// Executes a single command against a MySQL database.
+ /// </summary>
+ /// <param name="connectionString">Settings to use for this command</param>
+ /// <param name="commandText">Command text to use</param>
+ /// <returns><see cref="MySqlDataReader"/> object ready to read the results of the command</returns>
public static MySqlDataReader ExecuteReader(string connectionString, string commandText)
{
//pass through the call providing null for the set of SqlParameters
return ExecuteReader(connectionString, commandText, (MySqlParameter[])null);
}
+ /// <summary>
+ /// Executes a single command against a MySQL database.
+ /// </summary>
+ /// <param name="connectionString">Settings to use for this command</param>
+ /// <param name="commandText">Command text to use</param>
+ /// <param name="commandParameters">Array of <see cref="MySqlParameter"/> objects to use with the command</param>
+ /// <returns><see cref="MySqlDataReader"/> object ready to read the results of the command</returns>
public static MySqlDataReader ExecuteReader(string connectionString, string commandText, params MySqlParameter[] commandParameters)
{
//create & open a SqlConnection
@@ -179,12 +266,26 @@ namespace ByteFX.Data.MySqlClient
#endregion
#region ExecuteScalar
+
+ /// <summary>
+ /// Execute a single command against a MySQL database.
+ /// </summary>
+ /// <param name="connectionString">Settings to use for the update</param>
+ /// <param name="commandText">Command text to use for the update</param>
+ /// <returns>The first column of the first row in the result set, or a null reference if the result set is empty.</returns>
public static object ExecuteScalar(string connectionString, string commandText)
{
//pass through the call providing null for the set of MySqlParameters
return ExecuteScalar(connectionString, commandText, (MySqlParameter[])null);
}
+ /// <summary>
+ /// Execute a single command against a MySQL database.
+ /// </summary>
+ /// <param name="connectionString">Settings to use for the command</param>
+ /// <param name="commandText">Command text to use for the command</param>
+ /// <param name="commandParameters">Parameters to use for the command</param>
+ /// <returns>The first column of the first row in the result set, or a null reference if the result set is empty.</returns>
public static object ExecuteScalar(string connectionString, string commandText, params MySqlParameter[] commandParameters)
{
//create & open a SqlConnection, and dispose of it after we are done.
@@ -197,12 +298,25 @@ namespace ByteFX.Data.MySqlClient
}
}
+ /// <summary>
+ /// Execute a single command against a MySQL database.
+ /// </summary>
+ /// <param name="connection"><see cref="MySqlConnection"/> object to use</param>
+ /// <param name="commandText">Command text to use for the command</param>
+ /// <returns>The first column of the first row in the result set, or a null reference if the result set is empty.</returns>
public static object ExecuteScalar(MySqlConnection connection, string commandText)
{
//pass through the call providing null for the set of MySqlParameters
return ExecuteScalar(connection, commandText, (MySqlParameter[])null);
}
+ /// <summary>
+ /// Execute a single command against a MySQL database.
+ /// </summary>
+ /// <param name="connection"><see cref="MySqlConnection"/> object to use</param>
+ /// <param name="commandText">Command text to use for the command</param>
+ /// <param name="commandParameters">Parameters to use for the command</param>
+ /// <returns>The first column of the first row in the result set, or a null reference if the result set is empty.</returns>
public static object ExecuteScalar(MySqlConnection connection, string commandText, params MySqlParameter[] commandParameters)
{
//create a command and prepare it for execution
diff --git a/mcs/class/ByteFX.Data/mysqlclient/MySqlPool.cs b/mcs/class/ByteFX.Data/mysqlclient/MySqlPool.cs
index 718fd53592e..bc4828c5e19 100644
--- a/mcs/class/ByteFX.Data/mysqlclient/MySqlPool.cs
+++ b/mcs/class/ByteFX.Data/mysqlclient/MySqlPool.cs
@@ -9,26 +9,43 @@ namespace ByteFX.Data.MySqlClient
/// </summary>
internal sealed class MySqlPool
{
- private ArrayList inUsePool;
- private ArrayList idlePool;
- private int minSize;
- private int maxSize;
+ private ArrayList inUsePool;
+ private ArrayList idlePool;
+ private MySqlConnectionString settings;
+ private int minSize;
+ private int maxSize;
- public MySqlPool(int minSize, int maxSize)
+ public MySqlPool(MySqlConnectionString settings)
+ {
+ minSize = settings.MinPoolSize;
+ maxSize = settings.MaxPoolSize;
+ this.settings = settings;
+ inUsePool =new ArrayList();
+ idlePool = new ArrayList( settings.MinPoolSize );
+
+ // prepopulate the idle pool to minSize
+ for (int i=0; i < minSize; i++)
+ CreateNewPooledConnection();
+ }
+
+ private void CheckOutConnection(MySqlInternalConnection conn)
{
- this.minSize = minSize;
- this.maxSize = maxSize;
- inUsePool =new ArrayList(minSize);
- idlePool = new ArrayList(minSize);
}
private MySqlInternalConnection GetPooledConnection()
{
+ MySqlInternalConnection conn = null;
+
+ // if there are no idle connections and the in use pool is full
+ // then return null to indicate that we cannot provide a connection
+ // at this time.
+ if (idlePool.Count == 0 && inUsePool.Count == maxSize) return null;
+
lock (idlePool.SyncRoot)
{
for (int i=idlePool.Count-1; i >=0; i--)
{
- MySqlInternalConnection conn = (idlePool[i] as MySqlInternalConnection);
+ conn = (idlePool[i] as MySqlInternalConnection);
if (conn.IsAlive())
{
lock (inUsePool)
@@ -45,20 +62,44 @@ namespace ByteFX.Data.MySqlClient
}
}
}
- return null;
+
+ // if we couldn't get a pooled connection and there is still room
+ // make a new one
+ if (conn == null && (idlePool.Count+inUsePool.Count) < maxSize)
+ {
+ conn = CreateNewPooledConnection();
+ if (conn == null) return null;
+
+ lock (idlePool.SyncRoot)
+ lock (inUsePool.SyncRoot)
+ {
+ idlePool.Remove( conn );
+ inUsePool.Add( conn );
+ }
+ }
+
+ return conn;
}
- private MySqlInternalConnection CreateNewPooledConnection( MySqlConnectionString settings )
+ private MySqlInternalConnection CreateNewPooledConnection()
{
- MySqlInternalConnection conn = new MySqlInternalConnection( settings );
- conn.Open();
- return conn;
+ lock(idlePool.SyncRoot)
+ lock (inUsePool.SyncRoot)
+ {
+ // first we check if we are allowed to create another
+ if ((inUsePool.Count + idlePool.Count) == maxSize) return null;
+
+ MySqlInternalConnection conn = new MySqlInternalConnection( settings );
+ conn.Open();
+ idlePool.Add( conn );
+ return conn;
+ }
}
public void ReleaseConnection( MySqlInternalConnection connection )
{
- lock (inUsePool.SyncRoot)
- lock (idlePool.SyncRoot)
+ lock (idlePool.SyncRoot)
+ lock (inUsePool.SyncRoot)
{
inUsePool.Remove( connection );
if (connection.Settings.ConnectionLifetime != 0 && connection.IsTooOld())
@@ -68,20 +109,16 @@ namespace ByteFX.Data.MySqlClient
}
}
- public MySqlInternalConnection GetConnection(MySqlConnectionString settings)
+ public MySqlInternalConnection GetConnection()
{
- MySqlInternalConnection conn;
+ MySqlInternalConnection conn = null;
- DateTime start = DateTime.Now;
- TimeSpan ts;
- do
- {
- conn = GetPooledConnection();
- if (conn == null)
- conn = CreateNewPooledConnection( settings );
- ts = DateTime.Now.Subtract( start );
- } while (conn == null && ts.Seconds < settings.ConnectTimeout );
+ int start = Environment.TickCount;
+ int ticks = settings.ConnectTimeout * 1000;
+ // wait timeOut seconds at most to get a connection
+ while (conn == null && (Environment.TickCount - start) < ticks)
+ conn = GetPooledConnection();
// if pool size is at maximum, then we must have reached our timeout so we simply
// throw our exception
diff --git a/mcs/class/ByteFX.Data/mysqlclient/MySqlPoolManager.cs b/mcs/class/ByteFX.Data/mysqlclient/MySqlPoolManager.cs
index acc6eba4d35..d1b418476ef 100644
--- a/mcs/class/ByteFX.Data/mysqlclient/MySqlPoolManager.cs
+++ b/mcs/class/ByteFX.Data/mysqlclient/MySqlPoolManager.cs
@@ -36,7 +36,7 @@ namespace ByteFX.Data.MySqlClient
MySqlPool pool;
if (!pools.Contains( text ))
{
- pool = new MySqlPool( settings.MinPoolSize, settings.MaxPoolSize );
+ pool = new MySqlPool( settings );
pools.Add( text, pool );
}
else
@@ -44,7 +44,7 @@ namespace ByteFX.Data.MySqlClient
pool = (pools[text] as MySqlPool);
}
- return pool.GetConnection( settings );
+ return pool.GetConnection();
}
}
diff --git a/mcs/class/ByteFX.Data/mysqlclient/MySqlStream.cs b/mcs/class/ByteFX.Data/mysqlclient/MySqlStream.cs
index a7d33ec9230..faa027765a6 100644
--- a/mcs/class/ByteFX.Data/mysqlclient/MySqlStream.cs
+++ b/mcs/class/ByteFX.Data/mysqlclient/MySqlStream.cs
@@ -20,124 +20,96 @@ using System.IO;
using System.Net;
using System.Net.Sockets;
using ByteFX.Data.Common;
+using System.Threading;
namespace ByteFX.Data.MySqlClient
{
/// <summary>
/// Summary description for API.
/// </summary>
- internal class MySqlStream : Stream
+ internal class MySqlStream : MultiHostStream
{
- Stream stream;
- Socket socket;
- int timeOut;
+ public MySqlStream( string hostList, int port, int readTimeOut, int connectTimeOut ) :
+ base( hostList, port, readTimeOut, connectTimeOut )
- public MySqlStream( string host, int port, int timeout )
{
- if (port == -1)
- Create( host );
- else
- Create( host, port );
- timeOut = timeout;
}
- private void Create( string host, int port )
+ protected override void Error(string msg)
{
- socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
- IPHostEntry he = Dns.GetHostByName( host );
- IPEndPoint serverAddr = new IPEndPoint(he.AddressList[0], port);
-
- socket.Connect(serverAddr);
- stream = new NetworkStream(socket, true);
+ throw new MySqlException( msg, baseException );
}
- private void Create( string host )
+ protected override void TimeOut(MultiHostStreamErrorType error)
{
- string pipeName;
-
- if (host.ToLower().Equals("localhost"))
- pipeName = @"\\.\pipe\MySql";
- else
- pipeName = String.Format(@"\\{0}\pipe\MySql", host);
-
- stream = new ByteFX.Data.Common.NamedPipeStream(pipeName, FileAccess.ReadWrite);
- }
-
- public bool DataAvailable
- {
- get
+ switch (error)
{
- if (stream is NetworkStream)
- return ((NetworkStream)stream).DataAvailable;
- else return (stream as NamedPipeStream).DataAvailable;
+ case MultiHostStreamErrorType.Connecting:
+ throw new MySqlException("Timed out creating a new MySqlConnection");
+ case MultiHostStreamErrorType.Reading:
+ throw new MySqlException("Timed out reading from MySql");
}
- }
-
- public override bool CanRead
- {
- get { return stream.CanRead; }
- }
-
- public override bool CanWrite
- {
- get { return stream.CanWrite; }
}
- public override bool CanSeek
+ protected override bool CreateStream( IPAddress ip, string hostname, int port )
{
- get { return stream.CanSeek; }
+ if (port == -1)
+ return CreatePipeStream(ip, hostname);
+ else
+ return CreateSocketStream(ip, port);
}
- public override long Length
+ private bool CreatePipeStream( IPAddress ip, string hostname )
{
- get { return stream.Length; }
- }
+ string pipeName;
- public override long Position
- {
- get { return stream.Position; }
- set { stream.Position = value; }
- }
+ if (hostname.ToLower().Equals("localhost"))
+ pipeName = @"\\.\pipe\MySql";
+ else
+ pipeName = String.Format(@"\\{0}\pipe\MySql", ip.ToString());
- public override void Flush()
- {
- stream.Flush();
+ try
+ {
+ stream = new NamedPipeStream(pipeName, FileAccess.ReadWrite);
+ return true;
+ }
+ catch (Exception ex)
+ {
+ baseException = ex;
+ return false;
+ }
}
- public override int ReadByte()
+ private bool CreateSocketStream( IPAddress ip, int port )
{
- long start = Environment.TickCount;
- long timeout_ticks = timeOut * TimeSpan.TicksPerSecond;
+ Socket socket = new Socket(AddressFamily.InterNetwork,
+ SocketType.Stream, ProtocolType.Tcp);
- while (((Environment.TickCount - start) < timeout_ticks))
+ try
{
- if (DataAvailable)
- {
- int b = stream.ReadByte();
- return b;
- }
+ //
+ // Lets try to connect
+ IPEndPoint endPoint = new IPEndPoint( ip, port);
+ socket.Connect(endPoint);
+ socket.SetSocketOption( SocketOptionLevel.Tcp, SocketOptionName.NoDelay, 1 );
+ stream = new NetworkStream( socket, true );
+ return true;
+ }
+ catch (Exception ex)
+ {
+ baseException = ex;
+ return false;
}
- throw new Exception("Timeout waiting for response from server");
}
- public override int Read(byte[] buffer, int offset, int count)
+ protected override bool DataAvailable
{
- long start = Environment.TickCount;
- int numToRead = count;
- long timeout_ticks = timeOut * TimeSpan.TicksPerSecond;
-
- while (numToRead > 0 && ((Environment.TickCount - start) < timeout_ticks))
+ get
{
- if (DataAvailable)
- {
- int bytes_read = stream.Read(buffer, offset, numToRead);
- offset += bytes_read;
- numToRead -= bytes_read;
- }
+ if (stream is NetworkStream)
+ return ((NetworkStream)stream).DataAvailable;
+ else return (stream as NamedPipeStream).DataAvailable;
}
- if (numToRead > 0)
- throw new Exception("Timeout waiting for response from server");
- return count;
}
public int ReadInt24()
@@ -152,20 +124,6 @@ namespace ByteFX.Data.MySqlClient
stream.Close();
}
- public override void SetLength(long length)
- {
- stream.SetLength( length );
- }
-
- public override void Write(byte[] buffer, int offset, int count)
- {
- stream.Write( buffer, offset, count );
- }
-
- public override long Seek( long offset, SeekOrigin origin )
- {
- return stream.Seek( offset, origin );
- }
}
}
diff --git a/mcs/class/ByteFX.Data/mysqlclient/MysqlDefs.cs b/mcs/class/ByteFX.Data/mysqlclient/MysqlDefs.cs
index eed7d80ad0d..570e48eeb8d 100755
--- a/mcs/class/ByteFX.Data/mysqlclient/MysqlDefs.cs
+++ b/mcs/class/ByteFX.Data/mysqlclient/MysqlDefs.cs
@@ -69,30 +69,62 @@ namespace ByteFX.Data.MySqlClient
CHANGE_USER = 17,
}
+ /// <summary>
+ /// Specifies MySQL specific data type of a field, property, for use in a <see cref="MySqlParameter"/>.
+ /// </summary>
public enum MySqlDbType
{
- Decimal = 0,
- Byte = 1,
+ /// <summary> <see cref="Decimal"/><para>A fixed precision and scale numeric value between -1038 -1 and 10 38 -1.</para></summary>
+ Decimal = 0,
+ /// <summary> <see cref="Byte"/><para>The signed range is -128 to 127. The unsigned range is 0 to 255.</para></summary>
+ Byte = 1,
+ /// <summary><see cref="Int16"/><para>A 16-bit signed or unsigned integer. The signed range is -32768 to 32767. The unsigned range is 0 to 65535</para></summary>
Short = 2,
+ /// <summary><see cref="Int32"/><para>A 32-bit signed or unsigned integer</para></summary>
+ Int = 3,
+ /// <summary><b>Obsolete</b> Please use Int for 32 bit values</summary>
+ [Obsolete("Long is no longer the correct way of specifying a 32 bit value. Use Int")]
Long = 3,
+ /// <summary><see cref="Single"/><para>A small (single-precision) floating-point number. Allowable values are -3.402823466E+38 to -1.175494351E-38, 0, and 1.175494351E-38 to 3.402823466E+38.</para></summary>
Float = 4,
+ /// <summary><see cref="Double"/><para>A normal-size (double-precision) floating-point number. Allowable values are -1.7976931348623157E+308 to -2.2250738585072014E-308, 0, and 2.2250738585072014E-308 to 1.7976931348623157E+308.</para></summary>
Double = 5,
+ /// <summary>Specifies a null value</summary>
Null = 6,
+ /// <summary>A timestamp. The range is '1970-01-01 00:00:00' to sometime in the year 2037</summary>
Timestamp = 7,
+ /// <summary><see cref="Int64"/><para>A 64-bit signed or unsigned integer.</para></summary>
+ BigInt = 8,
+ /// <summary><b>Obsolete</b> Please use BigInt for 64 bit values</summary>
+ [Obsolete("LongLong is no longer the correct way of specifying a 64 bit value. Use BigInt")]
LongLong = 8,
+ /// <summary>Specifies a 24 (3 byte) signed or unsigned value.</summary>
Int24 = 9,
+ ///<summary>Date The supported range is '1000-01-01' to '9999-12-31'.</summary>
Date = 10,
+ /// <summary> Time <para>The range is '-838:59:59' to '838:59:59'.</para></summary>
Time = 11,
- Datetime = 12,
+ ///<summary>DateTime The supported range is '1000-01-01 00:00:00' to '9999-12-31 23:59:59'.</summary>
+ Datetime = 12,
+ /// <summary>A year in 2- or 4-digit format (default is 4-digit). The allowable values are 1901 to 2155, 0000 in the 4-digit year format, and 1970-2069 if you use the 2-digit format (70-69)</summary>
Year = 13,
+ /// <summary><b>Obsolete</b> Use Datetime or Date type</summary>
Newdate = 14,
+ /// <summary>An enumeration. A string object that can have only one value, chosen from the list of values 'value1', 'value2', ..., NULL or the special "" error value. An ENUM can have a maximum of 65535 distinct values</summary>
Enum = 247,
+ /// <summary>A set. A string object that can have zero or more values, each of which must be chosen from the list of values 'value1', 'value2', ... A SET can have a maximum of 64 members.</summary>
Set = 248,
+ /// <summary>A BLOB or TEXT column with a maximum length of 255 (2^8 - 1) characters</summary>
TinyBlob = 249,
+ /// <summary>A BLOB or TEXT column with a maximum length of 16777215 (2^24 - 1) characters</summary>
MediumBlob = 250,
+ /// <summary>A BLOB or TEXT column with a maximum length of 4294967295 or 4G (2^32 - 1) characters</summary>
LongBlob = 251,
+ /// <summary>A BLOB or TEXT column with a maximum length of 65535 (2^16 - 1) characters</summary>
Blob = 252,
+ /// <summary>A variable-length string containing 0 to 255 characters</summary>
VarChar = 253,
+ /// <summary><b>Obsolete</b> Use VarChar type</summary>
String = 254
};
diff --git a/mcs/class/ByteFX.Data/mysqlclient/Packet.cs b/mcs/class/ByteFX.Data/mysqlclient/Packet.cs
index 25634989768..ca4685e93df 100644
--- a/mcs/class/ByteFX.Data/mysqlclient/Packet.cs
+++ b/mcs/class/ByteFX.Data/mysqlclient/Packet.cs
@@ -4,7 +4,7 @@ using System.Text;
namespace ByteFX.Data.MySqlClient
{
- internal enum PacketType
+/* internal enum PacketType
{
None,
UpdateOrOk,
@@ -14,32 +14,28 @@ namespace ByteFX.Data.MySqlClient
Error,
LoadDataLocal,
Other
- }
+ }*/
/// <summary>
/// Summary description for Packet.
/// </summary>
- internal class Packet
+ internal class Packet : MemoryStream
{
- MemoryStream data;
- PacketType type = PacketType.None;
Encoding encoding;
+ private static int HEADER_LEN = 7;
- public Packet()
+ public Packet() : base(256+HEADER_LEN)
{
- data = new MemoryStream();
+ Position = HEADER_LEN;
}
- public Packet(int len)
+ public Packet(int len) : base(len+HEADER_LEN)
{
- data = new MemoryStream(len);
+ Position = HEADER_LEN;
}
- public Packet(byte[] bytes)
+ public Packet(byte[] bytes) : base(bytes, 0, bytes.Length, true, true)
{
- data = new MemoryStream( bytes.Length );
- data.Write( bytes, 0, bytes.Length );
- data.Position = 0;
}
public Encoding Encoding
@@ -48,73 +44,30 @@ namespace ByteFX.Data.MySqlClient
get { return encoding; }
}
- public int Length
- {
- get { return (int)data.Length; }
- }
-
- public PacketType Type
- {
- get { if (type == PacketType.None) ParseType(); return type; }
- set { type = value; }
- }
-
- public long Position
- {
- get { return data.Position; }
- set { data.Position = value; }
- }
-
- public void AppendPacket( Packet newPacket )
- {
- data.Position = data.Length;
- byte[] bytes = newPacket.GetBytes();
- data.Write( bytes, 0, bytes.Length );
- }
-
- private PacketType ParseType()
- {
- byte b = ReadByte();
-
- // a 1 byte packet with byte 0xfe means last packet
- if ( data.Length == 1 && b == 0xfe)
- type = PacketType.Last;
-
- // a first byte of 0xff means the packet is an error message
- else if ( b == 0xff )
- type = PacketType.Error;
-
- // the first byte == 0 means an update packet or column count
- else if ( b == 0 )
- type = PacketType.UpdateOrOk;
- else
- type = PacketType.Other;
- return type;
- }
-
- public byte[] GetBytes()
- {
- return data.ToArray();
- }
-
- public void WriteByte( byte b )
+ public byte this[int index]
{
- data.WriteByte( b );
+ get { return GetBuffer()[index]; }
}
- public byte ReadByte()
+ public new int Length
{
- return (byte)data.ReadByte();
+ get { return (int)base.Length; }
}
- public void ReadBytes( byte[] buffer, int offset, int len )
+ public bool IsLastPacket()
{
- data.Read( buffer, offset, len );
+ if (Length == 1 && this[0] == 0xfe) return true;
+ return false;
}
- public void WriteBytes( byte[] bytes, int offset, int len )
+ public byte[] GetBytes( byte packetSeq )
{
- data.Write( bytes, offset, len );
+ long oldPos = Position;
+ Position = 3;
+ WriteInteger( Length-HEADER_LEN, 3 );
+ WriteByte( packetSeq );
+ Position = oldPos;
+ return GetBuffer();
}
public int ReadNBytes()
@@ -129,7 +82,7 @@ namespace ByteFX.Data.MySqlClient
int len = ReadLenInteger();
byte[] buffer = new Byte[len];
- ReadBytes(buffer, 0, len);
+ Read(buffer, 0, len);
return encoding.GetString( buffer, 0, len);
}
@@ -148,7 +101,7 @@ namespace ByteFX.Data.MySqlClient
for (int x=0; x < numbytes; x++)
{
- data.WriteByte( (byte)(val&0xff) );
+ WriteByte( (byte)(val&0xff) );
val >>= 8;
}
}
@@ -164,7 +117,7 @@ namespace ByteFX.Data.MySqlClient
int raise = 1;
for (int x=0; x < numbytes; x++)
{
- int b = data.ReadByte();
+ int b = ReadByte();
val += (b*raise);
raise *= 256;
}
@@ -189,9 +142,9 @@ namespace ByteFX.Data.MySqlClient
}
}
- public bool CanRead
+ public bool HasMoreData
{
- get { return data.Position < data.Length; }
+ get { return Position < Length; }
}
#region String Functions
@@ -199,9 +152,9 @@ namespace ByteFX.Data.MySqlClient
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
- while ( CanRead )
+ while ( HasMoreData )
{
- byte b = ReadByte();
+ byte b = (byte)ReadByte();
if (b == 0) break;
sb.Append( Convert.ToChar( b ));
}
@@ -212,13 +165,13 @@ namespace ByteFX.Data.MySqlClient
public void WriteString(string v, Encoding encoding)
{
WriteStringNoNull(v, encoding);
- data.WriteByte(0);
+ WriteByte(0);
}
public void WriteStringNoNull(string v, Encoding encoding)
{
byte[] bytes = encoding.GetBytes(v);
- data.Write(bytes, 0, bytes.Length);
+ Write(bytes, 0, bytes.Length);
}
#endregion
diff --git a/mcs/class/ByteFX.Data/mysqlclient/command.cs b/mcs/class/ByteFX.Data/mysqlclient/command.cs
index 0a1224afea1..1dd3a20e5f2 100755
--- a/mcs/class/ByteFX.Data/mysqlclient/command.cs
+++ b/mcs/class/ByteFX.Data/mysqlclient/command.cs
@@ -22,10 +22,13 @@ using System.Collections;
namespace ByteFX.Data.MySqlClient
{
+ /// <summary>
+ /// Represents a SQL statement to execute against a MySQL database. This class cannot be inherited.
+ /// </summary>
+ /// <include file='docs/MySqlCommand.xml' path='MyDocs/MyMembers[@name="Class"]/*'/>
#if WINDOWS
[System.Drawing.ToolboxBitmap( typeof(MySqlCommand), "Designers.command.bmp")]
#endif
-
[System.ComponentModel.DesignerCategory("Code")]
public sealed class MySqlCommand : Component, IDbCommand, ICloneable
{
@@ -44,31 +47,43 @@ namespace ByteFX.Data.MySqlClient
{
}
- // Implement other constructors here.
+ /// <summary>
+ /// Overloaded. Initializes a new instance of the MySqlCommand class.
+ /// </summary>
public MySqlCommand(string cmdText)
{
this.cmdText = cmdText;
}
+ /// <summary>
+ /// Overloaded. Initializes a new instance of the MySqlCommand class.
+ /// </summary>
public MySqlCommand(System.ComponentModel.IContainer container)
{
- /// <summary>
- /// Required for Windows.Forms Class Composition Designer support
- /// </summary>
+ // Required for Windows.Forms Class Composition Designer support
container.Add(this);
}
+ /// <summary>
+ /// Overloaded. Initializes a new instance of the MySqlCommand class.
+ /// </summary>
public MySqlCommand(string cmdText, MySqlConnection connection)
{
this.cmdText = cmdText;
this.connection = connection;
}
+ /// <summary>
+ /// Disposes of this instance of MySqlCommand
+ /// </summary>
public new void Dispose()
{
base.Dispose();
}
+ /// <summary>
+ /// Overloaded. Initializes a new instance of the MySqlCommand class.
+ /// </summary>
public MySqlCommand(string cmdText, MySqlConnection connection, MySqlTransaction txn)
{
this.cmdText = cmdText;
@@ -92,7 +107,7 @@ namespace ByteFX.Data.MySqlClient
set { cmdText = value; }
}
- public int UpdateCount
+ internal int UpdateCount
{
get { return updateCount; }
}
@@ -207,6 +222,10 @@ namespace ByteFX.Data.MySqlClient
#endregion
#region Methods
+ /// <summary>
+ /// Attempts to cancel the execution of a MySqlCommand. This operation is not supported.
+ /// </summary>
+ /// <exception cref="NotSupportedException">This operation is not supported.</exception>
public void Cancel()
{
throw new NotSupportedException();
@@ -229,7 +248,7 @@ namespace ByteFX.Data.MySqlClient
private ArrayList SplitSql(string sql)
{
ArrayList commands = new ArrayList();
- System.IO.MemoryStream ms = new System.IO.MemoryStream();
+ System.IO.MemoryStream ms = new System.IO.MemoryStream(sql.Length);
// first we tack on a semi-colon, if not already there, to make our
// sql processing code easier. Then we ask our encoder to give us
@@ -292,7 +311,7 @@ namespace ByteFX.Data.MySqlClient
if (cmdByte != ' ') { goodcmd = true; break; }
if (goodcmd)
- commands.Add( ms.ToArray() );
+ commands.Add( byteArray );
ms.SetLength(0);
}
else if (parm_start == -1)
@@ -306,6 +325,21 @@ namespace ByteFX.Data.MySqlClient
return commands;
}
+ private void ReadOffResultSet()
+ {
+ Driver driver = connection.InternalConnection.Driver;
+
+ // first read off the schema
+ Packet packet = driver.ReadPacket();
+ while (! packet.IsLastPacket())
+ packet = driver.ReadPacket();
+
+ // now read off the data
+ packet = driver.ReadPacket();
+ while (! packet.IsLastPacket())
+ packet = driver.ReadPacket();
+ }
+
/// <summary>
/// Internal function to execute the next command in an array of commands
/// </summary>
@@ -318,16 +352,20 @@ namespace ByteFX.Data.MySqlClient
byte[] sql = (byte[])arraySql[0];
arraySql.RemoveAt(0);
- string s = connection.Encoding.GetString(sql);
- Packet packet = driver.SendSql( s );
- if (packet.Type == PacketType.UpdateOrOk)
+ Packet packet = driver.SendSql( sql );
+ byte b = (byte)packet.ReadByte();
+ if (b == 0)
+ {
+ if (updateCount == -1) updateCount = 0;
updateCount += (int)packet.ReadLenInteger();
- else if (packet.Type == PacketType.ResultSchema && stopAtResultSet)
+ }
+ else if (stopAtResultSet)
+ {
+ packet.Position--;
return packet;
- else do
- {
- packet = driver.ReadPacket();
- } while (packet.Type != PacketType.Last);
+ }
+ else
+ ReadOffResultSet();
}
return null;
}
@@ -347,7 +385,7 @@ namespace ByteFX.Data.MySqlClient
throw new MySqlException("There is already an open DataReader associated with this Connection which must be closed first.");
// execute any commands left in the queue from before.
- ExecuteBatch(false);
+ //ExecuteBatch(false);
arraySql = SplitSql( cmdText );
updateCount = 0;
@@ -376,14 +414,13 @@ namespace ByteFX.Data.MySqlClient
return ExecuteReader(CommandBehavior.Default);
}
+
+ /// <summary>
+ /// Overloaded. Sends the CommandText to the Connection and builds a MySqlDataReader.
+ /// </summary>
+ /// <returns></returns>
public MySqlDataReader ExecuteReader(CommandBehavior behavior)
{
- /*
- * ExecuteReader should retrieve results from the data source
- * and return a DataReader that allows the user to process
- * the results.
- */
-
// There must be a valid and open connection.
if (connection == null || connection.State != ConnectionState.Open)
throw new InvalidOperationException("Connection must be valid and open");
@@ -415,27 +452,15 @@ namespace ByteFX.Data.MySqlClient
sql = String.Format("SET SQL_SELECT_LIMIT=1;{0};SET sql_select_limit=-1;", cmdText);
}
- // execute any commands left in the queue from before.
- ExecuteBatch(false);
-
arraySql = SplitSql( sql );
+ updateCount = -1;
MySqlDataReader reader = new MySqlDataReader(this, behavior);
- try
- {
- if (reader.NextResult())
- {
- connection.Reader = reader;
- return reader;
- }
- return null;
- }
- catch (Exception e)
- {
- System.Diagnostics.Trace.WriteLine("Exception in ExecuteReader: " + e.Message);
- throw e;
- }
+ // move to the first resultset
+ reader.NextResult();
+ connection.Reader = reader;
+ return reader;
}
/// <summary>
@@ -453,11 +478,9 @@ namespace ByteFX.Data.MySqlClient
if (connection.Reader != null)
throw new MySqlException("There is already an open DataReader associated with this Connection which must be closed first.");
- // execute any commands left in the queue from before.
- ExecuteBatch(false);
-
arraySql = SplitSql( cmdText );
+ updateCount = -1;
MySqlDataReader reader = new MySqlDataReader(this, 0);
reader.NextResult();
object val = null;
@@ -477,12 +500,17 @@ namespace ByteFX.Data.MySqlClient
#endregion
#region ICloneable
+ /// <summary>
+ /// Creates a clone of this MySqlCommand object. CommandText, Connection, and Transaction properties
+ /// are included as well as the entire parameter list.
+ /// </summary>
+ /// <returns>The cloned MySqlCommand object</returns>
public object Clone()
{
MySqlCommand clone = new MySqlCommand(cmdText, connection, curTransaction);
foreach (MySqlParameter p in parameters)
{
- clone.Parameters.Add(p.Clone());
+ clone.Parameters.Add((p as ICloneable).Clone());
}
return clone;
}
diff --git a/mcs/class/ByteFX.Data/mysqlclient/dataadapter.cs b/mcs/class/ByteFX.Data/mysqlclient/dataadapter.cs
index e6e288177c3..80637834834 100755
--- a/mcs/class/ByteFX.Data/mysqlclient/dataadapter.cs
+++ b/mcs/class/ByteFX.Data/mysqlclient/dataadapter.cs
@@ -21,6 +21,10 @@ using System.ComponentModel;
namespace ByteFX.Data.MySqlClient
{
+ /// <summary>
+ /// Represents a set of data commands and a database connection that are used to fill a dataset and update a MySQL database. This class cannot be inherited.
+ /// </summary>
+ /// <include file='docs/MySqlDataAdapter.xml' path='MyDocs/MyMembers[@name="Class"]/*'/>
[System.Drawing.ToolboxBitmap( typeof(MySqlDataAdapter), "Designers.dataadapter.bmp")]
[System.ComponentModel.DesignerCategory("Code")]
public sealed class MySqlDataAdapter : DbDataAdapter, IDbDataAdapter
@@ -40,41 +44,63 @@ namespace ByteFX.Data.MySqlClient
static private readonly object EventRowUpdating = new object();
+ /// <summary>
+ /// Initializes a new instance of the MySqlDataAdapter class.
+ /// </summary>
public MySqlDataAdapter()
{
}
+ /// <summary>
+ /// Initializes a new instance of the MySqlDataAdapter class with the specified MySqlCommand as the SelectCommand property.
+ /// </summary>
+ /// <param name="selectCommand"></param>
public MySqlDataAdapter( MySqlCommand selectCommand )
{
SelectCommand = selectCommand;
}
- public MySqlDataAdapter( string selectCommandText, string selectConnString)
+ /// <summary>
+ /// Initializes a new instance of the MySqlDataAdapter class with a SelectCommand and a MySqlConnection object.
+ /// </summary>
+ /// <param name="selectCommandText"></param>
+ /// <param name="conn"></param>
+ public MySqlDataAdapter( string selectCommandText, MySqlConnection conn)
{
- SelectCommand = new MySqlCommand( selectCommandText,
- new MySqlConnection(selectConnString) );
+ SelectCommand = new MySqlCommand( selectCommandText, conn );
}
- public MySqlDataAdapter( string selectCommandText, MySqlConnection conn)
+ /// <summary>
+ /// Initializes a new instance of the MySqlDataAdapter class with a SelectCommand and a connection string.
+ /// </summary>
+ /// <param name="selectCommandText"></param>
+ /// <param name="selectConnString"></param>
+ public MySqlDataAdapter( string selectCommandText, string selectConnString)
{
- SelectCommand = new MySqlCommand( selectCommandText, conn );
+ SelectCommand = new MySqlCommand( selectCommandText,
+ new MySqlConnection(selectConnString) );
}
#region Properties
- [DataSysDescription("Used during Fill/FillSchema")]
- [Category("Fill")]
- public MySqlCommand SelectCommand
+ /// <summary>
+ /// Gets or sets a SQL statement to delete records from the data set.
+ /// </summary>
+ [DataSysDescription("Used during Update for deleted rows in Dataset.")]
+ public MySqlCommand DeleteCommand
{
- get { return m_selectCommand; }
- set { m_selectCommand = value; }
+ get { return m_deleteCommand; }
+ set { m_deleteCommand = value; }
}
- IDbCommand IDbDataAdapter.SelectCommand
+ IDbCommand IDbDataAdapter.DeleteCommand
{
- get { return m_selectCommand; }
- set { m_selectCommand = (MySqlCommand)value; }
+ get { return m_deleteCommand; }
+ set { m_deleteCommand = (MySqlCommand)value; }
}
+ /// <summary>
+ /// Gets or sets a SQL statement to insert new records into the data source.
+ /// </summary>
[DataSysDescription("Used during Update for new rows in Dataset.")]
public MySqlCommand InsertCommand
{
@@ -88,6 +114,26 @@ namespace ByteFX.Data.MySqlClient
set { m_insertCommand = (MySqlCommand)value; }
}
+ /// <summary>
+ /// Gets or sets a SQL statement used to select records in the data source.
+ /// </summary>
+ [DataSysDescription("Used during Fill/FillSchema")]
+ [Category("Fill")]
+ public MySqlCommand SelectCommand
+ {
+ get { return m_selectCommand; }
+ set { m_selectCommand = value; }
+ }
+
+ IDbCommand IDbDataAdapter.SelectCommand
+ {
+ get { return m_selectCommand; }
+ set { m_selectCommand = (MySqlCommand)value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a SQL statement used to update records in the data source.
+ /// </summary>
[DataSysDescription("Used during Update for modified rows in Dataset.")]
public MySqlCommand UpdateCommand
{
@@ -101,33 +147,41 @@ namespace ByteFX.Data.MySqlClient
set { m_updateCommand = (MySqlCommand)value; }
}
- [DataSysDescription("Used during Update for deleted rows in Dataset.")]
- public MySqlCommand DeleteCommand
- {
- get { return m_deleteCommand; }
- set { m_deleteCommand = value; }
- }
-
- IDbCommand IDbDataAdapter.DeleteCommand
- {
- get { return m_deleteCommand; }
- set { m_deleteCommand = (MySqlCommand)value; }
- }
#endregion
/*
* Implement abstract methods inherited from DbDataAdapter.
*/
+ /// <summary>
+ /// Overridden. See <see cref="DbDataAdapter.CreateRowUpdatedEvent"/>.
+ /// </summary>
+ /// <param name="dataRow"></param>
+ /// <param name="command"></param>
+ /// <param name="statementType"></param>
+ /// <param name="tableMapping"></param>
+ /// <returns></returns>
override protected RowUpdatedEventArgs CreateRowUpdatedEvent(DataRow dataRow, IDbCommand command, StatementType statementType, DataTableMapping tableMapping)
{
return new MySqlRowUpdatedEventArgs(dataRow, command, statementType, tableMapping);
}
+ /// <summary>
+ /// Overridden. See <see cref="DbDataAdapter.CreateRowUpdatingEvent"/>.
+ /// </summary>
+ /// <param name="dataRow"></param>
+ /// <param name="command"></param>
+ /// <param name="statementType"></param>
+ /// <param name="tableMapping"></param>
+ /// <returns></returns>
override protected RowUpdatingEventArgs CreateRowUpdatingEvent(DataRow dataRow, IDbCommand command, StatementType statementType, DataTableMapping tableMapping)
{
return new MySqlRowUpdatingEventArgs(dataRow, command, statementType, tableMapping);
}
+ /// <summary>
+ /// Overridden. Raises the RowUpdating event.
+ /// </summary>
+ /// <param name="value">A MySqlRowUpdatingEventArgs that contains the event data.</param>
override protected void OnRowUpdating(RowUpdatingEventArgs value)
{
MySqlRowUpdatingEventHandler handler = (MySqlRowUpdatingEventHandler) Events[EventRowUpdating];
@@ -137,6 +191,10 @@ namespace ByteFX.Data.MySqlClient
}
}
+ /// <summary>
+ /// Overridden. Raises the RowUpdated event.
+ /// </summary>
+ /// <param name="value">A MySqlRowUpdatedEventArgs that contains the event data. </param>
override protected void OnRowUpdated(RowUpdatedEventArgs value)
{
MySqlRowUpdatedEventHandler handler = (MySqlRowUpdatedEventHandler) Events[EventRowUpdated];
@@ -146,12 +204,18 @@ namespace ByteFX.Data.MySqlClient
}
}
+ /// <summary>
+ /// Occurs during Update before a command is executed against the data source. The attempt to update is made, so the event fires.
+ /// </summary>
public event MySqlRowUpdatingEventHandler RowUpdating
{
add { Events.AddHandler(EventRowUpdating, value); }
remove { Events.RemoveHandler(EventRowUpdating, value); }
}
+ /// <summary>
+ /// Occurs during Update after a command is executed against the data source. The attempt to update is made, so the event fires.
+ /// </summary>
public event MySqlRowUpdatedEventHandler RowUpdated
{
add { Events.AddHandler(EventRowUpdated, value); }
@@ -159,17 +223,36 @@ namespace ByteFX.Data.MySqlClient
}
}
+ /// <summary>
+ /// Represents the method that will handle the <see cref="MySqlDataAdapter.RowUpdating"/> event of a <see cref="MySqlDataAdapter"/>.
+ /// </summary>
public delegate void MySqlRowUpdatingEventHandler(object sender, MySqlRowUpdatingEventArgs e);
+
+ /// <summary>
+ /// Represents the method that will handle the <see cref="MySqlDataAdapter.RowUpdated"/> event of a <see cref="MySqlDataAdapter"/>.
+ /// </summary>
public delegate void MySqlRowUpdatedEventHandler(object sender, MySqlRowUpdatedEventArgs e);
- public class MySqlRowUpdatingEventArgs : RowUpdatingEventArgs
+ /// <summary>
+ /// Provides data for the RowUpdating event. This class cannot be inherited.
+ /// </summary>
+ public sealed class MySqlRowUpdatingEventArgs : RowUpdatingEventArgs
{
+ /// <summary>
+ /// Initializes a new instance of the MySqlRowUpdatingEventArgs class.
+ /// </summary>
+ /// <param name="row">The <see cref="DataRow"/> to <see cref="DbDataAdapter.Update"/>.</param>
+ /// <param name="command">The <see cref="IDbCommand"/> to execute during <see cref="DbDataAdapter.Update"/>.</param>
+ /// <param name="statementType">One of the <see cref="StatementType"/> values that specifies the type of query executed.</param>
+ /// <param name="tableMapping">The <see cref="DataTableMapping"/> sent through an <see cref="DbDataAdapter.Update"/>.</param>
public MySqlRowUpdatingEventArgs(DataRow row, IDbCommand command, StatementType statementType, DataTableMapping tableMapping)
: base(row, command, statementType, tableMapping)
{
}
- // Hide the inherited implementation of the command property.
+ /// <summary>
+ /// Gets or sets the MySqlCommand to execute when performing the Update.
+ /// </summary>
new public MySqlCommand Command
{
get { return (MySqlCommand)base.Command; }
@@ -177,14 +260,26 @@ namespace ByteFX.Data.MySqlClient
}
}
- public class MySqlRowUpdatedEventArgs : RowUpdatedEventArgs
+ /// <summary>
+ /// Provides data for the RowUpdated event. This class cannot be inherited.
+ /// </summary>
+ public sealed class MySqlRowUpdatedEventArgs : RowUpdatedEventArgs
{
+ /// <summary>
+ /// Initializes a new instance of the MySqlRowUpdatedEventArgs class.
+ /// </summary>
+ /// <param name="row">The <see cref="DataRow"/> sent through an <see cref="DbDataAdapter.Update"/>.</param>
+ /// <param name="command">The <see cref="IDbCommand"/> executed when <see cref="DbDataAdapter.Update"/> is called.</param>
+ /// <param name="statementType">One of the <see cref="StatementType"/> values that specifies the type of query executed.</param>
+ /// <param name="tableMapping">The <see cref="DataTableMapping"/> sent through an <see cref="DbDataAdapter.Update"/>.</param>
public MySqlRowUpdatedEventArgs(DataRow row, IDbCommand command, StatementType statementType, DataTableMapping tableMapping)
: base(row, command, statementType, tableMapping)
{
}
- // Hide the inherited implementation of the command property.
+ /// <summary>
+ /// Gets or sets the MySqlCommand executed when Update is called.
+ /// </summary>
new public MySqlCommand Command
{
get { return (MySqlCommand)base.Command; }
diff --git a/mcs/class/ByteFX.Data/mysqlclient/datareader.cs b/mcs/class/ByteFX.Data/mysqlclient/datareader.cs
index 1f4a3c6272d..bc166c53253 100755
--- a/mcs/class/ByteFX.Data/mysqlclient/datareader.cs
+++ b/mcs/class/ByteFX.Data/mysqlclient/datareader.cs
@@ -21,6 +21,10 @@ using System.Collections;
namespace ByteFX.Data.MySqlClient
{
+ /// <summary>
+ /// Provides a means of reading a forward-only stream of rows from a MySQL database. This class cannot be inherited.
+ /// </summary>
+ /// <include file='docs/MySqlDataReader.xml' path='MyDocs/MyMembers[@name="Class"]/*'/>
public sealed class MySqlDataReader : MarshalByRefObject, IEnumerable, IDataReader, IDisposable, IDataRecord
{
// The DataReader should always be open when returned to the user.
@@ -33,7 +37,6 @@ namespace ByteFX.Data.MySqlClient
private MySqlCommand command;
private bool canRead;
private bool hasRows;
-// private Packet rowPacket = null;
/*
* Keep track of the connection in order to implement the
@@ -54,14 +57,12 @@ namespace ByteFX.Data.MySqlClient
commandBehavior = behavior;
}
- /****
- * METHODS / PROPERTIES FROM IDataReader.
- ****/
+ /// <summary>
+ /// Gets a value indicating the depth of nesting for the current row. This method is not
+ /// supported currently and always returns 0.
+ /// </summary>
public int Depth
{
- /*
- * Always return a value of zero if nesting is not supported.
- */
get { return 0; }
}
@@ -73,7 +74,7 @@ namespace ByteFX.Data.MySqlClient
get { return ! isOpen; }
}
- public void Dispose()
+ void IDisposable.Dispose()
{
if (isOpen)
Close();
@@ -146,6 +147,10 @@ namespace ByteFX.Data.MySqlClient
}
}
+ /// <summary>
+ /// Gets the value of a column in its native format.
+ /// [C#] In C#, this property is the indexer for the MySqlDataReader class.
+ /// </summary>
public object this [ String name ]
{
// Look up the ordinal and return
@@ -183,13 +188,13 @@ namespace ByteFX.Data.MySqlClient
/// <summary>
/// Reads a stream of bytes from the specified column offset into the buffer an array starting at the given buffer offset.
/// </summary>
- /// <param name="i"></param>
- /// <param name="fieldOffset"></param>
- /// <param name="buffer"></param>
- /// <param name="bufferoffset"></param>
- /// <param name="length"></param>
- /// <returns></returns>
- public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
+ /// <param name="i">The zero-based column ordinal. </param>
+ /// <param name="dataIndex">The index within the field from which to begin the read operation. </param>
+ /// <param name="buffer">The buffer into which to read the stream of bytes. </param>
+ /// <param name="bufferIndex">The index for buffer to begin the read operation. </param>
+ /// <param name="length">The maximum length to copy into the buffer. </param>
+ /// <returns>The actual number of bytes read.</returns>
+ public long GetBytes(int i, long dataIndex, byte[] buffer, int bufferIndex, int length)
{
if (i >= _fields.Length)
throw new IndexOutOfRangeException();
@@ -199,15 +204,15 @@ namespace ByteFX.Data.MySqlClient
if (buffer == null)
return bytes.Length;
- /// adjust the length so we don't run off the end
- if (bytes.Length < (fieldOffset+length))
+ // adjust the length so we don't run off the end
+ if (bytes.Length < (dataIndex+length))
{
- length = (int)(bytes.Length - fieldOffset);
+ length = (int)(bytes.Length - dataIndex);
}
for (int x=0; x < length; x++)
{
- buffer[bufferoffset+x] = bytes[fieldOffset+x];
+ buffer[bufferIndex+x] = bytes[dataIndex+x];
}
return length;
@@ -247,7 +252,7 @@ namespace ByteFX.Data.MySqlClient
if (buffer == null)
return chars.Length;
- /// adjust the length so we don't run off the end
+ // adjust the length so we don't run off the end
if (chars.Length < (fieldOffset+length))
{
length = (int)(chars.Length - fieldOffset);
@@ -547,13 +552,8 @@ namespace ByteFX.Data.MySqlClient
#endregion
- public IDataReader GetData(int i)
+ IDataReader IDataRecord.GetData(int i)
{
- /*
- * The sample code does not support this method. Normally,
- * this would be used to expose nested tables and
- * other hierarchical data.
- */
throw new NotSupportedException("GetData not supported.");
}
@@ -578,13 +578,19 @@ namespace ByteFX.Data.MySqlClient
Driver driver = connection.InternalConnection.Driver;
+ // clear any rows that have not been read from the last rowset
ClearCurrentResult();
- // tell our command to execute the next sql batch
+ // tell our command to continue execution of the SQL batch until it its
+ // another resultset
Packet packet = command.ExecuteBatch(true);
- // if there was no more batches, then signal done
- if (packet == null) return false;
+ // if there was no more resultsets, then signal done
+ if (packet == null)
+ {
+ canRead = false;
+ return false;
+ }
// When executing query statements, the result byte that is returned
// from MySql is the column count. That is why we reference the LastResult
@@ -594,14 +600,20 @@ namespace ByteFX.Data.MySqlClient
_fields = new MySqlField[ packet.ReadLenInteger() ];
for (int x=0; x < _fields.Length; x++)
{
+ packet = driver.ReadPacket();
_fields[x] = new MySqlField();
_fields[x].ReadSchemaInfo( packet );
}
+ // read off the end of schema packet
+ packet = driver.ReadPacket();
+ if ( ! packet.IsLastPacket())
+ throw new MySqlException("Expected end of schema packet");
+
// now take a quick peek at the next packet to see if we have rows
//
packet = driver.PeekPacket();
- hasRows = packet.Type != PacketType.Last;
+ hasRows = ! packet.IsLastPacket();
canRead = hasRows;
connection.SetState( ConnectionState.Open );
@@ -625,7 +637,7 @@ namespace ByteFX.Data.MySqlClient
try
{
Packet rowPacket = driver.ReadPacket();
- if (rowPacket.Type == PacketType.Last)
+ if (rowPacket.IsLastPacket())
{
canRead = false;
return false;
@@ -665,16 +677,18 @@ namespace ByteFX.Data.MySqlClient
{
if (! canRead) return;
- Packet packet = connection.InternalConnection.Driver.ReadPacket();
+ Driver driver = connection.InternalConnection.Driver;
+
+ Packet packet = driver.ReadPacket();
// clean out any current resultset
- while (packet.Type != PacketType.Last)
- packet = connection.InternalConnection.Driver.ReadPacket();
+ while (! packet.IsLastPacket())
+ packet = driver.ReadPacket();
}
#endregion
#region IEnumerator
- public IEnumerator GetEnumerator()
+ IEnumerator IEnumerable.GetEnumerator()
{
return new System.Data.Common.DbEnumerator(this);
}
diff --git a/mcs/class/ByteFX.Data/mysqlclient/parameter.cs b/mcs/class/ByteFX.Data/mysqlclient/parameter.cs
index 7bcc2552801..8ce6aed3d24 100755
--- a/mcs/class/ByteFX.Data/mysqlclient/parameter.cs
+++ b/mcs/class/ByteFX.Data/mysqlclient/parameter.cs
@@ -24,25 +24,37 @@ using System.Reflection;
namespace ByteFX.Data.MySqlClient
{
+ /// <summary>
+ /// Represents a parameter to a <see cref="MySqlCommand"/>, and optionally, its mapping to <see cref="DataSet"/> columns. This class cannot be inherited.
+ /// </summary>
[TypeConverter(typeof(MySqlParameter.MySqlParameterConverter))]
public sealed class MySqlParameter : MarshalByRefObject, IDataParameter, IDbDataParameter, ICloneable
{
- MySqlDbType dbType = MySqlDbType.Null;
- DbType genericType;
- ParameterDirection direction = ParameterDirection.Input;
- bool isNullable = false;
- string paramName;
- string sourceColumn;
- DataRowVersion sourceVersion = DataRowVersion.Current;
- object paramValue = DBNull.Value;
- int size;
- byte precision=0, scale=0;
+ private MySqlDbType dbType = MySqlDbType.Null;
+ private DbType genericType;
+ private ParameterDirection direction = ParameterDirection.Input;
+ private bool isNullable = false;
+ private string paramName;
+ private string sourceColumn;
+ private DataRowVersion sourceVersion = DataRowVersion.Current;
+ private object paramValue = DBNull.Value;
+ private int size;
+ private byte precision=0, scale=0;
#region Constructors
+
+ /// <summary>
+ /// Initializes a new instance of the MySqlParameter class.
+ /// </summary>
public MySqlParameter()
{
}
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MySqlParameter"/> class with the parameter name and a value of the new MySqlParameter.
+ /// </summary>
+ /// <param name="parameterName">The name of the parameter to map. </param>
+ /// <param name="value">An <see cref="Object"/> that is the value of the <see cref="MySqlParameter"/>. </param>
public MySqlParameter(string parameterName, object value)
{
ParameterName = parameterName;
@@ -51,34 +63,54 @@ namespace ByteFX.Data.MySqlClient
genericType = GetGenericType( paramValue.GetType() );
}
- public MySqlParameter( string parameterName, MySqlDbType type)
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MySqlParameter"/> class with the parameter name and the data type.
+ /// </summary>
+ /// <param name="parameterName">The name of the parameter to map. </param>
+ /// <param name="dbType">One of the <see cref="MySqlDbType"/> values. </param>
+ public MySqlParameter( string parameterName, MySqlDbType dbType)
{
ParameterName = parameterName;
- dbType = type;
+ this.dbType = dbType;
}
- public MySqlParameter( string parameterName, MySqlDbType type, int size )
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MySqlParameter"/> class with the parameter name, the <see cref="MySqlDbType"/>, and the size.
+ /// </summary>
+ /// <param name="parameterName">The name of the parameter to map. </param>
+ /// <param name="dbType">One of the <see cref="MySqlDbType"/> values. </param>
+ /// <param name="size">The length of the parameter. </param>
+ public MySqlParameter( string parameterName, MySqlDbType dbType, int size )
{
ParameterName = parameterName;
- dbType = type;
+ this.dbType = dbType;
this.size = size;
}
- public MySqlParameter( string name, MySqlDbType dbType, int size, string sourceCol )
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MySqlParameter"/> class with the parameter name, the <see cref="MySqlDbType"/>, the size, and the source column name.
+ /// </summary>
+ /// <param name="parameterName">The name of the parameter to map. </param>
+ /// <param name="dbType">One of the <see cref="MySqlDbType"/> values. </param>
+ /// <param name="size">The length of the parameter. </param>
+ /// <param name="sourceColumn">The name of the source column. </param>
+ public MySqlParameter( string parameterName, MySqlDbType dbType, int size, string sourceColumn )
{
- ParameterName = name;
+ ParameterName = parameterName;
this.dbType = dbType;
this.size = size;
this.direction = ParameterDirection.Input;
this.precision = 0;
this.scale = 0;
- this.sourceColumn = sourceCol;
+ this.sourceColumn = sourceColumn;
this.sourceVersion = DataRowVersion.Current;
this.paramValue =null;
}
- public MySqlParameter(string name, MySqlDbType type, ParameterDirection dir, string col, DataRowVersion ver, object val)
+ internal MySqlParameter(string name, MySqlDbType type, ParameterDirection dir, string col, DataRowVersion ver, object val)
{
+ if (direction != ParameterDirection.Input)
+ throw new ArgumentException("Only input parameters are supported by MySql");
dbType = type;
direction = dir;
ParameterName = name;
@@ -87,10 +119,27 @@ namespace ByteFX.Data.MySqlClient
paramValue = val;
}
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MySqlParameter"/> class with the parameter name, the type of the parameter, the size of the parameter, a <see cref="ParameterDirection"/>, the precision of the parameter, the scale of the parameter, the source column, a <see cref="DataRowVersion"/> to use, and the value of the parameter.
+ /// </summary>
+ /// <param name="parameterName">The name of the parameter to map. </param>
+ /// <param name="dbType">One of the <see cref="MySqlDbType"/> values. </param>
+ /// <param name="size">The length of the parameter. </param>
+ /// <param name="direction">One of the <see cref="ParameterDirection"/> values. </param>
+ /// <param name="isNullable">true if the value of the field can be null, otherwise false. </param>
+ /// <param name="precision">The total number of digits to the left and right of the decimal point to which <see cref="MySqlParameter.Value"/> is resolved.</param>
+ /// <param name="scale">The total number of decimal places to which <see cref="MySqlParameter.Value"/> is resolved. </param>
+ /// <param name="sourceColumn">The name of the source column. </param>
+ /// <param name="sourceVersion">One of the <see cref="DataRowVersion"/> values. </param>
+ /// <param name="value">An <see cref="Object"/> that is the value of the <see cref="MySqlParameter"/>. </param>
+ /// <exception cref="ArgumentException"/>
public MySqlParameter( string parameterName, MySqlDbType dbType, int size, ParameterDirection direction,
bool isNullable, byte precision, byte scale, string sourceColumn, DataRowVersion sourceVersion,
object value)
{
+ if (direction != ParameterDirection.Input)
+ throw new ArgumentException("Only input parameters are supported by MySql");
+
ParameterName = parameterName;
this.dbType = dbType;
this.size = size;
@@ -104,6 +153,10 @@ namespace ByteFX.Data.MySqlClient
#endregion
#region Properties
+
+ /// <summary>
+ /// Gets or sets the <see cref="DbType"/> of the parameter.
+ /// </summary>
public DbType DbType
{
get
@@ -133,11 +186,11 @@ namespace ByteFX.Data.MySqlClient
case DbType.Int32:
case DbType.UInt32:
- MySqlDbType = MySqlDbType.Long; break;
+ MySqlDbType = MySqlDbType.Int; break;
case DbType.Int64:
case DbType.UInt64:
- MySqlDbType = MySqlDbType.LongLong; break;
+ MySqlDbType = MySqlDbType.BigInt; break;
case DbType.DateTime:
MySqlDbType = MySqlDbType.Datetime; break;
@@ -165,19 +218,10 @@ namespace ByteFX.Data.MySqlClient
}
}
- [Category("Data")]
- public MySqlDbType MySqlDbType
- {
- get
- {
- return dbType;
- }
- set
- {
- dbType = value;
- }
- }
-
+ /// <summary>
+ /// Gets or sets a value indicating whether the parameter is input-only, output-only, bidirectional, or a stored procedure return value parameter.
+ /// As of MySql version 4.1 and earlier, input-only is the only valid choice.
+ /// </summary>
[Category("Data")]
public ParameterDirection Direction
{
@@ -185,12 +229,34 @@ namespace ByteFX.Data.MySqlClient
set { direction = value; }
}
+ /// <summary>
+ /// Gets or sets a value indicating whether the parameter accepts null values.
+ /// </summary>
[Browsable(false)]
public Boolean IsNullable
{
get { return isNullable; }
}
+ /// <summary>
+ /// Gets or sets the MySqlDbType of the parameter.
+ /// </summary>
+ [Category("Data")]
+ public MySqlDbType MySqlDbType
+ {
+ get
+ {
+ return dbType;
+ }
+ set
+ {
+ dbType = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the name of the MySqlParameter.
+ /// </summary>
[Category("Misc")]
public String ParameterName
{
@@ -203,6 +269,39 @@ namespace ByteFX.Data.MySqlClient
}
}
+ /// <summary>
+ /// Gets or sets the maximum number of digits used to represent the <see cref="Value"/> property.
+ /// </summary>
+ [Category("Data")]
+ public byte Precision
+ {
+ get { return precision; }
+ set { precision = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the number of decimal places to which <see cref="Value"/> is resolved.
+ /// </summary>
+ [Category("Data")]
+ public byte Scale
+ {
+ get { return scale; }
+ set { scale = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the maximum size, in bytes, of the data within the column.
+ /// </summary>
+ [Category("Data")]
+ public int Size
+ {
+ get { return size; }
+ set { size = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the name of the source column that is mapped to the <see cref="DataSet"/> and used for loading or returning the <see cref="Value"/>.
+ /// </summary>
[Category("Data")]
public String SourceColumn
{
@@ -210,6 +309,9 @@ namespace ByteFX.Data.MySqlClient
set { sourceColumn = value; }
}
+ /// <summary>
+ /// Gets or sets the <see cref="DataRowVersion"/> to use when loading <see cref="Value"/>.
+ /// </summary>
[Category("Data")]
public DataRowVersion SourceVersion
{
@@ -217,6 +319,9 @@ namespace ByteFX.Data.MySqlClient
set { sourceVersion = value; }
}
+ /// <summary>
+ /// Gets or sets the value of the parameter.
+ /// </summary>
[TypeConverter(typeof(StringConverter))]
[Category("Data")]
public object Value
@@ -233,27 +338,6 @@ namespace ByteFX.Data.MySqlClient
}
}
- // implement methods of IDbDataParameter
- [Category("Data")]
- public byte Precision
- {
- get { return precision; }
- set { precision = value; }
- }
-
- [Category("Data")]
- public byte Scale
- {
- get { return scale; }
- set { scale = value; }
- }
-
- [Category("Data")]
- public int Size
- {
- get { return size; }
- set { size = value; }
- }
#endregion
private void EscapeByteArray( byte[] bytes, System.IO.MemoryStream s )
@@ -279,6 +363,10 @@ namespace ByteFX.Data.MySqlClient
s.Write( newbytes, 0, newx );
}
+ /// <summary>
+ /// Overridden. Gets a string containing the <see cref="ParameterName"/>.
+ /// </summary>
+ /// <returns></returns>
public override string ToString()
{
return paramName;
@@ -297,7 +385,7 @@ namespace ByteFX.Data.MySqlClient
return sb.ToString();
}
- public void SerializeToBytes( System.IO.MemoryStream s, MySqlConnection conn )
+ internal void SerializeToBytes( System.IO.MemoryStream s, MySqlConnection conn )
{
string parm_string = null;
byte[] bytes = null;
@@ -424,9 +512,9 @@ namespace ByteFX.Data.MySqlClient
case TypeCode.Int16:
case TypeCode.UInt16: return MySqlDbType.Int24;
case TypeCode.Int32:
- case TypeCode.UInt32: return MySqlDbType.Long;
+ case TypeCode.UInt32: return MySqlDbType.Int;
case TypeCode.Int64:
- case TypeCode.UInt64: return MySqlDbType.LongLong;
+ case TypeCode.UInt64: return MySqlDbType.BigInt;
case TypeCode.Single: return MySqlDbType.Float;
case TypeCode.Double: return MySqlDbType.Double;
case TypeCode.Decimal: return MySqlDbType.Decimal;
@@ -440,7 +528,7 @@ namespace ByteFX.Data.MySqlClient
#region ICloneable
- public object Clone()
+ object System.ICloneable.Clone()
{
MySqlParameter clone = new MySqlParameter( paramName, dbType, direction,
sourceColumn, sourceVersion, paramValue );
diff --git a/mcs/class/ByteFX.Data/mysqlclient/parameter_collection.cs b/mcs/class/ByteFX.Data/mysqlclient/parameter_collection.cs
index ecaadd0be26..84995140a4a 100755
--- a/mcs/class/ByteFX.Data/mysqlclient/parameter_collection.cs
+++ b/mcs/class/ByteFX.Data/mysqlclient/parameter_collection.cs
@@ -22,6 +22,10 @@ using System.ComponentModel;
namespace ByteFX.Data.MySqlClient
{
+ /// <summary>
+ /// Represents a collection of parameters relevant to a <see cref="MySqlCommand"/> as well as their respective mappings to columns in a <see cref="DataSet"/>. This class cannot be inherited.
+ /// </summary>
+ /// <include file='docs/MySqlParameterCollection.xml' path='MyDocs/MyMembers[@name="Class"]/*'/>
[Editor(typeof(ByteFX.Data.Common.DBParametersEditor), typeof(System.Drawing.Design.UITypeEditor))]
[ListBindable(true)]
public sealed class MySqlParameterCollection : MarshalByRefObject, IDataParameterCollection,
@@ -49,12 +53,12 @@ namespace ByteFX.Data.MySqlClient
_parms.CopyTo(array, index);
}
- public bool IsSynchronized
+ bool ICollection.IsSynchronized
{
get { return _parms.IsSynchronized; }
}
- public object SyncRoot
+ object ICollection.SyncRoot
{
get { return _parms.SyncRoot; }
}
@@ -70,11 +74,23 @@ namespace ByteFX.Data.MySqlClient
_parms.Clear();
}
+ /// <summary>
+ /// Gets a value indicating whether a MySqlParameter exists in the collection.
+ /// </summary>
+ /// <param name="value">The value of the <see cref="MySqlParameter"/> object to find. </param>
+ /// <returns>true if the collection contains the <see cref="MySqlParameter"/> object; otherwise, false.</returns>
+ /// <overloads>Gets a value indicating whether a <see cref="MySqlParameter"/> exists in the collection.</overloads>
public bool Contains(object value)
{
return _parms.Contains(value);
}
+ /// <summary>
+ /// Gets the location of a <see cref="MySqlParameter"/> in the collection.
+ /// </summary>
+ /// <param name="value">The <see cref="MySqlParameter"/> object to locate. </param>
+ /// <returns>The zero-based location of the <see cref="MySqlParameter"/> in the collection.</returns>
+ /// <overloads>Gets the location of a <see cref="MySqlParameter"/> in the collection.</overloads>
public int IndexOf(object value)
{
return _parms.IndexOf(value);
@@ -90,12 +106,12 @@ namespace ByteFX.Data.MySqlClient
_parms.Insert( index, value );
}
- public bool IsFixedSize
+ bool IList.IsFixedSize
{
get { return _parms.IsFixedSize; }
}
- public bool IsReadOnly
+ bool IList.IsReadOnly
{
get { return _parms.IsReadOnly; }
}
@@ -109,6 +125,11 @@ namespace ByteFX.Data.MySqlClient
_parms.Remove( value );
}
+ /// <summary>
+ /// Removes the specified <see cref="MySqlParameter"/> from the collection using a specific index.
+ /// </summary>
+ /// <param name="index">The zero-based index of the parameter. </param>
+ /// <overloads>Removes the specified <see cref="MySqlParameter"/> from the collection.</overloads>
public void RemoveAt( int index )
{
_parms.RemoveAt( index );
@@ -124,6 +145,11 @@ namespace ByteFX.Data.MySqlClient
}
}
+ /// <summary>
+ /// Adds the specified <see cref="MySqlParameter"/> object to the <see cref="MySqlParameterCollection"/>.
+ /// </summary>
+ /// <param name="value">The <see cref="MySqlParameter"/> to add to the collection.</param>
+ /// <returns>The index of the new <see cref="MySqlParameter"/> object.</returns>
public int Add( object value )
{
if (! (value is MySqlParameter)) throw new MySqlException("Only MySqlParameter objects may be stored");
@@ -139,6 +165,12 @@ namespace ByteFX.Data.MySqlClient
#endregion
#region IDataParameterCollection
+
+ /// <summary>
+ /// Gets a value indicating whether a <see cref="MySqlParameter"/> with the specified parameter name exists in the collection.
+ /// </summary>
+ /// <param name="name">The name of the <see cref="MySqlParameter"/> object to find.</param>
+ /// <returns>true if the collection contains the parameter; otherwise, false.</returns>
public bool Contains(string name)
{
if (name[0] == '@')
@@ -150,18 +182,27 @@ namespace ByteFX.Data.MySqlClient
return false;
}
- public int IndexOf( string name )
+ /// <summary>
+ /// Gets the location of the <see cref="MySqlParameter"/> in the collection with a specific parameter name.
+ /// </summary>
+ /// <param name="parameterName">The name of the <see cref="MySqlParameter"/> object to retrieve. </param>
+ /// <returns>The zero-based location of the <see cref="MySqlParameter"/> in the collection.</returns>
+ public int IndexOf( string parameterName )
{
- if (name[0] == '@')
- name = name.Substring(1, name.Length-1);
+ if (parameterName[0] == '@')
+ parameterName = parameterName.Substring(1, parameterName.Length-1);
for (int x=0; x < _parms.Count; x++)
{
MySqlParameter p = (MySqlParameter)_parms[x];
- if (p.ParameterName.ToLower().Equals( name.ToLower() )) return x;
+ if (p.ParameterName.ToLower().Equals( parameterName.ToLower() )) return x;
}
- throw new MySqlException("Parameter '" + name + "' not found in collection");
+ throw new MySqlException("Parameter '" + parameterName + "' not found in collection");
}
+ /// <summary>
+ /// Removes the specified <see cref="MySqlParameter"/> from the collection using the parameter name.
+ /// </summary>
+ /// <param name="name">The name of the <see cref="MySqlParameter"/> object to retrieve. </param>
public void RemoveAt( string name )
{
int index = IndexOf( name );
@@ -180,25 +221,40 @@ namespace ByteFX.Data.MySqlClient
#endregion
#region IEnumerable
- public IEnumerator GetEnumerator()
+ IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)_parms).GetEnumerator();
}
#endregion
#region Public Methods
+
+ /// <summary>
+ /// Gets the <see cref="MySqlParameter"/> at the specified index.
+ /// </summary>
+ /// <overloads>Gets the <see cref="MySqlParameter"/> with a specified attribute.
+ /// [C#] In C#, this property is the indexer for the <see cref="MySqlParameterCollection"/> class.
+ /// </overloads>
public MySqlParameter this[int index]
{
get { return (MySqlParameter)_parms[index]; }
set { _parms[index] = value; }
}
+ /// <summary>
+ /// Gets the <see cref="MySqlParameter"/> with the specified name.
+ /// </summary>
public MySqlParameter this[string name]
{
get { return (MySqlParameter)_parms[ IndexOf( name ) ]; }
set { _parms[ IndexOf( name ) ] = value; }
}
+ /// <summary>
+ /// Adds the specified <see cref="MySqlParameter"/> object to the <see cref="MySqlParameterCollection"/>.
+ /// </summary>
+ /// <param name="value">The <see cref="MySqlParameter"/> to add to the collection.</param>
+ /// <returns>The index of the new <see cref="MySqlParameter"/> object.</returns>
public MySqlParameter Add(MySqlParameter value)
{
if ( value.ParameterName == null ) throw new ArgumentException("parameter must be named");
@@ -207,21 +263,48 @@ namespace ByteFX.Data.MySqlClient
return value;
}
+ /// <summary>
+ /// Adds a <see cref="MySqlParameter"/> to the <see cref="MySqlParameterCollection"/> given the specified parameter name and value.
+ /// </summary>
+ /// <param name="parameterName">The name of the parameter.</param>
+ /// <param name="value">The <see cref="MySqlParameter.Value"/> of the <see cref="MySqlParameter"/> to add to the collection.</param>
+ /// <returns>The index of the new <see cref="MySqlParameter"/> object.</returns>
public MySqlParameter Add( string parameterName, object value )
{
return Add( new MySqlParameter( parameterName, value ) );
}
- public MySqlParameter Add(string parameterName, MySqlDbType type)
+ /// <summary>
+ /// Adds a <see cref="MySqlParameter"/> to the <see cref="MySqlParameterCollection"/> given the parameter name and the data type.
+ /// </summary>
+ /// <param name="parameterName">The name of the parameter.</param>
+ /// <param name="dbType">One of the <see cref="MySqlDbType"/> values. </param>
+ /// <returns>The index of the new <see cref="MySqlParameter"/> object.</returns>
+ public MySqlParameter Add(string parameterName, MySqlDbType dbType)
{
- return Add(new MySqlParameter(parameterName, type));
+ return Add(new MySqlParameter(parameterName, dbType));
}
+ /// <summary>
+ /// Adds a <see cref="MySqlParameter"/> to the <see cref="MySqlParameterCollection"/> with the parameter name, the data type, and the column length.
+ /// </summary>
+ /// <param name="parameterName">The name of the parameter.</param>
+ /// <param name="dbType">One of the <see cref="MySqlDbType"/> values. </param>
+ /// <param name="size">The length of the column.</param>
+ /// <returns>The index of the new <see cref="MySqlParameter"/> object.</returns>
public MySqlParameter Add(string parameterName, MySqlDbType dbType, int size)
{
return Add(new MySqlParameter(parameterName, dbType, size ));
}
+ /// <summary>
+ /// Adds a <see cref="MySqlParameter"/> to the <see cref="MySqlParameterCollection"/> with the parameter name, the data type, the column length, and the source column name.
+ /// </summary>
+ /// <param name="parameterName">The name of the parameter.</param>
+ /// <param name="dbType">One of the <see cref="MySqlDbType"/> values. </param>
+ /// <param name="size">The length of the column.</param>
+ /// <param name="sourceColumn">The name of the source column.</param>
+ /// <returns>The index of the new <see cref="MySqlParameter"/> object.</returns>
public MySqlParameter Add(string parameterName, MySqlDbType dbType, int size, string sourceColumn)
{
return Add(new MySqlParameter(parameterName, dbType, size, sourceColumn));
diff --git a/mcs/class/ByteFX.Data/mysqlclient/transcaction.cs b/mcs/class/ByteFX.Data/mysqlclient/transcaction.cs
index f52a74c4620..213dac7818d 100755
--- a/mcs/class/ByteFX.Data/mysqlclient/transcaction.cs
+++ b/mcs/class/ByteFX.Data/mysqlclient/transcaction.cs
@@ -20,7 +20,11 @@ using System.Data;
namespace ByteFX.Data.MySqlClient
{
- public class MySqlTransaction : IDbTransaction
+ /// <summary>
+ /// Represents a SQL transaction to be made in a MySQL database. This class cannot be inherited.
+ /// </summary>
+ /// <include file='docs/MySqlTransaction.xml' path='MyDocs/MyMembers[@name="Class"]/*'/>
+ public sealed class MySqlTransaction : IDbTransaction
{
private IsolationLevel _level;
private MySqlConnection _conn;
@@ -31,22 +35,35 @@ namespace ByteFX.Data.MySqlClient
_open = true;
}
- public IsolationLevel IsolationLevel
- {
- get { return _level; }
- set { _level = value; }
- }
+ #region Properties
+ /// <summary>
+ /// Gets the <see cref="MySqlConnection"/> object associated with the transaction, or a null reference (Nothing in Visual Basic) if the transaction is no longer valid.
+ /// </summary>
public IDbConnection Connection
{
get { return _conn; }
set { _conn = (MySqlConnection)value; }
}
- public void Dispose()
+ /// <summary>
+ /// Specifies the <see cref="IsolationLevel"/> for this transaction.
+ /// </summary>
+ public IsolationLevel IsolationLevel
+ {
+ get { return _level; }
+ set { _level = value; }
+ }
+
+ #endregion
+
+ void System.IDisposable.Dispose()
{
}
+ /// <summary>
+ /// Commits the database transaction.
+ /// </summary>
public void Commit()
{
if (_conn == null || _conn.State != ConnectionState.Open)
@@ -65,6 +82,9 @@ namespace ByteFX.Data.MySqlClient
}
}
+ /// <summary>
+ /// Overloaded. Rolls back a transaction from a pending state.
+ /// </summary>
public void Rollback()
{
if (_conn == null || _conn.State != ConnectionState.Open)
diff --git a/mcs/class/Microsoft.JScript/Microsoft.JScript/ChangeLog b/mcs/class/Microsoft.JScript/Microsoft.JScript/ChangeLog
index fdb5bc41d5a..cad0fd09a7b 100644
--- a/mcs/class/Microsoft.JScript/Microsoft.JScript/ChangeLog
+++ b/mcs/class/Microsoft.JScript/Microsoft.JScript/ChangeLog
@@ -1,3 +1,16 @@
+2003-11-30 Cesar Lopez Nataren <cesar@ciencias.unam.mx>
+
+ * expression.cs: Added new field to Call class, so it can handle more arguments.
+
+ * StringLiteral.cs (Emit) : Load the string value.
+
+ * Literal.cs: BooleanLiteral, Resolve always return true. Emit the value and box it to Boolean.
+
+ * CodeGenerator.cs: Set parent if 'JScript 0' to GlobalScope. Set
+ custom attribute. Build default 'JScript 0' constructor. Emit
+ default initial/final code of 'Global Code'. Create default
+ 'JScript Main'.
+
2003-11-29 Cesar Lopez Nataren <cesar@ciencias.unam.mx>
* jscript-lexer-grammar.g: define new rule 'arguments' instead of
diff --git a/mcs/class/Microsoft.JScript/Microsoft.JScript/CodeGenerator.cs b/mcs/class/Microsoft.JScript/Microsoft.JScript/CodeGenerator.cs
index 781c03f5468..396ec8af05b 100644
--- a/mcs/class/Microsoft.JScript/Microsoft.JScript/CodeGenerator.cs
+++ b/mcs/class/Microsoft.JScript/Microsoft.JScript/CodeGenerator.cs
@@ -11,6 +11,8 @@ using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;
+using Microsoft.JScript.Vsa;
+using System.Runtime.CompilerServices;
namespace Microsoft.JScript {
@@ -78,8 +80,18 @@ namespace Microsoft.JScript {
TypeBuilder type_builder;
type_builder = module_builder.DefineType ("JScript 0");
+
+ type_builder.SetParent (typeof (GlobalScope));
+ type_builder.SetCustomAttribute (new CustomAttributeBuilder
+ (typeof (CompilerGlobalScopeAttribute).GetConstructor (new Type [] {}), new object [] {}));
+
EmitContext ec = new EmitContext (type_builder);
+ //
+ // Build the default constructor of the type
+ //
+ emit_default_script_constructor (ec);
+
// here we only emit code for declarations.
prog.Emit (ec);
@@ -96,18 +108,129 @@ namespace Microsoft.JScript {
ec.ig = method.GetILGenerator ();
ec.is_global_code_method = true;
- prog.Emit (ec);
+ emit_default_init_global_code (ec.ig);
+ prog.Emit (ec);
+ emit_default_end_global_code (ec.ig);
ec.type_builder.CreateType ();
+
+ //
+ // Build the default 'JScript Main' class
+ //
+ ec.type_builder = module_builder.DefineType ("JScript Main");
+ emit_jscript_main (ec.type_builder);
+ ec.type_builder.CreateType ();
+ }
+
+ internal static void emit_default_init_global_code (ILGenerator ig)
+ {
+ ig.Emit (OpCodes.Ldarg_0);
+ ig.Emit (OpCodes.Ldfld, typeof (ScriptObject).GetField ("engine"));
+ ig.Emit (OpCodes.Ldarg_0);
+ ig.Emit (OpCodes.Call,
+ typeof (VsaEngine).GetMethod ("PushScriptObject",
+ new Type [] { typeof (ScriptObject)}));
+ }
+
+ internal static void emit_default_end_global_code (ILGenerator ig)
+ {
+ ig.Emit (OpCodes.Ldarg_0);
+ ig.Emit (OpCodes.Ldfld, typeof (ScriptObject).GetField ("engine"));
+ ig.Emit (OpCodes.Call, typeof (VsaEngine).GetMethod ("PopScriptObject"));
+ ig.Emit (OpCodes.Pop);
+ ig.Emit (OpCodes.Ret);
+ }
+
+ internal static void emit_default_script_constructor (EmitContext ec)
+ {
+ ConstructorBuilder cons_builder;
+ TypeBuilder tb = ec.type_builder;
+ cons_builder = tb.DefineConstructor (MethodAttributes.Public,
+ CallingConventions.Standard,
+ new Type [] { typeof (GlobalScope) });
+
+ ILGenerator ig = cons_builder.GetILGenerator ();
+ ig.Emit (OpCodes.Ldarg_0);
+ ig.Emit (OpCodes.Ldarg_1);
+ ig.Emit (OpCodes.Dup);
+ ig.Emit (OpCodes.Ldfld,
+ typeof (ScriptObject).GetField ("engine"));
+
+ ig.Emit (OpCodes.Call,
+ typeof (GlobalScope).GetConstructor (new Type [] {typeof (GlobalScope),
+ typeof (VsaEngine)}));
+ ig.Emit (OpCodes.Ret);
+ }
+
+ internal static void emit_jscript_main (TypeBuilder tb)
+ {
+ emit_jscript_main_constructor (tb);
+ emit_jscript_main_entry_point (tb);
+ }
+
+ internal static void emit_jscript_main_constructor (TypeBuilder tb)
+ {
+ ConstructorBuilder cons = tb.DefineConstructor (MethodAttributes.Public,
+ CallingConventions.Standard,
+ new Type [] {});
+ ILGenerator ig = cons.GetILGenerator ();
+ ig.Emit (OpCodes.Ldarg_0);
+ ig.Emit (OpCodes.Call, typeof (Object).GetConstructor (new Type [] {}));
+ ig.Emit (OpCodes.Ret);
+ }
+
+ internal static void emit_jscript_main_entry_point (TypeBuilder tb)
+ {
+ MethodBuilder method;
+ method = tb.DefineMethod ("Main",
+ MethodAttributes.Public | MethodAttributes.Static,
+ typeof (void), new Type [] {typeof (String [])});
+
+ method.SetCustomAttribute (new CustomAttributeBuilder
+ (typeof (STAThreadAttribute).GetConstructor (
+ new Type [] {}),
+ new object [] {}));
+
+ ILGenerator ig = method.GetILGenerator ();
+
+ ig.DeclareLocal (typeof (GlobalScope));
+
+ ig.Emit (OpCodes.Ldc_I4_1);
+ ig.Emit (OpCodes.Ldc_I4_1);
+ ig.Emit (OpCodes.Newarr, typeof (string));
+ ig.Emit (OpCodes.Dup);
+ ig.Emit (OpCodes.Ldc_I4_0);
+
+ ig.Emit (OpCodes.Ldstr,
+ "mscorlib, Version=1.0.3300.0, Culture=neutral, Pub" +
+ "licKeyToken=b77a5c561934e089");
+
+ ig.Emit (OpCodes.Stelem_Ref);
+
+ ig.Emit (OpCodes.Call,
+ typeof (VsaEngine).GetMethod ("CreateEngineAndGetGlobalScope",
+ new Type [] {typeof (bool),
+ typeof (string [])}));
+ ig.Emit (OpCodes.Stloc_0);
+ ig.Emit (OpCodes.Ldloc_0);
+
+ ig.Emit (OpCodes.Newobj,
+ assembly_builder.GetType ("JScript 0").GetConstructor (
+ new Type [] {typeof (GlobalScope)}));
+ ig.Emit (OpCodes.Call,
+ assembly_builder.GetType ("JScript 0").GetMethod (
+ "Global Code", new Type [] {}));
+ ig.Emit (OpCodes.Pop);
+ ig.Emit (OpCodes.Ret);
+
+ assembly_builder.SetEntryPoint (method);
}
public static void Run (string file_name, AST prog)
{
CodeGenerator.Init (file_name);
CodeGenerator.Emit (prog);
-
- CodeGenerator.Save (trim_extension (file_name) +
- ".exe");
+ CodeGenerator.Save (trim_extension (file_name) + ".exe");
}
}
}
diff --git a/mcs/class/Microsoft.JScript/Microsoft.JScript/Literal.cs b/mcs/class/Microsoft.JScript/Microsoft.JScript/Literal.cs
index 303708e6a0b..2749c604f46 100644
--- a/mcs/class/Microsoft.JScript/Microsoft.JScript/Literal.cs
+++ b/mcs/class/Microsoft.JScript/Microsoft.JScript/Literal.cs
@@ -8,6 +8,7 @@
//
using System;
+using System.Reflection.Emit;
namespace Microsoft.JScript {
@@ -40,12 +41,19 @@ namespace Microsoft.JScript {
internal override bool Resolve (IdentificationTable context)
{
- throw new NotImplementedException ();
+ return true;
}
internal override void Emit (EmitContext ec)
{
- throw new NotImplementedException ();
+ if (ec.is_global_code_method) {
+ if (val)
+ ec.ig.Emit (OpCodes.Ldc_I4_1);
+ else
+ ec.ig.Emit (OpCodes.Ldc_I4_0);
+
+ ec.ig.Emit (OpCodes.Box, typeof (System.Boolean));
+ }
}
}
diff --git a/mcs/class/Microsoft.JScript/Microsoft.JScript/StringLiteral.cs b/mcs/class/Microsoft.JScript/Microsoft.JScript/StringLiteral.cs
index 9aa1984b2b8..bc2eeb9d617 100644
--- a/mcs/class/Microsoft.JScript/Microsoft.JScript/StringLiteral.cs
+++ b/mcs/class/Microsoft.JScript/Microsoft.JScript/StringLiteral.cs
@@ -8,6 +8,7 @@
//
using System;
+using System.Reflection.Emit;
namespace Microsoft.JScript {
@@ -37,7 +38,9 @@ namespace Microsoft.JScript {
internal override void Emit (EmitContext ec)
{
- throw new NotImplementedException ();
+ if (ec.is_global_code_method) {
+ ec.ig.Emit (OpCodes.Ldstr, str);
+ }
}
}
}
diff --git a/mcs/class/Microsoft.JScript/Microsoft.JScript/expression.cs b/mcs/class/Microsoft.JScript/Microsoft.JScript/expression.cs
index 35d3fc162e8..81d3e16616a 100755
--- a/mcs/class/Microsoft.JScript/Microsoft.JScript/expression.cs
+++ b/mcs/class/Microsoft.JScript/Microsoft.JScript/expression.cs
@@ -29,21 +29,24 @@ namespace Microsoft.JScript {
if (oper != JSToken.None)
sb.Append (oper + " ");
- sb.Append (operand.ToString ());
+ if (operand != null)
+ sb.Append (operand.ToString ());
return sb.ToString ();
}
internal override bool Resolve (IdentificationTable context)
{
- operand.Resolve (context);
+ if (operand != null)
+ operand.Resolve (context);
return true;
}
internal override void Emit (EmitContext ec)
{
- throw new NotImplementedException ();
+ if (operand != null)
+ operand.Emit (ec);
}
}
@@ -144,34 +147,41 @@ namespace Microsoft.JScript {
public class Call : AST {
- internal AST left;
- internal AST args;
+ internal AST member_exp;
+ internal AST args1;
+ internal AST args2;
- public Call (AST left, AST args)
+ public Call (AST member_exp, AST args1, AST args2)
{
- this.left = left;
- this.args = args;
+ this.member_exp = member_exp;
+ this.args1 = args1;
+ this.args2 = args2;
}
public override string ToString ()
{
StringBuilder sb = new StringBuilder ();
- if (left != null)
- sb.Append (left.ToString () + " ");
- if (args != null)
- sb.Append (args.ToString ());
+ if (member_exp != null)
+ sb.Append (member_exp.ToString () + " ");
+ if (args1 != null)
+ sb.Append (args1.ToString ());
+ if (args2 != null)
+ sb.Append (args2.ToString ());
return sb.ToString ();
}
internal override bool Resolve (IdentificationTable context)
{
- if (left != null)
- left.Resolve (context);
+ if (member_exp != null)
+ member_exp.Resolve (context);
+
+ if (args1 != null)
+ args1.Resolve (context);
- if (args != null)
- args.Resolve (context);
+ if (args2 != null)
+ args2.Resolve (context);
return true;
}
diff --git a/mcs/class/Mono.Security/Mono.Security.Cryptography/MD5SHA1CryptoServiceProvider.cs b/mcs/class/Mono.Security/Mono.Security.Cryptography/MD5SHA1CryptoServiceProvider.cs
new file mode 100755
index 00000000000..bf97dfd3a82
--- /dev/null
+++ b/mcs/class/Mono.Security/Mono.Security.Cryptography/MD5SHA1CryptoServiceProvider.cs
@@ -0,0 +1,127 @@
+/* Transport Security Layer (TLS)
+ * Copyright (c) 2003 Carlos Guzmán Álvarez
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+using System;
+using System.Security.Cryptography;
+
+namespace Mono.Security.Cryptography
+{
+ internal class MD5SHA1CryptoServiceProvider : HashAlgorithm
+ {
+ #region FIELDS
+
+ private HashAlgorithm md5;
+ private HashAlgorithm sha;
+ private bool hashing;
+
+ #endregion
+
+ #region CONSTRUCTORS
+
+ public MD5SHA1CryptoServiceProvider()
+ {
+ this.md5 = new MD5CryptoServiceProvider();
+ this.sha = new SHA1CryptoServiceProvider();
+
+ // Set HashSizeValue
+ this.HashSizeValue = this.md5.HashSize + this.sha.HashSize;
+ }
+
+ #endregion
+
+ #region METHODS
+
+ public override void Initialize()
+ {
+ this.md5.Initialize();
+ this.sha.Initialize();
+ this.hashing = false;
+ }
+
+ protected override byte[] HashFinal()
+ {
+ if (!hashing)
+ {
+ this.hashing = true;
+ }
+ // Finalize the original hash
+ this.md5.TransformFinalBlock(new byte[0], 0, 0);
+ this.sha.TransformFinalBlock(new byte[0], 0, 0);
+
+ byte[] hash = new byte[36];
+
+ System.Array.Copy(this.md5.Hash, 0, hash, 0, 16);
+ System.Array.Copy(this.sha.Hash, 0, hash, 16, 20);
+
+ return hash;
+ }
+
+ protected override void HashCore(
+ byte[] array,
+ int ibStart,
+ int cbSize)
+ {
+ if (!hashing)
+ {
+ hashing = true;
+ }
+ this.md5.TransformBlock(array, ibStart, cbSize, array, ibStart);
+ this.sha.TransformBlock(array, ibStart, cbSize, array, ibStart);
+ }
+
+ public byte[] CreateSignature(RSA rsa)
+ {
+ if (rsa == null)
+ {
+ throw new CryptographicUnexpectedOperationException ("missing key");
+ }
+
+ #warning "MD5SHA1 hash is not supported by .NET"
+ RSAPKCS1SignatureFormatter f = new RSAPKCS1SignatureFormatter(rsa);
+ f.SetHashAlgorithm("MD5SHA1");
+
+ return f.CreateSignature(this.Hash);
+ }
+
+ public bool VerifySignature(RSA rsa, byte[] rgbSignature)
+ {
+ if (rsa == null)
+ {
+ throw new CryptographicUnexpectedOperationException ("missing key");
+ }
+ if (rgbSignature == null)
+ {
+ throw new ArgumentNullException ("rgbSignature");
+ }
+
+ #warning "MD5SHA1 hash is not supported by .NET"
+ RSAPKCS1SignatureDeformatter d = new RSAPKCS1SignatureDeformatter(rsa);
+ d.SetHashAlgorithm("MD5SHA1");
+
+ return d.VerifySignature(this.Hash, rgbSignature);
+ }
+
+ #endregion
+ }
+}
diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsCompressionMethod.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsCompressionMethod.cs
new file mode 100755
index 00000000000..371ad6ec72f
--- /dev/null
+++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsCompressionMethod.cs
@@ -0,0 +1,37 @@
+/* Transport Security Layer (TLS)
+ * Copyright (c) 2003 Carlos Guzmán Álvarez
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+using System;
+
+namespace Mono.Security.Protocol.Tls
+{
+ // Information about compression methods allowed by TLS
+ // can be found in:
+ // draft-ietf-tls-compression-05.txt (http://www.ietf.org/internet-drafts/draft-ietf-tls-compression-05.txt)
+ public enum TlsCompressionMethod : byte
+ {
+ None = 0,
+ Zlib = 1
+ }
+}
diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsNetworkStream.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsNetworkStream.cs
new file mode 100644
index 00000000000..e30730eaf87
--- /dev/null
+++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsNetworkStream.cs
@@ -0,0 +1,369 @@
+/* Transport Security Layer (TLS)
+ * Copyright (c) 2003 Carlos Guzmán Álvarez
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+using System;
+using System.IO;
+using System.Net;
+using System.Net.Sockets;
+
+namespace Mono.Security.Protocol.Tls
+{
+ public class TlsNetworkStream : Stream, IDisposable
+ {
+ #region PROPERTIES
+
+ private TlsSocket socket;
+ private bool ownsSocket;
+ private bool canRead;
+ private bool canWrite;
+ private bool disposed;
+
+ #endregion
+
+ #region PROPERTIES
+
+ public override bool CanRead
+ {
+ get { return canRead; }
+ }
+
+ public override bool CanSeek
+ {
+ get { return false; }
+ }
+
+ public override bool CanWrite
+ {
+ get { return canWrite; }
+ }
+
+ public override long Length
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public override long Position
+ {
+ get { throw new NotSupportedException(); }
+ set { throw new NotSupportedException(); }
+
+ }
+
+ public bool DataAvailable
+ {
+ get
+ {
+ if (socket == null)
+ {
+ throw new IOException();
+ }
+
+ if (this.socket.Session.IsSecure)
+ {
+ if ((this.socket.InputBuffer.Length - this.socket.InputBuffer.Position) > 0)
+ {
+ return true;
+ }
+ }
+
+ // If there are bytes in the socket buffer return true
+ // otherwise false
+ return this.socket.Available != 0;
+ }
+ }
+
+ #endregion
+
+ #region DESTRUCTOR
+
+ ~TlsNetworkStream()
+ {
+ this.Dispose(false);
+ }
+
+ #endregion
+
+ #region IDISPOSABLE
+
+ void IDisposable.Dispose()
+ {
+ this.Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!disposed)
+ {
+ if (disposing)
+ {
+ if (this.socket != null)
+ {
+ if (this.ownsSocket)
+ {
+ try
+ {
+ this.socket.Shutdown(SocketShutdown.Both);
+ }
+ catch{}
+ finally
+ {
+ this.socket.Close();
+ }
+ }
+ }
+ this.ownsSocket = false;
+ this.canRead = false;
+ this.canWrite = false;
+ this.socket = null;
+ }
+
+ disposed = true;
+ }
+ }
+
+ #endregion
+
+ #region PROTECTED_PROPERTIES
+
+ protected bool Readable
+ {
+ get { return this.canRead; }
+ set { this.canRead = value;}
+ }
+
+ protected TlsSocket Socket
+ {
+ get { return socket; }
+ }
+
+ protected bool Writeable
+ {
+ get { return this.canWrite; }
+ set { this.canWrite = value; }
+ }
+
+ #endregion
+
+ #region CONSTRUCTORS
+
+ public TlsNetworkStream(TlsSocket socket)
+ : this(socket, FileAccess.ReadWrite, false)
+ {
+ }
+
+ public TlsNetworkStream(TlsSocket socket, bool ownsSocket)
+ : this(socket, FileAccess.ReadWrite, ownsSocket)
+ {
+ }
+
+ public TlsNetworkStream(TlsSocket socket, FileAccess access)
+ : this(socket, FileAccess.ReadWrite, false)
+ {
+ }
+
+ public TlsNetworkStream(TlsSocket socket, FileAccess access, bool ownsSocket)
+ {
+ if (socket == null)
+ {
+ throw new ArgumentNullException("socket is a null reference.");
+ }
+ if (!socket.Blocking)
+ {
+ throw new IOException("socket is in a nonblocking state.");
+ }
+ if (socket.SocketType != SocketType.Stream)
+ {
+ throw new IOException("The SocketType property of socket is not SocketType.Stream.");
+ }
+ if (!socket.Connected)
+ {
+ throw new IOException("socket is not connected.");
+ }
+
+ this.socket = socket;
+ this.ownsSocket = ownsSocket;
+ switch (access)
+ {
+ case FileAccess.Read:
+ this.canRead = true;
+ break;
+
+ case FileAccess.ReadWrite:
+ this.canRead = true;
+ this.canWrite = true;
+ break;
+
+ case FileAccess.Write:
+ this.canWrite = true;
+ break;
+ }
+ }
+
+ #endregion
+
+ #region METHODS
+
+ public override IAsyncResult BeginRead(
+ byte[] buffer,
+ int offset,
+ int count,
+ AsyncCallback callback,
+ object state)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override IAsyncResult BeginWrite(
+ byte[] buffer,
+ int offset,
+ int count,
+ AsyncCallback callback,
+ object state)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override int EndRead(IAsyncResult asyncResult)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override void EndWrite(IAsyncResult asyncResult)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override void Close()
+ {
+ ((IDisposable)this).Dispose();
+ }
+
+ public override void Flush()
+ {
+ }
+
+ public override int Read(byte[] buffer, int offset, int size)
+ {
+ if (buffer == null)
+ {
+ throw new ArgumentNullException("buffer is a null reference.");
+ }
+ if (offset < 0)
+ {
+ throw new ArgumentOutOfRangeException("offset is less than 0.");
+ }
+ if (offset > buffer.Length)
+ {
+ throw new ArgumentOutOfRangeException("offset is greater than the length of buffer.");
+ }
+ if (size < 0)
+ {
+ throw new ArgumentOutOfRangeException("size is less than 0.");
+ }
+ if (size > (buffer.Length - offset))
+ {
+ throw new ArgumentOutOfRangeException("size is less than the length of buffer minus the value of the offset parameter.");
+ }
+ if (disposed)
+ {
+ throw new ObjectDisposedException("The NetworkStream is closed.");
+ }
+ if (!socket.Connected)
+ {
+ throw new IOException("The underlying Socket is closed.");
+ }
+
+ try
+ {
+ return socket.Receive(buffer, offset, size, SocketFlags.None);
+ }
+ catch (TlsException ex)
+ {
+ throw ex;
+ }
+ catch (Exception ex)
+ {
+ throw new IOException("IO exception during read.", ex);
+ }
+ }
+
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override void SetLength(long value)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override void Write(byte[] buffer, int offset, int size)
+ {
+ if (buffer == null)
+ {
+ throw new ArgumentNullException("buffer is a null reference.");
+ }
+ if (offset < 0)
+ {
+ throw new ArgumentOutOfRangeException("offset is less than 0.");
+ }
+ if (offset > buffer.Length)
+ {
+ throw new ArgumentOutOfRangeException("offset is greater than the length of buffer.");
+ }
+ if (size < 0)
+ {
+ throw new ArgumentOutOfRangeException("size is less than 0.");
+ }
+ if (size > (buffer.Length - offset))
+ {
+ throw new ArgumentOutOfRangeException("size is less than the length of buffer minus the value of the offset parameter.");
+ }
+ if (disposed)
+ {
+ throw new ObjectDisposedException("The NetworkStream is closed.");
+ }
+ if (!socket.Connected)
+ {
+ throw new IOException("The underlying Socket is closed.");
+ }
+
+ try
+ {
+ socket.Send(buffer, offset, size, SocketFlags.None);
+ }
+ catch (TlsException ex)
+ {
+ throw ex;
+ }
+ catch (Exception ex)
+ {
+ throw new IOException("IO exception during Write.", ex);
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsProtocol.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsProtocol.cs
new file mode 100644
index 00000000000..4315a1e2c5d
--- /dev/null
+++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsProtocol.cs
@@ -0,0 +1,34 @@
+/* Transport Security Layer (TLS)
+ * Copyright (c) 2003 Carlos Guzmán Álvarez
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+using System;
+
+namespace Mono.Security.Protocol.Tls
+{
+ public enum TlsProtocol : short
+ {
+ Tls1 = (0x03 << 8) | 0x01,
+ Ssl3 = (0x03 << 8) | 0x00
+ }
+} \ No newline at end of file
diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSession.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSession.cs
new file mode 100644
index 00000000000..1303c7c3b80
--- /dev/null
+++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSession.cs
@@ -0,0 +1,265 @@
+/* Transport Security Layer (TLS)
+ * Copyright (c) 2003 Carlos Guzmán Álvarez
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+using System;
+using System.IO;
+using System.Collections;
+using System.Text;
+using System.Net;
+using System.Net.Sockets;
+using System.Security.Cryptography;
+
+using Mono.Security.Protocol.Tls.Alerts;
+
+namespace Mono.Security.Protocol.Tls
+{
+ public sealed class TlsSession
+ {
+ #region EVENTS
+
+ public event TlsWarningAlertEventHandler WarningAlert;
+
+ #endregion
+
+ #region FIELDS
+
+ private byte[] sessionId;
+ private TlsSessionContext context;
+ private TlsSessionSettings settings;
+ private TlsSocket socket;
+ private TlsNetworkStream networkStream;
+ private bool isSecure;
+ private TlsSessionState state;
+
+ #endregion
+
+ #region PROPERTIES
+
+ public byte[] SessionId
+ {
+ get { return sessionId; }
+ }
+
+ public TlsNetworkStream NetworkStream
+ {
+ get { return networkStream; }
+ }
+
+ public TlsSessionState State
+ {
+ get { return state; }
+ }
+
+ #endregion
+
+ #region INTERNAL_PROPERTIES
+
+ internal TlsSessionContext Context
+ {
+ get { return context; }
+ }
+
+ internal bool IsSecure
+ {
+ get { return isSecure; }
+ set { isSecure = value; }
+ }
+
+ internal TlsSessionSettings Settings
+ {
+ get { return settings; }
+ }
+
+ #endregion
+
+ #region CONSTRUCTORS
+
+ public TlsSession(TlsSessionSettings settings)
+ {
+ this.settings = settings;
+ this.context = new TlsSessionContext();
+ this.sessionId = new byte[0];
+
+ // Initialize socket for connection
+ this.initializeSocket();
+ }
+
+ #endregion
+
+ #region EXCEPTION_METHODS
+
+ internal TlsException CreateException(TlsAlertLevel alertLevel, TlsAlertDescription alertDesc)
+ {
+ return CreateException(TlsAlert.GetAlertMessage(alertDesc));
+ }
+
+ internal TlsException CreateException(string format, params object[] args)
+ {
+ StringBuilder message = new StringBuilder();
+ message.AppendFormat(format, args);
+
+ return CreateException(message.ToString());
+ }
+
+ internal TlsException CreateException(string message)
+ {
+ this.state = TlsSessionState.Broken;
+
+ // Throw an exception will made the connection unavailable
+ // for this both streams will be closed
+ closeStreams();
+
+ return new TlsException(message);
+ }
+
+ #endregion
+
+ #region METHODS
+
+ public void Open()
+ {
+ try
+ {
+ this.context.Protocol = settings.Protocol;
+ this.context.CompressionMethod = settings.CompressionMethod;
+ this.context.SupportedCiphers = TlsCipherSuiteFactory.GetSupportedCiphers(context.Protocol);
+ this.state = TlsSessionState.OpeningSecure;
+ this.socket.DoHandshake();
+ this.state = TlsSessionState.OpenSecure;
+ }
+ catch (TlsException ex)
+ {
+ this.state = TlsSessionState.Broken;
+ throw ex;
+ }
+ catch (Exception ex)
+ {
+ this.state = TlsSessionState.Broken;
+ this.closeStreams();
+ throw ex;
+ }
+ }
+
+ public void Close()
+ {
+ try
+ {
+ this.state = TlsSessionState.Closing;
+
+ if (isSecure)
+ {
+ TlsCloseNotifyAlert alert = new TlsCloseNotifyAlert(this);
+
+ // Write close notify
+ this.socket.SendAlert(alert);
+
+ // Check that the session is finished by the client and by server
+ if (!this.context.ConnectionEnd)
+ {
+ throw new TlsException("Invalid session termination");
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ this.state = TlsSessionState.Broken;
+ throw ex;
+ }
+ finally
+ {
+ // Close streams
+ closeStreams();
+
+ this.state = TlsSessionState.Closed;
+ }
+ }
+
+ #endregion
+
+ #region INTERNAL_METHODS
+
+ internal void RaiseWarningAlert(TlsAlertLevel level, TlsAlertDescription description)
+ {
+ if (WarningAlert != null)
+ {
+ WarningAlert(this, new TlsWarningAlertEventArgs(level, description));
+ }
+ }
+
+ internal void SetSessionId(byte[] sessionId)
+ {
+ this.sessionId = sessionId;
+ }
+
+ #endregion
+
+ #region PRIVATE_METHODS
+
+ private void initializeSocket()
+ {
+ try
+ {
+ this.state = TlsSessionState.Opening;
+
+ // Initialize socket
+ IPAddress hostadd = Dns.Resolve(settings.ServerName).AddressList[0];
+ IPEndPoint EPhost = new IPEndPoint(hostadd, settings.ServerPort);
+
+ // Create the socket
+ socket = new TlsSocket(
+ this,
+ AddressFamily.InterNetwork,
+ SocketType.Stream,
+ ProtocolType.IP);
+
+ // Make the socket to connect to the Server
+ socket.Connect(EPhost);
+ networkStream = new TlsNetworkStream(socket, true);
+
+ this.state = TlsSessionState.Open;
+ }
+ catch (Exception ex)
+ {
+ this.state = TlsSessionState.Broken;
+ throw ex;
+ }
+ }
+
+ private void closeStreams()
+ {
+ // Reset session state
+ this.context.IsActual = false;
+
+ // Close the socket and the networkStream
+ this.networkStream.Close();
+
+ // Reset session information
+ this.isSecure = false;
+ this.context = new TlsSessionContext();
+ this.sessionId = new byte[0];
+ }
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSessionContext.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSessionContext.cs
new file mode 100644
index 00000000000..c9e85cee0d2
--- /dev/null
+++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSessionContext.cs
@@ -0,0 +1,289 @@
+/* Transport Security Layer (TLS)
+ * Copyright (c) 2003 Carlos Guzmán Álvarez
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+using System;
+using System.Text;
+using System.Security.Cryptography;
+
+using Mono.Security.Cryptography;
+using Mono.Security.Protocol.Tls.Handshake;
+
+namespace Mono.Security.Protocol.Tls
+{
+ internal class TlsSessionContext
+ {
+ #region FIELDS
+
+ // Protocol version
+ private TlsProtocol protocol;
+
+ // Compression method
+ private TlsCompressionMethod compressionMethod;
+
+ // Information sent and request by the server in the Handshake protocol
+ private TlsServerSettings serverSettings;
+
+ // Cipher suite information
+ private CipherSuite cipher;
+ private TlsCipherSuiteCollection supportedCiphers;
+
+ // Misc
+ private bool isActual;
+ private bool helloDone;
+ private bool handshakeFinished;
+ private bool connectionEnd;
+
+ // Sequence numbers
+ private long writeSequenceNumber;
+ private long readSequenceNumber;
+
+ // Random data
+ private byte[] clientRandom;
+ private byte[] serverRandom;
+ private byte[] randomCS;
+ private byte[] randomSC;
+
+ // Key information
+ private byte[] masterSecret;
+ private byte[] clientWriteMAC;
+ private byte[] serverWriteMAC;
+ private byte[] clientWriteKey;
+ private byte[] serverWriteKey;
+ private byte[] clientWriteIV;
+ private byte[] serverWriteIV;
+
+ // Handshake hashes
+ private TlsStream handshakeMessages;
+
+ #endregion
+
+ #region INTERNAL_CONSTANTS
+
+ internal const short MAX_FRAGMENT_SIZE = 16384; // 2^14
+
+ #endregion
+
+ #region PROPERTIES
+
+ public TlsProtocol Protocol
+ {
+ get { return this.protocol; }
+ set { this.protocol = value; }
+ }
+
+ public TlsCompressionMethod CompressionMethod
+ {
+ get { return this.compressionMethod; }
+ set { this.compressionMethod = value; }
+ }
+
+ public TlsServerSettings ServerSettings
+ {
+ get { return this.serverSettings; }
+ set { this.serverSettings = value; }
+ }
+
+ public bool IsActual
+ {
+ get { return this.isActual; }
+ set { this.isActual = value; }
+ }
+
+ public bool HelloDone
+ {
+ get { return helloDone; }
+ set { helloDone = value; }
+ }
+
+ public bool HandshakeFinished
+ {
+ get { return handshakeFinished; }
+ set { handshakeFinished = value; }
+ }
+
+ public bool ConnectionEnd
+ {
+ get { return this.connectionEnd; }
+ set { this.connectionEnd = value; }
+ }
+
+ public CipherSuite Cipher
+ {
+ get { return this.cipher; }
+ set { this.cipher = value; }
+ }
+
+ public TlsCipherSuiteCollection SupportedCiphers
+ {
+ get { return supportedCiphers; }
+ set { supportedCiphers = value; }
+ }
+
+ public TlsStream HandshakeMessages
+ {
+ get { return this.handshakeMessages; }
+ }
+
+ public long WriteSequenceNumber
+ {
+ get { return this.writeSequenceNumber; }
+ set { this.writeSequenceNumber = value; }
+ }
+
+ public long ReadSequenceNumber
+ {
+ get { return this.readSequenceNumber; }
+ set { this.readSequenceNumber = value; }
+ }
+
+ public byte[] ClientRandom
+ {
+ get { return this.clientRandom; }
+ set { this.clientRandom = value; }
+ }
+
+ public byte[] ServerRandom
+ {
+ get { return this.serverRandom; }
+ set { this.serverRandom = value; }
+ }
+
+ public byte[] RandomCS
+ {
+ get { return this.randomCS; }
+ set { this.randomCS = value; }
+ }
+
+ public byte[] RandomSC
+ {
+ get { return this.randomSC; }
+ set { this.randomSC = value; }
+ }
+
+ public byte[] MasterSecret
+ {
+ get { return this.masterSecret; }
+ set { this.masterSecret = value; }
+ }
+
+ public byte[] ClientWriteMAC
+ {
+ get { return this.clientWriteMAC; }
+ set { this.clientWriteMAC = value; }
+ }
+
+ public byte[] ServerWriteMAC
+ {
+ get { return this.serverWriteMAC; }
+ set { this.serverWriteMAC = value; }
+ }
+
+ public byte[] ClientWriteKey
+ {
+ get { return this.clientWriteKey; }
+ set { this.clientWriteKey = value; }
+ }
+
+ public byte[] ServerWriteKey
+ {
+ get { return this.serverWriteKey; }
+ set { this.serverWriteKey = value; }
+ }
+
+ public byte[] ClientWriteIV
+ {
+ get { return this.clientWriteIV; }
+ set { this.clientWriteIV = value; }
+ }
+
+ public byte[] ServerWriteIV
+ {
+ get { return this.serverWriteIV; }
+ set { this.serverWriteIV = value; }
+ }
+
+ #endregion
+
+ #region CONSTRUCTORS
+
+ public TlsSessionContext()
+ {
+ this.protocol = TlsProtocol.Tls1;
+ this.compressionMethod = TlsCompressionMethod.None;
+ this.serverSettings = new TlsServerSettings();
+ this.handshakeMessages = new TlsStream();
+ }
+
+ #endregion
+
+ #region METHODS
+
+ public int GetUnixTime()
+ {
+ DateTime now = DateTime.Now.ToUniversalTime();
+ TimeSpan unixTime = now.Subtract(new DateTime(1970, 1, 1));
+
+ return (int)unixTime.TotalSeconds;
+ }
+
+ public byte[] GetSecureRandomBytes(int count)
+ {
+ byte[] secureBytes = new byte[count];
+
+ RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
+ rng.GetNonZeroBytes(secureBytes);
+
+ return secureBytes;
+ }
+
+ public void ClearKeyInfo()
+ {
+ // Clear Master Secret
+ this.masterSecret = null;
+
+ // Clear client and server random
+ this.clientRandom = null;
+ this.serverRandom = null;
+ this.randomCS = null;
+ this.randomSC = null;
+
+ // Clear client keys
+ this.clientWriteKey = null;
+ this.clientWriteIV = null;
+
+ // Clear server keys
+ this.serverWriteKey = null;
+ this.serverWriteIV = null;
+
+ // Clear MAC keys if protocol is different than Ssl3
+ if (this.protocol != TlsProtocol.Ssl3)
+ {
+ this.clientWriteMAC = null;
+ this.serverWriteMAC = null;
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSessionSettings.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSessionSettings.cs
new file mode 100644
index 00000000000..7614e99f207
--- /dev/null
+++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSessionSettings.cs
@@ -0,0 +1,218 @@
+/* Transport Security Layer (TLS)
+ * Copyright (c) 2003 Carlos Guzmán Álvarez
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+using System;
+using System.Text;
+using System.Security.Cryptography.X509Certificates;
+
+namespace Mono.Security.Protocol.Tls
+{
+ public sealed class TlsSessionSettings
+ {
+ #region FIELDS
+
+ private string serverName;
+ private int serverPort;
+ private Encoding encoding;
+ private TlsProtocol protocol;
+ private TlsCompressionMethod compressionMethod;
+ private X509CertificateCollection certificates;
+
+ #endregion
+
+ #region PROPERTIES
+
+ public string ServerName
+ {
+ get { return serverName; }
+ set { serverName = value; }
+ }
+
+ public int ServerPort
+ {
+ get { return serverPort; }
+ set { serverPort = value; }
+ }
+
+ public Encoding Encoding
+ {
+ get { return encoding; }
+ set { encoding = value; }
+ }
+
+ public TlsProtocol Protocol
+ {
+ get { return protocol; }
+ set
+ {
+ if (value != TlsProtocol.Tls1 &&
+ value != TlsProtocol.Ssl3)
+ {
+ throw new NotSupportedException("Specified protocol is not supported");
+ }
+ protocol = value;
+ }
+ }
+
+ public TlsCompressionMethod CompressionMethod
+ {
+ get { return compressionMethod; }
+ set
+ {
+ if (value != TlsCompressionMethod.None)
+ {
+ throw new NotSupportedException("Specified compression method is not supported");
+ }
+ compressionMethod = value;
+ }
+ }
+
+ public X509CertificateCollection Certificates
+ {
+ get { return certificates; }
+ set { certificates = value; }
+ }
+
+ #endregion
+
+ #region CONSTRUCTORS
+
+ public TlsSessionSettings()
+ {
+ this.protocol = TlsProtocol.Tls1;
+ this.compressionMethod = TlsCompressionMethod.None;
+ this.certificates = new X509CertificateCollection();
+ this.serverName = "localhost";
+ this.serverPort = 443;
+ this.encoding = Encoding.Default;
+ }
+
+ public TlsSessionSettings(TlsProtocol protocol) : this()
+ {
+ this.Protocol = protocol;
+ }
+
+ public TlsSessionSettings(TlsProtocol protocol, Encoding encoding) : this(protocol)
+ {
+ this.encoding = encoding;
+ }
+
+ public TlsSessionSettings(string serverName) : this()
+ {
+ this.serverName = serverName;
+ }
+
+ public TlsSessionSettings(string serverName, Encoding encoding) : this()
+ {
+ this.serverName = serverName;
+ this.encoding = encoding;
+ }
+
+ public TlsSessionSettings(string serverName, int serverPort) : this()
+ {
+ this.serverName = serverName;
+ this.serverPort = serverPort;
+ }
+
+ public TlsSessionSettings(string serverName, int serverPort, Encoding encoding) : this()
+ {
+ this.serverName = serverName;
+ this.serverPort = serverPort;
+ this.encoding = encoding;
+ }
+
+ public TlsSessionSettings(TlsProtocol protocol, string serverName) : this(protocol)
+ {
+ this.serverName = serverName;
+ }
+
+ public TlsSessionSettings(TlsProtocol protocol, string serverName, Encoding encoding) : this(protocol)
+ {
+ this.serverName = serverName;
+ this.encoding = encoding;
+ }
+
+
+ public TlsSessionSettings(TlsProtocol protocol, string serverName, int serverPort) : this(protocol)
+ {
+ this.serverName = serverName;
+ this.serverPort = serverPort;
+ }
+
+ public TlsSessionSettings(TlsProtocol protocol, string serverName, int serverPort, Encoding encoding) : this(protocol)
+ {
+ this.serverName = serverName;
+ this.serverPort = serverPort;
+ this.encoding = encoding;
+ }
+
+ public TlsSessionSettings(TlsProtocol protocol, X509CertificateCollection certificates) : this(protocol)
+ {
+ this.certificates = certificates;
+ }
+
+ public TlsSessionSettings(TlsProtocol protocol, X509CertificateCollection certificates, Encoding encoding) : this(protocol)
+ {
+ this.certificates = certificates;
+ this.encoding = encoding;
+ }
+
+ public TlsSessionSettings(TlsProtocol protocol, X509CertificateCollection certificates, string serverName, int serverPort) : this(protocol)
+ {
+ this.certificates = certificates;
+ this.serverName = serverName;
+ this.serverPort = serverPort;
+ }
+
+ public TlsSessionSettings(TlsProtocol protocol, X509CertificateCollection certificates, string serverName, int serverPort, Encoding encoding) : this(protocol)
+ {
+ this.certificates = certificates;
+ this.serverName = serverName;
+ this.serverPort = serverPort;
+ this.encoding = encoding;
+ }
+
+ public TlsSessionSettings(TlsProtocol protocol, X509Certificate[] certificates)
+ : this(protocol, new X509CertificateCollection(certificates))
+ {
+ }
+
+ public TlsSessionSettings(TlsProtocol protocol, X509Certificate[] certificates, Encoding encoding)
+ : this(protocol, new X509CertificateCollection(certificates), encoding)
+ {
+ }
+
+ public TlsSessionSettings(TlsProtocol protocol, X509Certificate[] certificates, string serverName, int serverPort) :
+ this(protocol, new X509CertificateCollection(certificates), serverName, serverPort)
+ {
+ }
+
+ public TlsSessionSettings(TlsProtocol protocol, X509Certificate[] certificates, string serverName, int serverPort, Encoding encoding) :
+ this(protocol, new X509CertificateCollection(certificates), serverName, serverPort, encoding)
+ {
+ }
+
+ #endregion
+ }
+}
diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSocket.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSocket.cs
new file mode 100644
index 00000000000..dce8206a683
--- /dev/null
+++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSocket.cs
@@ -0,0 +1,664 @@
+/* Transport Security Layer (TLS)
+ * Copyright (c) 2003 Carlos Guzmán Álvarez
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+using System;
+using System.IO;
+using System.Net;
+using System.Collections;
+using System.Net.Sockets;
+using System.Security.Cryptography;
+
+using Mono.Security.Protocol.Tls;
+using Mono.Security.Protocol.Tls.Alerts;
+using Mono.Security.Protocol.Tls.Handshake;
+using Mono.Security.Protocol.Tls.Handshake.Client;
+
+namespace Mono.Security.Protocol.Tls
+{
+ public sealed class TlsSocket : Socket
+ {
+ #region FIELDS
+
+ private TlsSession session;
+ private BufferedStream inputBuffer;
+
+ #endregion
+
+ #region PROPERTIES
+
+ internal TlsSession Session
+ {
+ get { return this.session; }
+ }
+
+ internal BufferedStream InputBuffer
+ {
+ get { return this.inputBuffer; }
+ }
+
+ #endregion
+
+ #region CONSTRUCTORS
+
+ private TlsSocket(
+ AddressFamily addressFamily,
+ SocketType socketType,
+ ProtocolType protocolType
+ ) : base(addressFamily, socketType, protocolType)
+ {
+ this.inputBuffer = new BufferedStream(new MemoryStream());
+ }
+
+ public TlsSocket(
+ TlsSession session,
+ AddressFamily addressFamily,
+ SocketType socketType,
+ ProtocolType protocolType
+ ) : this(addressFamily, socketType, protocolType)
+ {
+ this.session = session;
+ }
+
+ #endregion
+
+ #region REPLACED_METHODS
+
+ public new void Close()
+ {
+ this.resetBuffer();
+ base.Close();
+ if (this.session.State != TlsSessionState.Closing &&
+ this.session.State != TlsSessionState.Closed)
+ {
+ this.session.Close();
+ }
+ }
+
+ public new int Receive(byte[] buffer)
+ {
+ return this.Receive(buffer, 0, buffer != null ? buffer.Length : 0, SocketFlags.None);
+ }
+
+ public new int Receive(byte[] buffer, SocketFlags socketFlags)
+ {
+ return this.Receive(buffer, 0, buffer != null ? buffer.Length : 0, socketFlags);
+ }
+
+ public new int Receive(byte[] buffer, int size, SocketFlags socketFlags)
+ {
+ return this.Receive(buffer, 0, size, socketFlags);
+ }
+
+ public new int Receive(byte[] buffer, int offset, int size, SocketFlags socketFlags)
+ {
+ if (!this.session.IsSecure)
+ {
+ return base.Receive(buffer, offset, size, socketFlags);
+ }
+
+ // If actual buffer is full readed reset it
+ if (this.inputBuffer.Position == this.inputBuffer.Length)
+ {
+ this.resetBuffer();
+ }
+
+ // Check if we have space in the middle buffer
+ // if not Read next TLS record and update the inputBuffer
+ while ((this.inputBuffer.Length - this.inputBuffer.Position) < size)
+ {
+ // Read next record and write it into the inputBuffer
+ long position = this.inputBuffer.Position;
+ byte[] record = this.receiveRecord();
+
+ if (record.Length > 0)
+ {
+ // Write new data to the inputBuffer
+ this.inputBuffer.Seek(0, SeekOrigin.End);
+ this.inputBuffer.Write(record, 0, record.Length);
+
+ // Restore buffer position
+ this.inputBuffer.Seek(position, SeekOrigin.Begin);
+ }
+
+ if (base.Available == 0)
+ {
+ break;
+ }
+ }
+
+ return this.inputBuffer.Read(buffer, offset, size);
+ }
+
+ public new int Send(byte[] buffer)
+ {
+ return this.Send(buffer, 0, buffer != null ? buffer.Length : 0, SocketFlags.None);
+ }
+
+ public new int Send(byte[] buffer, SocketFlags socketFlags)
+ {
+ return this.Send(buffer, 0, buffer != null ? buffer.Length : 0, socketFlags);
+ }
+
+ public new int Send(byte[] buffer, int size, SocketFlags socketFlags)
+ {
+ return this.Send(buffer, 0, size, socketFlags);
+ }
+
+ public new int Send(byte[] buffer, int offset, int size, SocketFlags socketFlags)
+ {
+ if (!this.session.IsSecure)
+ {
+ return base.Send(buffer, offset, size, socketFlags);
+ }
+
+ // Send the buffer as a TLS record
+ byte[] recordData = new byte[size];
+ System.Array.Copy(buffer, offset, recordData, 0, size);
+
+ return this.sendRecord(TlsContentType.ApplicationData, recordData);
+ }
+
+ #endregion
+
+ #region TLS_RECORD_METHODS
+
+ private byte[] receiveRecord()
+ {
+ if (this.session.Context.ConnectionEnd)
+ {
+ throw this.session.CreateException("The session is finished and it's no longer valid.");
+ }
+
+ TlsContentType contentType = (TlsContentType)this.ReadByte();
+ TlsProtocol protocol = (TlsProtocol)this.ReadShort();
+ short length = this.ReadShort();
+
+ // Read Record data
+ int received = 0;
+ byte[] buffer = new byte[length];
+ while (received != length)
+ {
+ received += base.Receive(
+ buffer, received, buffer.Length - received, SocketFlags.None);
+ }
+
+ TlsStream message = new TlsStream(buffer);
+
+ // Check that the message has a valid protocol version
+ if (protocol != this.session.Context.Protocol)
+ {
+ throw session.CreateException("Invalid protocol version on message received from server");
+ }
+
+ // Decrypt message contents if needed
+ if (contentType == TlsContentType.Alert && length == 2)
+ {
+ }
+ else
+ {
+ if (session.Context.IsActual &&
+ contentType != TlsContentType.ChangeCipherSpec)
+ {
+ message = this.decryptRecordFragment(
+ contentType,
+ protocol,
+ message.ToArray());
+ }
+ }
+
+ byte[] result = message.ToArray();
+
+ // Process record
+ switch (contentType)
+ {
+ case TlsContentType.Alert:
+ this.processAlert((TlsAlertLevel)message.ReadByte(),
+ (TlsAlertDescription)message.ReadByte());
+ break;
+
+ case TlsContentType.ChangeCipherSpec:
+ // Reset sequence numbers
+ this.session.Context.ReadSequenceNumber = 0;
+ break;
+
+ case TlsContentType.ApplicationData:
+ break;
+
+ case TlsContentType.Handshake:
+ while (!message.EOF)
+ {
+ this.processHandshakeMessage(message);
+ }
+ // Update handshakes of current messages
+ this.session.Context.HandshakeMessages.Write(message.ToArray());
+ break;
+
+ default:
+ throw session.CreateException("Unknown record received from server.");
+ }
+
+ return result;
+ }
+
+ #endregion
+
+ #region TLS_CRYPTO_METHODS
+
+ private byte[] encryptRecordFragment(TlsContentType contentType, byte[] fragment)
+ {
+ // Calculate message MAC
+ byte[] mac = this.session.Context.Cipher.ComputeClientRecordMAC(contentType, fragment);
+
+ // Encrypt the message
+ byte[] ecr = this.session.Context.Cipher.EncryptRecord(fragment, mac);
+
+ // Set new IV
+ if (this.session.Context.Cipher.CipherMode == CipherMode.CBC)
+ {
+ byte[] iv = new byte[this.session.Context.Cipher.IvSize];
+ System.Array.Copy(ecr, ecr.Length - iv.Length, iv, 0, iv.Length);
+ this.session.Context.Cipher.UpdateClientCipherIV(iv);
+ }
+
+ // Update sequence number
+ this.session.Context.WriteSequenceNumber++;
+
+ return ecr;
+ }
+
+ private TlsStream decryptRecordFragment(TlsContentType contentType,
+ TlsProtocol protocol,
+ byte[] fragment)
+ {
+ byte[] dcrFragment = null;
+ byte[] dcrMAC = null;
+
+ // Decrypt message
+ this.session.Context.Cipher.DecryptRecord(fragment, ref dcrFragment, ref dcrMAC);
+
+ // Set new IV
+ if (this.session.Context.Cipher.CipherMode == CipherMode.CBC)
+ {
+ byte[] iv = new byte[session.Context.Cipher.IvSize];
+ System.Array.Copy(fragment, fragment.Length - iv.Length, iv, 0, iv.Length);
+ this.session.Context.Cipher.UpdateServerCipherIV(iv);
+ }
+
+ // Check MAC code
+ byte[] mac = this.session.Context.Cipher.ComputeServerRecordMAC(contentType, dcrFragment);
+
+ // Check that the mac is correct
+ if (mac.Length != dcrMAC.Length)
+ {
+ throw new TlsException("Invalid MAC received from server.");
+ }
+ for (int i = 0; i < mac.Length; i++)
+ {
+ if (mac[i] != dcrMAC[i])
+ {
+ throw new TlsException("Invalid MAC received from server.");
+ }
+ }
+
+ // Update sequence number
+ this.session.Context.ReadSequenceNumber++;
+
+ return new TlsStream(dcrFragment);
+ }
+
+ #endregion
+
+ #region TLS_SEND_METHODS
+
+ internal int SendAlert(TlsAlert alert)
+ {
+ // Write record
+ int bytesSent = this.sendRecord(TlsContentType.Alert, alert.ToArray());
+
+ // Update session
+ alert.UpdateSession();
+
+ // Reset message contents
+ alert.Reset();
+
+ return bytesSent;
+ }
+
+ private int sendRecord(TlsHandshakeType type)
+ {
+ TlsHandshakeMessage msg = createClientHandshakeMessage(type);
+
+ // Write record
+ int bytesSent = this.sendRecord(msg.ContentType, msg.EncodeMessage());
+
+ // Update session
+ msg.UpdateSession();
+
+ // Reset message contents
+ msg.Reset();
+
+ return bytesSent;
+ }
+
+ private int sendChangeCipherSpec()
+ {
+ // Send Change Cipher Spec message
+ int bytesSent = this.sendRecord(TlsContentType.ChangeCipherSpec, new byte[] {1});
+
+ // Reset sequence numbers
+ this.session.Context.WriteSequenceNumber = 0;
+
+ // Make the pending state to be the current state
+ this.session.Context.IsActual = true;
+
+ // Send Finished message
+ bytesSent += this.sendRecord(TlsHandshakeType.Finished);
+
+ return bytesSent;
+ }
+
+ private int sendRecord(TlsContentType contentType, byte[] recordData)
+ {
+ if (this.session.Context.ConnectionEnd)
+ {
+ throw this.session.CreateException("The session is finished and it's no longer valid.");
+ }
+
+ int bytesSent = 0;
+ byte[][] fragments = fragmentData(recordData);
+ for (int i = 0; i < fragments.Length; i++)
+ {
+ byte[] fragment = fragments[i];
+
+ if (this.session.Context.IsActual)
+ {
+ // Encrypt fragment
+ fragment = this.encryptRecordFragment(contentType, fragment);
+ }
+
+ // Write tls message
+ TlsStream record = new TlsStream();
+ record.Write((byte)contentType);
+ record.Write((short)this.session.Context.Protocol);
+ record.Write((short)fragment.Length);
+ record.Write(fragment);
+
+ // Write record
+ bytesSent += base.Send(record.ToArray());
+
+ // Reset record data
+ record.Reset();
+ }
+
+ return bytesSent;
+ }
+
+ private byte[][] fragmentData(byte[] messageData)
+ {
+ ArrayList d = new ArrayList();
+
+ int position = 0;
+
+ while (position < messageData.Length)
+ {
+ short fragmentLength = 0;
+ byte[] fragmentData;
+ if ((messageData.Length - position) > TlsSessionContext.MAX_FRAGMENT_SIZE)
+ {
+ fragmentLength = TlsSessionContext.MAX_FRAGMENT_SIZE;
+ }
+ else
+ {
+ fragmentLength = (short)(messageData.Length - position);
+ }
+ fragmentData = new byte[fragmentLength];
+
+ System.Array.Copy(messageData, position, fragmentData, 0, fragmentLength);
+
+ d.Add(fragmentData);
+
+ position += fragmentLength;
+ }
+
+ byte[][] result = new byte[d.Count][];
+ for (int i = 0; i < d.Count; i++)
+ {
+ result[i] = (byte[])d[i];
+ }
+
+ return result;
+ }
+
+ #endregion
+
+ #region MESSAGE_PROCESSING
+
+ private void processHandshakeMessage(TlsStream handMsg)
+ {
+ TlsHandshakeType handshakeType = (TlsHandshakeType)handMsg.ReadByte();
+ TlsHandshakeMessage message = null;
+
+ // Read message length
+ int length = handMsg.ReadInt24();
+
+ // Read message data
+ byte[] data = new byte[length];
+ handMsg.Read(data, 0, length);
+
+ // Create and process the server message
+ message = this.createServerHandshakeMessage(handshakeType, data);
+
+ // Update session
+ if (message != null)
+ {
+ message.UpdateSession();
+ }
+ }
+
+ private void processAlert(TlsAlertLevel alertLevel, TlsAlertDescription alertDesc)
+ {
+ switch (alertLevel)
+ {
+ case TlsAlertLevel.Fatal:
+ throw this.session.CreateException(alertLevel, alertDesc);
+
+ case TlsAlertLevel.Warning:
+ default:
+ switch (alertDesc)
+ {
+ case TlsAlertDescription.CloseNotify:
+ this.session.Context.ConnectionEnd = true;
+ break;
+
+ default:
+ this.session.RaiseWarningAlert(alertLevel, alertDesc);
+ break;
+ }
+ break;
+ }
+ }
+
+ #endregion
+
+ #region MISC_METHODS
+
+ private void resetBuffer()
+ {
+ this.inputBuffer.SetLength(0);
+ this.inputBuffer.Position = 0;
+ }
+
+ private byte ReadByte()
+ {
+ byte[] b = new byte[1];
+ base.Receive(b);
+
+ return b[0];
+ }
+
+ private short ReadShort()
+ {
+ byte[] b = new byte[2];
+ base.Receive(b);
+
+ short val = BitConverter.ToInt16(b, 0);
+
+ return System.Net.IPAddress.HostToNetworkOrder(val);
+ }
+
+ #endregion
+
+ #region HANDSHAKE_METHODS
+
+ /*
+ Client Server
+
+ ClientHello -------->
+ ServerHello
+ Certificate*
+ ServerKeyExchange*
+ CertificateRequest*
+ <-------- ServerHelloDone
+ Certificate*
+ ClientKeyExchange
+ CertificateVerify*
+ [ChangeCipherSpec]
+ Finished -------->
+ [ChangeCipherSpec]
+ <-------- Finished
+ Application Data <-------> Application Data
+
+ Fig. 1 - Message flow for a full handshake
+ */
+
+ internal void DoHandshake()
+ {
+ // Reset isSecure field
+ this.session.IsSecure = false;
+
+ // Send client hello
+ this.sendRecord(TlsHandshakeType.ClientHello);
+
+ // Read server response
+ while (!this.session.Context.HelloDone)
+ {
+ // Read next record
+ this.receiveRecord();
+ }
+
+ // Send client certificate if requested
+ if (this.session.Context.ServerSettings.CertificateRequest)
+ {
+ this.sendRecord(TlsHandshakeType.Certificate);
+ }
+
+ // Send Client Key Exchange
+ this.sendRecord(TlsHandshakeType.ClientKeyExchange);
+
+ // Now initialize session cipher with the generated keys
+ this.session.Context.Cipher.InitializeCipher();
+
+ // Send certificate verify if requested
+ if (this.session.Context.ServerSettings.CertificateRequest)
+ {
+ this.sendRecord(TlsHandshakeType.CertificateVerify);
+ }
+
+ // Send Cipher Spec protocol
+ this.sendChangeCipherSpec();
+
+ // Read Cipher Spec protocol
+ this.receiveRecord();
+
+ // Read server finished
+ if (!this.session.Context.HandshakeFinished)
+ {
+ this.receiveRecord();
+ }
+
+ // Clear Key Info
+ this.session.Context.ClearKeyInfo();
+
+ // Set isSecure
+ this.session.IsSecure = true;
+ }
+
+ private TlsHandshakeMessage createClientHandshakeMessage(TlsHandshakeType type)
+ {
+ switch (type)
+ {
+ case TlsHandshakeType.ClientHello:
+ return new TlsClientHello(session);
+
+ case TlsHandshakeType.Certificate:
+ return new TlsClientCertificate(session);
+
+ case TlsHandshakeType.ClientKeyExchange:
+ return new TlsClientKeyExchange(session);
+
+ case TlsHandshakeType.CertificateVerify:
+ return new TlsClientCertificateVerify(session);
+
+ case TlsHandshakeType.Finished:
+ return new TlsClientFinished(session);
+
+ default:
+ throw new InvalidOperationException("Unknown client handshake message type: " + type.ToString() );
+ }
+ }
+
+ private TlsHandshakeMessage createServerHandshakeMessage(TlsHandshakeType type, byte[] buffer)
+ {
+ switch (type)
+ {
+ case TlsHandshakeType.HelloRequest:
+ this.sendRecord(TlsHandshakeType.ClientHello);
+ return null;
+
+ case TlsHandshakeType.ServerHello:
+ return new TlsServerHello(session, buffer);
+
+ case TlsHandshakeType.Certificate:
+ return new TlsServerCertificate(session, buffer);
+
+ case TlsHandshakeType.ServerKeyExchange:
+ return new TlsServerKeyExchange(session, buffer);
+
+ case TlsHandshakeType.CertificateRequest:
+ return new TlsServerCertificateRequest(session, buffer);
+
+ case TlsHandshakeType.ServerHelloDone:
+ return new TlsServerHelloDone(session, buffer);
+
+ case TlsHandshakeType.Finished:
+ return new TlsServerFinished(session, buffer);
+
+ default:
+ throw this.session.CreateException("Unknown server handshake message received ({0})", type.ToString());
+ }
+ }
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/mcs/class/System.Data.ObjectSpaces/System.Data.ObjectSpaces/PersistenceErrorBehaviour.cs b/mcs/class/System.Data.ObjectSpaces/System.Data.ObjectSpaces/PersistenceErrorBehaviour.cs
new file mode 100755
index 00000000000..7f24e7c36f4
--- /dev/null
+++ b/mcs/class/System.Data.ObjectSpaces/System.Data.ObjectSpaces/PersistenceErrorBehaviour.cs
@@ -0,0 +1,21 @@
+//
+// System.Data.ObjectSpaces.PersistenceErrorBehaviour.cs - The behaviour to follow when a persistence error occurs
+//
+// Author:
+// Mark Easton (mark.easton@blinksoftware.co.uk)
+//
+// (C) BLiNK Software Ltd. http://www.blinksoftware.co.uk
+//
+
+#if NET_1_2
+
+namespace System.Data.ObjectSpaces
+{
+ public enum PersistenceErrorBehaviour
+ {
+ ThrowAtFirstError,
+ ThrowAfterCompletion
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/mcs/class/System.Data.ObjectSpaces/System.Data.ObjectSpaces/PersisteneceErrorType.cs b/mcs/class/System.Data.ObjectSpaces/System.Data.ObjectSpaces/PersisteneceErrorType.cs
new file mode 100755
index 00000000000..d87e7a5bc0a
--- /dev/null
+++ b/mcs/class/System.Data.ObjectSpaces/System.Data.ObjectSpaces/PersisteneceErrorType.cs
@@ -0,0 +1,23 @@
+//
+// System.Data.ObjectSpaces.PersistenceErrorType.cs - The type of persistence error
+//
+// Author:
+// Mark Easton (mark.easton@blinksoftware.co.uk)
+//
+// (C) BLiNK Software Ltd. http://www.blinksoftware.co.uk
+//
+
+#if NET_1_2
+
+namespace System.Data.ObjectSpaces
+{
+ public enum PersistenceErrorType
+ {
+ Inserting,
+ Deleting,
+ Updating,
+ Unknown
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/mcs/class/System.Web/System.Web.UI/TODO b/mcs/class/System.Web/System.Web.UI/TODO
new file mode 100644
index 00000000000..de529b87f86
--- /dev/null
+++ b/mcs/class/System.Web/System.Web.UI/TODO
@@ -0,0 +1,42 @@
+AttributeCollection
+BaseParser
+BasePartialCachingControl
+CompiledTemplateBuilder
+ConstructorNeedsTagAttribute
+ControlBuilder
+ControlBuilderAttribute
+ControlCollection
+CssStyleCollection
+DataBinder
+DataBinding
+DataBindingCollection
+DataBindingHandlerAttribute
+DataBoundLiteralControl
+DesignTimeParseData
+DesignTimeTemplateParser
+EmptyControlCollection
+Html32TextWriter
+HtmlTextWriter
+ImageClickEventArgs
+LosFormatter
+Page
+PageParser
+ParseChildrenAttribute
+PartialCachingAttribute
+PartialCachingControl
+PersistChildrenAttribute
+PersistanceModeAttribute
+RootBuilder
+SimpleWebHandlerParser
+StateBag
+StaticPartialCachingControl
+TagPrefixAttribute
+TemplateBuilder
+TemplateContainerAttribute
+TemplateControl
+TemplateControlParser
+ToolboxDataAttribute
+UserControl
+ValidationPropertyAttribute
+ValidatorCollection
+WebServiceProvider
diff --git a/mcs/class/System/Test/system_linux_test.args b/mcs/class/System/Test/system_linux_test.args
new file mode 100644
index 00000000000..48b00f0b2dd
--- /dev/null
+++ b/mcs/class/System/Test/system_linux_test.args
@@ -0,0 +1,37 @@
+Microsoft.CSharp/CodeGeneratorFromCompileUnitTest.cs
+Microsoft.CSharp/CodeGeneratorFromExpressionTest.cs
+Microsoft.CSharp/CodeGeneratorFromNamespaceTest.cs
+Microsoft.CSharp/CodeGeneratorFromStatementTest.cs
+Microsoft.CSharp/CodeGeneratorFromTypeTest.cs
+Microsoft.CSharp/CodeGeneratorTestBase.cs
+System/UriBuilderTest.cs
+System/UriTest.cs
+System.Collections.Specialized/BasicOperationsTest.cs
+System.Collections.Specialized/BitVector32Test.cs
+System.Collections.Specialized/HybridDictionaryTest.cs
+System.Collections.Specialized/ListDictionaryTest.cs
+System.Collections.Specialized/NameValueCollectionTest.cs
+System.Collections.Specialized/StringCollectionTest.cs
+System.ComponentModel/EventHandlerListTests.cs
+System.Diagnostics/TraceTest.cs
+System.Diagnostics/SwitchesTest.cs
+System.Diagnostics/DiagnosticsConfigurationHandlerTest.cs
+System.Net/CookieCollectionTest.cs
+System.Net/CookieTest.cs
+System.Net/CredentialCacheTest.cs
+System.Net/DnsTest.cs
+System.Net/FileWebRequestTest.cs
+System.Net/HttpWebRequestTest.cs
+System.Net/IPAddressTest.cs
+System.Net/IPEndPointTest.cs
+System.Net/ServicePointManagerTest.cs
+System.Net/ServicePointTest.cs
+System.Net/SocketPermissionTest.cs
+System.Net/WebHeaderCollectionTest.cs
+System.Net/WebProxyTest.cs
+System.Net/WebRequestTest.cs
+System.Net.Sockets/TcpClientTest.cs
+System.Net.Sockets/TcpListenerTest.cs
+System.Text.RegularExpressions/PerlTest.cs
+System.Text.RegularExpressions/PerlTrials.cs
+System.Text.RegularExpressions/RegexTrial.cs
diff --git a/mcs/class/corlib/System.Reflection/common.src b/mcs/class/corlib/System.Reflection/common.src
deleted file mode 100644
index 022b6768fcc..00000000000
--- a/mcs/class/corlib/System.Reflection/common.src
+++ /dev/null
@@ -1,25 +0,0 @@
-Assembly.cs
-AssemblyNameFlags.cs
-BindingFlags.cs
-CallingConventions.cs
-ConstructorInfo.cs
-DefaultMemberAttribute.cs
-EventAttributes.cs
-EventInfo.cs
-FieldAttributes.cs
-FieldInfo.cs
-ICustomAttributeProvider.cs
-MemberFilter.cs
-MemberInfo.cs
-MemberTypes.cs
-MethodAttributes.cs
-MethodBase.cs
-MethodImplAttributes.cs
-MethodInfo.cs
-Module.cs
-ParameterAttributes.cs
-PropertyAttributes.cs
-PropertyInfo.cs
-ResourceAttributes.cs
-ResourceLocation.cs
-TypeAttributes.cs
diff --git a/mono/metadata/ChangeLog b/mono/metadata/ChangeLog
index 163c2c269ac..05192716e37 100644
--- a/mono/metadata/ChangeLog
+++ b/mono/metadata/ChangeLog
@@ -1,3 +1,7 @@
+2003-11-30 Zoltan Varga <vargaz@freemail.hu>
+
+ * reflection.c (fixup_method): Add support for MonoCMethod.
+
2003-11-28 Zoltan Varga <vargaz@freemail.hu>
* gc.c: Fix hangs and error messages when GC_DONT_GC is set.
diff --git a/mono/metadata/reflection.c b/mono/metadata/reflection.c
index b0109420c51..2c965ccab32 100644
--- a/mono/metadata/reflection.c
+++ b/mono/metadata/reflection.c
@@ -2990,7 +2990,8 @@ fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *asse
} else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
ctor = (MonoReflectionCtorBuilder *)iltoken->member;
idx = ctor->table_idx;
- } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
+ } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
+ !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
} else {
diff --git a/mono/mini/cpu-g4.md b/mono/mini/cpu-g4.md
index 9ac80f0d45c..034a4126c1c 100644
--- a/mono/mini/cpu-g4.md
+++ b/mono/mini/cpu-g4.md
@@ -229,7 +229,8 @@ mul.ovf: dest:i src1:i src2:i len:8
mul.ovf.un: dest:i src1:i src2:i len:12
sub.ovf:
sub.ovf.un:
-endfinally: len:10
+start_handler: len:8
+endfinally: len:12
leave:
leave.s:
stind.i:
@@ -257,7 +258,7 @@ ldloc:
ldloca:
stloc:
localloc: dest:i src1:i len:30
-endfilter:
+endfilter: len:12
unaligned.:
volatile.:
tail.:
diff --git a/mono/mini/inssel-ppc.brg b/mono/mini/inssel-ppc.brg
index 5e46e4c7bdc..85447734ee0 100644
--- a/mono/mini/inssel-ppc.brg
+++ b/mono/mini/inssel-ppc.brg
@@ -12,7 +12,23 @@
stmt: OP_START_HANDLER {
MonoInst *spvar = mono_find_spvar_for_region (s, s->cbb->region);
- MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, spvar->inst_basereg, spvar->inst_offset, ppc_sp);
+ /*MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, spvar->inst_basereg, spvar->inst_offset, ppc_sp);
+ */
+ tree->inst_left = spvar;
+ mono_bblock_add_inst (s->cbb, tree);
+}
+
+stmt: CEE_ENDFINALLY {
+ MonoInst *spvar = mono_find_spvar_for_region (s, s->cbb->region);
+ tree->inst_left = spvar;
+ mono_bblock_add_inst (s->cbb, tree);
+}
+
+stmt: OP_ENDFILTER (reg) {
+ MonoInst *spvar = mono_find_spvar_for_region (s, s->cbb->region);
+ tree->inst_left = spvar;
+ tree->sreg1 = state->left->reg1;
+ mono_bblock_add_inst (s->cbb, tree);
}
stmt: CEE_STIND_I8 (OP_REGVAR, lreg) {
diff --git a/mono/mini/mini-ppc.c b/mono/mini/mini-ppc.c
index ae6fa0647dc..9414cd61c91 100644
--- a/mono/mini/mini-ppc.c
+++ b/mono/mini/mini-ppc.c
@@ -1685,8 +1685,8 @@ alloc_int_reg (MonoCompile *cfg, InstList *curinst, MonoInst *ins, int sym_reg,
}
/* use ppc_r3-ppc_10 as temp registers */
-#define PPC_CALLER_REGS (0x7f<<3)
-#define PPC_CALLER_FREGS (0x7f<<2)
+#define PPC_CALLER_REGS (0xff<<3)
+#define PPC_CALLER_FREGS (0xff<<2)
/*
* Local register allocation.
@@ -2305,7 +2305,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
ppc_rlwinm (code, ins->dreg, ins->sreg1, 0, 16, 31);
break;
case OP_COMPARE:
- if (ins->next && ins->next->opcode >= CEE_BNE_UN && ins->next->opcode <= CEE_BLT_UN)
+ if (ins->next && (ins->next->opcode >= CEE_BNE_UN && ins->next->opcode <= CEE_BLT_UN))
ppc_cmpl (code, 0, 0, ins->sreg1, ins->sreg2);
else
ppc_cmp (code, 0, 0, ins->sreg1, ins->sreg2);
@@ -2365,8 +2365,11 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
break;
case OP_SUB_IMM:
// we add the negated value
- g_assert (ppc_is_imm16 (-ins->inst_imm));
- ppc_addi (code, ins->dreg, ins->sreg1, -ins->inst_imm);
+ if (ppc_is_imm16 (-ins->inst_imm))
+ ppc_addi (code, ins->dreg, ins->sreg1, -ins->inst_imm);
+ else
+ ppc_load (code, ppc_r11, ins->inst_imm);
+ ppc_subf (code, ins->dreg, ins->sreg2, ppc_r11);
break;
case OP_SBB_IMM:
ppc_load (code, ppc_r11, ins->inst_imm);
@@ -2590,12 +2593,20 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
ppc_bl (code, 0);
break;
}
+ case OP_START_HANDLER:
+ ppc_mflr (code, ppc_r0);
+ ppc_stw (code, ppc_r0, ins->inst_left->inst_offset, ins->inst_left->inst_basereg);
+ break;
case OP_ENDFILTER:
if (ins->sreg1 != ppc_r3)
ppc_mr (code, ppc_r3, ins->sreg1);
+ ppc_lwz (code, ppc_r0, ins->inst_left->inst_offset, ins->inst_left->inst_basereg);
+ ppc_mtlr (code, ppc_r0);
ppc_blr (code);
break;
case CEE_ENDFINALLY:
+ ppc_lwz (code, ppc_r0, ins->inst_left->inst_offset, ins->inst_left->inst_basereg);
+ ppc_mtlr (code, ppc_r0);
ppc_blr (code);
break;
case OP_CALL_HANDLER:
@@ -2645,7 +2656,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
case OP_CGT:
case OP_CGT_UN:
ppc_li (code, ins->dreg, 1);
- ppc_bc (code, PPC_BR_TRUE, PPC_BR_LT, 2);
+ ppc_bc (code, PPC_BR_TRUE, PPC_BR_GT, 2);
ppc_li (code, ins->dreg, 0);
break;
case OP_COND_EXC_EQ:
diff --git a/runtime/Makefile.am b/runtime/Makefile.am
index a979435d303..3188fcec98e 100644
--- a/runtime/Makefile.am
+++ b/runtime/Makefile.am
@@ -27,7 +27,7 @@ assemblies_DATA = \
Mono.Data.SybaseClient.dll \
Mono.Data.TdsClient.dll \
Mono.Data.Tds.dll \
- Mono.Directory.LDAP.dll \
+ Novell.Directory.Ldap.dll \
Mono.GetOptions.dll \
Mono.Http.dll \
Mono.PEToolkit.dll \
diff --git a/web/plans b/web/plans
index db6f6dde7c8..f53aecd4e95 100755
--- a/web/plans
+++ b/web/plans
@@ -8,7 +8,7 @@
Currently you can read our plans for <a
href="ado-net.html">ADO.NET</a>, <a
- href="asp-net">ASP.NET</a>, <a href="java.html">Java</a> and
+ href="asp-net.html">ASP.NET</a>, <a href="java.html">Java</a> and
<a href="winforms.html">WinForms</a>.
diff --git a/web/sqlite b/web/sqlite
index 35ee3056896..6730477202c 100755
--- a/web/sqlite
+++ b/web/sqlite
@@ -82,7 +82,7 @@
{
string connectionString = "URI=file:SqliteTest.db";
IDbConnection dbcon;
- dbcon = new MySQLConnection(connectionString);
+ dbcon = new SqliteConnection(connectionString);
dbcon.Open();
IDbCommand dbcmd = dbcon.CreateCommand();
// requires a table to be created named employee