private static void NewInstanceRPCHandler <T, I>(PacketHeader header, Connection connection, string instanceName) where T : I, new() { lock (locker) { string instanceId = GetInstanceId(typeof(T).Name + instanceName + connection.ConnectionInfo.NetworkIdentifier.ToString()); RPCRemoteObject wrapper = null; if (!RPCObjectsById.TryGetValue(instanceId, out wrapper)) { var instance = new T(); wrapper = new RPCRemoteObject(instance, typeof(I), RPCRemoteObject.RPCObjectType.Private, instanceId, timeoutByInterfaceType[typeof(I)]); RPCObjectsById.Add(instanceId, wrapper); } wrapper.AddClientSubscription <T, I>(connection); if (!newConnectionByIdHandlers.ContainsKey(typeof(I))) { var del = new NetworkComms.PacketHandlerCallBackDelegate <string>(RetrieveByIDRPCHandler <T, I>); serverConnection.AppendIncomingPacketHandler <string>(typeof(I).Name + "-NEW-RPC-CONNECTION-BY-ID", del); newConnectionByIdHandlers.Add(typeof(I), del); } string returnPacketType = header.GetOption(PacketHeaderStringItems.RequestedReturnPacketType); connection.SendObject(returnPacketType, instanceId); } }
private static void RunRPCFunctionHandler <T, I>(PacketHeader header, Connection connection, RemoteCallWrapper wrapper) where T : I { I instance = default(I); MethodInfo funcRef = typeof(I).GetMethod(wrapper.name); try { lock (locker) { instance = (I)(RPCObjectsById[wrapper.instanceId].RPCObject); } } catch (Exception) { wrapper.result = null; wrapper.Exception = "SERVER SIDE EXCEPTION\n\n" + "Invalid instanceID" + "\n\nEND SERVER SIDE EXCEPTION\n\n"; connection.SendObject(header.PacketType, wrapper); return; } object[] args = null; if (wrapper.args == null) { args = new object[0]; } else { args = (from arg in wrapper.args select arg.UntypedValue).ToArray(); } try { wrapper.result = RPCArgumentBase.CreateDynamic(funcRef.Invoke(instance, args)); wrapper.args = (from arg in args select RPCArgumentBase.CreateDynamic(arg)).ToList(); } catch (Exception e) { wrapper.result = null; if (e.InnerException != null) { e = e.InnerException; } wrapper.Exception = "SERVER SIDE EXCEPTION\n\n" + e.ToString() + "\n\nEND SERVER SIDE EXCEPTION\n\n"; } string returnPacketType = header.GetOption(PacketHeaderStringItems.RequestedReturnPacketType); connection.SendObject(returnPacketType, wrapper); }
private static void RetrieveByIDRPCHandler <T, I>(PacketHeader header, Connection connection, string instanceId) where T : I { lock (locker) { if (!RPCObjectsById.ContainsKey(instanceId) || RPCObjectsById[instanceId].InterfaceType != typeof(I)) { instanceId = String.Empty; } else { var instanceWrapper = RPCObjectsById[instanceId]; instanceWrapper.AddClientSubscription <T, I>(connection); } string returnPacketType = header.GetOption(PacketHeaderStringItems.RequestedReturnPacketType); connection.SendObject(returnPacketType, instanceId); } }
/// <summary> /// Handles an incoming packet of type 'PartialFileData' /// </summary> /// <param name="header">Header associated with incoming packet</param> /// <param name="connection">The connection associated with incoming packet</param> /// <param name="data">The incoming data</param> private void IncomingPartialFileData(PacketHeader header, Connection connection, byte[] data) { try { SendInfo info = null; ReceivedFile file = null; //Perform this in a thread safe way lock (syncRoot) { //Extract the packet sequence number from the header //The header can also user defined parameters long sequenceNumber = header.GetOption(PacketHeaderLongItems.PacketSequenceNumber); if (incomingDataInfoCache.ContainsKey(connection.ConnectionInfo) && incomingDataInfoCache[connection.ConnectionInfo].ContainsKey(sequenceNumber)) { //We have the associated SendInfo so we can add this data directly to the file info = incomingDataInfoCache[connection.ConnectionInfo][sequenceNumber]; incomingDataInfoCache[connection.ConnectionInfo].Remove(sequenceNumber); //Check to see if we have already received any files from this location if (!receivedFilesDict.ContainsKey(connection.ConnectionInfo)) { receivedFilesDict.Add(connection.ConnectionInfo, new Dictionary <string, ReceivedFile>()); } //Check to see if we have already initialised this file if (!receivedFilesDict[connection.ConnectionInfo].ContainsKey(info.Filename)) { receivedFilesDict[connection.ConnectionInfo].Add(info.Filename, new ReceivedFile(info.Filename, connection.ConnectionInfo, info.TotalBytes)); AddNewReceivedItem(receivedFilesDict[connection.ConnectionInfo][info.Filename]); } file = receivedFilesDict[connection.ConnectionInfo][info.Filename]; } else { //We do not yet have the associated SendInfo so we just add the data to the cache if (!incomingDataCache.ContainsKey(connection.ConnectionInfo)) { incomingDataCache.Add(connection.ConnectionInfo, new Dictionary <long, byte[]>()); } incomingDataCache[connection.ConnectionInfo].Add(sequenceNumber, data); } } //If we have everything we need we can add data to the ReceivedFile if (info != null && file != null && !file.IsCompleted) { file.AddData(info.BytesStart, 0, data.Length, data); //Perform a little clean-up file = null; data = null; GC.Collect(); } else if (info == null ^ file == null) { throw new Exception("Either both are null or both are set. Info is " + (info == null ? "null." : "set.") + " File is " + (file == null ? "null." : "set.") + " File is " + (file.IsCompleted ? "completed." : "not completed.")); } } catch (Exception ex) { //If an exception occurs we write to the log window and also create an error file AddLineToLog("Exception - " + ex.ToString()); LogTools.LogException(ex, "IncomingPartialFileDataError"); } }
/// <summary> /// Returns the <see cref="SendReceiveOptions"/> to be used for the provided <see cref="PacketHeader"/>. Ensures there /// will not be a serializer or data processor clash for different delegate levels. /// </summary> /// <param name="header">The <see cref="PacketHeader"/> options are desired.</param> /// <returns>The requested <see cref="SendReceiveOptions"/></returns> internal SendReceiveOptions IncomingPacketSendReceiveOptions(PacketHeader header) { //Are there connection specific or global packet handlers? bool connectionSpecificHandlers = false; lock (_syncRoot) connectionSpecificHandlers = incomingPacketHandlers.ContainsKey(header.PacketType); bool globalHandlers = NetworkComms.GlobalIncomingPacketHandlerExists(header.PacketType); //Get connection specific options for this packet type, if there aren't any use the connection default options SendReceiveOptions connectionSpecificOptions = PacketTypeUnwrapperOptions(header.PacketType); if (connectionSpecificOptions == null) { connectionSpecificOptions = ConnectionDefaultSendReceiveOptions; } //Get global options for this packet type, if there aren't any use the global default options SendReceiveOptions globalOptions = NetworkComms.GlobalPacketTypeUnwrapperOptions(header.PacketType); if (globalOptions == null) { globalOptions = NetworkComms.DefaultSendReceiveOptions; } if (connectionSpecificHandlers && globalHandlers) { if (!connectionSpecificOptions.OptionsCompatible(globalOptions)) { throw new PacketHandlerException("Attempted to determine correct sendReceiveOptions for packet of type '" + header.PacketType + "'. Unable to continue as connection specific and global sendReceiveOptions are not equal."); } //We need to combine options in this case using the connection specific option in preference if both are present var combinedOptions = new Dictionary <string, string>(globalOptions.Options); foreach (var pair in connectionSpecificOptions.Options) { combinedOptions[pair.Key] = pair.Value; } //If the header specifies a serializer and data processors we will auto detect those if (header.ContainsOption(PacketHeaderLongItems.SerializerProcessors)) { DataSerializer serializer; List <DataProcessor> dataProcessors; DPSManager.GetSerializerDataProcessorsFromIdentifier(header.GetOption(PacketHeaderLongItems.SerializerProcessors), out serializer, out dataProcessors); return(new SendReceiveOptions(serializer, dataProcessors, combinedOptions)); } //Otherwise we will use options that were specified return(new SendReceiveOptions(connectionSpecificOptions.DataSerializer, connectionSpecificOptions.DataProcessors, combinedOptions)); } ////////////////////////////////////////////// //// Changed 20/05/14 to fix bug when encryption options is set on the listener and not the packet handler ////////////////////////////////////////////// else //if (connectionSpecificHandlers) { //If the header specifies a serializer and data processors we will auto detect those if (header.ContainsOption(PacketHeaderLongItems.SerializerProcessors)) { DataSerializer serializer; List <DataProcessor> dataProcessors; DPSManager.GetSerializerDataProcessorsFromIdentifier(header.GetOption(PacketHeaderLongItems.SerializerProcessors), out serializer, out dataProcessors); return(new SendReceiveOptions(serializer, dataProcessors, connectionSpecificOptions.Options)); } return(connectionSpecificOptions); } //else //{ // //If the header specifies a serializer and data processors we will auto detect those // if (header.ContainsOption(PacketHeaderLongItems.SerializerProcessors)) // { // DataSerializer serializer; // List<DataProcessor> dataProcessors; // DPSManager.GetSerializerDataProcessorsFromIdentifier(header.GetOption(PacketHeaderLongItems.SerializerProcessors), out serializer, out dataProcessors); // return new SendReceiveOptions(serializer, dataProcessors, globalOptions.Options); // } // //If just globalHandlers is set (or indeed no handlers at all we just return the global options // return globalOptions; //} }