/// <summary> /// Handle the received pdu from server. /// </summary> /// <param name="rpcePdu"> /// Received pdu received from server. /// </param> /// <param name="responseStub"> /// A byte array of the response stub of a method. /// RpceStubDecoder can be used to NDR un-marshal parameters to a byte array. /// </param> /// <exception cref="InvalidOperationException"> /// Thrown when receive error from server or RPC connection has not been established. /// </exception> private void HandleRpcePdu(RpcePdu rpcePdu, out byte[] responseStub) { if (rpcePdu is RpceCoResponsePdu) { responseStub = (rpcePdu as RpceCoResponsePdu).stub; } else if (rpcePdu is RpceCoFaultPdu) { throw new InvalidOperationException((rpcePdu as RpceCoFaultPdu).status.ToString()); } else { throw new InvalidOperationException(rpcePdu.GetType().ToString()); } }
/// <summary> /// Parse the identifier of the call from the received pdu from server. /// </summary> /// <param name="rpcePdu"> /// Received pdu received from server. /// </param> /// <exception cref="RpceDisconnectedException"> /// Thrown when receive shutdown PDU. /// </exception> /// <exception cref="InvalidOperationException"> /// Thrown when receive error from server. /// </exception> /// <returns>Return the identifier of the call if success, otherwise throw an exception.</returns> private uint ParseRpcePdu(RpcePdu rpcePdu) { if (rpcePdu is RpceCoResponsePdu) { return((rpcePdu as RpceCoResponsePdu).call_id); } else if (rpcePdu is RpceCoFaultPdu) { return((rpcePdu as RpceCoFaultPdu).call_id); } if (rpcePdu is RpceCoShutdownPdu) { throw new RpceDisconnectedException("Shutdown PDU received"); } throw new InvalidOperationException( string.Format("Unexpected packet type received - {0}.", rpcePdu.GetType().Name)); }
/// <summary> /// Parse the identifier of the call from the received pdu from server. /// </summary> /// <param name="rpcePdu"> /// Received pdu received from server. /// </param> /// <exception cref="RpceDisconnectedException"> /// Thrown when receive shutdown PDU. /// </exception> /// <exception cref="InvalidOperationException"> /// Thrown when receive error from server. /// </exception> /// <returns>Return the identifier of the call if success, otherwise throw an exception.</returns> private uint ParseRpcePdu(RpcePdu rpcePdu) { if (rpcePdu is RpceCoResponsePdu) { return (rpcePdu as RpceCoResponsePdu).call_id; } else if (rpcePdu is RpceCoFaultPdu) { return (rpcePdu as RpceCoFaultPdu).call_id; } if (rpcePdu is RpceCoShutdownPdu) { throw new RpceDisconnectedException("Shutdown PDU received"); } throw new InvalidOperationException( string.Format("Unexpected packet type received - {0}.", rpcePdu.GetType().Name)); }
/// <summary> /// Connect and bind to a RPCE remote host. /// </summary> /// <param name="protocolSequence"> /// A protocol sequence.<para/> /// Support ncacn_ip_tcp and ncacn_np only. /// </param> /// <param name="networkAddress"> /// A network address of RPCE remote host. /// </param> /// <param name="endpoint"> /// An endpoint that its format and content /// are associated with the protocol sequence. /// </param> /// <param name="transportCredential"> /// If connect by SMB/SMB2, it's the security credential /// used by underlayer transport (SMB/SMB2). /// If connect by TCP, this parameter is ignored. /// </param> /// <param name="interfaceId"> /// A Guid of interface_id that is binding to. /// </param> /// <param name="interfaceMajorVersion"> /// interface_major_ver that is binding to. /// </param> /// <param name="interfaceMinorVersion"> /// interface_minor_ver that is binding to. /// </param> /// <param name="securityContext"> /// A security provider. If setting to null, indicate the default authentication type NTLM is selected. /// </param> /// <param name="connectSecurityContext"> /// A security provider for connect authentication. If setting to null, indicate the default authentication type NTLM is selected. /// </param> /// <param name="authenticationLevel"> /// An authentication level. /// </param> /// <param name="supportsHeaderSign"> /// Indicates whether client supports header sign or not. /// </param> /// <param name="timeout"> /// Timeout period. /// </param> /// <exception cref="ArgumentNullException"> /// Thrown when protSeq, networkAddr or endpoint is null. /// </exception> /// <exception cref="InvalidOperationException"> /// Thrown when receive error from server. /// </exception> public virtual void Bind( string protocolSequence, string networkAddress, string endpoint, AccountCredential transportCredential, Guid interfaceId, ushort interfaceMajorVersion, ushort interfaceMinorVersion, ClientSecurityContext securityContext, ClientSecurityContext connectSecurityContext, RpceAuthenticationLevel authenticationLevel, bool supportsHeaderSign, TimeSpan timeout) { if (protocolSequence == null) { throw new ArgumentNullException("protocolSequence"); } if (networkAddress == null) { throw new ArgumentNullException("networkAddress"); } if (endpoint == null) { throw new ArgumentNullException("endpoint"); } // RPC over named-pipe does not support asynchronous call in this library. // http://msdn.microsoft.com/en-us/library/windows/desktop/aa373551(v=vs.85).aspx rpceClient.Context.IsAsynchronous = (string.Compare(protocolSequence, RpceUtility.RPC_OVER_NAMED_PIPE_PROTOCOL_SEQUENCE, true) != 0); rpceClient.Connect(protocolSequence, networkAddress, endpoint, transportCredential, timeout, connectSecurityContext == null ? SecurityPackageType.Ntlm : connectSecurityContext.PackageType); rpceClient.SetAuthInfo(securityContext, authenticationLevel, rpceClient.Context.AuthenticationContextId); RpceCoBindPdu bindPdu = rpceClient.CreateCoBindPdu( //read from context, donot hardcode. rpceClient.Context.RpcVersionMinor, // default is rpc vers 5.0 supportsHeaderSign ? RpceCoPfcFlags.PFC_SUPPORT_HEADER_SIGN : RpceCoPfcFlags.None, rpceClient.ComputeNextCallId(), // call id, default is 1 rpceClient.Context.MaxTransmitFragmentSize, // max xmit frag rpceClient.Context.MaxReceiveFragmentSize, // max recv frag rpceClient.Context.AssociateGroupId, // assoc group id, default 0 interfaceId, interfaceMajorVersion, interfaceMinorVersion, rpceClient.Context.NdrVersion, // default is NDR (rpceClient.Context.BindTimeFeatureNegotiationBitmask != RpceBindTimeFeatureNegotiationBitmask.None) // default is None ? (RpceBindTimeFeatureNegotiationBitmask?)rpceClient.Context.BindTimeFeatureNegotiationBitmask : null); FragmentAndSendPdu(bindPdu); RpcePdu receivedPdu = ReceiveAndReassemblePdu(timeout); if (receivedPdu is RpceCoBindAckPdu) { if (rpceClient.Context.NdrVersion == RpceNdrVersion.None) { throw new InvalidOperationException("Neither NDR nor NDR64 is supported."); } } else { RpceCoBindNakPdu bindNakPdu = receivedPdu as RpceCoBindNakPdu; if (bindNakPdu != null) { throw new InvalidOperationException(bindNakPdu.provider_reject_reason.ToString()); } else { throw new InvalidOperationException( string.Format("Unexpected packet type received - {0}.", receivedPdu.GetType().Name)); } } while (rpceClient.Context.SecurityContext != null && rpceClient.Context.SecurityContext.NeedContinueProcessing) { RpceCoAlterContextPdu alterContextPdu = rpceClient.CreateCoAlterContextPdu(); FragmentAndSendPdu(alterContextPdu); receivedPdu = ReceiveAndReassemblePdu(timeout); RpceCoFaultPdu faultPdu = receivedPdu as RpceCoFaultPdu; if (faultPdu != null) { throw new InvalidOperationException(faultPdu.status.ToString()); } if (!(receivedPdu is RpceCoAlterContextRespPdu)) { throw new InvalidOperationException("Expect alter_context_pdu, but received others."); } } if (rpceClient.Context.SecurityContext != null && rpceClient.Context.SecurityContext.Token != null && rpceClient.Context.SecurityContext.Token.Length != 0) { RpceCoAuth3Pdu auth3Pdu = rpceClient.CreateCoAuth3Pdu(); FragmentAndSendPdu(auth3Pdu); // no expected response from server rpceClient.Context.OutstandingCalls.Remove(auth3Pdu.call_id); } if (rpceClient.Context.IsAsynchronous) { // Start the receiving thread to receive the response from server. cancellationToken = new CancellationTokenSource(); receiveTask = new Task(EventLoop, cancellationToken.Token); //new Thread(new ThreadStart(EventLoop)); //receiveThread.IsBackground = true; receiveTask.Start(); } }