public void ConnectOverRDMA(string localIpAddress, string remoteIpAddress, int port, uint maxReceiveSize, out RdmaAdapterInfo adapterInfo)
        {
            NtStatus status;

            RdmaProviderInfo[] providers;
            status = (NtStatus)RdmaProvider.LoadRdmaProviders(out providers);
            if (status != NtStatus.STATUS_SUCCESS)
            {
                throw new InvalidOperationException("Failed to load RDMA providers!");
            }

            RdmaAdapter adapter = null;

            foreach (var provider in providers)
            {
                if (provider.Provider == null)
                {
                    continue;
                }
                RdmaAdapter outputAdapter;
                status = (NtStatus)provider.Provider.OpenAdapter(localIpAddress, (short)AddressFamily.InterNetwork, out outputAdapter);
                if (status == NtStatus.STATUS_SUCCESS)
                {
                    adapter = outputAdapter;
                    break;
                }
            }

            if (adapter == null)
            {
                throw new InvalidOperationException("Failed to find the specified RDMA adapter!");
            }

            status = (NtStatus)adapter.Query(out adapterInfo);
            if (status != (int)NtStatus.STATUS_SUCCESS)
            {
                throw new InvalidOperationException("Failed to query RDMA provider info!");
            }


            status = smbdClient.ConnectToServerOverRdma(
                localIpAddress,
                remoteIpAddress,
                port,
                AddressFamily.InterNetwork,
                adapterInfo.MaxInboundRequests,
                adapterInfo.MaxOutboundRequests,
                adapterInfo.MaxInboundReadLimit,
                maxReceiveSize
                );

            if (status != NtStatus.STATUS_SUCCESS)
            {
                throw new InvalidOperationException("ConnectToServerOverRdma failed!");
            }

            decoder.TransportType = Smb2TransportType.Rdma;
        }
        /// <summary>
        /// SmbdEndpoint constructor will load RDMA providers and initialize default connection values.
        /// </summary>
        /// <param name="inboundEntries">maximum number of outstanding Receive requests.</param>
        /// <param name="outboundEntries">maximum number of outstanding Send, SendAndInvalidate
        /// , Bind, Invalidate, Read, and Write requests.
        /// </param>
        /// <param name="inboundSegment">inbound segments limit</param>
        /// <param name="outboundSegment">outbound segments limit</param>
        /// <param name="inboundReadLimit">maximum inbound read limit for the local Network
        /// Direct adapter. This value can be zero if you do not support
        /// </param>
        /// <param name="outboundReadLimit"></param>
        /// <param name="inboundDataSize">Max Size of RDMA inbound data</param>
        /// <param name="logEvent">Delegate to log SMBD event</param>
        public SmbdConnectionEndpoint(
            uint inboundEntries,
            uint outboundEntries,
            uint inboundSegment,
            uint outboundSegment,
            uint inboundReadLimit,
            uint outboundReadLimit,
            uint inboundDataSize,
            SmbdLogEvent logEvent = null
            )
        {
            this.logEndpointEvent = logEvent;

            LogEvent("Loading the providers of registered network drivers.");
            initializeStatus = (NtStatus)RdmaProvider.LoadRdmaProviders(out rdmaProvidersList);

            this.inboundEntries       = inboundEntries;
            this.outboundEntries      = outboundEntries;
            this.inboundSegment       = inboundSegment;
            this.outboundSegment      = outboundSegment;
            this.inboundReadLimit     = inboundReadLimit;
            this.outboundReadLimit    = outboundReadLimit;
            this.completionQueueDepth = (inboundEntries + outboundEntries);
            this.inboundDataSize      = inboundDataSize;

            isConnected        = false;
            memoryWindowList   = new List <SmbdMemoryWindow>();
            receiveRequestList = new List <SmbdRequest>();

            locker = new Object();

            otherRequestResult   = new SyncFilterQueue <SmbdRequestResult>();
            receiveRequestResult = new SyncFilterQueue <SmbdRequestResult>();

            disconnectSemaphore = new Semaphore(0, 1);
            //threadStopSemaphore = new Semaphore(0, THREAD_COUNT);

            // one more for Semaphore Release when disconnection
            rdmaNotificationSemaphore = new Semaphore(0, (int)completionQueueDepth + 1);
            requestCount = 0;

            ReceivePostedCount = 0;

            #region output provider information
            if (initializeStatus != NtStatus.STATUS_SUCCESS)
            {
                LogEvent(string.Format("Load provider with error code: {0}", (NtStatus)initializeStatus));
                return;
            }
            if (rdmaProvidersList == null)
            {
                LogEvent("The returned providers list is NULL");
                return;
            }

            LogEvent(string.Format("{0} providers of registered network drivers have been load,", rdmaProvidersList.Length));
            int providerIndex = 0;
            foreach (RdmaProviderInfo info in rdmaProvidersList)
            {
                if (info != null)
                {
                    LogEvent(string.Format("Load provider {1}: {0}", info.Path, ++providerIndex));
                }
            }
            LogEvent("Loading providers is completed");
            #endregion
        }