GibTreaty

NetworkDownloadHandler.cs

May 27th, 2018
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 11.72 KB | None | 0 0
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. using UnityEngine.Events;
  6. using UnityEngine.Networking;
  7.  
  8. /// <summary>
  9. /// Use RegisterClientHandlers() in NetworkManager.OnClientConnect
  10. /// Use RegisterServerHandlers() in NetworkManager.OnServerStart
  11. ///
  12. /// NetworkDownloadHandler.SendData() to send data (either as client to server or server to client)
  13. /// </summary>
  14. public class NetworkDownloadHandler : MonoBehaviour {
  15.  
  16.     const short ServerReceiver = 10000;
  17.     const short ClientReceiver = 10001;
  18.     const short ClientNotifier = 10002;
  19.     const short ServerNotifier = 10003;
  20.     static int defaultBufferSize = 1024; //max ethernet MTU is ~1400
  21.  
  22.     static NetworkDownloadHandler _current = null;
  23.  
  24.     static List<Guid> transmissionIds = new List<Guid>();
  25.     static Dictionary<Guid, Data> transmissionData = new Dictionary<Guid, Data>();
  26.  
  27.     public static event Action<Guid, Data> OnCompleteReceive;
  28.     public static event Action<Guid, Data> OnCompleteSend;
  29.     public static event Action<Guid, Data> OnPartialReceive;
  30.     public static event Action<Guid, Data> OnPartialSend;
  31.  
  32.     #region Properties
  33.     public static int TransmissionIDCount {
  34.         get { return transmissionIds.Count; }
  35.     }
  36.  
  37.     static NetworkDownloadHandler Current {
  38.         get {
  39.             if(_current == null) CreateNetworkDownloadHandlerObject();
  40.  
  41.             return _current;
  42.         }
  43.     }
  44.     #endregion
  45.  
  46.     public static void ClearDownloadedData() {
  47.         transmissionIds.Clear();
  48.         transmissionData.Clear();
  49.     }
  50.     public static void ClearDownloadedData(Func<KeyValuePair<Guid, Data>, bool> requirements) {
  51.         List<Guid> clearData = new List<Guid>();
  52.  
  53.         foreach(var pair in transmissionData)
  54.             if(requirements(pair))
  55.                 clearData.Add(pair.Key);
  56.  
  57.         foreach(var clear in clearData) {
  58.             transmissionIds.Remove(clear);
  59.             transmissionData.Remove(clear);
  60.         }
  61.     }
  62.  
  63.     IEnumerator ClientSendDataRoutine(Guid id, byte[] data, Action<Data> onCompleteSend) {
  64.         while(transmissionIds.Count > 0)
  65.             yield return null;
  66.  
  67.         NotifyServerOfDataBeingSent(id, data.Length);
  68.  
  69.         yield return null;
  70.  
  71.         transmissionIds.Add(id);
  72.  
  73.         var transmitData = new Data(data);
  74.         var bufferSize = defaultBufferSize;
  75.  
  76.         while(transmitData.currentIndex < transmitData.data.Length - 1) {
  77.             if(!NetworkClient.active || ClientScene.readyConnection == null) break;
  78.  
  79.             var remaining = transmitData.data.Length - transmitData.currentIndex;
  80.  
  81.             if(remaining < bufferSize)
  82.                 bufferSize = remaining;
  83.  
  84.             var bufferedData = new byte[bufferSize];
  85.  
  86.             Array.Copy(transmitData.data, transmitData.currentIndex, bufferedData, 0, bufferSize);
  87.  
  88.             SendDataToServer(id, bufferedData);
  89.             transmitData.currentIndex += bufferSize;
  90.             transmitData.LastTransmissionTime = Time.realtimeSinceStartup;
  91.  
  92.             yield return null;
  93.  
  94.             OnPartialSend?.Invoke(id, transmitData);
  95.         }
  96.  
  97.         transmissionIds.Remove(id);
  98.  
  99.         onCompleteSend?.Invoke(transmitData);
  100.         OnCompleteSend?.Invoke(id, transmitData);
  101.     }
  102.  
  103.     public static Guid ClientSendData(byte[] data, Action<Data> onCompleteSend) {
  104.         var id = Guid.NewGuid();
  105.  
  106.         ClientSendData(id, data, onCompleteSend);
  107.  
  108.         return id;
  109.     }
  110.     public static void ClientSendData(Guid id, byte[] data, Action<Data> onCompleteSend) {
  111.         Current.StartCoroutine(Current.ClientSendDataRoutine(id, data, onCompleteSend));
  112.     }
  113.  
  114.     static void CreateNetworkDownloadHandlerObject() {
  115.         var gameObject = new GameObject("Network Download Handler", typeof(NetworkDownloadHandler));
  116.  
  117.         _current = gameObject.GetComponent<NetworkDownloadHandler>();
  118.     }
  119.  
  120.     NetworkWriter GetDataWriter(short messageType, Guid id, byte[] data) {
  121.         var writer = new NetworkWriter();
  122.  
  123.         writer.StartMessage(messageType);
  124.         writer.WriteBytesFull(id.ToByteArray());
  125.         writer.WriteBytesFull(data);
  126.         writer.FinishMessage();
  127.  
  128.         return writer;
  129.     }
  130.  
  131.     public static Data GetStoredData(Guid id) {
  132.         Data data;
  133.  
  134.         if(transmissionData.TryGetValue(id, out data))
  135.             return data;
  136.  
  137.         return null;
  138.     }
  139.  
  140.     public static Guid GetTransmissionID(int index) {
  141.         return transmissionIds[index];
  142.     }
  143.  
  144.     void NotifyClientsOfDataBeingSent(Guid id, int dataLength, IEnumerable<NetworkConnection> sendToConnections) {
  145.         if(!NetworkServer.active || sendToConnections == null) return;
  146.  
  147.         var writer = new NetworkWriter();
  148.  
  149.         writer.StartMessage(ClientNotifier);
  150.         writer.WriteBytesFull(id.ToByteArray());
  151.         writer.Write(dataLength);
  152.         writer.FinishMessage();
  153.  
  154.         foreach(var connection in sendToConnections)
  155.             if(connection.hostId > -1)
  156.                 connection.SendWriter(writer, Channels.DefaultReliable);
  157.     }
  158.  
  159.     void NotifyServerOfDataBeingSent(Guid id, int dataLength) {
  160.         if(!NetworkClient.active || ClientScene.readyConnection == null) return;
  161.  
  162.         var writer = new NetworkWriter();
  163.  
  164.         writer.StartMessage(ServerNotifier);
  165.         writer.WriteBytesFull(id.ToByteArray());
  166.         writer.Write(dataLength);
  167.         writer.FinishMessage();
  168.  
  169.         ClientScene.readyConnection.SendWriter(writer, Channels.DefaultReliable);
  170.     }
  171.  
  172.     static void ReceiveData(NetworkMessage netMsg) {
  173.         var id = new Guid(netMsg.reader.ReadBytesAndSize());
  174.         var bufferedData = netMsg.reader.ReadBytesAndSize();
  175.  
  176.         if(!transmissionData.ContainsKey(id))
  177.             return;
  178.  
  179.         var storedData = transmissionData[id];
  180.         Array.Copy(bufferedData, 0, storedData.data, storedData.currentIndex, bufferedData.Length);
  181.  
  182.         storedData.currentIndex += bufferedData.Length;
  183.         storedData.LastTransmissionTime = Time.realtimeSinceStartup;
  184.  
  185.         storedData.OnPartialReceive?.Invoke();
  186.         OnPartialReceive?.Invoke(id, storedData);
  187.  
  188.         if(storedData.currentIndex < storedData.data.Length - 1)
  189.             return;
  190.  
  191.         transmissionData.Remove(id);
  192.  
  193.         storedData.OnCompleteReceive?.Invoke();
  194.         OnCompleteReceive?.Invoke(id, storedData);
  195.     }
  196.  
  197.     public static void RegisterClientHandlers() {
  198.         NetworkManager.singleton.client.RegisterHandler(ClientReceiver, ReceiveData);
  199.         NetworkManager.singleton.client.RegisterHandler(ClientNotifier, TransmissionNotifier);
  200.     }
  201.  
  202.     public static void RegisterServerHandlers() {
  203.         NetworkServer.RegisterHandler(ServerReceiver, ReceiveData);
  204.         NetworkServer.RegisterHandler(ServerNotifier, TransmissionNotifier);
  205.     }
  206.  
  207.     public static Guid SendData(byte[] data, Action<Data> onCompleteSend = null, IEnumerable<NetworkConnection> sendToConnections = null) {
  208.         var id = Guid.NewGuid();
  209.  
  210.         SendData(id, data, onCompleteSend, sendToConnections);
  211.  
  212.         return id;
  213.     }
  214.     public static void SendData(Guid id, byte[] data, Action<Data> onCompleteSend = null, IEnumerable<NetworkConnection> sendToConnections = null) {
  215.         if(NetworkServer.active) {
  216.             ServerSendData(id, data, onCompleteSend, sendToConnections);
  217.         }
  218.         else if(NetworkClient.active) {
  219.             ClientSendData(id, data, onCompleteSend);
  220.         }
  221.     }
  222.  
  223.     void SendDataToClient(Guid id, byte[] data, IEnumerable<NetworkConnection> sendToConnections) {
  224.         if(sendToConnections == null) return;
  225.  
  226.         var writer = GetDataWriter(ClientReceiver, id, data);
  227.  
  228.         foreach(var connection in sendToConnections)
  229.             if(connection.hostId > -1)
  230.                 connection.SendWriter(writer, 2);
  231.     }
  232.  
  233.     void SendDataToServer(Guid id, byte[] data) {
  234.         var writer = GetDataWriter(ServerReceiver, id, data);
  235.  
  236.         if(ClientScene.readyConnection != null)
  237.             ClientScene.readyConnection.SendWriter(writer, 2);
  238.     }
  239.  
  240.     public static Guid ServerSendData(byte[] data, Action<Data> onCompleteSend, IEnumerable<NetworkConnection> sendToConnections) {
  241.         var id = Guid.NewGuid();
  242.  
  243.         ServerSendData(id, data, onCompleteSend, sendToConnections);
  244.  
  245.         return id;
  246.     }
  247.     public static void ServerSendData(Guid id, byte[] data, Action<Data> onCompleteSend, IEnumerable<NetworkConnection> sendToConnections) {
  248.         Current.StartCoroutine(Current.ServerSendDataRoutine(id, data, onCompleteSend, sendToConnections));
  249.     }
  250.  
  251.     IEnumerator ServerSendDataRoutine(Guid id, byte[] data, Action<Data> onCompleteSend, IEnumerable<NetworkConnection> sendToConnections) {
  252.         if(transmissionIds.Count > 0) {
  253.             while(transmissionIds.Count > 0)
  254.                 yield return null;
  255.  
  256.             yield return new WaitForSeconds(1);
  257.         }
  258.  
  259.         NotifyClientsOfDataBeingSent(id, data.Length, sendToConnections);
  260.  
  261.         yield return null;
  262.  
  263.         transmissionIds.Add(id);
  264.  
  265.         var transmitData = new Data(data);
  266.         var bufferSize = defaultBufferSize;
  267.  
  268.         while(transmitData.currentIndex < transmitData.data.Length - 1) {
  269.             if(!NetworkServer.active) break;
  270.  
  271.             bool atLeastOneConnection = false;
  272.  
  273.             foreach(var connection in sendToConnections)
  274.                 if(connection != null && connection.hostId > -1) {
  275.                     atLeastOneConnection = true;
  276.                     break;
  277.                 }
  278.  
  279.             if(!atLeastOneConnection)
  280.                 break;
  281.  
  282.             var remaining = transmitData.data.Length - transmitData.currentIndex;
  283.  
  284.             if(remaining < bufferSize)
  285.                 bufferSize = remaining;
  286.  
  287.             var bufferedData = new byte[bufferSize];
  288.  
  289.             Array.Copy(transmitData.data, transmitData.currentIndex, bufferedData, 0, bufferSize);
  290.  
  291.             SendDataToClient(id, bufferedData, sendToConnections);
  292.             transmitData.currentIndex += bufferSize;
  293.             transmitData.LastTransmissionTime = Time.realtimeSinceStartup;
  294.  
  295.             yield return null;
  296.  
  297.             OnPartialSend?.Invoke(id, transmitData);
  298.         }
  299.  
  300.         transmissionIds.Remove(id);
  301.  
  302.         onCompleteSend?.Invoke(transmitData);
  303.         OnCompleteSend?.Invoke(id, transmitData);
  304.     }
  305.  
  306.     static void TransmissionNotifier(NetworkMessage netMsg) {
  307.         var id = new Guid(netMsg.reader.ReadBytesAndSize());
  308.         var size = netMsg.reader.ReadInt32();
  309.  
  310.         Debug.LogError("TransmissionNotifier id:" + netMsg.conn.connectionId + "\nguid" + id.ToString());
  311.  
  312.         if(transmissionData.ContainsKey(id))
  313.             return;
  314.  
  315.         transmissionData[id] = new Data(new byte[size]);
  316.     }
  317.  
  318.     public class Data {
  319.         public int currentIndex;
  320.         public byte[] data;
  321.  
  322.         public Action OnPartialReceive;
  323.         public Action OnCompleteReceive;
  324.  
  325.         #region Properties
  326.         /// <summary>Time since starting the download</summary>
  327.         public float ElapsedTime {
  328.             get { return Time.realtimeSinceStartup - TimeStarted; }
  329.         }
  330.  
  331.         /// <summary>Last time data was sent or received</summary>
  332.         public float LastTransmissionTime { get; set; }
  333.  
  334.         /// <summary>Time that the data was started being sent or received</summary>
  335.         public float TimeStarted { get; private set; }
  336.  
  337.         /// <summary>Time it took to finish downloading or uploading the data</summary>
  338.         public float TotalTransmissionTime {
  339.             get { return LastTransmissionTime - TimeStarted; }
  340.         }
  341.         #endregion
  342.  
  343.         public Data(byte[] data) {
  344.             currentIndex = 0;
  345.             this.data = data;
  346.  
  347.             TimeStarted = Time.realtimeSinceStartup;
  348.         }
  349.     }
  350. }
Add Comment
Please, Sign In to add comment