/// <summary>
        /// Read data from memory window
        /// </summary>
        /// <param name="data"></param>
        /// <param name="bufferDescriptor">Buffer Descriptor point to memory windows</param>
        public NtStatus ReadMemoryWindow(byte[] data, RdmaBufferDescriptorV1 bufferDescriptor)
        {
            foreach (SmbdMemoryWindow mw in memoryWindowList)
            {
                if (mw.BufferDescriptor.Token != bufferDescriptor.Token)
                {
                    continue;
                }
                // get memory window
                if (mw.IsValid)
                {
                    NtStatus status = (NtStatus)RdmaEndpoint.ReadFromMemory(mw.MemoryHandlerId, data);
                    return(status);
                }
                return(NtStatus.STATUS_INVALID_PARAMETER_2);
            }

            return(NtStatus.STATUS_INVALID_PARAMETER_2);
        }
        /// <summary>
        /// Send data over RDMA
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public NtStatus SendData(byte[] data)
        {
            RdmaSegment sge = new RdmaSegment();

            sge.Length        = (uint)data.LongLength;
            sge.MemoryHandler = 0;

            // register memory
            rdmaAdapter.RegisterMemory(sge.Length, out sge.MemoryHandler);
            // Write data to memory
            RdmaEndpoint.WriteToMemory(sge.MemoryHandler, data);

            // send
            UInt64   resultId;
            NtStatus status = (NtStatus)rdmaEndpoint.Send(new RdmaSegment[] { sge }, out resultId);

            if (status != NtStatus.STATUS_SUCCESS)
            {
                return(status);
            }
            // send request has been submitted
            requestCount++;
            rdmaNotificationSemaphore.Release();

            // get the notification
            SmbdRequestResult item = GetRequestResult(new TimeSpan(0, 0, 5), RequestType.Send);

            this.LogEvent(string.Format("Send data with result id: 0x{0:X}. And get notification with id: 0x{1:X}, status: {2}",
                                        resultId,
                                        item.ResultId,
                                        item.ResultInfo.Status
                                        ));

            // deregister memory
            rdmaAdapter.DeregisterMemory(sge.MemoryHandler);

            return((NtStatus)item.ResultInfo.Status);
        }
        /// <summary>
        /// Receive data over RDMA
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public NtStatus ReceiveData(TimeSpan timeout, out byte[] data)
        {
            SmbdRequestResult item   = GetRequestResult(timeout, RequestType.Receive);
            NtStatus          status = (NtStatus)item.ResultInfo.Status;

            if (status != NtStatus.STATUS_SUCCESS)
            {
                data = null;
                return(status);
            }

            this.LogEvent(string.Format("Receive {0} bytes from entry 0x{1:X}",
                                        item.ResultInfo.BytesTransferred,
                                        item.EntryIndex));

            data   = new byte[item.ResultInfo.BytesTransferred];
            status = (NtStatus)RdmaEndpoint.ReadFromMemory(
                this.receiveEntries[item.EntryIndex].Segment.MemoryHandler,
                data);
            // reset
            this.receiveEntries[receiveIndex].IsOccupied = false;
            return(status);
        }