コード例 #1
0
        protected override void OnMessage(MessageEventArgs e)
        {
            lock (_lock)
            {
                if (e.Type == Opcode.Binary)
                {
                    if (!CanSend)
                    {
                        Send("error: readonly connection");
                        Logger.Warn(_channel.Endpoint + " | received transaction on a readonly connection");
                        return;
                    }

                    if (!IsLive)
                    {
                        Send("error: past situation cannot be edited");
                        Logger.Warn(_channel.Endpoint + " | received transaction on a past situation connection");
                        return;
                    }

                    _protoModelObserver.Reset();

                    string senderID;
                    try
                    {
                        senderID = _fromProtobuf.Convert(e.RawData, _strictServer);
                    }
                    catch (Exception ex)
                    {
                        Logger.Warn(ex.Message);
                        return;
                    }

                    if (senderID == "undefined")
                    {
                        Logger.Warn(_channel.Endpoint + " | undefined senderID detected. Ignores");
                        return;
                    }

                    Logger.Info(_channel.Endpoint + " | " + senderID + " | transaction received | " + e.RawData.Length + " bytes");
                    Logger.Debug(Convert.ToBase64String(e.RawData));

                    LastSenderID = senderID;

                    _toProtobuf.ApplyThingsSuppressions(_protoModelObserver.Deletions);

                    // Broadcast to other clients
                    if (_protoModelObserver.SomethingChanged())
                    {
                        foreach (var session in Sessions.Sessions)
                        {
                            if (session != this)
                            {
                                var s = session as BroadcastService;
                                if (s != null)
                                {
                                    var transaction = _protoModelObserver.GetTransaction(s._toProtobuf, senderID, false, !s.CanReceive || !s.IsLive);
                                    //s.Send(s._toProtobuf.Convert(transaction));
                                    s.Send(transaction);
                                }
                            }
                        }
                    }
                }
                else if (e.Type == Opcode.Text)
                {
                    if ("live" == e.Data)
                    {
                        IsLive = true;

                        if (CurrentWarehouse != null && CanReceive)
                        {
                            _currentProtoModelObserver.Reset();
                            CurrentWarehouse.RegisterObserver(_currentProtoModelObserver);
                            TimeMachine.SynchronizeWarehouse(LiveWarehouse, CurrentWarehouse);
                            if (_currentProtoModelObserver.SomethingChanged())
                            {
                                var transaction = _currentProtoModelObserver.GetTransaction(_toProtobuf,
                                                                                            Configuration.TimeMachineSenderName);
                                Send(transaction);
                            }
                            CurrentWarehouse = null;
                        }

                        Send("live");
                        Logger.Info(_channel.Endpoint + " | " + LastSenderID + " | live");
                    }
                    else if ("pause" == e.Data)
                    {
                        IsLive = false;
                        Send("pause");

                        CurrentWarehouse = new Warehouse();
                        CurrentWarehouse.RegisterCollection(LiveWarehouse.Things);

                        Logger.Info(_channel.Endpoint + " | " + LastSenderID + " | pause");
                    }
                    else
                    {
                        Match match;
                        if ((match = _loadRegex.Match(e.Data)).Success)
                        {
                            IsLive = false;
                            Logger.Info(_channel.Endpoint + " | " + LastSenderID + " | load");
                            var  timestamp = match.Groups[1].Value;
                            long parsedTimestamp;
                            if (!long.TryParse(timestamp, out parsedTimestamp))
                            {
                                DateTime parsedDateTime;
                                if (!DateTime.TryParse(timestamp, out parsedDateTime))
                                {
                                    Logger.Info(_channel.Endpoint + " | " + LastSenderID +
                                                " | unable to parse the timestamp");
                                    Send("error: unable to parse the timestamp");
                                }

                                parsedTimestamp = parsedDateTime.Subtract(DateTimeEpoch).Ticks / 10000;
                            }

                            var oldSituation = TimeMachine.RetrieveWarehouse(parsedTimestamp);

                            if (oldSituation == null)
                            {
                                Send("error: no result found");
                                return;
                            }

                            if (CurrentWarehouse == null)
                            {
                                CurrentWarehouse = new Warehouse();
                                CurrentWarehouse.RegisterCollection(LiveWarehouse.Things);
                            }

                            _currentProtoModelObserver.Reset();
                            CurrentWarehouse.RegisterObserver(_currentProtoModelObserver);
                            TimeMachine.SynchronizeWarehouse(oldSituation, CurrentWarehouse);
                            if (_currentProtoModelObserver.SomethingChanged())
                            {
                                var transaction = _currentProtoModelObserver.GetTransaction(_toProtobuf, Configuration.TimeMachineSenderName);
                                var protoData   = _toProtobuf.Convert(transaction);
                                Send(protoData);
                            }
                        }
                        else
                        {
                            Send("error: instruction unknown");
                            Logger.Info(_channel.Endpoint + " | " + LastSenderID + " | instruction unknown");
                        }
                    }
                }
            }
        }