Bug #25057 Unable to connect to any of the specified MySQL hosts
Submitted: 14 Dec 2006 3:06 Modified: 15 May 2007 11:54
Reporter: Jeff Chan Email Updates:
Status: No Feedback Impact on me:
None 
Category:Connector / NET Severity:S1 (Critical)
Version:5.0.2 OS:Windows (WIN XP)
Assigned to: CPU Architecture:Any
Tags: Connector/Net, Mono

[14 Dec 2006 3:06] Jeff Chan
Description:
I use the Connector for .NET v2 on MONO V1.2.2.1

When open the connection, I will get an exception "Unable to connect to any of the specified MySQL hosts". The code is ok when it run on .NET V2.0

How to repeat:
the following is my test code:

            MySql.Data.MySqlClient.MySqlConnection conn;
            string myConnectionString;

            myConnectionString = "Server=192.168.1.92;Uid=jabberd2;Pwd=secret;Database=jabberd2;";

            try
            {
                conn = new MySql.Data.MySqlClient.MySqlConnection();
                conn.ConnectionString = myConnectionString;
                conn.Open();

                Console.WriteLine("Open OK");

                conn.Close();
            }
            catch (MySql.Data.MySqlClient.MySqlException ex)
            {
                Console.WriteLine(ex.ToString());
            }

It's a console program, which be written in VS2005.

It works well on .NET V2.0 but not on MONO V1.2.2.1

Suggested fix:
I have found the problem.
In StreamCreator.cs 

private Stream CreateSocketStream(IPAddress ip, uint port, bool unix)
{
...
  IAsyncResult ias = socket.BeginConnect(endPoint, null, null);
  if (!ias.AsyncWaitHandle.WaitOne((int)timeOut * 1000, true))
  {
     socket.Close();
     return null;
  }
...
}

timeOut is always ZERO. So WaitOne will return immediately.

I only write some code to fix timeOut if it equals ZERO

  if (timeOut == 0)
     timeOut = 30;

 IAsyncResult ias = socket.BeginConnect(endPoint, null, null);
 if (!ias.AsyncWaitHandle.WaitOne((int)timeOut * 1000, true))
 {
  socket.Close();
  return null;
 }
[14 Dec 2006 3:39] Jeff Chan
I find that some time port is also ZERO.
[19 Dec 2006 3:45] Jeff Chan
Hi, Tonci.

I have read the code of Connector. I find that in the MySqlConnectionStringBuilder.cs some properties, such as Port, use DefaultValue attribute to define its default value, but those have a condition '#if !PocketPC && !MONO'. This condition will skip the DefaultValue attribute when the code are compiled or ran on MONO. Then the corresponding properties which do not specified in ConnectionString will return ZERO or NULL. So it causes this bug.

I suggest assigning the default value when parsing ConnectionString instead of using DefaultValue attribute.
[17 Jan 2007 22:24] Tonci Grgin
Jeff, I'm having some problems with mono on my Suse box. Will get back to this report as soon as I solve them.
[14 Mar 2007 6:17] Justin Kruger
we found the problem to lie in the "BeginConnect" statement. When we changed a line or two, and used the "Connect" method as MS does in there example docs, we are now able to connect.

I will paste some code in the morning.
[14 Mar 2007 7:43] Tonci Grgin
Justin good, thanks. I'm setting this to "Need feedback" and wait for your paste.
[14 Mar 2007 14:45] Justin Kruger
Here is the code that we changed to get it to work.

Its nice that it works now, but we know that it does not fill a general purpose need in its current state. we are also aware that the async characteristics will be broken by including this code directly.

private Stream CreateSocketStream(IPAddress ip, uint port, bool unix)
{
  IPHostEntry myHost = Dns.GetHostEntry(ip);
  IPAddress myIP = myHost.AddressList[0];

  EndPoint endPoint;
            
  //AsyncCallback callback = new AsyncCallback(tempCallBack);
  //object callbackstate = new object();

  if (!Platform.IsWindows() && unix)
	endPoint = CreateUnixEndPoint(hostList);
  else
	endPoint = new IPEndPoint(ip, (int)port);

  endPoint = new IPEndPoint(myIP, 3306);

  /*Socket socket = unix ?
	new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.IP) :
	new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);*/
   
  //TODO:tempfix to open socket a different way
  Socket mySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  mySocket.Connect(endPoint);
  //IAsyncResult ias = socket.BeginConnect(endPoint, null, null);
  /*if (!ias.AsyncWaitHandle.WaitOne((int)timeOut * 1000, true))
    {
	socket.Close();
	return null;
    }
    try
    {
	socket.EndConnect(ias);
    }
    catch (Exception)
    {
	socket.Close();
	return null;
    }

    return new NetworkStream(socket, true);*/

    return new NetworkStream(mySocket, true);
}

if i come up with replacable code i will post it, but do not count on it for now.
[15 Mar 2007 21:36] Justin Kruger
How do I contact the person that choose this original code structure?

I have questions on a few choices while searching the msdn documentation and forums i found these:

http://msdn2.microsoft.com/en-us/library/bew39x2a.aspx

http://msdn2.microsoft.com/en-us/library/6aeby4wt.aspx

i am just a little lost when it looks like there is no need for an async call when everything in the code suggests that it is not being used like one.

as such i am curious if somehow the port is already open when it gets opened again, and then it looks like the port is busy.
[15 Mar 2007 23:46] Justin Kruger
this code seems to work just fine, but it completely avoids the async call functionality.  it also looks like all of the async code functionality was constrained to this function, so removing it should not be a problem.  I still would like to know why it was in there in the first place, but no worries now.

the below code should work on mono, could someone check?

i think this will fix a lot of user problems if implemented, but it may introduce 3 more as the rule of thumb goes.

		private Stream CreateSocketStream(IPAddress ip, uint port, bool unix)
		{
            //IPHostEntry myHost = Dns.GetHostEntry(ip);
            //IPAddress myIP = myHost.AddressList[0];

            EndPoint endPoint;
            
            //AsyncCallback callback = new AsyncCallback(tempCallBack);
            //object callbackstate = new object();

			if (!Platform.IsWindows() && unix)
				endPoint = CreateUnixEndPoint(hostList);
			else
				endPoint = new IPEndPoint(ip, (int)port);

            //endPoint = new IPEndPoint(myIP, 3306);

			Socket socket = unix ?
				new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.IP) :
				new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            //TODO:tempfix to open socket a different way
            //Socket mySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            socket.Connect(endPoint);
			//IAsyncResult ias = socket.BeginConnect(endPoint, null, null);
			/*if (!ias.AsyncWaitHandle.WaitOne((int)timeOut * 1000, true))
			{
				socket.Close();
				return null;
			}
			try
			{
				socket.EndConnect(ias);
			}
			catch (Exception)
			{
				socket.Close();
				return null;
			}
			*/

            return new NetworkStream(socket, true);
		}
[24 Mar 2007 13:17] Christian Cunlif
I've found a way to circumvent the bug, while the (excellent) library is not patched. To do so, simply add the "Connect Timeou" and "port" keys into the connection string - it will then work on Mono/Linux.

Ex: 
Server=localhost;Database=mydb;Connect Timeout=30;port=3306;Uid=root;Pwd=XXX
[24 Mar 2007 14:07] Justin Kruger
I tried that on windows, and it does not work, the only solution i found was the one listed above.

has any one else tried the above change for linux?
[14 Apr 2007 23:00] Bugs System
No feedback was provided for this bug for over a month, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".
[15 Apr 2007 11:54] Tonci Grgin
I am sorry for neglecting this report as my struggle with mono continues. 

Does the new version work correctly?
[15 May 2007 23:00] Bugs System
No feedback was provided for this bug for over a month, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".