void OnHeaderPacketRead <TState>(PacketData data, object[] args) { if (data.Completed) // 当前包已使用完 { packet.Dispose(); trans.Input(OnHeaderInput <TState>, args); return; } source = data.Buffer; sourceSize = data.Size; sourceOffset = 0; ContinueConstruct((IOCallback <TState>)args[0], (TState)args[1]); }
void CompleteBufferInput <TState>(IPipeline pipeline, IPacket packet, object[] args) { reader.SetSource(packet.Buffer, packet.Size); packet.Dispose(); // used var callback = (IOCompleteCallback <TState>)args[0]; var state = (TState)args[1]; Input(callback, state); // }
/// <summary> /// 继续读取报文 /// </summary> /// <typeparam name="TReadState"></typeparam> /// <param name="callback"></param> /// <param name="state"></param> protected void ReadPaket <TReadState>(IOCompleteCallback <TReadState> callback, TReadState state) { if (packet != null) { // 存在有效报文继续处理 if (packetOffset < packet.Size) { callback(pipeline, this.packet, state); return; } packet.Dispose(); } pipeline.Input(OnPacketRead <TReadState>, new object[] { callback, state }); }
void CompleteTransOutput <TState>(IPipeline pipeline, IPacket packet, int completeSize) { if (completeSize == outputPacket.Size) { transPacket.Dispose(); ((IOCompleteCallback <TState>)callback)(tunnelPipeline, outputPacket, (TState)state); } else // 未完继续 { var dataSize = Math.Min(BufferPacket.BufferSize, outputPacket.Size - completeSize); Array.Copy(outputPacket.Buffer, completeSize, packet.Buffer, 0, dataSize); transPacket.Relive(dataSize); pipeline.Output(packet, CompleteTransOutput <TState>, dataSize + completeSize); } }
/// <summary> /// Sends a <see cref="Packet"/> to the provided endPoint. Offers more performance if an identical packet is being sent to multiple peers. /// NOTE: Any possible reply will be ignored unless listening for incoming UDP packets. /// </summary> /// <typeparam name="packetPayloadObjectType">The type of object encapsulated by the provided packet</typeparam> /// <param name="packetToSend">The packet to send</param> /// <param name="ipEndPoint">The destination IPEndPoint. Supports multicast endpoints.</param> /// <param name="sendReceiveOptions">The sendReceiveOptions to use for this send</param> /// <param name="applicationLayerProtocol">If enabled NetworkComms.Net uses a custom /// application layer protocol to provide useful features such as inline serialisation, /// transparent packet transmission, remote peer handshake and information etc. We strongly /// recommend you use the NetworkComms.Net application layer protocol.</param> public static void SendObject <packetPayloadObjectType>(IPacket packetToSend, IPEndPoint ipEndPoint, SendReceiveOptions sendReceiveOptions, ApplicationLayerProtocolStatus applicationLayerProtocol) { if (ipEndPoint == null) { throw new ArgumentNullException("ipEndPoint"); } if (sendReceiveOptions == null) { throw new ArgumentNullException("sendReceiveOptions"); } if (applicationLayerProtocol == ApplicationLayerProtocolStatus.Undefined) { throw new ArgumentException("A value of ApplicationLayerProtocolStatus.Undefined is invalid when using this method.", "applicationLayerProtocol"); } if (sendReceiveOptions.Options.ContainsKey("ReceiveConfirmationRequired")) { throw new ArgumentException("Attempted to use a rouge UDP sender when the provided send receive" + " options specified the ReceiveConfirmationRequired option, which is unsupported. Please create a specific connection" + "instance to use this feature.", "sendReceiveOptions"); } //Check the send receive options if (applicationLayerProtocol == ApplicationLayerProtocolStatus.Disabled) { if (sendReceiveOptions.DataSerializer != DPSManager.GetDataSerializer <NullSerializer>()) { throw new ArgumentException("Attempted to use a rouge UDP sender when the provided send receive" + " options serialiser was not NullSerializer. Please provide compatible send receive options in order to successfully" + " instantiate this unmanaged connection.", "sendReceiveOptions"); } if (sendReceiveOptions.DataProcessors.Count > 0) { throw new ArgumentException("Attempted to use a rouge UDP sender when the provided send receive" + " options contains data processors. Data processors may not be used with unmanaged connections." + " Please provide compatible send receive options in order to successfully instantiate this unmanaged connection.", "sendReceiveOptions"); } } List <UDPConnection> connectionsToUse = null; //If we are already listening on what will be the outgoing adaptor we can send with that client to ensure reply packets are collected //The exception here is the broadcasting which goes out all adaptors if (ipEndPoint.Address != IPAddress.Broadcast) { #region Discover best local endpoint //Initialise best local end point as match all IPEndPoint bestLocalEndPoint = new IPEndPoint(IPAddress.Any, 0); try { bestLocalEndPoint = IPTools.BestLocalEndPoint(ipEndPoint); //Set the port to 0 to match all. bestLocalEndPoint.Port = 0; } catch (SocketException ex) { throw new ConnectionSetupException("Attempting to determine the best local endPoint to connect to " + ipEndPoint + " resulted in a socket exception.", ex); } catch (Exception ex) { LogTools.LogException(ex, "BestLocalEndPointError", "Error while attempting to determine the best local end point to contact " + ipEndPoint.ToString()); } #endregion Discover best local endpoint #region Check For Existing Local Listener List <UDPConnectionListener> existingListeners = Connection.ExistingLocalListeners <UDPConnectionListener>(bestLocalEndPoint); for (int i = 0; i < existingListeners.Count; i++) { if (existingListeners[i].UDPConnection.ConnectionInfo.ApplicationLayerProtocol == applicationLayerProtocol) { connectionsToUse = new List <UDPConnection> { existingListeners[i].UDPConnection }; //Once we have a matching connection we can break break; } } #endregion Check For Existing Local Listener //If we have not picked up an existing listener we need to use/create a rougeSender if (connectionsToUse == null) { #region Check For Suitable Rouge Sender lock (udpRogueSenderCreationLocker) { if (NetworkComms.commsShutdown) { throw new CommunicationException("Attempting to send UDP packet but NetworkCommsDotNet is in the process of shutting down."); } else { if (!udpRogueSenders.ContainsKey(applicationLayerProtocol) || !udpRogueSenders[applicationLayerProtocol].ContainsKey(bestLocalEndPoint) || udpRogueSenders[applicationLayerProtocol][bestLocalEndPoint].ConnectionInfo.ConnectionState == ConnectionState.Shutdown) { //Create a new rogue sender if (NetworkComms.LoggingEnabled) { NetworkComms.Logger.Trace("Creating UDPRougeSender."); } if (!udpRogueSenders.ContainsKey(applicationLayerProtocol)) { udpRogueSenders.Add(applicationLayerProtocol, new Dictionary <IPEndPoint, UDPConnection>()); } IPAddress anyRemoteIP = AnyRemoteIPAddress(ipEndPoint.AddressFamily); udpRogueSenders[applicationLayerProtocol][bestLocalEndPoint] = new UDPConnection(new ConnectionInfo(ConnectionType.UDP, new IPEndPoint(anyRemoteIP, 0), bestLocalEndPoint, applicationLayerProtocol), sendReceiveOptions, UDPConnection.DefaultUDPOptions, false); } connectionsToUse = new List <UDPConnection> { udpRogueSenders[applicationLayerProtocol][bestLocalEndPoint] }; } } #endregion Check For Suitable Rouge Sender } } else { #region Get A Sender On All Interfaces For Broadcast lock (udpRogueSenderCreationLocker) { //We do something special for broadcasts by selected EVERY adaptor if (NetworkComms.LoggingEnabled) { NetworkComms.Logger.Trace("Getting senders for UDP broadcasting."); } if (!udpRogueSenders.ContainsKey(applicationLayerProtocol)) { udpRogueSenders.Add(applicationLayerProtocol, new Dictionary <IPEndPoint, UDPConnection>()); } connectionsToUse = new List <UDPConnection>(); //This is a broadcast and we need to send the broadcast over every local adaptor List <IPAddress> validLocalIPAddresses = HostInfo.IP.FilteredLocalAddresses(); foreach (IPAddress address in validLocalIPAddresses) { IPEndPoint currentLocalIPEndPoint = new IPEndPoint(address, 0); List <UDPConnectionListener> existingListeners = Connection.ExistingLocalListeners <UDPConnectionListener>(currentLocalIPEndPoint); //If there is an existing listener we use that if (existingListeners.Count > 0) { for (int i = 0; i < existingListeners.Count; i++) { if (existingListeners[i].UDPConnection.ConnectionInfo.ApplicationLayerProtocol == applicationLayerProtocol) { connectionsToUse.Add(existingListeners[i].UDPConnection); //Once we have a matching connection we can break break; } } } else { //If not we check the rouge senders if (!udpRogueSenders[applicationLayerProtocol].ContainsKey(currentLocalIPEndPoint) || udpRogueSenders[applicationLayerProtocol][currentLocalIPEndPoint].ConnectionInfo.ConnectionState == ConnectionState.Shutdown) { IPAddress anyRemoteIP = AnyRemoteIPAddress(currentLocalIPEndPoint.AddressFamily); udpRogueSenders[applicationLayerProtocol][currentLocalIPEndPoint] = new UDPConnection(new ConnectionInfo(ConnectionType.UDP, new IPEndPoint(anyRemoteIP, 0), currentLocalIPEndPoint, applicationLayerProtocol), sendReceiveOptions, UDPConnection.DefaultUDPOptions, false); } connectionsToUse.Add(udpRogueSenders[applicationLayerProtocol][currentLocalIPEndPoint]); } } } #endregion Get A Sender On All Interfaces For Broadcast } foreach (UDPConnection connection in connectionsToUse) { try { //This has been commented out for the time being as it made no difference to the broadcast issue //we were investigating at the time we had issues //Use the network broadcast address instead of the global broadcast address where possible //if (ipEndPoint.Address == IPAddress.Broadcast && connection.ConnectionInfo.LocalIPEndPoint.AddressFamily == AddressFamily.InterNetwork) //{ // IPEndPoint ipEndPointToUse = new IPEndPoint(IPTools.GetIPv4NetworkBroadcastAddress(connection.ConnectionInfo.LocalIPEndPoint.Address), ipEndPoint.Port); // connection.SendPacketSpecific<packetPayloadObjectType>(packetToSend, ipEndPointToUse); //} //else connection.SendPacketSpecific <packetPayloadObjectType>(packetToSend, ipEndPoint); } catch (SocketException) { /* Ignore any socket exceptions */ } } //Dispose of the packet packetToSend.Dispose(); }
void CompleteOutput(IPipeline output, IPacket packet, IPipeline input) { packet.Dispose(); // used. input.Input(CompleteInput, output); }