Пример #1
0
        internal void StartTransport(FunapiTransport transport)
        {
            if (transport == null)
                return;

            DebugUtils.Log("Starting {0} transport.", transport.Protocol);

            lock (state_lock_)
            {
                if (state_ == State.kUnknown)
                {
                    Start();
                    return;
                }
            }

            transport.Start();
        }
Пример #2
0
        private void StopTransport(FunapiTransport transport)
        {
            if (transport == null)
                return;

            DebugUtils.Log("Stopping {0} transport.", transport.Protocol);

            StopPingTimer(transport);

            transport.Stop();
        }
Пример #3
0
        //---------------------------------------------------------------------
        // FunapiTransport-related functions
        //---------------------------------------------------------------------
        public void AttachTransport(FunapiTransport transport)
        {
            DebugUtils.Assert(transport != null);

            lock (transports_lock_)
            {
                if (transports_.ContainsKey(transport.Protocol))
                {
                    StringBuilder strlog = new StringBuilder();
                    strlog.AppendFormat("AttachTransport - transport of '{0}' type already exists.", transport.Protocol);
                    strlog.Append(" You should call DetachTransport first.");
                    DebugUtils.LogWarning(strlog.ToString());
                    return;
                }

                // Callback functions
                transport.ConnectTimeoutCallback += new TransportEventHandler(OnConnectTimeout);
                transport.StartedInternalCallback += new TransportEventHandler(OnTransportStarted);
                transport.StoppedCallback += new TransportEventHandler(OnTransportStopped);
                transport.ConnectFailureCallback += new TransportEventHandler(OnTransportConnectFailure);
                transport.DisconnectedCallback += new TransportEventHandler(OnTransportDisconnected);
                transport.ReceivedCallback += new TransportReceivedHandler(OnTransportReceived);
                transport.MessageFailureCallback += new TransportMessageHandler(OnTransportFailure);

                transport.ProtobufHelper = serializer_;

                transports_[transport.Protocol] = transport;

                if (default_protocol_ == TransportProtocol.kDefault)
                {
                    SetDefaultProtocol(transport.Protocol);
                }

                if (Started)
                {
                    StartTransport(transport);
                }

                DebugUtils.Log("{0} transport attached.", transport.Protocol);
            }
        }
Пример #4
0
        private void StartPingTimer(FunapiTransport transport)
        {
            if (transport.Protocol != TransportProtocol.kTcp)
                return;

            string timer_id = string.Format("{0}_ping", transport.str_protocol);
            timer_.AddTimer(timer_id, transport.PingIntervalSeconds, true, OnPingTimerEvent, transport.Protocol);
            transport.PingWaitTime = 0f;

            DebugUtils.Log("Start ping - interval seconds: {0}, timeout seconds: {1}",
                           transport.PingIntervalSeconds, transport.PingTimeoutSeconds);
        }
Пример #5
0
        private void StopPingTimer(FunapiTransport transport)
        {
            if (transport.Protocol != TransportProtocol.kTcp)
                return;

            transport.PingTime = 0;

            string timer_id = string.Format("{0}_ping", transport.str_protocol);
            if (timer_.ContainTimer(timer_id))
                timer_.KillTimer(timer_id);
        }
Пример #6
0
        private void SendPingMessage(FunapiTransport transport)
        {
            long timestamp = DateTime.Now.Ticks;

            // Send response
            if (transport.Encoding == FunEncoding.kJson)
            {
                object msg = transport.JsonHelper.Deserialize("{}");
                transport.JsonHelper.SetStringField(msg, kMsgTypeBodyField, kClientPingMessageType);
                transport.JsonHelper.SetStringField(msg, kSessionIdBodyField, session_id_);
                transport.JsonHelper.SetIntegerField(msg, kPingTimestampField, timestamp);
                transport.SendMessage(new FunapiMessage(transport.Protocol, kClientPingMessageType, msg));
            }
            else if (transport.Encoding == FunEncoding.kProtobuf)
            {
                FunPingMessage ping = new FunPingMessage();
                ping.timestamp = timestamp;
                FunMessage msg = CreateFunMessage(ping, MessageType.cs_ping);
                msg.msgtype = kClientPingMessageType;
                msg.sid = session_id_;
                transport.SendMessage(new FunapiMessage(transport.Protocol, kClientPingMessageType, msg));
            }

            transport.PingWaitTime += transport.PingIntervalSeconds;
            DebugUtils.DebugLog("Send {0} ping - timestamp: {1}", transport.str_protocol, timestamp);
        }
Пример #7
0
        private void SetTransportStarted(FunapiTransport transport, bool send_unsent = true)
        {
            if (transport == null)
                return;

            transport.OnStarted();

            if (send_unsent && unsent_queue_.Count > 0)
            {
                SendUnsentMessages();
            }

            if (transport.EnablePing && transport.PingIntervalSeconds > 0)
            {
                StartPingTimer(transport);
            }
        }
Пример #8
0
        private void OnServerPingMessage(FunapiTransport transport, object body)
        {
            if (transport == null)
            {
                DebugUtils.Log("OnServerPingMessage - transport is null.");
                return;
            }

            // Send response
            if (transport.Encoding == FunEncoding.kJson)
            {
                transport.JsonHelper.SetStringField(body, kMsgTypeBodyField, kServerPingMessageType);

                if (session_id_.Length > 0)
                    transport.JsonHelper.SetStringField(body, kSessionIdBodyField, session_id_);

                transport.SendMessage(new FunapiMessage(transport.Protocol,
                                                        kServerPingMessageType,
                                                        transport.JsonHelper.Clone(body)));
            }
            else if (transport.Encoding == FunEncoding.kProtobuf)
            {
                FunMessage msg = body as FunMessage;
                FunPingMessage obj = (FunPingMessage)GetMessage(msg, MessageType.cs_ping);
                if (obj == null)
                    return;

                FunPingMessage ping = new FunPingMessage();
                ping.timestamp = obj.timestamp;
                if (obj.data.Length > 0) {
                    ping.data = new byte[obj.data.Length];
                    Buffer.BlockCopy(ping.data, 0, obj.data, 0, obj.data.Length);
                }

                FunMessage send_msg = CreateFunMessage(ping, MessageType.cs_ping);
                send_msg.msgtype = msg.msgtype;
                send_msg.sid = session_id_;

                transport.SendMessage(new FunapiMessage(transport.Protocol, kServerPingMessageType, send_msg));
            }
        }
Пример #9
0
        private void SendAck(FunapiTransport transport, UInt32 ack)
        {
            DebugUtils.Assert(session_reliability_);
            if (transport == null)
            {
                DebugUtils.Log("SendAck - transport is null.");
                return;
            }

            if (state_ == State.kStopped)
                return;

            DebugUtils.DebugLog("{0} send ack message - ack:{1}", transport.Protocol, ack);

            if (transport.Encoding == FunEncoding.kJson)
            {
                object ack_msg = transport.JsonHelper.Deserialize("{}");
                transport.JsonHelper.SetStringField(ack_msg, kSessionIdBodyField, session_id_);
                transport.JsonHelper.SetIntegerField(ack_msg, kAckNumberField, ack);
                transport.SendMessage(new FunapiMessage(transport.Protocol, "", ack_msg));
            }
            else if (transport.Encoding == FunEncoding.kProtobuf)
            {
                FunMessage ack_msg = new FunMessage();
                ack_msg.sid = session_id_;
                ack_msg.ack = ack;
                transport.SendMessage(new FunapiMessage(transport.Protocol, "", ack_msg));
            }
        }
Пример #10
0
        private bool OnSeqReceived(FunapiTransport transport, UInt32 seq)
        {
            if (first_receiving_)
            {
                first_receiving_ = false;
            }
            else
            {
                UInt32 seq_interval = seq - seq_recvd_;
                if (seq_interval < 1 && Math.Abs(seq_interval) < kStableSequenceInterval)
                {
                    DebugUtils.Log("Received previous sequence number {0}. Skipping message.", seq);
                    SendAck(transport, seq_recvd_ + 1);
                    return false;
                }
                else if (seq_interval != 1)
                {
                    DebugUtils.LogWarning("Received wrong sequence number {0}. {1} expected.",
                                          seq, seq_recvd_ + 1);
                    StopTransport(transport);
                    return false;
                }
            }

            seq_recvd_ = seq;
            SendAck(transport, seq_recvd_ + 1);

            return true;
        }
Пример #11
0
        private void OnClientPingMessage(FunapiTransport transport, object body)
        {
            if (transport == null)
            {
                DebugUtils.Log("OnClientPingMessage - transport is null.");
                return;
            }

            long timestamp = 0;

            if (transport.Encoding == FunEncoding.kJson)
            {
                if (transport.JsonHelper.HasField(body, kPingTimestampField))
                {
                    timestamp = (long)transport.JsonHelper.GetIntegerField(body, kPingTimestampField);
                }
            }
            else if (transport.Encoding == FunEncoding.kProtobuf)
            {
                FunMessage msg = body as FunMessage;
                object obj = GetMessage(msg, MessageType.cs_ping);
                if (obj == null)
                    return;

                FunPingMessage ping = obj as FunPingMessage;
                timestamp = ping.timestamp;
            }

            if (transport.PingWaitTime > 0)
                transport.PingWaitTime -= transport.PingIntervalSeconds;

            transport.PingTime = (int)((DateTime.Now.Ticks - timestamp) / 10000);

            DebugUtils.DebugLog("Receive {0} ping - timestamp:{1} time={2} ms",
                                transport.str_protocol, timestamp, transport.PingTime);
        }
Пример #12
0
        private void OnAckReceived(FunapiTransport transport, UInt32 ack)
        {
            DebugUtils.Assert(session_reliability_);
            if (transport == null)
            {
                DebugUtils.LogError("OnAckReceived - transport is null.");
                return;
            }

            while (send_queue_.Count > 0)
            {
                UInt32 seq;
                FunapiMessage last_msg = send_queue_.Peek();
                if (transport.Encoding == FunEncoding.kJson)
                {
                    seq = (UInt32)transport.JsonHelper.GetIntegerField(last_msg.message, kSeqNumberField);
                }
                else if (transport.Encoding == FunEncoding.kProtobuf)
                {
                    seq = (last_msg.message as FunMessage).seq;
                }
                else
                {
                    DebugUtils.Assert(false);
                    seq = 0;
                }

                if (SeqLess(ack, seq))
                {
                    send_queue_.Dequeue();
                }
                else
                {
                    break;
                }
            }

            if (transport.state == FunapiTransport.State.kWaitForAck)
            {
                foreach (FunapiMessage msg in send_queue_)
                {
                    if (transport.Encoding == FunEncoding.kJson)
                    {
                        UInt32 seq = (UInt32)transport.JsonHelper.GetIntegerField(msg.message, kSeqNumberField);
                        DebugUtils.Assert(seq == ack || SeqLess(seq, ack));
                        transport.SendMessage(msg);
                    }
                    else if (transport.Encoding == FunEncoding.kProtobuf)
                    {
                        UInt32 seq = (msg.message as FunMessage).seq;
                        DebugUtils.Assert(seq == ack || SeqLess (seq, ack));
                        transport.SendMessage(msg);
                    }
                    else
                    {
                        DebugUtils.Assert(false);
                    }
                }

                SetTransportStarted(transport);
            }
        }
Пример #13
0
        private void StartPingTimer(FunapiTransport transport)
        {
            if (transport.Protocol != TransportProtocol.kTcp)
                return;

            string timer_id = string.Format("{0}_ping", transport.str_protocol);
            timer_.AddTimer(timer_id, ping_interval_, true, OnPingTimerEvent, transport.Protocol);
            transport.PingWaitTime = 0f;
        }
Пример #14
0
        public FunapiNetwork(FunapiTransport transport, bool session_reliability,
                              SessionInitHandler on_session_initiated, SessionCloseHandler on_session_closed)
            : this(session_reliability)
        {
            OnSessionInitiated += new SessionInitHandler(on_session_initiated);
            OnSessionClosed += new SessionCloseHandler(on_session_closed);

            AttachTransport(transport);
            SetDefaultProtocol(transport.Protocol);
        }