Пример #1
0
        protected void processHandshake(IMutableMessage handshake)
        {
            if (handshake.Successful)
            {
                // @@ax: I think this should be able to return a list of objects?
                Object serverTransportObject;
                handshake.TryGetValue(Message_Fields.SUPPORTED_CONNECTION_TYPES_FIELD, out serverTransportObject);
                IList <Object> serverTransports = serverTransportObject as IList <Object>;
                //Console.WriteLine("Supported transport: {0}", serverTransport);
                //IList<Object> serverTransports = new List<Object>();
                //serverTransports.Add(serverTransport);
                IList <ClientTransport> negotiatedTransports = transportRegistry.Negotiate(serverTransports, BAYEUX_VERSION);
                ClientTransport         newTransport         = negotiatedTransports.Count == 0 ? null : negotiatedTransports[0];
                if (newTransport == null)
                {
                    updateBayeuxClientState(
                        delegate(BayeuxClientState oldState)
                    {
                        return(new DisconnectedState(this, oldState.transport));
                    },
                        delegate()
                    {
                        receive(handshake);
                    });

                    // Signal the failure
                    String error = "405:c" + transportRegistry.AllowedTransports + ",s" + serverTransports.ToString() + ":no transport";

                    handshake.Successful = false;
                    handshake[Message_Fields.ERROR_FIELD] = error;
                    // TODO: also update the advice with reconnect=none for listeners ?
                }
                else
                {
                    updateBayeuxClientState(
                        delegate(BayeuxClientState oldState)
                    {
                        if (newTransport != oldState.transport)
                        {
                            oldState.transport.reset();
                            newTransport.init();
                        }

                        String action = getAdviceAction(handshake.Advice, Message_Fields.RECONNECT_RETRY_VALUE);
                        if (Message_Fields.RECONNECT_RETRY_VALUE.Equals(action))
                        {
                            return(new ConnectingState(this, oldState.handshakeFields, handshake.Advice, newTransport, handshake.ClientId));
                        }
                        else if (Message_Fields.RECONNECT_NONE_VALUE.Equals(action))
                        {
                            return(new DisconnectedState(this, oldState.transport));
                        }

                        return(null);
                    },
                        delegate()
                    {
                        receive(handshake);
                    });
                }
            }
            else
            {
                updateBayeuxClientState(
                    delegate(BayeuxClientState oldState)
                {
                    String action = getAdviceAction(handshake.Advice, Message_Fields.RECONNECT_HANDSHAKE_VALUE);
                    if (Message_Fields.RECONNECT_HANDSHAKE_VALUE.Equals(action) || Message_Fields.RECONNECT_RETRY_VALUE.Equals(action))
                    {
                        return(new RehandshakingState(this, oldState.handshakeFields, oldState.transport, oldState.nextBackoff()));
                    }
                    else if (Message_Fields.RECONNECT_NONE_VALUE.Equals(action))
                    {
                        return(new DisconnectedState(this, oldState.transport));
                    }
                    return(null);
                },
                    delegate()
                {
                    receive(handshake);
                });
            }
        }
Пример #2
0
		/// <summary>
		/// Processes a handshaking message have just arrived.
		/// </summary>
		public virtual void ProcessHandshake(IMutableMessage handshake)
		{
			if (null == handshake)
				throw new ArgumentNullException("handshake");

			// DEBUG
			if (logger.IsDebugEnabled)
				logger.DebugFormat("Processing meta handshake: {0}", handshake);

			if (handshake.IsSuccessful)
			{
				object field;
				object[] serverTransports = handshake.TryGetValue(Message.SupportedConnectionTypesField, out field)
					? ObjectConverter.ToObject<object[]>(field) : null;

				IList<ClientTransport> negotiatedTransports
					= (serverTransports != null && serverTransports.Length > 0)
					? _transportRegistry.Negotiate(Array.ConvertAll<object, string>(
						serverTransports, o => (null == o) ? null : o.ToString()), BayeuxVersion) : null;

				ClientTransport newTransport = (negotiatedTransports != null && negotiatedTransports.Count > 0)
					? negotiatedTransports[0] : null;
				if (newTransport == null)
				{
					// Signal the failure
					string error = String.Format(CultureInfo.InvariantCulture, "405:c{0},s{1}:No transport",
						ObjectConverter.Serialize(this.AllowedTransports), ObjectConverter.Serialize(serverTransports));

					handshake.IsSuccessful = false;
					handshake[Message.ErrorField] = error;
					// TODO: Also update the advice with reconnect=none for listeners ?

					this.UpdateBayeuxClientState(oldState =>
						{
							return (oldState == null) ? null : new DisconnectedState(this, oldState.Transport);
						},
						() =>
						{
							this.Receive(handshake);
						});
				}
				else	// Has a valid transport ?
				{
					this.UpdateBayeuxClientState(oldState =>
						{
							if (oldState != null)
							{
								if (!newTransport.Equals(oldState.Transport))
								{
									oldState.Transport.Reset();
									newTransport.Init();
								}

								string action = GetAdviceAction(handshake.Advice, Message.ReconnectRetryValue);
								if (Message.ReconnectRetryValue.Equals(action, StringComparison.OrdinalIgnoreCase))
								{
									return new ConnectingState(this, oldState.HandshakeFields,
										handshake.Advice, newTransport, handshake.ClientId);
								}
								else if (Message.ReconnectNoneValue.Equals(action, StringComparison.OrdinalIgnoreCase))
								{
									return new DisconnectedState(this, oldState.Transport);
								}
							}

							return null;
						},
						() =>
						{
							this.Receive(handshake);
						});
				}
			}
			else	// Try to re-handshake when an error message was arrived
			{
				this.UpdateBayeuxClientState(oldState =>
					{
						if (oldState != null)
						{
							string action = GetAdviceAction(handshake.Advice, Message.ReconnectHandshakeValue);
							if (Message.ReconnectHandshakeValue.Equals(action, StringComparison.OrdinalIgnoreCase)
								|| Message.ReconnectRetryValue.Equals(action, StringComparison.OrdinalIgnoreCase))
							{
								return new ReHandshakingState(this, oldState.HandshakeFields,
									oldState.Transport, oldState.NextBackOff);
							}
							else if (Message.ReconnectNoneValue.Equals(action, StringComparison.OrdinalIgnoreCase))
							{
								return new DisconnectedState(this, oldState.Transport);
							}
						}

						return null;
					},
					() =>
					{
						this.Receive(handshake);
					});
			}
		}
Пример #3
0
        protected void processHandshake(IMutableMessage handshake)
        {
            if (handshake.Successful)
            {
                // @@ax: I think this should be able to return a list of objects?
                Object serverTransportObject;
                handshake.TryGetValue(Message_Fields.SUPPORTED_CONNECTION_TYPES_FIELD, out serverTransportObject);
                IList<Object> serverTransports = serverTransportObject as IList<Object>;
                //Console.WriteLine("Supported transport: {0}", serverTransport);
                //IList<Object> serverTransports = new List<Object>();
                //serverTransports.Add(serverTransport);
                IList<ClientTransport> negotiatedTransports = transportRegistry.Negotiate(serverTransports, BAYEUX_VERSION);
                ClientTransport newTransport = negotiatedTransports.Count == 0 ? null : negotiatedTransports[0];
                if (newTransport == null)
                {
                    updateBayeuxClientState(
                            delegate(BayeuxClientState oldState)
                            {
                                return new DisconnectedState(this, oldState.transport);
                            },
                            delegate()
                            {
                                receive(handshake);
                            });

                    // Signal the failure
                    String error = "405:c" + transportRegistry.AllowedTransports + ",s" + serverTransports.ToString() + ":no transport";

                    handshake.Successful = false;
                    handshake[Message_Fields.ERROR_FIELD] = error;
                    // TODO: also update the advice with reconnect=none for listeners ?
                }
                else
                {
                    updateBayeuxClientState(
                            delegate(BayeuxClientState oldState)
                            {
                                if (newTransport != oldState.transport)
                                {
                                    oldState.transport.reset();
                                    newTransport.init();
                                }

                                String action = getAdviceAction(handshake.Advice, Message_Fields.RECONNECT_RETRY_VALUE);
                                if (Message_Fields.RECONNECT_RETRY_VALUE.Equals(action))
                                    return new ConnectingState(this, oldState.handshakeFields, handshake.Advice, newTransport, handshake.ClientId);
                                else if (Message_Fields.RECONNECT_NONE_VALUE.Equals(action))
                                    return new DisconnectedState(this, oldState.transport);

                                return null;
                            },
                            delegate()
                            {
                                receive(handshake);
                            });
                }
            }
            else
            {
                updateBayeuxClientState(
                        delegate(BayeuxClientState oldState)
                        {
                            String action = getAdviceAction(handshake.Advice, Message_Fields.RECONNECT_HANDSHAKE_VALUE);
                            if (Message_Fields.RECONNECT_HANDSHAKE_VALUE.Equals(action) || Message_Fields.RECONNECT_RETRY_VALUE.Equals(action))
                                return new RehandshakingState(this, oldState.handshakeFields, oldState.transport, oldState.nextBackoff());
                            else if (Message_Fields.RECONNECT_NONE_VALUE.Equals(action))
                                return new DisconnectedState(this, oldState.transport);
                            return null;
                        },
                        delegate()
                        {
                            receive(handshake);
                        });
            }
        }
Пример #4
0
		/// <summary>
		/// En-queues or sends a channel message.
		/// </summary>
		public virtual void EnqueueSend(IMutableMessage message)
		{
			if (null == message) return;

			if (this.CanSend)
			{
				bool sent = this.SendMessages(message);
				// DEBUG
				if (logger.IsDebugEnabled)
					logger.DebugFormat("{0} message: {1}", sent ? "Sent" : "Failed", message);
			}
			else
			{
				bool found = false;
				lock (_messagesQueue)
				{
					// Check existence of the message before enqueue
					object field1, field2;
					foreach (IMutableMessage m in _messagesQueue)
					{
						if (String.Compare(m.Channel, message.Channel, StringComparison.OrdinalIgnoreCase) == 0
							&& ((m.TryGetValue(Message.SubscriptionField, out field1)
									&& message.TryGetValue(Message.SubscriptionField, out field2)
									&& field1 != null && field2 != null && field1.Equals(field2))
								|| (m.Data != null && message.Data != null && m.Data.Equals(message.Data)))
							)
						{
							found = true;
							break;
						}
					}

					// Ignores duplicate messages
					if (!found)
						_messagesQueue.Add(message);
				}

				// DEBUG
				if (!found && logger.IsDebugEnabled)
					logger.DebugFormat("Enqueued message {0} (batching: {1})", message, this.IsBatching);
			}
		}
Пример #5
0
        protected void ProcessHandshake(IMutableMessage handshake)
        {
            if (handshake.Successful)
            {
                handshake.TryGetValue(MessageFields.SupportedConnectionTypesField, out var serverTransportObject);
                var serverTransports     = JsonConvert.DeserializeObject <IList <object> >(serverTransportObject.ToString());
                var negotiatedTransports = _transportRegistry.Negotiate(serverTransports, BayeuxVersion);
                var newTransport         = negotiatedTransports.Count == 0 ? null : negotiatedTransports[0];
                if (newTransport == null)
                {
                    UpdateBayeuxClientState(
                        oldState => new DisconnectedState(this, oldState.Transport),
                        delegate
                    {
                        Receive(handshake);
                    });

                    // Signal the failure
                    var error = "405:c" + _transportRegistry.AllowedTransports + ",s" + serverTransports + ":no transport";

                    handshake.Successful = false;
                    handshake[MessageFields.ErrorField] = error;
                }
                else
                {
                    UpdateBayeuxClientState(
                        delegate(BayeuxClientState oldState)
                    {
                        if (newTransport != oldState.Transport)
                        {
                            oldState.Transport.Reset();
                            newTransport.Init();
                        }

                        var action = GetAdviceAction(handshake.Advice, MessageFields.ReconnectRetryValue);
                        if (MessageFields.ReconnectRetryValue.Equals(action))
                        {
                            return(new ConnectingState(this, oldState.HandshakeFields, handshake.Advice, newTransport, handshake.ClientId));
                        }
                        if (MessageFields.ReconnectNoneValue.Equals(action))
                        {
                            return(new DisconnectedState(this, oldState.Transport));
                        }

                        return(null);
                    },
                        delegate
                    {
                        Receive(handshake);
                    });
                }
            }
            else
            {
                UpdateBayeuxClientState(
                    delegate(BayeuxClientState oldState)
                {
                    var action = GetAdviceAction(handshake.Advice, MessageFields.ReconnectHandshakeValue);
                    if (MessageFields.ReconnectHandshakeValue.Equals(action) || MessageFields.ReconnectRetryValue.Equals(action))
                    {
                        return(new RehandshakingState(this, oldState.HandshakeFields, oldState.Transport, oldState.NextBackoff()));
                    }
                    if (MessageFields.ReconnectNoneValue.Equals(action))
                    {
                        return(new DisconnectedState(this, oldState.Transport));
                    }
                    return(null);
                },
                    delegate
                {
                    Receive(handshake);
                });
            }
        }