Exemple #1
0
        private PDUBase SendReceivePDU(PDUBase send_pdu)
        {
            try
            {
                CallId++;
                PDUHeader pdu_header = new PDUHeader()
                {
                    MajorVersion = PDUHeader.RPC_VERSION_MAJOR,
                    MinorVersion = PDUHeader.RPC_VERSION_MINOR,
                    DataRep      = _data_rep,
                    CallId       = CallId,
                    Type         = send_pdu.PDUType
                };

                List <byte[]> fragments = send_pdu.DoFragment(_max_send_fragment - PDUHeader.PDU_HEADER_SIZE);
                for (int i = 0; i < fragments.Count; ++i)
                {
                    pdu_header.Flags = send_pdu.GetFlags();
                    if (i == 0)
                    {
                        pdu_header.Flags |= PDUFlags.FirstFrag;
                    }
                    if (i == fragments.Count - 1)
                    {
                        pdu_header.Flags |= PDUFlags.LastFrag;
                    }

                    pdu_header.FragmentLength = (ushort)(fragments[i].Length + PDUHeader.PDU_HEADER_SIZE);
                    MemoryStream send_stm = new MemoryStream();
                    BinaryWriter writer   = new BinaryWriter(send_stm);
                    pdu_header.Write(writer);
                    writer.Write(fragments[i]);
                    byte[] fragment = send_stm.ToArray();
                    string name     = fragments.Count == 1 ? "RPC Named Pipe Send Buffer" : $"RPC Named Pipe Send Buffer - Fragment {i}";
                    RpcUtils.DumpBuffer(true, name, fragment);
                    if (_pipe.Write(fragment) != fragment.Length)
                    {
                        throw new RpcTransportException("Failed to write out PDU buffer.");
                    }
                }

                MemoryStream recv_stm    = new MemoryStream();
                PDUHeader    curr_header = new PDUHeader();
                int          frag_count  = 0;
                while ((curr_header.Flags & PDUFlags.LastFrag) == 0)
                {
                    var pdu = ReadPDU(frag_count++);
                    curr_header = pdu.Item1;
                    if (curr_header.CallId != CallId)
                    {
                        throw new RpcTransportException("Mismatching call ID.");
                    }
                    recv_stm.Write(pdu.Item2, 0, pdu.Item2.Length);
                }

                return(CheckFault(curr_header.ToPDU(recv_stm.ToArray())));
            }
            catch (EndOfStreamException)
            {
                throw new RpcTransportException("End of stream.");
            }
        }
        private Tuple <PDUBase, AuthData> SendReceivePDU(int call_id, PDUBase send_pdu, byte[] auth_data,
                                                         bool receive_pdu, RpcTransportSecurityContext security_context)
        {
            try
            {
                int trailing_auth_length = auth_data.Length > 0 ? auth_data.Length + AuthData.PDU_AUTH_DATA_HEADER_SIZE : 0;

                PDUHeader pdu_header = new PDUHeader()
                {
                    MajorVersion = PDUHeader.RPC_VERSION_MAJOR,
                    MinorVersion = PDUHeader.RPC_VERSION_MINOR,
                    DataRep      = _data_rep,
                    CallId       = CallId,
                    Type         = send_pdu.PDUType,
                    Flags        = PDUFlags.LastFrag | PDUFlags.FirstFrag,
                    AuthLength   = checked ((ushort)auth_data.Length)
                };

                byte[] pdu_data        = send_pdu.ToArray();
                int    pdu_data_length = pdu_data.Length + PDUHeader.PDU_HEADER_SIZE;
                int    auth_padding    = 0;
                if (auth_data.Length > 0 && (pdu_data_length & 15) != 0 && send_pdu.PDUType != PDUType.Auth3)
                {
                    auth_padding = 16 - (pdu_data_length & 15);
                }

                pdu_header.FragmentLength = checked ((ushort)(pdu_data.Length + PDUHeader.PDU_HEADER_SIZE + trailing_auth_length + auth_padding));
                MemoryStream send_stm = new MemoryStream();
                BinaryWriter writer   = new BinaryWriter(send_stm);
                pdu_header.Write(writer);
                writer.Write(pdu_data);
                if (auth_data.Length > 0)
                {
                    writer.Write(new byte[auth_padding]);
                    new AuthData(security_context.TransportSecurity.AuthenticationType, security_context.TransportSecurity.AuthenticationLevel,
                                 auth_padding, security_context.ContextId, auth_data).Write(writer, auth_padding);
                }
                byte[] fragment = send_stm.ToArray();
                RpcUtils.DumpBuffer(true, $"{GetType().Name} Send Buffer", fragment);
                if (!WriteFragment(fragment))
                {
                    throw new RpcTransportException("Failed to write out PDU buffer.");
                }
                _send_sequence_no++;
                if (!receive_pdu)
                {
                    return(null);
                }

                var pdu         = ReadPDU(0);
                var curr_header = pdu.Item1;
                if (!curr_header.Flags.HasFlagAllSet(PDUFlags.LastFrag | PDUFlags.FirstFrag))
                {
                    throw new RpcTransportException($"Invalid PDU flags {curr_header.Flags}.");
                }

                if (curr_header.CallId != call_id)
                {
                    throw new RpcTransportException($"Mismatching call ID - {curr_header.CallId} should be {call_id}.");
                }

                if (pdu.Item3.ContextId != security_context.ContextId)
                {
                    throw new RpcTransportException($"Mismatching context ID - {pdu.Item3.ContextId} should be {security_context.ContextId}.");
                }

                _recv_sequence_no++;

                return(Tuple.Create(CheckFault(curr_header.ToPDU(pdu.Item2)), pdu.Item3));
            }
            catch (EndOfStreamException)
            {
                throw new RpcTransportException("End of stream.");
            }
        }