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(); }
private void StopTransport(FunapiTransport transport) { if (transport == null) return; DebugUtils.Log("Stopping {0} transport.", transport.Protocol); StopPingTimer(transport); transport.Stop(); }
//--------------------------------------------------------------------- // 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); } }
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); }
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); }
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); }
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); } }
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)); } }
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)); } }
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; }
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); }
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); } }
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; }
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); }