/// <summary> /// adds a fragment to the combined message. /// </summary> /// <returns>the fragment description for the message</returns> private FragmentedMsgDesc AddFragmentInternal(Stream fragment, bool isLastFragment) { CdrInputStreamImpl cdrInput = new CdrInputStreamImpl(fragment); GiopHeader header = new GiopHeader(cdrInput); CheckGiop1_2OrLater(header); // GIOP 1.2 or newer: read request id from fragment msg header uint reqId = cdrInput.ReadULong(); int payLoadLength = (int)(header.ContentMsgLength - 4); lock (m_fragmentedMsgs.SyncRoot) { FragmentedMsgDesc fragmentDesc = (FragmentedMsgDesc)m_fragmentedMsgs[reqId]; if (fragmentDesc == null) { throw new IOException("illegal fragment; not found previous fragment for request-id: " + reqId); } if (!isLastFragment) { fragmentDesc.AddFragment(cdrInput, payLoadLength); } else { fragmentDesc.AddLastFragment(cdrInput, payLoadLength); // remove the desc for unfinished msg from table m_fragmentedMsgs.Remove(reqId); } return(fragmentDesc); } }
internal Stream FinishFragmentedMsg(Stream fragment, out GiopHeader combinedHeader) { FragmentedMsgDesc result = AddFragmentInternal(fragment, true); combinedHeader = result.CombinedHeader; return(result.Target); }
/// <summary> /// begins receiving a new message from transport; can be called again, after message has been completed. /// </summary> public void StartReceiveMessage() { m_messageToReceive = new MemoryStream(); m_header = null; m_expectedMessageLength = GiopHeader.HEADER_LENGTH; // giop header-length m_bytesRead = 0; StartReceiveNextMessagePart(); }
internal FragmentedMsgDesc(CdrInputStreamImpl firstFragment, int nrOfBytesFromCurrentPos, GiopHeader header, uint reqId) { m_target = new MemoryStream(); m_header = header; CdrOutputStream outputStream = header.WriteToStream(m_target, (uint)nrOfBytesFromCurrentPos); // place-holder header outputStream.WriteULong(reqId); // add req-id, because already read AddFragment(firstFragment, nrOfBytesFromCurrentPos); }
/// <summary> /// create a close connection message /// </summary> /// <param name="version"></param> /// <returns></returns> private Stream PrepareMessageCloseMessage(GiopVersion version) { Debug.WriteLine("create a close connection message"); Stream targetStream = new MemoryStream(); GiopHeader header = new GiopHeader(version.Major, version.Minor, m_headerFlags, GiopMsgTypes.CloseConnection); header.WriteToStream(targetStream, 0); targetStream.Seek(0, SeekOrigin.Begin); return(targetStream); }
private void CheckGiop1_2OrLater(GiopHeader header) { if (header.Version.IsBeforeGiop1_2()) { // for giop 1.0 fragmentation is not allowed // for giop 1.1 fragmentation is not supported by IIOP.NET, because defragmentation // is not possible without complete demarshalling Debug.WriteLine("fragment using giop version " + header.Version + " not supported by IIOP.NET / not allowed"); throw new IOException("fragmentation not supported for 1.0/1.1"); } }
/// <summary> /// extracts the request id from a non-fragmented reply message /// </summary> /// <param name="replyMessage"></param> private uint ExtractRequestIdFromReplyMessage(Stream replyMessage) { replyMessage.Seek(0, SeekOrigin.Begin); CdrInputStreamImpl reader = new CdrInputStreamImpl(replyMessage); GiopHeader msgHeader = new GiopHeader(reader); if (msgHeader.Version.IsBeforeGiop1_2()) { // GIOP 1.0 / 1.1, the service context collection preceeds the id SkipServiceContexts(reader); } return(reader.ReadULong()); }
internal void AddLastFragment(CdrInputStreamImpl fragmentToAdd, int nrOfBytesFromCurrentPos) { AddFragment(fragmentToAdd, nrOfBytesFromCurrentPos); // write adapted header m_target.Seek(0, SeekOrigin.Begin); m_newHeader = new GiopHeader(Header.Version.Major, Header.Version.Minor, (byte)(Header.GiopFlags ^ GiopHeader.FRAGMENT_MASK), Header.GiopType); m_newHeader.WriteToStream(m_target, ((uint)m_target.Length) - GiopHeader.HEADER_LENGTH); m_target.Seek(0, SeekOrigin.Begin); }
/// <summary>Start a new fragmented msg</summary> internal void StartFragment(Stream fragment) { CdrInputStreamImpl cdrInput = new CdrInputStreamImpl(fragment); GiopHeader header = new GiopHeader(cdrInput); CheckGiop1_2OrLater(header); // GIOP 1.2 or newer: read request id from msg; for giop 1.2, the requestId follows just // after the header for request, reply, locateRequest and locateReply; only those messages // can be fragmented uint reqId = cdrInput.ReadULong(); int payLoadLength = (int)(header.ContentMsgLength - 4); lock (m_fragmentedMsgs.SyncRoot) { FragmentedMsgDesc fragmentDesc = new FragmentedMsgDesc(cdrInput, payLoadLength, header, reqId); m_fragmentedMsgs[reqId] = fragmentDesc; } }
private void HandleReadCompleted(IAsyncResult ar) { try { int read = m_onTransport.EndRead(ar); if (read <= 0) { // connection has been closed by the other end m_messageHandler.MsgReceivedConnectionClosedException(); return; } int offset = m_bytesRead; m_bytesRead += read; // copy to message stream m_messageToReceive.Write(m_buffer, 0, read); // handle header if (m_header == null) { // copy to giop-header buffer Array.Copy(m_buffer, 0, m_giopHeaderBuffer, offset, read); if (m_bytesRead == 12) { m_header = new GiopHeader(m_giopHeaderBuffer); m_expectedMessageLength = (int)(m_expectedMessageLength + m_header.ContentMsgLength); } } if (HasNextMessagePart()) { StartReceiveNextMessagePart(); } else { // completed m_messageToReceive.Seek(0, SeekOrigin.Begin); m_messageHandler.MsgReceivedCallback(this); } } catch (Exception ex) { m_messageHandler.MsgReceivedCallbackException(ex); } }
internal static bool IsStartFragment(GiopHeader header) { return(header.GiopType != GiopMsgTypes.Fragment); }
/// <summary> /// create a close connection message /// </summary> /// <param name="version"></param> /// <returns></returns> private Stream PrepareMessageCloseMessage(GiopVersion version) { Debug.WriteLine("create a close connection message"); Stream targetStream = new MemoryStream(); GiopHeader header = new GiopHeader(version.Major, version.Minor, m_headerFlags, GiopMsgTypes.CloseConnection); header.WriteToStream(targetStream, 0); targetStream.Seek(0, SeekOrigin.Begin); return targetStream; }
internal void MsgReceivedCallback(MessageReceiveTask messageReceived) { Stream messageStream = messageReceived.MessageStream; GiopHeader header = messageReceived.Header; if (FragmentedMessageAssembler.IsFragmentedMessage(header)) { // defragment if (FragmentedMessageAssembler.IsStartFragment(header)) { m_fragmentAssembler.StartFragment(messageStream); messageReceived.StartReceiveMessage(); // receive next message return; // wait for next callback } else if (!FragmentedMessageAssembler.IsLastFragment(header)) { m_fragmentAssembler.AddFragment(messageStream); messageReceived.StartReceiveMessage(); // receive next message return; // wait for next callback } else { messageStream = m_fragmentAssembler.FinishFragmentedMsg(messageStream, out header); } } // here, the message is no longer fragmented, don't check for fragment here switch (header.GiopType) { case GiopMsgTypes.Request: ProcessRequestMessage(messageStream, messageReceived); // process this message // don't receive next message here, new message reception is started by dispatcher at appropriate time break; case GiopMsgTypes.LocateRequest: ProcessLocateRequestMessage(messageStream, messageReceived); // process this message // don't receive next message here, new message reception is started by dispatcher at appropriate time break; case GiopMsgTypes.Reply: // see, if somebody is interested in the response lock (m_waitingForResponse.SyncRoot) { uint replyForRequestId = ExtractRequestIdFromReplyMessage(messageStream); IResponseWaiter waiter = (IResponseWaiter)m_waitingForResponse[replyForRequestId]; if (waiter != null) { m_waitingForResponse.Remove(replyForRequestId); waiter.Response = messageStream; waiter.Notify(); } else { Debug.WriteLine("received not expected reply for request with id " + replyForRequestId); } } messageReceived.StartReceiveMessage(); // receive next message break; case GiopMsgTypes.LocateReply: // ignore, not interesting messageReceived.StartReceiveMessage(); // receive next message break; case GiopMsgTypes.CloseConnection: CloseConnection(); AbortAllPendingRequestsWaiting(); // if requests are waiting for a reply, abort them RaiseConnectionClosedEvent(); // inform about connection closure break; case GiopMsgTypes.CancelRequest: CdrInputStreamImpl input = new CdrInputStreamImpl(messageStream); GiopHeader cancelHeader = new GiopHeader(input); uint requestIdToCancel = input.ReadULong(); m_fragmentAssembler.CancelFragmentsIfInProgress(requestIdToCancel); messageReceived.StartReceiveMessage(); // receive next message break; case GiopMsgTypes.MessageError: CloseConnectionAfterUnexpectedException(new MARSHAL(16, CompletionStatus.Completed_MayBe)); AbortAllPendingRequestsWaiting(); // if requests are waiting for a reply, abort them RaiseConnectionClosedEvent(); // inform about connection closure break; default: // should not occur; // hint: fragment is also considered as error here, // because fragment should be handled before this loop // send message error SendErrorResponseMessage(); messageReceived.StartReceiveMessage(); // receive next message break; } }
internal Stream FinishFragmentedMsg(Stream fragment, out GiopHeader combinedHeader) { FragmentedMsgDesc result = AddFragmentInternal(fragment, true); combinedHeader = result.CombinedHeader; return result.Target; }
/// <summary> /// extracts the request id from a non-fragmented reply message /// </summary> /// <param name="replyMessage"></param> private uint ExtractRequestIdFromReplyMessage(Stream replyMessage) { replyMessage.Seek(0, SeekOrigin.Begin); CdrInputStreamImpl reader = new CdrInputStreamImpl(replyMessage); GiopHeader msgHeader = new GiopHeader(reader); if (msgHeader.Version.IsBeforeGiop1_2()) { // GIOP 1.0 / 1.1, the service context collection preceeds the id SkipServiceContexts(reader); } return reader.ReadULong(); }
private uint AddFinishFragment(CdrOutputStreamImpl targetStream, GiopVersion version, byte endianFlags, uint reqId, uint reqContentLength, uint offsetInMsg) { byte giopFlags = endianFlags; // no more fragments GiopHeader fragmentHeader = new GiopHeader(version.Major, version.Minor, endianFlags, GiopMsgTypes.Request); uint contentLength = 0; if (!((version.Major == 1) && (version.Minor <= 1))) { // GIOP 1.2 contentLength = 4 + reqContentLength; } else { contentLength = reqContentLength; } fragmentHeader.WriteToStream(targetStream, contentLength); if (!((version.Major == 1) && (version.Minor <= 1))) { // GIOP 1.2 targetStream.WriteULong(reqId); } // more is not needed to write a correct GIOP-message for this test from here for (uint i = offsetInMsg; i < (offsetInMsg + reqContentLength); i++) { targetStream.WriteOctet((byte)(i % 255)); } return offsetInMsg + reqContentLength; }
/// <param name="expectedContentLength">length in bytes after the request-id</param> private void CheckAssembledMessage(Stream msgStream, GiopVersion version, byte endianFlags, uint reqId, uint expectedContentLength) { CdrInputStreamImpl inStream = new CdrInputStreamImpl(msgStream); GiopHeader header = new GiopHeader(inStream); Assert.AreEqual(GiopMsgTypes.Request, header.GiopType); Assert.AreEqual(version, header.Version); uint contentLength = 0; uint msgReqId = 0; if (!((version.Major == 1) && (version.Minor <= 1))) { // GIOP 1.2 // req-id contentLength = (uint)(4 + expectedContentLength); msgReqId = inStream.ReadULong(); } else { // svc-cntx + req-id contentLength = (uint)(8 + expectedContentLength); inStream.ReadULong(); // svc-cnxt msgReqId = inStream.ReadULong(); } Assert.AreEqual(contentLength, header.ContentMsgLength); Assert.AreEqual(endianFlags, header.GiopFlags); for (int i = 0; i < expectedContentLength; i++) { Assert.AreEqual(i % 255, inStream.ReadOctet()); } }
internal static bool IsLastFragment(GiopHeader header) { return (header.GiopType == GiopMsgTypes.Fragment) && (!header.IsFragmentedBitSet()); }
/// <param name="fragmentContentBlocks">the nr of 4 byte blocks in the content; /// must be even for GIOP 1.2</param> private CdrOutputStreamImpl AddStartMsg(Stream targetStream, GiopVersion version, byte endianFlags, uint reqId, uint fragmentContentBlocks, out uint offsetInMsg) { byte giopFlags = (byte)(endianFlags | ((byte)2)); // more fragments CdrOutputStreamImpl cdrOut = new CdrOutputStreamImpl(targetStream, endianFlags, version); GiopHeader startHeader = new GiopHeader(version.Major, version.Minor, giopFlags, GiopMsgTypes.Request); uint contentLength = 0; if (!((version.Major == 1) && (version.Minor <= 1))) { // GIOP 1.2 contentLength = (uint)(4 + (fragmentContentBlocks * 4)); } else { contentLength = (uint)(8 + (fragmentContentBlocks * 4)); } startHeader.WriteToStream(cdrOut, contentLength); if ((version.Major == 1) && (version.Minor == 1)) { // GIOP 1.1: add service context list here cdrOut.WriteULong(0); // no contexts } cdrOut.WriteULong(reqId); // request id // more is not needed to write a correct GIOP-message for this test from here for (uint i = 0; i < fragmentContentBlocks * 4; i++) { cdrOut.WriteOctet((byte)(i % 255)); } offsetInMsg = fragmentContentBlocks * 4; return cdrOut; }
/// <summary> /// adds a fragment to the combined message. /// </summary> /// <returns>the fragment description for the message</returns> private FragmentedMsgDesc AddFragmentInternal(Stream fragment, bool isLastFragment) { CdrInputStreamImpl cdrInput = new CdrInputStreamImpl(fragment); GiopHeader header = new GiopHeader(cdrInput); CheckGiop1_2OrLater(header); // GIOP 1.2 or newer: read request id from fragment msg header uint reqId = cdrInput.ReadULong(); int payLoadLength = (int)(header.ContentMsgLength - 4); lock(m_fragmentedMsgs.SyncRoot) { FragmentedMsgDesc fragmentDesc = (FragmentedMsgDesc) m_fragmentedMsgs[reqId]; if (fragmentDesc == null) { throw new IOException("illegal fragment; not found previous fragment for request-id: " + reqId); } if (!isLastFragment) { fragmentDesc.AddFragment(cdrInput, payLoadLength); } else { fragmentDesc.AddLastFragment(cdrInput, payLoadLength); // remove the desc for unfinished msg from table m_fragmentedMsgs.Remove(reqId); } return fragmentDesc; } }
/// <summary>checks, if the message is only a fragment; non-legal fragmentted messages are not discovered here. /// Only the fragmented or not fact is considered</summary> internal static bool IsFragmentedMessage(GiopHeader header) { return((header.GiopType == GiopMsgTypes.Fragment) || header.IsFragmentedBitSet()); }
internal static bool IsLastFragment(GiopHeader header) { return((header.GiopType == GiopMsgTypes.Fragment) && (!header.IsFragmentedBitSet())); }
/// <summary>checks, if the message is only a fragment; non-legal fragmentted messages are not discovered here. /// Only the fragmented or not fact is considered</summary> internal static bool IsFragmentedMessage(GiopHeader header) { return ((header.GiopType == GiopMsgTypes.Fragment) || header.IsFragmentedBitSet()); }
/// <summary>Start a new fragmented msg</summary> internal void StartFragment(Stream fragment) { CdrInputStreamImpl cdrInput = new CdrInputStreamImpl(fragment); GiopHeader header = new GiopHeader(cdrInput); CheckGiop1_2OrLater(header); // GIOP 1.2 or newer: read request id from msg; for giop 1.2, the requestId follows just // after the header for request, reply, locateRequest and locateReply; only those messages // can be fragmented uint reqId = cdrInput.ReadULong(); int payLoadLength = (int)(header.ContentMsgLength - 4); lock(m_fragmentedMsgs.SyncRoot) { FragmentedMsgDesc fragmentDesc = new FragmentedMsgDesc(cdrInput, payLoadLength, header, reqId); m_fragmentedMsgs[reqId] = fragmentDesc; } }
internal static bool IsStartFragment(GiopHeader header) { return header.GiopType != GiopMsgTypes.Fragment; }