/// <summary>serialises an outgoing .NET reply Message on server side</summary> internal void SerialiseOutgoingReplyMessage(IMessage replyMsg, IMessage requestMsg, GiopVersion version, Stream targetStream, GiopConnectionDesc conDesc) { if (replyMsg is ReturnMessage) { // write a CORBA response message into the stream targetStream GiopHeader header = new GiopHeader(version.Major, version.Minor, m_headerFlags, GiopMsgTypes.Reply); CdrMessageOutputStream msgOutput = new CdrMessageOutputStream(targetStream, header); GiopServerRequest request = new GiopServerRequest(requestMsg, (ReturnMessage)replyMsg, conDesc, m_interceptionOptions); // serialize the message m_ser.SerialiseReply(request, msgOutput.GetMessageContentWritingStream(), version, conDesc); msgOutput.CloseStream(); // write to the stream } else { throw new NotImplementedException("handling for this type of .NET message is not implemented at the moment, type: " + replyMsg.GetType()); } }
private void SerialiseResponseOk(CdrOutputStream targetStream, GiopServerRequest request, GiopVersion version) { // reply body // clarification form CORBA 2.6, chapter 15.4.2: no padding, when no arguments are serialised --> // for backward compatibility, do it nevertheless AlignBodyIfNeeded(targetStream, version); // marshal the parameters ArgumentsSerializer ser = m_argSerFactory.Create(request.CalledMethod.DeclaringType); ser.SerializeResponseArgs(request.RequestMethodName, request.ReturnValue, request.OutArgs, targetStream); }
/// <summary>serialize the GIOP message body of a repsonse message</summary> /// <param name="requestId">the requestId of the request, this response belongs to</param> internal void SerialiseReply(GiopServerRequest request, CdrOutputStream targetStream, GiopVersion version, GiopConnectionDesc conDesc) { Trace.WriteLine("serializing response for method: " + request.GetRequestedMethodNameInternal()); try { bool isExceptionReply = request.IsExceptionReply; Exception exceptionToSend = null; try { request.SetRequestPICurrentFromThreadScopeCurrent(); // copy from thread scope picurrent after processing request by servant // reply interception point if (!request.IsExceptionReply) { request.InterceptSendReply(); } else { exceptionToSend = request.InterceptSendException(request.IdlException); } } catch (Exception ex) { // update the reply with the exception from interception layer isExceptionReply = true; if (SerialiseAsSystemException(ex)) { exceptionToSend = ex; } else { exceptionToSend = new UNKNOWN(300, CompletionStatus.Completed_MayBe); } } ServiceContextList cntxColl = request.ResponseServiceContext; SetCodeSet(targetStream, conDesc); if (version.IsBeforeGiop1_2()) { // for GIOP 1.0 / 1.1 SerialiseContext(targetStream, cntxColl); // serialize the context } targetStream.WriteULong(request.RequestId); if (!isExceptionReply) { Trace.WriteLine("sending normal response to client"); targetStream.WriteULong(0); // reply status ok if (!version.IsBeforeGiop1_2()) { // for GIOP 1.2 and later, service context is here SerialiseContext(targetStream, cntxColl); // serialize the context } // serialize a response to a successful request SerialiseResponseOk(targetStream, request, version); Trace.WriteLine("reply body serialised"); } else { Trace.WriteLine("excpetion to send to client: " + exceptionToSend.GetType()); if (SerialiseAsSystemException(exceptionToSend)) { targetStream.WriteULong(2); // system exception } else if (SerialiseAsUserException(exceptionToSend)) { targetStream.WriteULong(1); // user exception } else { // should not occur targetStream.WriteULong(2); exceptionToSend = new INTERNAL(204, CompletionStatus.Completed_Yes); } if (!version.IsBeforeGiop1_2()) { // for GIOP 1.2 and later, service context is here SerialiseContext(targetStream, cntxColl); // serialize the context } AlignBodyIfNeeded(targetStream, version); if (SerialiseAsSystemException(exceptionToSend)) { SerialiseSystemException(targetStream, exceptionToSend); } else { SerialiseUserException(targetStream, (AbstractUserException)exceptionToSend); } Trace.WriteLine("exception reply serialised"); } } finally { request.ClearThreadScopePICurrent(); // no longer needed, clear afterwards to prevent access to stale data during next requests } }
/// <summary>deserialise the request body</summary> /// <param name="contextElements">the deserialised context elements, if any or null</param> private void DeserialiseRequestBody(CdrInputStream cdrStream, GiopVersion version, GiopServerRequest request, ArgumentsSerializer ser, out IDictionary contextElements) { // clarification from CORBA 2.6, chapter 15.4.1: no padding, when no arguments/no context elements // are serialised, i.e. body empty // ignores, if not enough bytes because no args/context; because in this case, no more bytes follow TryAlignBodyIfNeeded(cdrStream, version); // unmarshall parameters object[] args = ser.DeserializeRequestArgs(request.RequestMethodName, cdrStream, out contextElements); // for standard corba ops, adapt args: if (request.IsStandardCorbaOperation) { args = AdaptArgsForStandardOp(args, request.RequestUri); } request.RequestArgs = args; }
/// <summary> /// Deserialises the Giop Message body for a request /// </summary> /// <param name="cdrStream"></param> /// <param name="version"></param> /// <returns></returns> internal IMessage DeserialiseRequest(CdrInputStream cdrStream, GiopVersion version, GiopConnectionDesc conDesc, IInterceptionOption[] interceptionOptions) { MethodCall methodCallInfo = null; GiopServerRequest serverRequest = new GiopServerRequest(conDesc, interceptionOptions); serverRequest.Version = version; try { ServiceContextList cntxColl = null; if (version.IsBeforeGiop1_2()) { // GIOP 1.0 / 1.1 cntxColl = DeserialiseContext(cdrStream); // Service context deser } // read the request-ID and set it as a message property uint requestId = cdrStream.ReadULong(); serverRequest.RequestId = requestId; Trace.WriteLine("received a message with reqId: " + requestId); // read response-flags: byte respFlags = cdrStream.ReadOctet(); Debug.WriteLine("response-flags: " + respFlags); cdrStream.ReadPadding(3); // read reserved bytes serverRequest.ResponseFlags = respFlags; // decode the target of this request byte[] objectKey; serverRequest.RequestUri = ReadTarget(cdrStream, version, out objectKey); serverRequest.ObjectKey = objectKey; serverRequest.RequestMethodName = cdrStream.ReadString(); Trace.WriteLine("call for .NET object: " + serverRequest.RequestUri + ", methodName: " + serverRequest.RequestMethodName); if (version.IsBeforeGiop1_2()) { // GIOP 1.0 / 1.1 uint principalLength = cdrStream.ReadULong(); cdrStream.ReadOpaque((int)principalLength); } else { cntxColl = DeserialiseContext(cdrStream); // Service context deser } PerformCodeSetEstablishmentServer(version, conDesc, cntxColl); // set codeset for stream SetCodeSet(cdrStream, conDesc); // request header deserialised serverRequest.RequestServiceContext = cntxColl; serverRequest.InterceptReceiveRequestServiceContexts(); serverRequest.SetThreadScopeCurrentFromPICurrent(); // copy request scope picurrent to thread scope pi-current serverRequest.ResolveTargetType(); // determine the .net target object type and check if target object is available ArgumentsSerializer argSer = m_argSerFactory.Create(serverRequest.ServerTypeType); MethodInfo called = argSer.GetMethodInfoFor(serverRequest.RequestMethodName); serverRequest.ResolveCalledMethod(called); // set target method and handle special cases IDictionary contextElements; DeserialiseRequestBody(cdrStream, version, serverRequest, argSer, out contextElements); methodCallInfo = new MethodCall(serverRequest.Request); if (contextElements != null) { AddContextElementsToCallContext(methodCallInfo.LogicalCallContext, contextElements); } serverRequest.UpdateWithFinalRequest(methodCallInfo); serverRequest.InterceptReceiveRequest(); // all information now available return methodCallInfo; } catch (Exception e) { // an Exception encountered during deserialisation try { cdrStream.SkipRest(); // skip rest of the message, to not corrupt the stream } catch (Exception) { // ignore exception here, already an other exception leading to problems } ReturnMessage exceptionResponse; exceptionResponse = new ReturnMessage(e, methodCallInfo); throw new RequestDeserializationException(e, serverRequest.Request, exceptionResponse); // send exception interception point will be called when serialising exception response } }
/// <summary> /// construct a server request info based on the ServerRequest data. /// </summary> /// <remarks>delegates client requests normally to the serverRequest instance.</remarks> internal ServerRequestInfoImpl(GiopServerRequest serverRequest) : base(serverRequest) { m_serverRequest = serverRequest; }