private void OnLog(string condition, string stackTrace, LogType logType) { //DO NOT CALL Debug.Log in this function or it will cause an infinite loop! //Wait until this network is ready to log. if (!sendLogEvents || !networkManager.isRunning || (!networkManager.isServer && !networkManager.isConnected)) { return; } using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteString(condition); writer.WriteBool(includeStacktrace); if (includeStacktrace) { writer.WriteString(stackTrace); } writer.WriteByte((byte)logType); if (networkManager.isServer) { //Send to all clients that are expecting it. MessageSender.SendToSpecific(m_ClientsReceivingLogEvents, networkLogMessageType, "NETWORK_INTERNAL", stream); } else { //Send to server MessageSender.Send(networkManager.serverID, networkLogMessageType, networkManager.networkInternalChannel, stream); } } } }
/// <summary> /// Gets a SHA256 hash of parts of the NetworkingConfiguration instance /// </summary> /// <param name="cache"></param> /// <returns></returns> public ulong GetConfig(bool cache = true) { if (ConfigHash != null && cache) { return(ConfigHash.Value); } Sort(); using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteUInt16Packed(ProtocolVersion); writer.WriteString(MLAPIConstants.MLAPI_PROTOCOL_VERSION); for (int i = 0; i < Channels.Count; i++) { writer.WriteString(Channels[i].Name); writer.WriteByte((byte)Channels[i].Type); } if (EnableSceneSwitching) { for (int i = 0; i < RegisteredScenes.Count; i++) { writer.WriteString(RegisteredScenes[i]); } } if (HandleObjectSpawning && ForceSamePrefabs) { List <NetworkedPrefab> sortedPrefabList = NetworkedPrefabs.OrderBy(x => x.hash).ToList(); for (int i = 0; i < sortedPrefabList.Count; i++) { writer.WriteUInt64Packed(sortedPrefabList[i].hash); } } writer.WriteBool(ForceSamePrefabs); writer.WriteBool(HandleObjectSpawning); writer.WriteBool(EnableEncryption); writer.WriteBool(EnableSceneSwitching); writer.WriteBool(SignKeyExchange); writer.WriteBits((byte)RpcHashSize, 3); writer.WriteBits((byte)PrefabHashSize, 3); stream.PadStream(); if (cache) { ConfigHash = stream.ToArray().GetStableHash64(); return(ConfigHash.Value); } return(stream.ToArray().GetStableHash64()); } } }
/// <summary> /// Returns a base64 encoded version of the config /// </summary> /// <returns></returns> public string ToBase64() { NetworkConfig config = this; using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteUInt16Packed(config.ProtocolVersion); writer.WriteBits((byte)config.Transport, 5); writer.WriteUInt16Packed((ushort)config.Channels.Count); for (int i = 0; i < config.Channels.Count; i++) { writer.WriteString(config.Channels[i].Name); writer.WriteBits((byte)config.Channels[i].Type, 5); } writer.WriteUInt16Packed((ushort)config.RegisteredScenes.Count); for (int i = 0; i < config.RegisteredScenes.Count; i++) { writer.WriteString(config.RegisteredScenes[i]); } writer.WriteUInt16Packed((ushort)config.NetworkedPrefabs.Count); for (int i = 0; i < config.NetworkedPrefabs.Count; i++) { writer.WriteBool(config.NetworkedPrefabs[i].playerPrefab); writer.WriteString(config.NetworkedPrefabs[i].name); } writer.WriteInt32Packed(config.MessageBufferSize); writer.WriteInt32Packed(config.ReceiveTickrate); writer.WriteInt32Packed(config.MaxReceiveEventsPerTickRate); writer.WriteInt32Packed(config.SendTickrate); writer.WriteInt32Packed(config.EventTickrate); writer.WriteInt32Packed(config.MaxConnections); writer.WriteInt32Packed(config.ConnectPort); writer.WriteString(config.ConnectAddress); writer.WriteInt32Packed(config.ClientConnectionBufferTimeout); writer.WriteBool(config.ConnectionApproval); writer.WriteInt32Packed(config.SecondsHistory); writer.WriteBool(config.HandleObjectSpawning); writer.WriteBool(config.EnableEncryption); writer.WriteBool(config.SignKeyExchange); writer.WriteBool(config.EnableSceneSwitching); writer.WriteInt32Packed(config.LoadSceneTimeOut); writer.WriteBool(config.EnableTimeResync); writer.WriteBits((byte)config.RpcHashSize, 3); stream.PadStream(); return(Convert.ToBase64String(stream.ToArray())); } } }
/// <summary> /// Gets a SHA256 hash of parts of the NetworkingConfiguration instance /// </summary> /// <param name="cache"></param> /// <returns></returns> public ulong GetConfig(bool cache = true) { if (ConfigHash != null && cache) { return(ConfigHash.Value); } Sort(); using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteUInt16Packed(ProtocolVersion); writer.WriteString(MLAPIConstants.MLAPI_PROTOCOL_VERSION); for (int i = 0; i < Channels.Count; i++) { writer.WriteString(Channels[i].Name); writer.WriteByte((byte)Channels[i].Type); } if (EnableSceneSwitching) { for (int i = 0; i < RegisteredScenes.Count; i++) { writer.WriteString(RegisteredScenes[i]); } } if (HandleObjectSpawning && RequireNetworkedPrefabsAreSyncronized) { for (int i = 0; i < NetworkedPrefabs.Count; i++) { writer.WriteString(NetworkedPrefabs[i].name); } } writer.WriteBool(HandleObjectSpawning); writer.WriteBool(EnableEncryption); writer.WriteBool(EnableSceneSwitching); writer.WriteBool(SignKeyExchange); writer.WriteBits((byte)AttributeMessageMode, 3); // Returns a 160 bit / 20 byte / 5 int checksum of the config if (cache) { ConfigHash = stream.ToArray().GetStableHash64(); return(ConfigHash.Value); } return(stream.ToArray().GetStableHash64()); } } }
/// <summary> /// Gets a SHA256 hash of parts of the NetworkingConfiguration instance /// </summary> /// <param name="cache"></param> /// <returns></returns> public ulong GetConfig(bool cache = true) { if (ConfigHash != null && cache) { return(ConfigHash.Value); } Sort(); using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteUInt16Packed(ProtocolVersion); writer.WriteString(MLAPIConstants.MLAPI_PROTOCOL_VERSION); if (EnableSceneManagement && !AllowRuntimeSceneChanges) { for (int i = 0; i < RegisteredScenes.Count; i++) { writer.WriteString(RegisteredScenes[i]); } } if (ForceSamePrefabs) { List <NetworkedPrefab> sortedPrefabList = NetworkedPrefabs.OrderBy(x => x.Hash).ToList(); for (int i = 0; i < sortedPrefabList.Count; i++) { writer.WriteUInt64Packed(sortedPrefabList[i].Hash); } } writer.WriteBool(EnableNetworkedVar); writer.WriteBool(ForceSamePrefabs); writer.WriteBool(UsePrefabSync); writer.WriteBool(EnableSceneManagement); writer.WriteBool(EnsureNetworkedVarLengthSafety); writer.WriteBool(EnableEncryption); writer.WriteBool(SignKeyExchange); writer.WriteBits((byte)RpcHashSize, 2); stream.PadStream(); if (cache) { ConfigHash = stream.ToArray().GetStableHash64(); return(ConfigHash.Value); } return(stream.ToArray().GetStableHash64()); } } }
/// <summary> /// Returns a base64 encoded version of the config /// </summary> /// <returns></returns> public string ToBase64() { NetworkConfig config = this; using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteString(config.protocalVersion); writer.WriteInt32Packed(config.receiveTickrate); writer.WriteInt32Packed(config.maxReceiveEventsPerTickRate); writer.WriteInt32Packed(config.eventTickrate); writer.WriteInt32Packed(config.clientConnectionBufferTimeout); writer.WriteInt32Packed(config.secondsHistory); writer.WriteBool(config.enableTimeResync); writer.WriteBool(config.ensureNetworkedVarLengthSafety); writer.WriteBits((byte)config.rpcHashSize, 3); writer.WriteBool(recycleNetworkIDs); writer.WriteSinglePacked(networkIDRecycleDelay); writer.WriteBool(enableNetworkedVar); writer.WriteBool(clientSendSceneEvents); writer.WriteBool(serverSendSceneEvents); stream.PadStream(); return Convert.ToBase64String(stream.ToArray()); } } }
/// <summary> /// Gets a SHA256 hash of parts of the NetworkingConfiguration instance /// </summary> /// <param name="cache"></param> /// <returns></returns> public ulong GetConfig(bool cache = true) { if (ConfigHash != null && cache) return ConfigHash.Value; using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteString(protocalVersion); writer.WriteBool(enableNetworkedVar); writer.WriteBool(ensureNetworkedVarLengthSafety); writer.WriteBits((byte)rpcHashSize, 3); stream.PadStream(); if (cache) { ConfigHash = stream.ToArray().GetStableHash64(); return ConfigHash.Value; } return stream.ToArray().GetStableHash64(); } } }
public void Write(Stream stream) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteUInt64(ID); writer.WriteString(Name); } }
public void Write(Stream stream) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteByte((byte)LocationIndex); writer.WriteString(Question); writer.WriteIntArrayPacked(Answers, ANSWER_COUNT); } }
private void SpawnBall() { var netObj = Instantiate(ball).GetComponent <NetworkedObject>(); using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteString("Ball"); netObj.Spawn(stream, true); } } }
private void SpawnPlayer(bool left, ulong clientId) { var netObj = Instantiate(pong, new Vector3(left ? -6f : 6f, 0f), Quaternion.identity).GetComponent <NetworkedObject>(); using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteString(left ? "Left" : "Right"); netObj.SpawnAsPlayerObject(clientId, stream, true); } } }
/// <summary> /// [2nd step] This function is called for second when anchor is placed /// </summary> public void InitVideoStreamingController(List<AcquisitionDelays> acquisitionDelays, string streamId) { Debug.Log("InitVideoStreamingController called"); try { // debug information this.snackbarText = GameObject.Find("Snackbar").GetComponentInChildren<Text>(); // Init code this.streamId = String.Copy(streamId); this.secBetweenFrame = Settings.Settings.Instance.FPS; this.phoneIdCompleteSending = new HashSet<string>(); this.frameCounter = 0; this.acquiringInProgress = false; foreach (AcquisitionDelays delay in acquisitionDelays) { Debug.Log("Key = " + delay.Key + ", Value = " + delay.Value); } foreach (MLAPI.Connection.NetworkedClient client in NetworkingManager.Singleton.ConnectedClientsList) { Debug.Log("Client ID: " + client.ClientId); } Debug.Log("StreamID: " + this.streamId); foreach (AcquisitionDelays delay in acquisitionDelays) { Debug.Log("Invoke remote RPC on: " + delay.Key + " delay send: " + delay.Value); using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteString(this.streamId); writer.WriteDouble(delay.Value); InvokeClientRpcOnClientPerformance(InitVideoStreamingPerformance, delay.Key, stream); } } // InvokeClientRpcOnClient(InitVideoStreaming, delay.Key, this.streamId, delay.Value); Debug.Log("RPC client invoked"); } } catch (Exception e) { Debug.LogError("Exception InitVideoStreaming: " + e.ToString()); } }
public void Write(Stream stream) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteInt32(stacks.Count); foreach (KeyValuePair <string, InventoryItem> kvp in stacks) { InventoryItem curInvItem = kvp.Value; if (curInvItem.Value.name != kvp.Key) { Debug.LogWarning("NetworkSharedItem name did not match " + kvp.Key + " != " + curInvItem.Value.name); } writer.WriteString(kvp.Key); writer.WriteInt32(curInvItem.Count); } } }
/// <summary> /// Returns a base64 encoded version of the config /// </summary> /// <returns></returns> public string ToBase64() { NetworkConfig config = this; using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteUInt16Packed(config.ProtocolVersion); writer.WriteUInt16Packed((ushort)config.RegisteredScenes.Count); for (int i = 0; i < config.RegisteredScenes.Count; i++) { writer.WriteString(config.RegisteredScenes[i]); } writer.WriteInt32Packed(config.ServerTargetFramerate); writer.WriteInt32Packed(config.NetworkedTransformTickrate); writer.WriteInt32Packed(config.ClientCommandTickrate); writer.WriteInt32Packed(config.MaxReceiveEventsPerTickRate); writer.WriteInt32Packed(config.LagCompensationTickRate); writer.WriteInt32Packed(config.EventTickrate); writer.WriteInt32Packed(config.ClientConnectionBufferTimeout); writer.WriteBool(config.ConnectionApproval); writer.WriteInt32Packed(config.SecondsHistory); writer.WriteBool(config.EnableEncryption); writer.WriteBool(config.SignKeyExchange); writer.WriteInt32Packed(config.LoadSceneTimeOut); writer.WriteBool(config.EnableTimeResync); writer.WriteBool(config.EnsureNetworkedVarLengthSafety); writer.WriteBits((byte)config.RpcHashSize, 2); writer.WriteBool(ForceSamePrefabs); writer.WriteBool(UsePrefabSync); writer.WriteBool(EnableSceneManagement); writer.WriteBool(RecycleNetworkIds); writer.WriteSinglePacked(NetworkIdRecycleDelay); writer.WriteBool(EnableNetworkedVar); writer.WriteBool(AllowRuntimeSceneChanges); writer.WriteBool(EnableNetworkLogs); stream.PadStream(); return(Convert.ToBase64String(stream.ToArray())); } } }
/// <summary> /// Returns a base64 encoded version of the config /// </summary> /// <returns></returns> public string ToBase64() { NetworkConfig config = this; using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteUInt16Packed(config.ProtocolVersion); writer.WriteUInt16Packed((ushort)config.RegisteredScenes.Count); for (int i = 0; i < config.RegisteredScenes.Count; i++) { writer.WriteString(config.RegisteredScenes[i]); } writer.WriteInt32Packed(config.ReceiveTickrate); writer.WriteInt32Packed(config.MaxReceiveEventsPerTickRate); writer.WriteInt32Packed(config.SendTickrate); writer.WriteInt32Packed(config.EventTickrate); writer.WriteInt32Packed(config.ClientConnectionBufferTimeout); writer.WriteBool(config.ConnectionApproval); writer.WriteInt32Packed(config.SecondsHistory); writer.WriteBool(config.EnableEncryption); writer.WriteBool(config.SignKeyExchange); writer.WriteInt32Packed(config.LoadSceneTimeOut); writer.WriteBool(config.EnableTimeResync); writer.WriteBits((byte)config.RpcHashSize, 3); writer.WriteBool(ForceSamePrefabs); writer.WriteBool(UsePrefabSync); writer.WriteBool(EnableNetworkedVar); stream.PadStream(); return(Convert.ToBase64String(stream.ToArray())); } } }
/// <summary> /// this function splits FILES into MEMORY SAFE sized chunks and safely sends one before starting another /// /// files receipient needs to receive the same number of headers with each header packet (packet 1 counts as a header packet) /// </summary> public IEnumerator SendFilesDownloadRoutine(string[] _paths, ulong _clientID) { Debug.Log("coroutine started"); if (State != LargeRPCState.Idle) { Debug.LogWarning("Cannot start sending files while files are being sent, waiting for Idle state to begin"); yield break; } ReceiverID = _clientID; ChangeState(LargeRPCState.Send_SendingHeaders); #region comment -- header sizes /* -- Header sizes -- * packet 1 * int fileCount 4b | long downloadSize 8b | <start headers> * * header packets * int fileID 4b | string filename varsize | byte[256] hash 32b | long fileLength 8b | bool isLastInPacket 1bit * * subsequent packets * int fileID 4b | int filedata_length 4b | byte[var] filedata <=netChunkSize | bool isLastInPacket 1byte */ #endregion #region Grab Download Information // grab info for headers foreach (var path in _paths) { if (File.Exists(path)) { using (FileStream fs = File.Open(path, FileMode.Open)) { Debug.Log(fs.Name); int id = Headers.Count; byte[] fileHash = fs.sha256(); yield return(new WaitForEndOfFrame()); FileHeader header = new FileHeader(id, Path.GetFileName(path), fileHash, fs.Length); Headers.Add(header); DownloadSize += header.fileSize; } // let it exit if it needs to, giving StopRoutine() a chance yield return(0); } else { Debug.LogWarning("File not found, skipping: " + path); } } #endregion #region send headers PooledBitStream bitStream = PooledBitStream.Get(); PooledBitWriter writer = PooledBitWriter.Get(bitStream); // fileCount writer.WriteInt32(Headers.Count); // downloadSize writer.WriteInt64(DownloadSize); var headersThisPacket = 0; var packetsSent = 0; Debug.Log("Sending headers"); foreach (var header in Headers) { // let it exit if it needs to, giving StopRoutine() a chance yield return(0); Debug.Log(headersThisPacket + " " + packetsSent); var path = header.path; var id = header.id; headersThisPacket++; // fileID writer.WriteInt32(header.id); // filename writer.WriteString(path); Debug.Log(Encoding.Unicode.GetString(header.hash)); // hash writer.WriteByteArray(header.hash, 32); // fileLength writer.WriteInt64(header.fileSize); bool isLastPacket = id >= Headers.Count - 1; // send it off if we've filled up a packet if (headersThisPacket >= headersPerPacket || isLastPacket) { Debug.Log("message going out"); // isLastInPacket writer.WriteBit(true); CustomMessagingManager.SendNamedMessage(MessageName, _clientID, bitStream, "MLAPI_INTERNAL"); /* headers are pretty small, they really don't need the receiver to check in here unless it becomes a problem * * // if we haven't sent any packets yet when we get here, wait for an okay from the receiver * if (packetsSent == 0) * { * ChangeState(LargeRPCState.Send_AwaitingOkayToSend); * * while (State == LargeRPCState.Send_AwaitingOkayToSend) * { * yield return new WaitForSeconds(0.5f); * } * }*/ packetsSent++; Debug.Log("headers: " + headersThisPacket + " packets: " + packetsSent); headersThisPacket = 0; writer.Dispose(); bitStream.Dispose(); bitStream = PooledBitStream.Get(); writer = PooledBitWriter.Get(bitStream); // don't wait on the last one if (!isLastPacket) { yield return(new WaitForSeconds(1 / 14)); } } else { writer.WriteBit(false); } } writer.Dispose(); bitStream.Dispose(); #endregion ChangeState(LargeRPCState.Send_AwaitingFilesNeededList); ListenForFilesNeededListOrCompletion(); // loop start while (State != LargeRPCState.Complete) { // let it exit if it needs to, giving StopRoutine() a chance yield return(0); Debug.Log("Not done, running not-complete loop"); #region wait for needed files list while (State == LargeRPCState.Send_AwaitingFilesNeededList || State == LargeRPCState.Send_EnsuringIntegrity) { Debug.Log("waiting for list"); yield return(new WaitForSeconds(0.5f)); } Debug.Log("No longer waiting for list"); #endregion // runs ReceiveFilesNeededListFromReceiver, changes state to either Send_SendingFiles or Complete if (filesToSend.Count > 0) { Debug.Log("client still needs more files, sending"); #region send files bitStream = PooledBitStream.Get(); writer = PooledBitWriter.Get(bitStream); foreach (var header in Headers) { // let it exit if it needs to, giving StopRoutine() a chance yield return(0); Debug.Log("processing header"); if (File.Exists(header.path) && filesToSend.Contains(header.id)) { Debug.Log("file is needed"); using (FileStream fs = File.Open(header.path, FileMode.Open)) { // while loop pulled from fs.Read docs from microsoft, a little confusing to the glance but works and will be fast int numBytesToRead = (int)fs.Length; int numBytesRead = 0; while (numBytesToRead > 0) { Debug.Log("still bytes left"); int thisFileChunkSize = fileChunkSize; thisFileChunkSize = Mathf.Min(thisFileChunkSize, numBytesToRead); byte[] fileChunk = new byte[thisFileChunkSize]; // Read may return anything from 0 to numBytesToRead. int n = fs.Read(fileChunk, numBytesRead, thisFileChunkSize); foreach (byte[] netChunk in fileChunk.Slices(netChunkSize, false)) { Debug.Log("processing next chunk"); // fileID writer.WriteInt32(header.id); //writer.WriteInt32(netChunk.Length); Debug.Log("netchunk len: " + netChunk.Length); // filedata writer.WriteByteArray(netChunk); // isLastInPacket, need to add in its own size bool isLastInPacket = bitStream.Length + 1 >= netChunkSize || netChunk.Length < netChunkSize; writer.WriteBit(isLastInPacket); if (isLastInPacket) { CustomMessagingManager.SendNamedMessage(MessageName, _clientID, bitStream, "MLAPI_INTERNAL"); Debug.Log("packet sent"); yield return(new WaitForSeconds(1 / 14)); writer.Dispose(); bitStream.Dispose(); bitStream = PooledBitStream.Get(); writer = PooledBitWriter.Get(bitStream); } } // Break when the end of the file is reached. if (n == 0) { Debug.Log("end of file reached, this is a failsafe"); break; } numBytesRead += n; numBytesToRead -= n; } } } } Debug.Log("all headers processed"); filesToSend.Clear(); // just failsafing these, should be disposed of already writer.Dispose(); bitStream.Dispose(); #endregion ChangeState(LargeRPCState.Send_EnsuringIntegrity); } Debug.Log("Waiting before checking completion again"); yield return(new WaitForSeconds(1f)); } StopListening(); Debug.Log("files sent"); if (OnDownloadComplete != null) { OnDownloadComplete(SendOrReceiveFlag.Send, ReceiverID); } ChangeState(LargeRPCState.Idle); yield break; }