private void doOpen(string hostName)
        {
            string databaseName = parsedConnectionString.Database;

            int index = hostName.IndexOf(':');
            int port = PORT;
            if (index != -1)
            {
                try
                {
                    port = Int32.Parse(hostName.Substring(index + 1));
                }
                catch (FormatException e)
                {
                    throw new ArgumentException("Invalid port number in connection string", "ConnectionString", e);
                }
                hostName = hostName.Substring(0, index);
            }
            dataStream = new EncodedDataStream();
            authenticating = false;

            try
            {
                StringDictionary properties = new StringDictionary();
                Tag tag = new Tag("Connection");
                tag.addAttribute("Service", "SQL2");
                tag.addAttribute("Database", databaseName);
                if (parsedConnectionString.ContainsKey(NuoDbConnectionStringBuilder.ServerKey))
                {
                    tag.addAttribute("Server", parsedConnectionString.Server);
                    properties["Server"] = parsedConnectionString.Server;
                }
                string userName = null;
                if (parsedConnectionString.ContainsKey(NuoDbConnectionStringBuilder.UserKey))
                {
                    properties["User"] = userName = parsedConnectionString.User;
                    tag.addAttribute("User", userName);
                }

                string password = null;
                if (parsedConnectionString.ContainsKey(NuoDbConnectionStringBuilder.PasswordKey))
                {
                    password = parsedConnectionString.Password;
                }

                string cipher = DEFAULT_CIPHER;
                if (parsedConnectionString.ContainsKey(NuoDbConnectionStringBuilder.SchemaKey))
                {
                    tag.addAttribute("Schema", parsedConnectionString.Schema);
                    properties["Schema"] = parsedConnectionString.Schema;
                }
                // see comment below ... for now these are the only two types that
                // we can support in the client code
                if ((!cipher.Equals("RC4")) && (!cipher.Equals("None")))
                    throw new NuoDbSqlException("Unknown cipher: " + cipher);
                tag.addAttribute("Cipher", cipher);

                string xml = tag.ToString();
                CryptoSocket brokerSocket = new CryptoSocket(hostName, port);
                inputStream = brokerSocket.InputStream;
                outputStream = brokerSocket.OutputStream;

                dataStream.write(xml);
                dataStream.send(outputStream);

                dataStream.getMessage(inputStream);
                string response = dataStream.readString();
                brokerSocket.Close();
                Tag responseTag = new Tag();
                responseTag.parse(response);

                if (responseTag.Name.Equals("Error"))
                {
                    throw new NuoDbSqlException(responseTag.getAttribute("text", "error text not found"));
                }

                serverAddress = responseTag.getAttribute("Address", null);
                serverPort = responseTag.getIntAttribute("Port", 0);

                if (serverAddress == null || serverPort == 0)
                {
                    throw new NuoDbSqlException("no NuoDB nodes are available for database \"" + databaseName + "\"");
                }

                socket = new CryptoSocket(serverAddress, serverPort);
                //socket.TcpNoDelay = true;
                inputStream = socket.InputStream;
                outputStream = socket.OutputStream;
                dataStream.reset();
                dataStream.write(xml);
                dataStream.send(outputStream);

                RemotePassword remotePassword = new RemotePassword();
                string userKey = remotePassword.genClientKey();

                dataStream.startMessage(Protocol.OpenDatabase);
                dataStream.encodeInt(Protocol.PROTOCOL_VERSION);
                dataStream.encodeString(databaseName);

                getProcessConnection(databaseName);
                string dbUUId = processConnection.DatabaseUUId.ToString();

                // see if the app set the TimeZone. If so, it will be sent to the server
                // so set the local TZ to be the same. If not, send the current default
                // TZ  to the server. (Of course, this affects this connection only)
                /*
                                String timeZone = properties.getProperty(TIMEZONE_NAME);

                                if (timeZone == null)
                                {
                                    // Save the default at the time the connection was opened
                                    TimeZone tz = TimeZone.getDefault();
                                    sqlContext.setTimeZone(tz);
                                    sqlContext.setTimeZoneId(tz.getID());
                                    properties.setProperty(TIMEZONE_NAME, tz.getID());
                                }
                                else
                                {
                                    TimeZone tz = TimeZone.getTimeZone(timeZone);
                                    sqlContext.setTimeZone(tz);
                                    sqlContext.setTimeZoneId(tz.getID());
                                }
                */
                int count = properties.Count + 1 + ((dbUUId == null) ? 0 : 1); // Add LastCommitInfo and DatabaseUUId

                dataStream.encodeInt(count);
                foreach (DictionaryEntry property in properties)
                {
                    string name = (string)property.Key;
                    string value = (string)property.Value;
                    dataStream.encodeString(name);
                    dataStream.encodeString(value);
                }

                // LastCommitInfo and DatabaseUUId are sent as properties. This avoids sending another
                // message and keeps them from being protocol version sensitive

                string lastCommitParam = getProcessConnection(databaseName).getLastCommitInfo();
                dataStream.encodeString("LastCommitInfo");
                dataStream.encodeString(lastCommitParam);

                if (dbUUId != null)
                {
                    dataStream.encodeString("DatabaseUUId");
                    dataStream.encodeString(dbUUId);
                }

                // This  would have been the last commit txn id if that scheme was ever fully
                // implemented but it wasn't and this is now obsolete. keep it for compatibility with older servers

                dataStream.encodeLong(0);
                dataStream.encodeString(userKey);
                sendAndReceive(dataStream);

                protocolVersion = dataStream.getInt();
                string serverKey = dataStream.getString();
                string salt = dataStream.getString();
                dataStream.ProtocolVersion = protocolVersion;

                if (protocolVersion >= Protocol.PROTOCOL_VERSION5)
                {
                    processConnection.DatabaseUUId = dataStream.getUUId();
                }

                string upperUserName = userName.ToUpper();
                byte[] key = remotePassword.computeSessionKey(upperUserName, password, salt, serverKey);

                // NOTE: unlike the C++ implementation we only support RC4 in .NET
                // and it's a hard-coded class (instead of the factory interface
                // on the C++ CryptoSocket) so there's no checking to see which
                // cipher was requested here

                inputStream.encrypt(new CipherRC4(key));
                outputStream.encrypt(new CipherRC4(key));

                dataStream.startMessage(Protocol.Authentication);
                dataStream.encodeString("Success!");
                authenticating = true;
                sendAndReceive(dataStream);

                // if the caller requested a cipher of None and we got here then the
                // server accpeted it and expects us to disable crypto now

                if (cipher.Equals("None"))
                {
                    inputStream.encrypt(null);
                    outputStream.encrypt(null);
                }
            }
            catch (NuoDbSqlException e)
            {
            #if DEBUG
                System.Diagnostics.Trace.WriteLine("NuoDBConnection::doOpen(): exception " + e.ToString());
            #endif
                if (authenticating)
                {
                    throw new NuoDbSqlException("Authentication failed for database \"" + databaseName + "\"", e);
                }

                throw e;
            }
            catch (IOException exception)
            {
            #if DEBUG
                System.Diagnostics.Trace.WriteLine("NuoDBConnection::doOpen(): exception " + exception.ToString());
            #endif
                if (socket != null && socket.Connected)
                {
                    try
                    {
                        socket.Close();
                        socket = null;
                    }
                    catch (IOException)
                    {
                        // just ignore
                    }
                }

                throw new NuoDbSqlException(exception.ToString());
            }
            catch (XmlException exception)
            {
            #if DEBUG
                System.Diagnostics.Trace.WriteLine("NuoDBConnection::doOpen(): exception " + exception.ToString());
            #endif
                if (socket != null && socket.Connected)
                {
                    try
                    {
                        socket.Close();
                        socket = null;
                    }
                    catch (IOException)
                    {
                        // just ignore
                    }
                }

                throw new NuoDbSqlException(exception.ToString());
            }
        }
        private void doOpen(string hostName)
        {
            networkErrorOccurred = false;
            string databaseName = parsedConnectionString.Database;

            int index = hostName.IndexOf(':');
            int port = PORT;
            if (index != -1)
            {
                try
                {
                    port = Int32.Parse(hostName.Substring(index + 1));
                }
                catch (FormatException e)
                {
                    throw new ArgumentException("Invalid port number in connection string", "ConnectionString", e);
                }
                hostName = hostName.Substring(0, index);
            }
            dataStream = new EncodedDataStream();
            authenticating = false;

            try
            {
                StringDictionary properties = new StringDictionary();
                Tag tag = new Tag("Connection");
                tag.addAttribute("Service", "SQL2");
                tag.addAttribute("Database", databaseName);
                if (parsedConnectionString.ContainsKey(NuoDbConnectionStringBuilder.ServerKey))
                {
                    tag.addAttribute("Server", parsedConnectionString.Server);
                    properties["Server"] = parsedConnectionString.Server;
                }
                string userName = null;
                if (parsedConnectionString.ContainsKey(NuoDbConnectionStringBuilder.UserKey))
                {
                    properties["User"] = userName = parsedConnectionString.User;
                    tag.addAttribute("User", userName);
                }
                else
                {
                    throw new ArgumentException("Username is missing in connection string", "ConnectionString");
                }

                string password = "";
                if (parsedConnectionString.ContainsKey(NuoDbConnectionStringBuilder.PasswordKey))
                {
                    password = parsedConnectionString.Password;
                }

                string cipher = DEFAULT_CIPHER;
                if (parsedConnectionString.ContainsKey(NuoDbConnectionStringBuilder.CipherKey))
                {
                    properties["Cipher"] = cipher = parsedConnectionString.Cipher;
                }
                if (parsedConnectionString.ContainsKey(NuoDbConnectionStringBuilder.SchemaKey))
                {
                    tag.addAttribute("Schema", parsedConnectionString.Schema);
                    properties["Schema"] = parsedConnectionString.Schema;
                }

                if (parsedConnectionString.ContainsKey(NuoDbConnectionStringBuilder.LBTagKey))
                {
                    properties["LBTag"] = parsedConnectionString.LBTag;
                }
                if (parsedConnectionString.ContainsKey(NuoDbConnectionStringBuilder.ClientInfoKey))
                {
                    properties["clientInfo"] = parsedConnectionString.ClientInfo;
                }
                properties["clientProcessID"] = Process.GetCurrentProcess().Id.ToString();
                // see comment below ... for now these are the only two types that
                // we can support in the client code
                if ((!cipher.Equals("RC4")) && (!cipher.Equals("None")))
                    throw new NuoDbSqlException("Unknown cipher: " + cipher);
                tag.addAttribute("Cipher", cipher);

                string xml = tag.ToString();
                CryptoSocket brokerSocket = new CryptoSocket(hostName, port);
                inputStream = brokerSocket.InputStream;
                outputStream = brokerSocket.OutputStream;

                dataStream.write(xml);
                dataStream.send(outputStream);

                dataStream.getMessage(inputStream);
                string response = dataStream.readString();
                brokerSocket.Close();
                Tag responseTag = new Tag();
                responseTag.parse(response);

                if (responseTag.Name.Equals("Error"))
                {
                    throw new NuoDbSqlException(responseTag.getAttribute("text", "error text not found"));
                }

                serverAddress = responseTag.getAttribute("Address", null);
                serverPort = responseTag.getIntAttribute("Port", 0);

                if (serverAddress == null || serverPort == 0)
                {
                    throw new NuoDbSqlException("no NuoDB nodes are available for database \"" + databaseName + "\"");
                }

                socket = new CryptoSocket(serverAddress, serverPort);
                //socket.TcpNoDelay = true;
                inputStream = socket.InputStream;
                outputStream = socket.OutputStream;
                dataStream.reset();
                dataStream.write(xml);
                dataStream.send(outputStream);

                RemotePassword remotePassword = new RemotePassword();
                string userKey = remotePassword.genClientKey();

                dataStream.startMessage(Protocol.OpenDatabase);
                dataStream.encodeInt(Protocol.PROTOCOL_VERSION);
                dataStream.encodeString(databaseName);

                getProcessConnection(databaseName);
                string dbUUId = processConnection.DatabaseUUId.ToString();

            #if __MonoCS__
                // On Mono, timezone support is too much platform dependent
                sqlContext.TimeZone = TimeZoneInfo.Local;
            #else
                // see if the app set the TimeZone. If so, it will be sent to the server
                // so set the local TZ to be the same. If not, send the current default
                // TZ  to the server. (Of course, this affects this connection only)
                if (parsedConnectionString.ContainsKey(NuoDbConnectionStringBuilder.TimeZoneKey))
                {
                    string tzone = parsedConnectionString.TimeZone;
                    properties["TimeZone"] = tzone;
                    sqlContext.TimeZone = OlsonDatabase.FindWindowsTimeZone(tzone);
                }
                else
                {
                    // Save the default at the time the connection was opened
                    string tzone = TimeZoneInfo.Local.Id;
                    properties["TimeZone"] = OlsonDatabase.FindOlsonTimeZone(tzone);
                    // As described in http://msdn.microsoft.com/en-us/library/system.timezoneinfo.local.aspx TimeZoneInfo.Local
                    // always applies the DST setting of the current time, even if the DST settings of the tested date used different
                    // rules; so we fetch the complete definition from the database
                    sqlContext.TimeZone = TimeZoneInfo.FindSystemTimeZoneById(tzone);
                }
            #endif

                int count = properties.Count + 1 + ((dbUUId == null) ? 0 : 1); // Add LastCommitInfo and DatabaseUUId

                dataStream.encodeInt(count);
                foreach (DictionaryEntry property in properties)
                {
                    string name = (string)property.Key;
                    string value = (string)property.Value;
                    dataStream.encodeString(name);
                    dataStream.encodeString(value);
                }

                // LastCommitInfo and DatabaseUUId are sent as properties. This avoids sending another
                // message and keeps them from being protocol version sensitive

                string lastCommitParam = getProcessConnection(databaseName).getLastCommitInfo();
                dataStream.encodeString("LastCommitInfo");
                dataStream.encodeString(lastCommitParam);

                if (dbUUId != null)
                {
                    dataStream.encodeString("DatabaseUUId");
                    dataStream.encodeString(dbUUId);
                }

                // This  would have been the last commit txn id if that scheme was ever fully
                // implemented but it wasn't and this is now obsolete. keep it for compatibility with older servers

                dataStream.encodeLong(0);
                dataStream.encodeString(userKey);
                sendAndReceive(dataStream);

                protocolVersion = dataStream.getInt();
                string serverKey = dataStream.getString();
                string salt = dataStream.getString();
                dataStream.ProtocolVersion = protocolVersion;

                if (protocolVersion >= Protocol.PROTOCOL_VERSION5)
                {
                    processConnection.DatabaseUUId = dataStream.getUUId();
                }

                string upperUserName = userName.ToUpper();
                byte[] key = remotePassword.computeSessionKey(upperUserName, password, salt, serverKey);

                // NOTE: unlike the C++ implementation we only support RC4 in .NET
                // and it's a hard-coded class (instead of the factory interface
                // on the C++ CryptoSocket) so there's no checking to see which
                // cipher was requested here

                inputStream.encrypt(new CipherRC4(key));
                outputStream.encrypt(new CipherRC4(key));

                dataStream.startMessage(Protocol.Authentication);
                dataStream.encodeString("Success!");
                authenticating = true;
                sendAndReceive(dataStream);

                // if the caller requested a cipher of None and we got here then the
                // server accepted it and expects us to disable crypto now

                if (cipher.Equals("None"))
                {
                    inputStream.encrypt(null);
                    outputStream.encrypt(null);
                }
            }
            catch (NuoDbSqlException e)
            {
            #if DEBUG
                System.Diagnostics.Trace.WriteLine("NuoDBConnection::doOpen(): exception " + e.ToString());
            #endif
                if (authenticating)
                {
                    throw new NuoDbSqlException("Authentication failed for database \"" + databaseName + "\"");
                }

                throw e;
            }
            catch (IOException exception)
            {
            #if DEBUG
                System.Diagnostics.Trace.WriteLine("NuoDBConnection::doOpen(): exception " + exception.ToString());
            #endif
                networkErrorOccurred = true;
                if (socket != null && socket.Connected)
                {
                    try
                    {
                        socket.Close();
                        socket = null;
                    }
                    catch (IOException)
                    {
                        // just ignore
                    }
                }

                throw new NuoDbSqlException(exception.ToString());
            }
            catch (XmlException exception)
            {
            #if DEBUG
                System.Diagnostics.Trace.WriteLine("NuoDBConnection::doOpen(): exception " + exception.ToString());
            #endif
                if (socket != null && socket.Connected)
                {
                    try
                    {
                        socket.Close();
                        socket = null;
                    }
                    catch (IOException)
                    {
                        // just ignore
                    }
                }

                throw new NuoDbSqlException(exception.ToString());
            }

            if (parsedConnectionString.ContainsKey(NuoDbConnectionStringBuilder.ApplicationIntentKey))
            {
                string applicationIntent = parsedConnectionString.ApplicationIntent;
                if (applicationIntent.Equals("ReadOnly", StringComparison.InvariantCultureIgnoreCase))
                {
                    dataStream.startMessage(Protocol.SetReadOnly);
                    dataStream.encodeBoolean(true);
                    sendAsync(dataStream);
                }
            }
            if (parsedConnectionString.ContainsKey(NuoDbConnectionStringBuilder.IsolationLevelKey))
            {
                string isolationLevel = parsedConnectionString.IsolationLevel;
                int level = 0;
                if (isolationLevel.Equals("ReadCommitted", StringComparison.InvariantCultureIgnoreCase))
                {
                    // static const int TRANSACTION_READ_COMMITTED    = 2;
                    level = 2;
                }
                else if (isolationLevel.Equals("Serializable", StringComparison.InvariantCultureIgnoreCase))
                {
                    // static const int TRANSACTION_SERIALIZABLE      = 8;
                    level = 8;
                }
                else if (isolationLevel.Equals("WriteCommitted", StringComparison.InvariantCultureIgnoreCase))
                {
                    // static const int TRANSACTION_WRITE_COMMITTED   = 5;
                    level = 5;
                }
                else if (isolationLevel.Equals("ConsistentRead", StringComparison.InvariantCultureIgnoreCase))
                {
                    // static const int TRANSACTION_CONSISTENT_READ   = 7;
                    level = 7;
                }
                else
                {
                    throw new NuoDbSqlException("\"" + isolationLevel + "\" is not a valid isolation level");
                }
                dataStream.startMessage(Protocol.SetTransactionIsolation);
                dataStream.encodeInt(level);
                sendAndReceive(dataStream);
            }
        }