1 // This source code is dual-licensed under the Apache License, version 2 // 2.0, and the Mozilla Public License, version 1.1. 3 // 4 // The APL v2.0: 5 // 6 //--------------------------------------------------------------------------- 7 // Copyright (C) 2007-2010 LShift Ltd., Cohesive Financial 8 // Technologies LLC., and Rabbit Technologies Ltd. 9 // 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 13 // 14 // http://www.apache.org/licenses/LICENSE-2.0 15 // 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 //--------------------------------------------------------------------------- 22 // 23 // The MPL v1.1: 24 // 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 30 // 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 34 // under the License. 35 // 36 // The Original Code is The RabbitMQ .NET Client. 37 // 38 // The Initial Developers of the Original Code are LShift Ltd, 39 // Cohesive Financial Technologies LLC, and Rabbit Technologies Ltd. 40 // 41 // Portions created before 22-Nov-2008 00:00:00 GMT by LShift Ltd, 42 // Cohesive Financial Technologies LLC, or Rabbit Technologies Ltd 43 // are Copyright (C) 2007-2008 LShift Ltd, Cohesive Financial 44 // Technologies LLC, and Rabbit Technologies Ltd. 45 // 46 // Portions created by LShift Ltd are Copyright (C) 2007-2010 LShift 47 // Ltd. Portions created by Cohesive Financial Technologies LLC are 48 // Copyright (C) 2007-2010 Cohesive Financial Technologies 49 // LLC. Portions created by Rabbit Technologies Ltd are Copyright 50 // (C) 2007-2010 Rabbit Technologies Ltd. 51 // 52 // All Rights Reserved. 53 // 54 // Contributor(s): ______________________________________. 55 // 56 //--------------------------------------------------------------------------- 57 using System; 58 59 using RabbitMQ.Client; 60 using RabbitMQ.Client.Events; 61 using RabbitMQ.Client.Exceptions; 62 63 // We use spec version 0-9 for common constants such as frame types, 64 // error codes, and the frame end byte, since they don't vary *within 65 // the versions we support*. Obviously we may need to revisit this if 66 // that ever changes. 67 using CommonFraming = RabbitMQ.Client.Framing.v0_9; 68 69 namespace RabbitMQ.Client.Impl 70 { 71 ///<summary>Small ISession implementation used only for channel 0.</summary> 72 public class MainSession: Session 73 { 74 public bool m_closing = false; 75 public int m_closeClassId; 76 public int m_closeMethodId; 77 public int m_closeOkClassId; 78 public int m_closeOkMethodId; 79 80 public bool m_closeServerInitiated; 81 82 private readonly object m_closingLock = new object(); SessionCloseDelegate()83 public delegate void SessionCloseDelegate(); 84 public SessionCloseDelegate m_handler; 85 MainSession(ConnectionBase connection)86 public MainSession(ConnectionBase connection) 87 : base(connection, 0) 88 { 89 Command request; 90 connection.Protocol.CreateConnectionClose(0,"", 91 out request, 92 out m_closeOkClassId, 93 out m_closeOkMethodId); 94 m_closeClassId = request.Method.ProtocolClassId; 95 m_closeMethodId = request.Method.ProtocolMethodId; 96 } 97 98 ///<summary> Set channel 0 as quiescing </summary> 99 ///<remarks> 100 /// Method should be idempotent. Cannot use base.Close 101 /// method call because that would prevent us from 102 /// sending/receiving Close/CloseOk commands 103 ///</remarks> SetSessionClosing(bool closeServerInitiated)104 public void SetSessionClosing(bool closeServerInitiated) 105 { 106 lock(m_closingLock) 107 { 108 if (!m_closing) 109 { 110 m_closing = true; 111 m_closeServerInitiated = closeServerInitiated; 112 } 113 } 114 } 115 116 public SessionCloseDelegate Handler 117 { 118 get { return m_handler; } 119 set { m_handler = value; } 120 } 121 HandleFrame(Frame frame)122 public override void HandleFrame(Frame frame) 123 { 124 125 lock(m_closingLock) 126 { 127 if (!m_closing) 128 { 129 base.HandleFrame(frame); 130 return; 131 } 132 } 133 134 if (!m_closeServerInitiated 135 && (frame.Type == CommonFraming.Constants.FrameMethod)) 136 { 137 MethodBase method = Connection.Protocol.DecodeMethodFrom(frame.GetReader()); 138 if ((method.ProtocolClassId == m_closeClassId) 139 && (method.ProtocolMethodId == m_closeMethodId)) 140 { 141 base.HandleFrame(frame); 142 return; 143 } 144 145 if ((method.ProtocolClassId == m_closeOkClassId) 146 && (method.ProtocolMethodId == m_closeOkMethodId)) 147 { 148 // This is the reply (CloseOk) we were looking for 149 // Call any listener attached to this session 150 this.Handler(); 151 return; 152 } 153 } 154 155 // Either a non-method frame, or not what we were looking 156 // for. Ignore it - we're quiescing. 157 } 158 159 Transmit(Command cmd)160 public override void Transmit(Command cmd) 161 { 162 lock(m_closingLock) 163 { 164 if (!m_closing) 165 { 166 base.Transmit(cmd); 167 return; 168 } 169 } 170 171 // Allow always for sending close ok 172 // Or if application initiated, allow also for sending close 173 MethodBase method = cmd.m_method; 174 if ( ((method.ProtocolClassId == m_closeOkClassId) 175 && (method.ProtocolMethodId == m_closeOkMethodId)) 176 || (!m_closeServerInitiated && ( 177 (method.ProtocolClassId == m_closeClassId) && 178 (method.ProtocolMethodId == m_closeMethodId)) 179 )) 180 { 181 base.Transmit(cmd); 182 return; 183 } 184 } 185 } 186 } 187