private void ReceiveCreateView(NetMessage message, NetConnection server) { if (!server.IsServer && !server.IsPeer) { return; } int viewId = (int)message.Parameters[0]; int group = (int)message.Parameters[1]; string prefabRoot = (string)message.Parameters[2]; var stream = (NetStream)message.Parameters[3]; NetView.Relation relation = default(NetView.Relation); NetConnection controller = null; switch (message.MessageId) { case (int)ViewCmd.CreateOwnerView: controller = Socket.Self; relation = NetView.Relation.Owner; break; case (int)ViewCmd.CreatePeerView: relation = NetView.Relation.Peer; break; case (int)ViewCmd.CreateCreatorView: server = Socket.Self; relation = NetView.Relation.Creator; break; case (int)ViewCmd.CreateProxyView: relation = NetView.Relation.Proxy; break; } if (relation == NetView.Relation.Creator || relation == NetView.Relation.Peer) { var ipendpoint = (IPEndPoint)message.Parameters[4]; if (ipendpoint != null) { if (Socket.EndpointConnected(ipendpoint)) { controller = Socket.EndpointToConnection(ipendpoint); } else { NetLog.Error("Failed to create view, controller endpoint not connected: " + ipendpoint); } } } var view = CreateView(controller, server, viewId, group, prefabRoot, relation); view.TriggerReadInstantiateData(stream); if (OnNetViewCreated != null) { OnNetViewCreated(view); } }
/// <summary> Processes a response to an RPC assignment request. The assigned id and method name are added to the LocalRpcs dictionary. </summary> internal void ReceiveAssignmentResponse(NetMessage netMessage, NetConnection connection) { if (!connection.IsServer && !connection.IsPeer) { return; } var id = (ushort)netMessage.Parameters[0]; var methodName = (string)netMessage.Parameters[1]; if (RpcInfoCache.Exists(methodName) && !idToName.ContainsKey(id)) { idToName.Add(id, methodName); if (!nameToId.ContainsKey(methodName)) { nameToId.Add(methodName, id); } } else { NetLog.Error("Cannot assign local RPC. ID: " + id + " MethodName: " + methodName); } if (idToName.Count == RpcInfoCache.Count) { Socket.SendRequirementsMet(connection); } }
/// <summary> /// Sets request result and removes request from queue. /// </summary> internal void SetResponse(NetMessage message, NetConnection connection) { if (message.Parameters.Length < 2 || !(message.Parameters[0] is ushort)) { NetLog.Error("Received malformed request response. Discarding."); return; } ushort requestId = (ushort)message.Parameters[0]; uint key = CreateKey(message.ViewId, requestId); if (!requests.ContainsKey(key)) { //NetLog.Trace("Active request doesn't exist for response. Discarding."); return; } object requestObj = requests[key]; requests.Remove(key); if ((bool)message.Parameters[1]) { MethodInfo setResponse = requestObj.GetType().GetMethod("SetResponse"); setResponse.Invoke(requestObj, message.Parameters); } else { MethodInfo failureResponse = requestObj.GetType().GetMethod("FailureResponse", BindingFlags.NonPublic); failureResponse.Invoke(requestObj, null); } }
/// <summary> /// When an RPC is received, the targeted NetView is identified and DispatchRPC is called for that /// particular NetView object. DispatchRPC then identifies the targeted method and invokes it with /// the supplied parameters. /// </summary> internal void DispatchRpc(string methodName, NetMessage message, NetConnection connection) { if (!CachedRpcObjects.ContainsKey(methodName)) { NetLog.Error(string.Format("Can't find RPC method \"{0}\" for View {1}.", methodName, Id)); return; } Socket.Rpc.Invoke(CachedRpcObjects[methodName], methodName, message, connection); }
internal void Register(ushort commandId, Action <NetStream, NetConnection> target) { if (paramTypes.ContainsKey(commandId)) { NetLog.Error("Command Id already in use. Cannot add command."); return; } streamTargets.Add(commandId, target); paramTypes.Add(commandId, streamTypes); }
internal void Register(ushort commandId, Action <NetMessage, NetConnection> target, List <Type> types) { if (paramTypes.ContainsKey(commandId)) { NetLog.Error("Command Id already in use. Cannot add command."); return; } paramTypes.Add(commandId, types); targets.Add(commandId, target); }
/// <summary> Send overload that creates the NetMessage for the RPC. </summary> internal void Send(int viewId, bool reliable, string methodName, NetConnection target, params object[] parameters) { if (!Socket.Rpc.HasId(methodName)) { NetLog.Error("Send failed: RPC method name has not been assigned an ID."); return; } var netMessage = NetMessage.Create(Socket.Rpc.NameToId(methodName), (uint)viewId, parameters, reliable); target.Send(netMessage); }
/// <summary> Sends a reliable RPC that does not target a specific view. </summary> public void Send(string methodName, NetConnection target, params object[] parameters) { if (!Rpc.HasId(methodName)) { NetLog.Error("Remote RPC does not have an assigned ID: " + methodName); return; } var message = NetMessage.Create(Rpc.NameToId(methodName), 0, parameters, true); target.Send(message); }
/// <summary> /// Passes parameters from an incoming network message to the method associated with the RPC. /// </summary> internal void DispatchRpc(NetMessage message, NetConnection connection) { string methodName = Rpc.IdToName(message.MessageId); if (!rpcObjectInstances.ContainsKey(methodName)) { NetLog.Error(string.Format("Can't find method \"{0}\" for Viewless RPC.", methodName)); return; } Rpc.Invoke(rpcObjectInstances[methodName], methodName, message, connection); }
internal void RegisterParams(ushort commandId, List <Type> paramTypes) { if (this.paramTypes.ContainsKey(commandId)) { NetLog.Error("Command Id already in use. Cannot add command types."); return; } if (commandId < 1800 || commandId > 2047) { throw new Exception("Cannot register Command - Range: 1800-2047 - Provided: " + commandId); } this.paramTypes.Add(commandId, paramTypes); }
/// <summary> /// Returns the connection that matches the supplied target. /// Returns the server for Server or the first controller for Controllers. /// </summary> internal NetConnection GetTarget(RpcTarget target, NetView view) { switch (target) { case RpcTarget.Server: return(view.Server); case RpcTarget.Controllers: return(view.Controllers[0]); } NetLog.Error("Invalid RpcTarget for GetTarget. Only RpcTarget.Server or RpcTarget.Controllers can be used."); return(null); }
internal static NetMessage ReadNetMessage(NetStream stream) { List <Type> paramTypes; ushort messageId = stream.ReadUShort(11); uint viewId = 0; if (stream.ReadBool()) { viewId = stream.ReadUInt(20); } if (messageId == (int)Cmd.RequestResponse) { return(CreateResponseMessage(stream, messageId, viewId)); } if (messageId > 1800) { if (!stream.Socket.Command.Exists(messageId)) { NetLog.Error("Cannot deserialize message, Command ID not found: " + messageId); return(null); } paramTypes = stream.Socket.Command.ParamTypes(messageId); } else { if (!stream.Socket.Rpc.Exists(messageId)) { NetLog.Error("Cannot deserialize message, RPC ID not found: " + messageId); return(null); } paramTypes = stream.Socket.Rpc.ParamTypes(messageId); } NetMessage netMessage = NetMessage.Create(messageId, viewId, paramTypes.Count, false); if (stream.Socket.Rpc.TakesRequests(messageId)) { return(CreateRequestMessage(stream, netMessage, paramTypes)); } for (int i = 0; i < paramTypes.Count; i++) { netMessage.Parameters[i] = ReadParam(stream, paramTypes[i]); } return(netMessage); }
/// <summary> Send overload that creates the NetMessage for the RPC. </summary> internal void Send(int viewId, bool reliable, string methodName, List <NetConnection> targets, params object[] parameters) { if (!Socket.Rpc.HasId(methodName)) { NetLog.Error("Send failed: RPC method name has not been assigned an ID."); return; } var message = NetMessage.Create(Socket.Rpc.NameToId(methodName), (uint)viewId, parameters, reliable); for (int i = 0; i < targets.Count; i++) { targets[i].Send(message); } }
/// <summary> Send overload that creates the NetMessage for the RPC. </summary> internal void Send(int viewId, bool reliable, string methodName, RpcTarget target, params object[] parameters) { if (!Socket.Rpc.HasId(methodName)) { NetLog.Error("Send failed: RPC method name has not been assigned an ID."); return; } if (!ViewLookup.ContainsKey(viewId)) { return; } NetView view = ViewLookup[viewId]; var netMessage = NetMessage.Create(Socket.Rpc.NameToId(methodName), (uint)viewId, parameters, reliable); Send(view, netMessage, target); }
/// <summary> /// Starts the socket using the supplied endpoint. /// If the port is taken, the given port will be incremented to a free port. /// </summary> public void StartSocket(IPEndPoint endpoint) { Self = new NetConnection(false, false, this, endpoint); socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); try { const uint IOC_IN = 0x80000000; const uint IOC_VENDOR = 0x18000000; uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12; socket.IOControl((int)SIO_UDP_CONNRESET, new[] { Convert.ToByte(false) }, null); } catch { NetLog.Warning("Failed to set control code for ignoring ICMP port unreachable."); } socket.ReceiveBufferSize = 4194304; if (socket.ReceiveBufferSize != 4194304) { NetLog.Warning("ReceiveBufferSize restricted by OS."); } socket.SendBufferSize = 1048576; socket.Blocking = false; try { socket.Bind(endpoint); } catch (SocketException e) { if (e.ErrorCode == 10048) { var newEp = new IPEndPoint(endpoint.Address, endpoint.Port + 1); NetLog.Warning("Port in use. Incrementing and retrying..."); StartSocket(newEp); } else { NetLog.Error(e.Message); } return; } NetLog.Info(NetTime.StartDateTime() + " | Socket Started. Bound to: " + endpoint); NetTime.Milliseconds(); if (ProtocolAuthority) { Rpc.AssignLocalRpcs(); } Events.SocketStart(); }
/// <summary> Deserializes incoming reliable stream into NetMessages, forwards them to the NetSocket, releases the stream, /// increments the remote sequence, and retries the out-of-order buffer when needed. </summary> private void DeliverStream(NetStream strm) { // Deserialize stream into individual messages and pass them to the socket: while (NetSerializer.CanReadMessage(strm)) { var message = NetSerializer.ReadNetMessage(strm); if (message == null) { NetLog.Error("Failed to parse reliable message from: " + Connection.Endpoint + " Pos: " + strm.Pos + " Size: " + strm.Size); break; } Connection.Socket.ReceiveMessage(message, Connection); } // Return stream to pool and update receive buffer distances: strm.Release(); LastAcceptedRemoteSequence++; if (recvBuffer.Count > 0) { DecrementReceiveBuffer(); } }
internal static void WriteParam(NetStream stream, object param) { if (param == null) { // TODO: Explicit nullable params should be properly supported. stream.WriteBool(false); return; } // Get the object type so we can compare it: Type type = param.GetType(); // Built-in types: if (type == typeof(bool)) { stream.WriteBool((bool)param); } else if (type == typeof(byte)) { stream.WriteByte((byte)param); } else if (type == typeof(short)) { stream.WriteShort((short)param); } else if (type == typeof(ushort)) { stream.WriteUShort((ushort)param); } else if (type == typeof(int)) { stream.WriteInt((int)param); } else if (type == typeof(uint)) { stream.WriteUInt((uint)param); } else if (type == typeof(float)) { stream.WriteFloat((float)param); } else if (type == typeof(long)) { stream.WriteLong((long)param); } else if (type == typeof(ulong)) { stream.WriteULong((ulong)param); } else if (type == typeof(double)) { stream.WriteDouble((double)param); } else if (type == typeof(string)) { stream.WriteString((string)param); } else if (type == typeof(Vector2)) { stream.WriteVector2((Vector2)param); } else if (type == typeof(Vector3)) { stream.WriteVector3((Vector3)param); } else if (type == typeof(Quaternion)) { stream.WriteQuaternion((Quaternion)param); } else if (type == typeof(bool[])) { bool[] arr = (bool[])param; stream.WriteUShort((ushort)arr.Length); for (int i = 0; i < arr.Length; i++) { stream.WriteBool(arr[i]); } } else if (type == typeof(byte[])) { byte[] arr = (byte[])param; stream.WriteUShort((ushort)arr.Length); stream.WriteByteArray(arr, arr.Length); } else if (type == typeof(short[])) { short[] arr = (short[])param; stream.WriteUShort((ushort)arr.Length); for (int i = 0; i < arr.Length; i++) { stream.WriteShort(arr[i]); } } else if (type == typeof(ushort[])) { ushort[] arr = (ushort[])param; stream.WriteUShort((ushort)arr.Length); for (int i = 0; i < arr.Length; i++) { stream.WriteUShort(arr[i]); } } else if (type == typeof(int[])) { int[] arr = (int[])param; stream.WriteUShort((ushort)arr.Length); for (int i = 0; i < arr.Length; i++) { stream.WriteInt(arr[i]); } } else if (type == typeof(uint[])) { uint[] arr = (uint[])param; stream.WriteUShort((ushort)arr.Length); for (int i = 0; i < arr.Length; i++) { stream.WriteUInt(arr[i]); } } else if (type == typeof(float[])) { float[] arr = (float[])param; stream.WriteUShort((ushort)arr.Length); for (int i = 0; i < arr.Length; i++) { stream.WriteFloat(arr[i]); } } else if (type == typeof(string[])) { string[] arr = (string[])param; stream.WriteUShort((ushort)arr.Length); for (int i = 0; i < arr.Length; i++) { stream.WriteString(arr[i]); } } else if (type == typeof(char[])) { char[] arr = (char[])param; stream.WriteUShort((ushort)arr.Length); for (int i = 0; i < arr.Length; i++) { stream.WriteChar(arr[i]); } } else if (type == typeof(NetMessage)) { WriteNetMessage(stream, (NetMessage)param); } else if (type == typeof(NetMessage[])) { NetMessage[] arr = (NetMessage[])param; stream.WriteByte((byte)arr.Length); for (int i = 0; i < arr.Length; i++) { WriteNetMessage(stream, arr[i]); } } else if (type == typeof(IPAddress)) { IPAddress address = (IPAddress)param; stream.WriteByteArray(address.GetAddressBytes()); } else if (type == typeof(IPEndPoint)) { IPEndPoint ep = (IPEndPoint)param; stream.WriteBool(true); // non-null WriteParam(stream, ep.Address); stream.WriteUShort((ushort)ep.Port); } else if (type == typeof(NetZone)) { var zone = (NetZone)param; stream.WriteUInt(zone.Id); bool serializeEndpoint = zone.ServerEndpoint != null; stream.WriteBool(serializeEndpoint); if (serializeEndpoint) { WriteParam(stream, zone.ServerEndpoint); } stream.WriteVector3(zone.Position); stream.WriteInt(zone.ViewIdMin); stream.WriteInt(zone.ViewIdMax); } else if (type == typeof(NetStream)) { NetStream netStream = (NetStream)param; netStream.CopyTo(stream); } else if (HasType(type)) { Write(stream, type, param); } else { NetLog.Error("Failed to serialize, no serializer found: " + type); throw new Exception( "Serializer not implemented for type! You must add your own type check and serialization logic to serialize this type: " + type); } }