/// <summary> /// Calling this method to be notified when a new RPC connection is coming. /// Users, who don't care about the coming of a new connection, just call ExpectCall directly. /// </summary> /// <param name="ifId"> /// If_id to accept the bind. Null to accept all interface regardless the if_id. /// </param> /// <param name="ifMajorVer"> /// If_major_ver to accept the bind. Null to accept all interface regardless the if_major_ver. /// </param> /// <param name="ifMinorVer"> /// If_minor_ver to accept the bind. Null to accept all interface regardless the if_minor_ver. /// </param> /// <param name="timeout">Timeout of expecting a connection.</param> /// <param name="sessionContext">The sessionContext of binded connection.</param> /// <exception cref="InvalidOperationException"> /// Thrown when receive error from server. /// </exception> /// <exception cref="InvalidOperationException"> /// Thrown when securityProvider is null and auth_level is not NONE /// </exception> /// <exception cref="SspiException"> /// Thrown when accept client token failed /// </exception> public virtual void ExpectBind( Guid?ifId, ushort?ifMajorVer, ushort?ifMinorVer, TimeSpan timeout, out RpceServerSessionContext sessionContext) { if (this.registeredInterfaceList.Count > 0) { throw new InvalidOperationException("Auto accept bind was turned on, ExpectBind is not allowed."); } DateTime t0 = DateTime.Now; sessionContext = rpceServer.ExpectConnect(timeout); RpcIfMatchFunc matchFunc = delegate(RpcIf rpcIf) { return(!((ifId != null && rpcIf.id != ifId.Value) || (ifMajorVer != null && rpcIf.majorVer != ifMajorVer.Value) || (ifMinorVer != null && rpcIf.minorVer != ifMinorVer.Value))); }; while (!InternalExpectBind(matchFunc, timeout - (DateTime.Now - t0), ref sessionContext)) { if ((DateTime.Now - t0) >= timeout) { throw new TimeoutException(); } } }
/// <summary> /// Calling this method to be notified when a new RPC connection is coming. /// </summary> /// <param name="ifMatchFunc">Matching function.</param> /// <param name="timeout">Timeout of expecting a connection.</param> /// <param name="sessionContext">The sessionContext of binded connection.</param> /// <returns>If bind succeeded, return true; otherwise, false.</returns> private bool InternalExpectBind( RpcIfMatchFunc ifMatchFunc, TimeSpan timeout, ref RpceServerSessionContext sessionContext) { RpcePdu receivedPdu = ReceiveAndReassemblePdu(timeout, ref sessionContext); RpceCoBindPdu bindPdu = receivedPdu as RpceCoBindPdu; if (bindPdu == null) { throw new InvalidOperationException("Expect bind_pdu, but received others."); } RpcIf rpcIf = new RpcIf(sessionContext.InterfaceId, sessionContext.InterfaceMajorVersion, sessionContext.InterfaceMinorVersion); if (!ifMatchFunc(rpcIf)) { // Interface doesn't match, response BindNak RpceCoBindNakPdu bindNakPdu = rpceServer.CreateCoBindNakPdu(sessionContext, p_reject_reason_t.REASON_NOT_SPECIFIED, null); FragmentAndSendPdu(sessionContext, bindNakPdu); return(false); } RpceCoBindAckPdu bindAckPdu = rpceServer.CreateCoBindAckPdu(sessionContext); FragmentAndSendPdu(sessionContext, bindAckPdu); while (sessionContext.SecurityContext != null && sessionContext.SecurityContextNeedContinueProcessing) { receivedPdu = ReceiveAndReassemblePdu(timeout, ref sessionContext); RpceCoAlterContextPdu alterContextPdu = receivedPdu as RpceCoAlterContextPdu; RpceCoAuth3Pdu auth3Pdu = receivedPdu as RpceCoAuth3Pdu; if (alterContextPdu != null) { RpceCoAlterContextRespPdu alterContextRespPdu = rpceServer.CreateCoAlterContextRespPdu(sessionContext); FragmentAndSendPdu(sessionContext, alterContextRespPdu); } else if (auth3Pdu != null) { //Do nothing } } return(true); }
/// <summary> /// Receive and reassemble PDU. /// </summary> /// <param name="timeout">Timeout of receiving PDU</param> /// <param name="sessionContext">Context of the RPCE session</param> /// <returns>Received PDU</returns> private RpcePdu ReceiveAndReassemblePdu( TimeSpan timeout, ref RpceServerSessionContext sessionContext) { RpcePdu receivedPdu; bool expectAny = sessionContext == null; WaitForEvent: if (expectAny) { sessionContext = null; } EventType eventType = rpceServer.ExpectEvent(timeout, ref sessionContext, out receivedPdu); if (this.registeredInterfaceList.Count > 0) { // auto accept connect/bind/disconnect if (eventType == EventType.Connected) { RpcIfMatchFunc matchFunc = delegate(RpcIf rpcIf) { for (int i = 0; i < this.registeredInterfaceList.Count; i++) { if (this.registeredInterfaceList[i].Equals(rpcIf)) { return(true); } } return(false); }; InternalExpectBind(matchFunc, timeout, ref sessionContext); goto WaitForEvent; } else if (eventType == EventType.Disconnected) { goto WaitForEvent; } else { // it is a PDU. } } else if (eventType != EventType.ReceivedPacket) { throw new InvalidOperationException( string.Format("Unexpected event ({0}) received.", eventType)); } RpceCoPdu receivedCoPdu = receivedPdu as RpceCoPdu; if (receivedCoPdu == null) { return(receivedPdu); } List <RpceCoPdu> pduList = new List <RpceCoPdu>(); pduList.Add(receivedCoPdu); while ((receivedCoPdu.pfc_flags & RpceCoPfcFlags.PFC_LAST_FRAG) == 0) { receivedPdu = rpceServer.ExpectPdu(timeout, ref sessionContext); receivedCoPdu = receivedPdu as RpceCoPdu; if (receivedCoPdu == null) { throw new InvalidOperationException("CL PDU received inside a connection."); } pduList.Add(receivedCoPdu); } return(RpceUtility.ReassemblePdu(sessionContext, pduList.ToArray())); }
/// <summary> /// Calling this method to be notified when a new RPC connection is coming. /// </summary> /// <param name="ifMatchFunc">Matching function.</param> /// <param name="timeout">Timeout of expecting a connection.</param> /// <param name="sessionContext">The sessionContext of binded connection.</param> /// <returns>If bind succeeded, return true; otherwise, false.</returns> private bool InternalExpectBind( RpcIfMatchFunc ifMatchFunc, TimeSpan timeout, ref RpceServerSessionContext sessionContext) { RpcePdu receivedPdu = ReceiveAndReassemblePdu(timeout, ref sessionContext); RpceCoBindPdu bindPdu = receivedPdu as RpceCoBindPdu; if (bindPdu == null) { throw new InvalidOperationException("Expect bind_pdu, but received others."); } RpcIf rpcIf = new RpcIf(sessionContext.InterfaceId, sessionContext.InterfaceMajorVersion, sessionContext.InterfaceMinorVersion); if (!ifMatchFunc(rpcIf)) { // Interface doesn't match, response BindNak RpceCoBindNakPdu bindNakPdu = rpceServer.CreateCoBindNakPdu(sessionContext, p_reject_reason_t.REASON_NOT_SPECIFIED, null); FragmentAndSendPdu(sessionContext, bindNakPdu); return false; } RpceCoBindAckPdu bindAckPdu = rpceServer.CreateCoBindAckPdu(sessionContext); FragmentAndSendPdu(sessionContext, bindAckPdu); while (sessionContext.SecurityContext != null && sessionContext.SecurityContextNeedContinueProcessing) { receivedPdu = ReceiveAndReassemblePdu(timeout, ref sessionContext); RpceCoAlterContextPdu alterContextPdu = receivedPdu as RpceCoAlterContextPdu; RpceCoAuth3Pdu auth3Pdu = receivedPdu as RpceCoAuth3Pdu; if (alterContextPdu != null) { RpceCoAlterContextRespPdu alterContextRespPdu = rpceServer.CreateCoAlterContextRespPdu(sessionContext); FragmentAndSendPdu(sessionContext, alterContextRespPdu); } else if (auth3Pdu != null) { //Do nothing } } return true; }