1 // This source code is dual-licensed under the Apache License, version
2 // 2.0, and the Mozilla Public License, version 1.1.
6 //---------------------------------------------------------------------------
7 // Copyright (C) 2007, 2008 LShift Ltd., Cohesive Financial
8 // Technologies LLC., and Rabbit Technologies Ltd.
10 // Licensed under the Apache License, Version 2.0 (the "License");
11 // you may not use this file except in compliance with the License.
12 // You may obtain a copy of the License at
14 // http://www.apache.org/licenses/LICENSE-2.0
16 // Unless required by applicable law or agreed to in writing, software
17 // distributed under the License is distributed on an "AS IS" BASIS,
18 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 // See the License for the specific language governing permissions and
20 // limitations under the License.
21 //---------------------------------------------------------------------------
25 //---------------------------------------------------------------------------
26 // The contents of this file are subject to the Mozilla Public License
27 // Version 1.1 (the "License"); you may not use this file except in
28 // compliance with the License. You may obtain a copy of the License at
29 // http://www.rabbitmq.com/mpl.html
31 // Software distributed under the License is distributed on an "AS IS"
32 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
33 // License for the specific language governing rights and limitations
36 // The Original Code is The RabbitMQ .NET Client.
38 // The Initial Developers of the Original Code are LShift Ltd.,
39 // Cohesive Financial Technologies LLC., and Rabbit Technologies Ltd.
41 // Portions created by LShift Ltd., Cohesive Financial Technologies
42 // LLC., and Rabbit Technologies Ltd. are Copyright (C) 2007, 2008
43 // LShift Ltd., Cohesive Financial Technologies LLC., and Rabbit
46 // All Rights Reserved.
48 // Contributor(s): ______________________________________.
50 //---------------------------------------------------------------------------
55 using RabbitMQ.Client.Exceptions;
57 // We use spec version 0-9 for common constants such as frame types,
58 // error codes, and the frame end byte, since they don't vary *within
59 // the versions we support*. Obviously we may need to revisit this if
61 using CommonFraming = RabbitMQ.Client.Framing.v0_9;
63 namespace RabbitMQ.Client.Impl
69 public byte[] m_payload;
71 public int Type { get { return m_type; } }
72 public int Channel { get { return m_channel; } }
73 public byte[] Payload { get { return m_payload; } }
75 public MemoryStream m_accumulator;
79 public Frame(int type, int channel)
84 m_accumulator = new MemoryStream();
87 public Frame(int type, int channel, byte[] payload)
95 public static Frame ReadFrom(NetworkBinaryReader reader)
100 type = reader.ReadByte();
104 // Probably an AMQP protocol header, otherwise meaningless
105 ProcessProtocolHeader(reader);
108 channel = reader.ReadUInt16();
109 int payloadSize = reader.ReadInt32(); // FIXME - throw exn on unreasonable value
110 byte[] payload = reader.ReadBytes(payloadSize);
111 if (payload.Length != payloadSize)
114 throw new MalformedFrameException("Short frame - expected " +
115 payloadSize + " bytes, got " +
116 payload.Length + " bytes");
119 int frameEndMarker = reader.ReadByte();
120 if (frameEndMarker != CommonFraming.Constants.FrameEnd)
122 throw new MalformedFrameException("Bad frame end marker: " + frameEndMarker);
125 return new Frame(type, channel, payload);
128 public static void ProcessProtocolHeader(NetworkBinaryReader reader)
132 byte b1 = reader.ReadByte();
133 byte b2 = reader.ReadByte();
134 byte b3 = reader.ReadByte();
135 if (b1 != 'M' || b2 != 'Q' || b3 != 'P')
137 throw new MalformedFrameException("Invalid AMQP protocol header from server");
140 int transportHigh = reader.ReadByte();
141 int transportLow = reader.ReadByte();
142 int serverMajor = reader.ReadByte();
143 int serverMinor = reader.ReadByte();
144 throw new PacketNotRecognizedException(transportHigh,
149 catch (EndOfStreamException)
151 // Ideally we'd wrap the EndOfStreamException in the
152 // MalformedFrameException, but unfortunately the
153 // design of MalformedFrameException's superclass,
154 // ProtocolViolationException, doesn't permit
155 // this. Fortunately, the call stack in the
156 // EndOfStreamException is largely irrelevant at this
157 // point, so can safely be ignored.
158 throw new MalformedFrameException("Invalid AMQP protocol header from server");
162 public void FinishWriting()
164 if (m_accumulator != null)
166 m_payload = m_accumulator.ToArray();
167 m_accumulator = null;
171 public void WriteTo(NetworkBinaryWriter writer)
174 writer.Write((byte)m_type);
175 writer.Write((ushort)m_channel);
176 writer.Write((uint)m_payload.Length);
177 writer.Write((byte[])m_payload);
178 writer.Write((byte)CommonFraming.Constants.FrameEnd);
181 public NetworkBinaryReader GetReader()
183 return new NetworkBinaryReader(new MemoryStream(m_payload));
186 public NetworkBinaryWriter GetWriter()
188 return new NetworkBinaryWriter(m_accumulator);
191 public override string ToString()
193 return base.ToString() + string.Format("(type={0}, channel={1}, {2} bytes of payload)",
198 : Payload.Length.ToString());