Esempio n. 1
0
 /// <summary>
 /// Dispose object
 /// </summary>
 public override void Dispose()
 {
     try
     {
         SendControlPacket(SNISMUXFlags.SMUX_FIN);
     }
     catch (Exception e)
     {
         SNICommon.ReportSNIError(SNIProviders.SMUX_PROV, 0, 0, e.Message);
     }
 }
Esempio n. 2
0
        /// <summary>
        /// Start receiving
        /// </summary>
        /// <returns></returns>
        public uint StartReceive()
        {
            SNIPacket packet = null;

            if (ReceiveAsync(ref packet) == TdsEnums.SNI_SUCCESS_IO_PENDING)
            {
                return(TdsEnums.SNI_SUCCESS_IO_PENDING);
            }

            return(SNICommon.ReportSNIError(SNIProviders.SMUX_PROV, 0, SNICommon.ConnNotUsableError, string.Empty));
        }
Esempio n. 3
0
        public SNINpHandle(string serverName, string pipeName, long timerExpire, object callbackObject)
        {
            _targetServer     = serverName;
            _callbackObject   = callbackObject;
            _writeScheduler   = new ConcurrentExclusiveSchedulerPair().ExclusiveScheduler;
            _writeTaskFactory = new TaskFactory(_writeScheduler);

            try
            {
                _pipeStream = new NamedPipeClientStream(
                    serverName,
                    pipeName,
                    PipeDirection.InOut,
                    PipeOptions.Asynchronous | PipeOptions.WriteThrough);

                bool isInfiniteTimeOut = long.MaxValue == timerExpire;
                if (isInfiniteTimeOut)
                {
                    _pipeStream.Connect(Threading.Timeout.Infinite);
                }
                else
                {
                    TimeSpan ts = DateTime.FromFileTime(timerExpire) - DateTime.Now;
                    ts = ts.Ticks < 0 ? TimeSpan.FromTicks(0) : ts;

                    _pipeStream.Connect((int)ts.TotalMilliseconds);
                }
            }
            catch (TimeoutException te)
            {
                SNICommon.ReportSNIError(SNIProviders.NP_PROV, SNICommon.ConnOpenFailedError, te);
                _status = TdsEnums.SNI_ERROR;
                return;
            }
            catch (IOException ioe)
            {
                SNICommon.ReportSNIError(SNIProviders.NP_PROV, SNICommon.ConnOpenFailedError, ioe);
                _status = TdsEnums.SNI_ERROR;
                return;
            }

            if (!_pipeStream.IsConnected || !_pipeStream.CanWrite || !_pipeStream.CanRead)
            {
                SNICommon.ReportSNIError(SNIProviders.NP_PROV, 0, SNICommon.ConnOpenFailedError, string.Empty);
                _status = TdsEnums.SNI_ERROR;
                return;
            }

            _sslOverTdsStream = new SslOverTdsStream(_pipeStream);
            _sslStream        = new SslStream(_sslOverTdsStream, true, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);

            _stream = _pipeStream;
            _status = TdsEnums.SNI_SUCCESS;
        }
Esempio n. 4
0
 /// <summary>
 /// Enable SSL on a connection
 /// </summary>
 /// <param name="handle">Connection handle</param>
 /// <returns>SNI error code</returns>
 public uint EnableSsl(SNIHandle handle, uint options)
 {
     try
     {
         return(handle.EnableSsl(options));
     }
     catch (Exception e)
     {
         return(SNICommon.ReportSNIError(SNIProviders.SSL_PROV, SNICommon.HandshakeFailureError, e));
     }
 }
Esempio n. 5
0
 /// <summary>
 /// Dispose object
 /// </summary>
 public override void Dispose()
 {
     try
     {
         SendControlPacket(SNISMUXFlags.SMUX_FIN);
     }
     catch (Exception e)
     {
         SNICommon.ReportSNIError(SNIProviders.SMUX_PROV, SNICommon.InternalExceptionError, e);
         throw;
     }
 }
Esempio n. 6
0
        /// <summary>
        /// Receive a packet synchronously
        /// </summary>
        /// <param name="packet">SNI packet</param>
        /// <param name="timeoutInMilliseconds">Timeout in Milliseconds</param>
        /// <returns>SNI error code</returns>
        public override uint Receive(out SNIPacket packet, int timeoutInMilliseconds)
        {
            packet = null;
            int  queueCount;
            uint result = TdsEnums.SNI_SUCCESS_IO_PENDING;

            while (true)
            {
                lock (_receivedPacketQueue)
                {
                    if (_connectionError != null)
                    {
                        return(SNICommon.ReportSNIError(_connectionError));
                    }

                    queueCount = _receivedPacketQueue.Count;

                    if (queueCount > 0)
                    {
                        packet = _receivedPacketQueue.Dequeue();

                        if (queueCount == 1)
                        {
                            _packetEvent.Reset();
                        }

                        result = TdsEnums.SNI_SUCCESS;
                    }
                }

                if (result == TdsEnums.SNI_SUCCESS)
                {
                    lock (this)
                    {
                        _receiveHighwater++;
                    }

                    SendAckIfNecessary();
                    return(result);
                }

                if (!_packetEvent.Wait(timeoutInMilliseconds))
                {
                    SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.SMUX_PROV, 0, SNICommon.ConnTimeoutError, string.Empty);
                    return(TdsEnums.SNI_WAIT_TIMEOUT);
                }
            }
        }
Esempio n. 7
0
        /// <summary>
        /// Creates an SNINpHandle object
        /// </summary>
        /// <param name="fullServerName">Server string representing a UNC pipe path.</param>
        /// <param name="timerExpire">Timer expiration</param>
        /// <param name="callbackObject">Asynchronous I/O callback object</param>
        /// <param name="parallel">Should MultiSubnetFailover be used. Only returns an error for named pipes.</param>
        /// <returns>SNINpHandle</returns>
        private SNINpHandle CreateNpHandle(string fullServerName, long timerExpire, object callbackObject, bool parallel)
        {
            if (parallel)
            {
                SNICommon.ReportSNIError(SNIProviders.NP_PROV, 0, SNICommon.MultiSubnetFailoverWithNonTcpProtocol, string.Empty);
                return(null);
            }

            if (fullServerName.Length == 0 || fullServerName.Contains("/")) // Pipe paths only allow back slashes
            {
                SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.NP_PROV, 0, SNICommon.InvalidConnStringError, string.Empty);
                return(null);
            }

            string serverName, pipeName;

            if (!fullServerName.Contains(@"\"))
            {
                serverName = fullServerName;
                pipeName   = SNINpHandle.DefaultPipePath;
            }
            else
            {
                try
                {
                    Uri    pipeURI      = new Uri(fullServerName);
                    string resourcePath = pipeURI.AbsolutePath;

                    string pipeToken = "/pipe/";
                    if (!resourcePath.StartsWith(pipeToken))
                    {
                        SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.NP_PROV, 0, SNICommon.InvalidConnStringError, string.Empty);
                        return(null);
                    }
                    pipeName   = resourcePath.Substring(pipeToken.Length);
                    serverName = pipeURI.Host;
                }
                catch (UriFormatException)
                {
                    SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.NP_PROV, 0, SNICommon.InvalidConnStringError, string.Empty);
                    return(null);
                }
            }

            return(new SNINpHandle(serverName, pipeName, timerExpire, callbackObject));
        }
Esempio n. 8
0
        public override uint SendAsync(SNIPacket packet, SNIAsyncCallback callback = null)
        {
            SNIPacket newPacket = packet;

            _writeTaskFactory.StartNew(() =>
            {
                try
                {
                    lock (this)
                    {
                        packet.WriteToStream(_stream);
                    }
                }
                catch (Exception e)
                {
                    SNICommon.ReportSNIError(SNIProviders.NP_PROV, SNICommon.InternalExceptionError, e);

                    if (callback != null)
                    {
                        callback(packet, TdsEnums.SNI_ERROR);
                    }
                    else
                    {
                        _sendCallback(packet, TdsEnums.SNI_ERROR);
                    }

                    return;
                }

                if (callback != null)
                {
                    callback(packet, TdsEnums.SNI_SUCCESS);
                }
                else
                {
                    _sendCallback(packet, TdsEnums.SNI_SUCCESS);
                }
            });

            return(TdsEnums.SNI_SUCCESS_IO_PENDING);
        }
Esempio n. 9
0
        public override uint EnableSsl(uint options)
        {
            _validateCert = (options & TdsEnums.SNI_SSL_VALIDATE_CERTIFICATE) != 0;

            try
            {
                _sslStream.AuthenticateAsClientAsync(_targetServer).GetAwaiter().GetResult();
                _sslOverTdsStream.FinishHandshake();
            }
            catch (AuthenticationException aue)
            {
                return(SNICommon.ReportSNIError(SNIProviders.NP_PROV, SNICommon.InternalExceptionError, aue));
            }
            catch (InvalidOperationException ioe)
            {
                return(SNICommon.ReportSNIError(SNIProviders.NP_PROV, SNICommon.InternalExceptionError, ioe));
            }

            _stream = _sslStream;
            return(TdsEnums.SNI_SUCCESS);
        }
Esempio n. 10
0
        /// <summary>
        /// Create a SNI connection handle
        /// </summary>
        /// <param name="callbackObject">Asynchronous I/O callback object</param>
        /// <param name="fullServerName">Full server name from connection string</param>
        /// <param name="ignoreSniOpenTimeout">Ignore open timeout</param>
        /// <param name="timerExpire">Timer expiration</param>
        /// <param name="instanceName">Instance name</param>
        /// <param name="spnBuffer">SPN</param>
        /// <param name="flushCache">Flush packet cache</param>
        /// <param name="async">Asynchronous connection</param>
        /// <param name="parallel">Attempt parallel connects</param>
        /// <returns>SNI handle</returns>
        public SNIHandle CreateConnectionHandle(object callbackObject, string fullServerName, bool ignoreSniOpenTimeout, long timerExpire, out byte[] instanceName, byte[] spnBuffer, bool flushCache, bool async, bool parallel)
        {
            instanceName    = new byte[1];
            instanceName[0] = 0;

            string[] serverNameParts = fullServerName.Split(':');

            if (serverNameParts.Length > 2)
            {
                SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.INVALID_PROV, 0, SNICommon.InvalidConnStringError, string.Empty);
                return(null);
            }

            // Default to using tcp if no protocol is provided
            if (serverNameParts.Length == 1)
            {
                return(CreateTcpHandle(serverNameParts[0], timerExpire, callbackObject, parallel));
            }

            switch (serverNameParts[0])
            {
            case TdsEnums.TCP:
                return(CreateTcpHandle(serverNameParts[1], timerExpire, callbackObject, parallel));

            case TdsEnums.NP:
                return(CreateNpHandle(serverNameParts[1], timerExpire, callbackObject, parallel));

            default:
                if (parallel)
                {
                    SNICommon.ReportSNIError(SNIProviders.INVALID_PROV, 0, SNICommon.MultiSubnetFailoverWithNonTcpProtocol, string.Empty);
                }
                else
                {
                    SNICommon.ReportSNIError(SNIProviders.INVALID_PROV, 0, SNICommon.ProtocolNotSupportedError, string.Empty);
                }
                return(null);
            }
        }
Esempio n. 11
0
        /// <summary>
        /// Creates an SNINpHandle object
        /// </summary>
        /// <param name="fullServerName">Server string representing a UNC pipe path.</param>
        /// <param name="timerExpire">Timer expiration</param>
        /// <param name="callbackObject">Asynchronous I/O callback object</param>
        /// <param name="parallel">Should MultiSubnetFailover be used. Only returns an error for named pipes.</param>
        /// <returns>SNINpHandle</returns>
        private SNINpHandle CreateNpHandle(string fullServerName, long timerExpire, object callbackObject, bool parallel)
        {
            if (parallel)
            {
                SNICommon.ReportSNIError(SNIProviders.INVALID_PROV, 0, SNICommon.MultiSubnetFailoverWithNonTcpProtocol, string.Empty);
                return(null);
            }

            // Named Pipe Format: np:\\<host name>\pipe\<pipe name>
            const int minPipeLength = 10; // eg: //./pipe/a
            string    pipePath      = fullServerName.Trim();

            if (pipePath.Length < minPipeLength)
            {
                SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.NP_PROV, 0, SNICommon.InvalidConnStringError, string.Empty);
                return(null);
            }

            if (pipePath[0] != '\\' || pipePath[1] != '\\')
            {
                SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.NP_PROV, 0, SNICommon.InvalidConnStringError, string.Empty);
                return(null);
            }

            int endofServerName = pipePath.IndexOf('\\', 2);

            string pipeToken = @"\pipe\";

            if (0 != string.Compare(pipeToken, 0, pipePath, endofServerName, pipeToken.Length))
            {
                SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.NP_PROV, 0, SNICommon.InvalidConnStringError, string.Empty);
                return(null);
            }

            string serverName = pipePath.Substring(2, endofServerName - 2);
            string pipeName   = pipePath.Substring(endofServerName + pipeToken.Length);

            return(new SNINpHandle(serverName, pipeName, timerExpire, callbackObject));
        }
Esempio n. 12
0
        /// <summary>
        /// Create a SNI connection handle
        /// </summary>
        /// <param name="callbackObject">Asynchronous I/O callback object</param>
        /// <param name="fullServerName">Full server name from connection string</param>
        /// <param name="ignoreSniOpenTimeout">Ignore open timeout</param>
        /// <param name="timerExpire">Timer expiration</param>
        /// <param name="instanceName">Instance name</param>
        /// <param name="spnBuffer">SPN</param>
        /// <param name="flushCache">Flush packet cache</param>
        /// <param name="async">Asynchronous connection</param>
        /// <param name="parallel">Attempt parallel connects</param>
        /// <returns>SNI handle</returns>
        public SNIHandle CreateConnectionHandle(object callbackObject, string fullServerName, bool ignoreSniOpenTimeout, long timerExpire, out byte[] instanceName, byte[] spnBuffer, bool flushCache, bool async, bool parallel)
        {
            instanceName    = new byte[1];
            instanceName[0] = 0;

            string[] serverNameParts = fullServerName.Split(':');

            if (serverNameParts.Length > 2)
            {
                SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.INVALID_PROV, 0, 0, "Connection string is not formatted correctly");
                return(null);
            }

            // Default to using tcp if no protocol is provided
            if (serverNameParts.Length == 1)
            {
                return(ConstructTcpHandle(serverNameParts[0], timerExpire, callbackObject, parallel));
            }

            switch (serverNameParts[0])
            {
            case TdsEnums.TCP:
                return(ConstructTcpHandle(serverNameParts[1], timerExpire, callbackObject, parallel));

            default:
                if (parallel)
                {
                    SNICommon.ReportSNIError(SNIProviders.INVALID_PROV, 0, (int)SNINativeMethodWrapper.SniSpecialErrors.MultiSubnetFailoverWithNonTcpProtocol, SR.SNI_ERROR_49);
                }
                else
                {
                    SNICommon.ReportSNIError(SNIProviders.INVALID_PROV, 0, 8, SR.SNI_ERROR_8);
                }
                return(null);
            }
        }
Esempio n. 13
0
 private uint ReportTcpSNIError(uint nativeError, uint sniError, string errorMessage)
 {
     _status = TdsEnums.SNI_ERROR;
     return(SNICommon.ReportSNIError(SNIProviders.TCP_PROV, nativeError, sniError, errorMessage));
 }
Esempio n. 14
0
 private uint ReportTcpSNIError(Exception sniException)
 {
     _status = TdsEnums.SNI_ERROR;
     return(SNICommon.ReportSNIError(SNIProviders.TCP_PROV, SNICommon.InternalExceptionError, sniException));
 }
Esempio n. 15
0
        /// <summary>
        /// Process a receive completion
        /// </summary>
        /// <param name="packet">SNI packet</param>
        /// <param name="sniErrorCode">SNI error code</param>
        public void HandleReceiveComplete(SNIPacket packet, uint sniErrorCode)
        {
            SNISMUXHeader currentHeader  = null;
            SNIPacket     currentPacket  = null;
            SNIMarsHandle currentSession = null;

            if (sniErrorCode != TdsEnums.SNI_SUCCESS)
            {
                lock (this)
                {
                    HandleReceiveError();
                    return;
                }
            }

            while (true)
            {
                lock (this)
                {
                    if (_currentHeaderByteCount != SNISMUXHeader.HEADER_LENGTH)
                    {
                        currentHeader  = null;
                        currentPacket  = null;
                        currentSession = null;

                        while (_currentHeaderByteCount != SNISMUXHeader.HEADER_LENGTH)
                        {
                            int bytesTaken = packet.TakeData(_headerBytes, _currentHeaderByteCount, SNISMUXHeader.HEADER_LENGTH - _currentHeaderByteCount);
                            _currentHeaderByteCount += bytesTaken;

                            if (bytesTaken == 0)
                            {
                                sniErrorCode = ReceiveAsync(ref packet);

                                if (sniErrorCode == TdsEnums.SNI_SUCCESS_IO_PENDING)
                                {
                                    return;
                                }

                                HandleReceiveError();
                                return;
                            }
                        }

                        _currentHeader = new SNISMUXHeader()
                        {
                            SMID           = _headerBytes[0],
                            flags          = _headerBytes[1],
                            sessionId      = BitConverter.ToUInt16(_headerBytes, 2),
                            length         = BitConverter.ToUInt32(_headerBytes, 4) - SNISMUXHeader.HEADER_LENGTH,
                            sequenceNumber = BitConverter.ToUInt32(_headerBytes, 8),
                            highwater      = BitConverter.ToUInt32(_headerBytes, 12)
                        };

                        _dataBytesLeft = (int)_currentHeader.length;
                        _currentPacket = new SNIPacket(null);
                        _currentPacket.Allocate((int)_currentHeader.length);
                    }

                    currentHeader = _currentHeader;
                    currentPacket = _currentPacket;

                    if (_currentHeader.flags == (byte)SNISMUXFlags.SMUX_DATA)
                    {
                        if (_dataBytesLeft > 0)
                        {
                            int length = packet.TakeData(_currentPacket, _dataBytesLeft);
                            _dataBytesLeft -= length;

                            if (_dataBytesLeft > 0)
                            {
                                sniErrorCode = ReceiveAsync(ref packet);

                                if (sniErrorCode == TdsEnums.SNI_SUCCESS_IO_PENDING)
                                {
                                    return;
                                }

                                HandleReceiveError();
                                return;
                            }
                        }
                    }

                    _currentHeaderByteCount = 0;

                    if (!_sessions.ContainsKey(_currentHeader.sessionId))
                    {
                        SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.SMUX_PROV, 0, SNICommon.InvalidParameterError, string.Empty);
                        HandleReceiveError();
                        _lowerHandle.Dispose();
                        _lowerHandle = null;
                        return;
                    }

                    if (_currentHeader.flags == (byte)SNISMUXFlags.SMUX_FIN)
                    {
                        _sessions.Remove(_currentHeader.sessionId);
                    }
                    else
                    {
                        currentSession = _sessions[_currentHeader.sessionId];
                    }
                }

                if (currentHeader.flags == (byte)SNISMUXFlags.SMUX_DATA)
                {
                    currentSession.HandleReceiveComplete(currentPacket, currentHeader);
                }

                if (_currentHeader.flags == (byte)SNISMUXFlags.SMUX_ACK)
                {
                    try
                    {
                        currentSession.HandleAck(currentHeader.highwater);
                    }
                    catch (Exception e)
                    {
                        SNICommon.ReportSNIError(SNIProviders.SMUX_PROV, SNICommon.InternalExceptionError, e);
                    }
                }

                lock (this)
                {
                    if (packet.DataLeft == 0)
                    {
                        sniErrorCode = ReceiveAsync(ref packet);

                        if (sniErrorCode == TdsEnums.SNI_SUCCESS_IO_PENDING)
                        {
                            return;
                        }

                        HandleReceiveError();
                        return;
                    }
                }
            }
        }
Esempio n. 16
0
        /// <summary>
        /// Create a SNI connection handle
        /// </summary>
        /// <param name="callbackObject">Asynchronous I/O callback object</param>
        /// <param name="fullServerName">Full server name from connection string</param>
        /// <param name="ignoreSniOpenTimeout">Ignore open timeout</param>
        /// <param name="timerExpire">Timer expiration</param>
        /// <param name="instanceName">Instance name</param>
        /// <param name="spnBuffer">SPN</param>
        /// <param name="flushCache">Flush packet cache</param>
        /// <param name="async">Asynchronous connection</param>
        /// <param name="parallel">Attempt parallel connects</param>
        /// <returns>SNI handle</returns>
        public SNIHandle CreateConnectionHandle(object callbackObject, string fullServerName, bool ignoreSniOpenTimeout, long timerExpire, out byte[] instanceName, ref byte[] spnBuffer, bool flushCache, bool async, bool parallel, bool isIntegratedSecurity)
        {
            instanceName = new byte[1];

            SNIHandle sniHandle = null;

            if (fullServerName.IndexOf(':') == -1)
            {
                // default to using tcp if no protocol is provided
                sniHandle = CreateTcpHandle(fullServerName, timerExpire, callbackObject, parallel, ref spnBuffer, isIntegratedSecurity);
            }
            else
            {
                string serverNameWithOutProtocol = null;

                // when tcp protocol is specified
                if ((serverNameWithOutProtocol = GetServerNameWithOutProtocol(fullServerName, TdsEnums.TCP + ":")) != null)
                {
                    sniHandle = CreateTcpHandle(serverNameWithOutProtocol, timerExpire, callbackObject, parallel, ref spnBuffer, isIntegratedSecurity);
                }
                // when np protocol is specified
                else if ((serverNameWithOutProtocol = GetServerNameWithOutProtocol(fullServerName, TdsEnums.NP + ":\\\\")) != null ||
                         (serverNameWithOutProtocol = GetServerNameWithOutProtocol(fullServerName, "\\\\")) != null)
                {
                    sniHandle = CreateNpHandle(serverNameWithOutProtocol, timerExpire, callbackObject, parallel);
                }
                // possibly error case
                else
                {
                    int       portOrInstanceNameIndex             = Math.Max(fullServerName.LastIndexOf(','), fullServerName.LastIndexOf('\\'));
                    string    serverNameWithOutPortOrInstanceName = portOrInstanceNameIndex > 0 ? fullServerName.Substring(0, portOrInstanceNameIndex) : fullServerName;
                    IPAddress address = null;

                    // when no protocol is specified, and fullServerName is IPv6
                    if (IPAddress.TryParse(serverNameWithOutPortOrInstanceName, out address) && address.AddressFamily == AddressFamily.InterNetworkV6)
                    {
                        // default to using tcp if no protocol is provided
                        sniHandle = CreateTcpHandle(fullServerName, timerExpire, callbackObject, parallel, ref spnBuffer, isIntegratedSecurity);
                    }
                    // error case for sure
                    else
                    {
                        // when invalid protocol is specified
                        if (IsOccursOnce(fullServerName, ':'))
                        {
                            SNICommon.ReportSNIError(
                                SNIProviders.INVALID_PROV, 0,
                                (uint)(parallel ? SNICommon.MultiSubnetFailoverWithNonTcpProtocol : SNICommon.ProtocolNotSupportedError),
                                string.Empty);
                        }
                        // when fullServerName is in invalid format
                        else
                        {
                            SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.INVALID_PROV, 0, SNICommon.InvalidConnStringError, string.Empty);
                        }
                    }
                }
            }

            return(sniHandle);
        }