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."); } }