private void SendGatewayInformationResponse(PUP p) { // // Pup Type: 201 (octal) // Pup ID: same as in Request Pup // Pup Contents: one or more groups of four bytes, each providing routing information for // one network, as follows: // // <target-net> <gateway-net> <gateway-host> <hop-count> // // In each group, the first byte specifies the target network number. If the gateway host is // directly connected to that network, then the <hop-count> is zero and the <gateway-net> and // <gateway-host> describe the gateway’s connection to the network. // If the gateway host is not directly connected to the target network, then the second and // third bytes give the network and host numbers of another gateway through which the // responding gateway routes Pups to that network, and the fourth byte gives the hop count, // i.e., the number of additional gateways (not including itself) through which the responding // gateway believes a Pup must pass to reach the specified network. A hop count greater than // the constant maxHops (presently 15) signifies that the target network is believed to be // inaccessible. // byte[] infoArray = GetGatewayInformationArray(); PUPPort localPort = new PUPPort(DirectoryServices.Instance.LocalHostAddress, p.DestinationPort.Socket); // Response must contain our network number; this is used to tell clients what network they're on if they don't already know. PUPPort remotePort = new PUPPort(DirectoryServices.Instance.LocalNetwork, p.SourcePort.Host, p.SourcePort.Socket); PUP response = new PUP(PupType.GatewayInformationResponse, p.ID, remotePort, localPort, infoArray); Router.Instance.SendPup(response); }
/// <summary> /// Called when a PUP comes in on a known socket. Establishes a new BSP channel. /// A worker of the appropriate type is woken up to service the channel. /// </summary> /// <param name="p"></param> public static void EstablishRendezvous(PUP p, Type workerType) { if (p.Type != PupType.RFC) { Log.Write(LogType.Error, LogComponent.RTP, "Expected RFC pup, got {0}", p.Type); return; } UInt32 socketID = SocketIDGenerator.GetNextSocketID(); Log.Write(LogType.Error, LogComponent.Exp, "setting up rendezvous on {0} {1} with socketID {2}", p.DestinationPort, p.SourcePort, socketID); BSPChannel newChannel = new BSPChannel(p, socketID); newChannel.OnDestroy += OnChannelDestroyed; _activeChannels.Add(socketID, newChannel); // // Initialize the worker for this channel. InitializeWorkerForChannel(newChannel, workerType); // Send RFC response to complete the rendezvous: // Modify the destination port to specify our network PUPPort sourcePort = p.DestinationPort; sourcePort.Network = DirectoryServices.Instance.LocalNetwork; PUP rfcResponse = new PUP(PupType.RFC, p.ID, newChannel.ClientPort, sourcePort, newChannel.ServerPort.ToArray()); Log.Write(LogComponent.RTP, "Establishing Rendezvous, ID {0}, Server port {1}, Client port {2}.", p.ID, newChannel.ServerPort, newChannel.ClientPort); Router.Instance.SendPup(rfcResponse); }
/// <summary> /// Routes a locally received PUP to the proper destination host. /// </summary> /// <param name="pup"></param> public void RouteIncomingLocalPacket(PUP pup, bool route) { // // Check the network -- if it specifies network zero (coming from a host that doesn't yet know what // network it's on, or specifying the current network) or our network // we will pass it on to the protocol suite. // if (pup.DestinationPort.Network == 0 || pup.DestinationPort.Network == DirectoryServices.Instance.LocalHostAddress.Network) { Log.Write(LogType.Verbose, LogComponent.PUP, "Routing incoming packet."); _localProtocolDispatcher.ReceivePUP(pup); } else if (route) { // // Not for our network -- see if we know where to route it. // RoutePacketExternally(pup); } else { // // Not local, and we were asked not to route this PUP, so drop it on the floor. // } }
private void RouteIncomingExternalPacket(PUP p) { // // Ensure that this is for our network; otherwise this has been misrouted. // (Since we don't do multi-hop routing, any packet coming in through a gateway // interface must be destined for us.) // if (p.DestinationPort.Network == DirectoryServices.Instance.LocalNetwork) { // // Send it out on the local network for anyone to see. // _pupPacketInterface.Send(p); // // And if it's intended for us (the IFS server) let our services have a crack at it, too. // if (p.DestinationPort.Host == DirectoryServices.Instance.LocalHostAddress.Host || // us specifically p.DestinationPort.Host == 0) // broadcast { _localProtocolDispatcher.ReceivePUP(p); } } else { // // This was misrouted. Log it and drop. // Log.Write(LogType.Error, LogComponent.Routing, "PUP was misrouted; intended for network {0}, host {1}", p.DestinationPort.Network, p.DestinationPort.Host); } }
public void Send(PUP p) { // // Write PUP to UDP: // // For now, no actual routing (Gateway not implemented yet), everything is on the same 'net. // Just send a broadcast UDP with the encapsulated frame inside of it. // // Build the outgoing data; this is: // 1st word: length of data following // 2nd word: 3mbit destination / source bytes // 3rd word: frame type (PUP) byte[] encapsulatedFrame = new byte[6 + p.RawData.Length]; // 3mbit Packet length encapsulatedFrame[0] = (byte)((p.RawData.Length / 2 + 2) >> 8); encapsulatedFrame[1] = (byte)(p.RawData.Length / 2 + 2); // addressing encapsulatedFrame[2] = p.DestinationPort.Host; encapsulatedFrame[3] = p.SourcePort.Host; // frame type encapsulatedFrame[4] = (byte)(_pupFrameType >> 8); encapsulatedFrame[5] = (byte)_pupFrameType; // Actual data p.RawData.CopyTo(encapsulatedFrame, 6); // Send as UDP broadcast. _udpClient.Send(encapsulatedFrame, encapsulatedFrame.Length, _broadcastEndpoint); }
/// <summary> /// Pings the client with an empty AData PUP, which will cause it to respond with an ACK containing client BSP information. /// </summary> private void RequestClientStats() { // // Send an empty AData PUP to keep the connection alive and to update the client data stats. // PUP aData = new PUP(PupType.AData, _sendPos, _clientConnectionPort, _serverConnectionPort, new byte[0]); Router.Instance.SendPup(aData); }
/// <summary> /// Finds the appropriate channel for the given PUP. /// </summary> /// <param name="p"></param> /// <returns></returns> private static BSPChannel FindChannelForPup(PUP p) { if (_activeChannels.ContainsKey(p.DestinationPort.Socket)) { return(_activeChannels[p.DestinationPort.Socket]); } else { return(null); } }
/// <summary> /// Sends a Mark (or AMark) to the client. /// </summary> /// <param name="markType"></param> /// <param name="ack"></param> public void SendMark(byte markType, bool ack) { if (_destroyed) { return; } PUP markPup = new PUP(ack ? PupType.AMark : PupType.Mark, _sendPos, _clientConnectionPort, _serverConnectionPort, new byte[] { markType }); // Send it. SendDataPup(markPup); }
/// <summary> /// Handles an End request from the client. /// </summary> /// <param name="p"></param> public void End(PUP p) { PUP endReplyPup = new PUP(PupType.EndReply, p.ID, _clientConnectionPort, _serverConnectionPort, new byte[0]); Router.Instance.SendPup(endReplyPup); // "The receiver of the End PUP responds by returning an EndReply Pup with matching ID and then // _dallying_ up to some reasonably long timeout interval (say, 10 seconds) in order to respond to // a retransmitted End Pup should its initial EndReply be lost. If and when the dallying end of the // stream connection receives its EndReply, it may immediately self destruct." // TODO: actually make this happen... }
private void ReceiveCallback(Packet p) { // // Filter out encapsulated 3mbit frames and look for PUPs, forward them on. // if ((int)p.Ethernet.EtherType == _3mbitFrameType) { Log.Write(LogType.Verbose, LogComponent.Ethernet, "3mbit pup received."); MemoryStream packetStream = p.Ethernet.Payload.ToMemoryStream(); // Read the length prefix (in words), convert to bytes. // Subtract off 2 words for the ethernet header int length = ((packetStream.ReadByte() << 8) | (packetStream.ReadByte())) * 2 - 4; // Read the address (1st word of 3mbit packet) byte destination = (byte)packetStream.ReadByte(); byte source = (byte)packetStream.ReadByte(); // Read the type and switch on it int etherType3mbit = ((packetStream.ReadByte() << 8) | (packetStream.ReadByte())); // // Ensure this is a packet we're interested in. // if (etherType3mbit == _pupFrameType && // it's a PUP (destination == DirectoryServices.Instance.LocalHost || // for us, or... destination == 0)) // broadcast { try { PUP pup = new PUP(packetStream, length); _routerCallback(pup, destination != 0); } catch (Exception e) { // An error occurred, log it. Log.Write(LogType.Error, LogComponent.PUP, "Error handling PUP: {0} {1}\n\n{2}", e.Message, e.StackTrace, e.InnerException); } } else { Log.Write(LogType.Warning, LogComponent.Ethernet, "3mbit packet is not a PUP, dropping"); } } else { // Not a PUP, Discard the packet. We will not log this, so as to keep noise down. //Log.Write(LogLevel.DroppedPacket, "Not a PUP. Dropping."); } }
protected void Page_Load(object sender, EventArgs e) { if (!PUP.IsMode("e")) { PUP.IncludeJQuery = true; } if (!PUP.IsMode("aep")) { //StyleOverridePH.Controls.Add(new LiteralControl("<style type='text/css'>body {background-position: center top; background-image: url(/dreamstudio/images/bkgd/DarkSkyBkgd.jpg); text-align:center; margin:0 auto;}</style>")); StyleOverridePH.Controls.Add(new LiteralControl("<style type='text/css'>#MasterAll{background:#fff;height:auto;width:100%;min-width:750px;max-width:950px;text-align:left;margin: 0 auto;}</style>")); StyleOverridePH.Controls.Add(new LiteralControl("<style type='text/css'>#ContentArea{margin-left: 24px; margin-right: 20px;}</style>")); } else { //TopNavigationPanel.Visible = false; SearchPanel.Visible = false; } if (PUP.IsMode("a")) { StyleOverridePH.Controls.Add(new LiteralControl("<style type='text/css'>body {text-align:left; margin:0 auto;}</style>")); StyleOverridePH.Controls.Add(new LiteralControl("<style type='text/css'>#ContentArea{margin-left: 0px; margin-right: 0px;}</style>")); StyleOverridePH.Controls.Add(new LiteralControl("<style type='text/css'>.contentArea{margin-left: 0px; margin-right: 0px;}</style>")); StyleOverridePH.Controls.Add(new LiteralControl("<style type='text/css'>#MasterAll{background:#fff;height:auto;width:100%;min-width:180px;max-width:950px;text-align:left;margin: 0 auto;}</style>")); } if (PUP.IsMode("ae")) { StyleOverridePH.Controls.Add(new LiteralControl("<style type='text/css'>body {line-height: 1em; } .contentBox { margin-top: 80px; } .masterMessageArea { background-color:#fff; }</style>")); SearchPanel.Visible = false; //FooterPanel.Visible = false; } if (PUP.IsMode("ae")) { HeaderPanel.Visible = false; } //HomeHL.NavigateUrl = PUP.GetLink("/core/item/page.aspx", 56809); //ArtworkHL.NavigateUrl = PUP.GetLink("/core/item/page.aspx", 56810); //AboutHL.NavigateUrl = PUP.GetLink("/core/item/page.aspx", 56819); //ContactHL.NavigateUrl = PUP.GetLink("/core/item/page.aspx", 56820); if (PUP.IContains(PUP.Host, "dynamicspd.com")) { CopyrightHL.NavigateUrl = "http://DynamicsPD.com"; CopyrightHL.Text = "© " + DateTime.Now.Year.ToString() + " Patrol Dynamics - Community Policing System"; } else if (PUP.ItemID != 94009) // The Old Explorer { CopyrightHL.NavigateUrl = "http://DreamStudio.com"; CopyrightHL.Text = "© " + DateTime.Now.Year.ToString() + " dreamstudio"; } CopyrightHL.CssClass = "tinytext"; }
private void RoutePacketExternally(PUP p) { RoutingTableEntry destinationNetworkEntry = _routingTable.GetAddressForNetworkNumber(p.DestinationPort.Network); if (destinationNetworkEntry != null) { // // Send this out through the external network interface. // if (_gatewayUdpClient != null) { Log.Write(LogType.Verbose, LogComponent.Routing, "-> PUP routed to {0}:{1}, type {2} source {3} destination {4}.", destinationNetworkEntry.HostAddress, destinationNetworkEntry.Port, p.Type, p.SourcePort, p.DestinationPort); try { _gatewayUdpClientLock.EnterWriteLock(); _gatewayUdpClient.Send(p.RawData, p.RawData.Length, destinationNetworkEntry.HostAddress, destinationNetworkEntry.Port); } catch (Exception e) { Log.Write(LogType.Error, LogComponent.Routing, "Gateway UDP client send failed, error {0}. Continuing.", e.Message); } finally { _gatewayUdpClientLock.ExitWriteLock(); } } } else { // // We don't know where to send this, drop it instead. // Log.Write( LogType.Verbose, LogComponent.Routing, "Outgoing PUP is for unknown network {0}, dropping.", p.DestinationPort.Network); } }
/// <summary> /// Sends an Abort PUP to the client, (generally indicating a catastrophic failure of some sort.) /// </summary> /// <param name="message"></param> public void SendAbort(string message) { if (_destroyed) { return; } PUP abortPup = new PUP(PupType.Abort, _startPos, _clientConnectionPort, _serverConnectionPort, Helpers.StringToArray(message)); // // Send this directly, do not wait for the client to be ready (since it may be wedged, and we don't expect anyone to actually notice // this anyway). // Router.Instance.SendPup(abortPup); }
/// <summary> /// Sends a PUP. Will block if client is unable to receive data. If timeouts expire, channel will be shut down. /// </summary> /// <param name="p"></param> private void SendDataPup(PUP p) { // // Sanity check: This should only be called for Data or Mark pups. // if (p.Type != PupType.AData && p.Type != PupType.Data && p.Type != PupType.Mark && p.Type != PupType.AMark) { throw new InvalidOperationException("Invalid PUP type for SendDataPup."); } // // Add the pup to the output window. This may block if the window is full. // AddPupToOutputWindow(p); }
public void SendEnd() { PUP endPup = new PUP(PupType.EFTPEnd, _sendPos, _clientConnectionPort, _serverConnectionPort, new byte[0]); Router.Instance.SendPup(endPup); // Await an ack _outputAckEvent.WaitOne(EFTPAckTimeoutPeriod); _sendPos++; // Send another end to close things off. endPup = new PUP(PupType.EFTPEnd, _sendPos, _clientConnectionPort, _serverConnectionPort, new byte[0]); Router.Instance.SendPup(endPup); }
/// <summary> /// Sends an ACK to the client. /// </summary> private void SendAck() { _inputLock.EnterReadLock(); BSPAck ack = new BSPAck(); ack.MaxBytes = MaxBytes; ack.MaxPups = MaxPups; ack.BytesSent = MaxBytes; _inputLock.ExitReadLock(); PUP ackPup = new PUP(PupType.Ack, _recvPos, _clientConnectionPort, _serverConnectionPort, Serializer.Serialize(ack)); Router.Instance.SendPup(ackPup); Log.Write(LogType.Verbose, LogComponent.BSP, "ACK sent."); }
public void Send(PUP p) { // // Write PUP to ethernet: // // Build the outgoing data; this is: // 1st word: length of data following // 2nd word: 3mbit destination / source bytes // 3rd word: frame type (PUP) byte[] encapsulatedFrame = new byte[6 + p.RawData.Length]; // 3mbit Packet length encapsulatedFrame[0] = (byte)((p.RawData.Length / 2 + 2) >> 8); encapsulatedFrame[1] = (byte)(p.RawData.Length / 2 + 2); // addressing encapsulatedFrame[2] = p.DestinationPort.Host; encapsulatedFrame[3] = p.SourcePort.Host; // frame type encapsulatedFrame[4] = (byte)(_pupFrameType >> 8); encapsulatedFrame[5] = (byte)_pupFrameType; // Actual data p.RawData.CopyTo(encapsulatedFrame, 6); MacAddress destinationMac = new MacAddress(_10mbitBroadcast); // Build the outgoing packet; place the source/dest addresses, type field and the PUP data. EthernetLayer ethernetLayer = new EthernetLayer { Source = _interface.GetMacAddress(), Destination = destinationMac, EtherType = (EthernetType)_3mbitFrameType, }; PayloadLayer payloadLayer = new PayloadLayer { Data = new Datagram(encapsulatedFrame), }; PacketBuilder builder = new PacketBuilder(ethernetLayer, payloadLayer); // Send it over the 'net! _communicator.SendPacket(builder.Build(DateTime.Now)); }
public BSPChannel(PUP rfcPup, UInt32 socketID) { _inputLock = new ReaderWriterLockSlim(); _outputLock = new ReaderWriterLockSlim(); _inputWriteEvent = new AutoResetEvent(false); _inputQueue = new Queue <ushort>(65536); _outputAckEvent = new AutoResetEvent(false); _outputReadyEvent = new AutoResetEvent(false); _dataReadyEvent = new AutoResetEvent(false); _outputQueue = new Queue <byte>(65536); _outputWindow = new List <PUP>(16); _outputWindowLock = new ReaderWriterLockSlim(); _destroyed = false; // Init IDs, etc. based on RFC PUP _lastClientRecvPos = _startPos = _recvPos = _sendPos = rfcPup.ID; // Set up socket addresses. // The client sends the connection port it prefers to use // in the RFC pup. _clientConnectionPort = new PUPPort(rfcPup.Contents, 0); _originalDestinationPort = rfcPup.DestinationPort; // If the client doesn't know what network it's on, it's now on ours. if (_clientConnectionPort.Network == 0) { _clientConnectionPort.Network = DirectoryServices.Instance.LocalNetwork; } // We create our connection port using a unique socket address. _serverConnectionPort = new PUPPort(DirectoryServices.Instance.LocalHostAddress, socketID); // // Init MaxPups to indicate that we need to find out what the client actually supports when we first // start sending data. // _clientLimits.MaxPups = 0xffff; // Create our consumer thread for output and kick it off. _consumerThread = new Thread(OutputConsumerThread); _consumerThread.Start(); }
public void RecvAck(PUP p) { // // Sanity check that the client's position matches ours. // _lastRecvPos = p.ID; if (_lastRecvPos != _sendPos) { Log.Write(LogType.Error, LogComponent.EFTP, "Client position does not match server ({0} != {1}", _lastRecvPos, _sendPos); } // // Unblock those waiting for an ACK. // _outputAckEvent.Set(); }
private void GatewayInformationWorker() { uint infoPupID = (uint)(new Random().Next()); while (true) { // // From gatewayinformation.press: // "Each gateway host must also periodically broadcast Gateway Information Pups, as described above, // on all directly-connected networks. The frequency of this broadcast should be approximately one // every 30 seconds, and immediately whenever the gateway’s own routing table changes (see below). // These Pups should be sent from socket 2 to socket 2." // // At this time, we don't do anything with gateway information PUPs that we receive -- they could // at some point be used as originally intended, to dynamically update routing tables, but it would // require some serious security investments to make sure that the tables don't get poisoned. // However, even though we don't use them, some Alto software does. For example, the PUP libraries // used by Mazewar expect to get periodic updates or eventually it will assume the route is no longer // viable and drop connections. // // Delay 30 seconds Thread.Sleep(30000); byte[] infoArray = GetGatewayInformationArray(); // From us, on socket 2 PUPPort localPort = new PUPPort(DirectoryServices.Instance.LocalHostAddress, 2); // // The set of known networks is by default the set of directly-connected networks. // byte[] knownNetworks = Router.Instance.RoutingTable.GetKnownNetworks(); foreach (byte network in knownNetworks) { // Send a broadcast to the specified network PUPPort remotePort = new PUPPort(network, 0, 2); PUP infoPup = new PUP(PupType.GatewayInformationResponse, infoPupID++, remotePort, localPort, infoArray); Router.Instance.SendPup(infoPup); Log.Write(LogComponent.MiscServices, "Gateway Information packet sent to network {0}", network); } } }
/// <summary> /// Called by dispatcher to send incoming data destined for this protocol /// </summary> /// <param name="p"></param> public override void RecvData(PUP p) { switch (p.Type) { case PupType.GatewayInformationRequest: SendGatewayInformationResponse(p); break; case PupType.GatewayInformationResponse: // Currently a no-op. Log.Write(LogComponent.MiscServices, String.Format("Gateway Information handler unimplemented.")); break; default: Log.Write(LogComponent.MiscServices, String.Format("Unhandled Gateway protocol {0} ({1})", p.Type, (int)p.Type)); break; } }
protected void Page_Load(object sender, EventArgs e) { SiteID = PUP.SiteID; //T = PUP.WrapID + "." + PUP.SiteID; // Wrap and SiteID if (PUP.IContains(PUP.Host, "localhost") || PUP.IContains(PUP.Host, "review.")) { T += "?db=system"; } //TitleLT.Text = PUP.SiteTitle.ToUpper(); FooterLiteral.Text = GetFooterLinks(""); AllMenu(); if (PUP.IsMode("aep")) { NavPanel.Visible = false; FooterPanel.Visible = false; } }
/// <summary> /// Invoked when the client sends an ACK. /// Update our record of the client's PUP buffers. /// </summary> /// <param name="ackPUP"></param> public void RecvAck(PUP ackPUP) { //_outputWindowLock.EnterWriteLock(); _clientLimits = (BSPAck)Serializer.Deserialize(ackPUP.Contents, typeof(BSPAck)); Log.Write(LogType.Verbose, LogComponent.BSP, "ACK from client: bytes sent {0}, max bytes {1}, max pups {2}", _clientLimits.BytesSent, _clientLimits.MaxBytes, _clientLimits.MaxPups); _lastClientRecvPos = ackPUP.ID; // // Unblock those waiting for an ACK. // _outputAckEvent.Set(); }
public static void RecvData(PUP p) { EFTPChannel channel = FindChannelForPup(p); if (channel == null) { Log.Write(LogType.Error, LogComponent.EFTP, "Received EFTP PUP on an unconnected socket, ignoring."); return; } switch (p.Type) { case PupType.EFTPData: { channel.RecvData(p); } break; case PupType.EFTPAck: { channel.RecvAck(p); } break; case PupType.EFTPEnd: { channel.End(p); } break; case PupType.EFTPAbort: { string abortMessage = Helpers.ArrayToString(p.Contents); Log.Write(LogType.Warning, LogComponent.RTP, String.Format("EFTP aborted, message: '{0}'", abortMessage)); DestroyChannel(channel); } break; default: throw new NotImplementedException(String.Format("Unhandled EFTP PUP type {0}.", p.Type)); } }
private void Receive(MemoryStream packetStream) { // // Look for PUPs, forward them on. // // Read the length prefix (in words), convert to bytes. // Subtract off 2 words for the ethernet header int length = ((packetStream.ReadByte() << 8) | (packetStream.ReadByte())) * 2 - 4; // Read the address (1st word of 3mbit packet) byte destination = (byte)packetStream.ReadByte(); byte source = (byte)packetStream.ReadByte(); // Read the type and switch on it int etherType3mbit = ((packetStream.ReadByte() << 8) | (packetStream.ReadByte())); // // Ensure this is a packet we're interested in. // if (etherType3mbit == _pupFrameType && // it's a PUP (destination == DirectoryServices.Instance.LocalHost || // for us, or... destination == 0)) // broadcast { try { Log.Write(LogType.Normal, LogComponent.UDP, "UDP receive"); PUP pup = new PUP(packetStream, length); _routerCallback(pup, destination != 0); } catch (Exception e) { // An error occurred, log it. Log.Write(LogType.Error, LogComponent.PUP, "UDP Error handling PUP: {0} {1} {2}", e.Message, e.StackTrace, e.InnerException); } } else { Log.Write(LogType.Warning, LogComponent.Ethernet, "UDP packet is not a PUP, dropping"); } }
/// <summary> /// Adds the specified data/mark PUP to the moving output window, these PUPs will be picked up by the Output Thread /// and sent when the client is ready for them. /// </summary> /// <param name="p"></param> private void AddPupToOutputWindow(PUP p) { // Ensure things are set up EstablishWindow(); _outputWindowLock.EnterUpgradeableReadLock(); if (_outputWindow.Count < _clientLimits.MaxPups) { // // There's space in the window, so go for it. // _outputWindowLock.EnterWriteLock(); _outputWindow.Add(p); _outputWindowLock.ExitWriteLock(); } else { // // No space right now -- wait until the consumer has made some space. // // Leave the lock so the consumer is unblocked _outputWindowLock.ExitUpgradeableReadLock(); _outputReadyEvent.WaitOne(); // Re-enter. _outputWindowLock.EnterUpgradeableReadLock(); _outputWindowLock.EnterWriteLock(); _outputWindow.Add(p); _outputWindowLock.ExitWriteLock(); } // // Tell the Consumer thread we've added a new PUP to be consumed. // _dataReadyEvent.Set(); _outputWindowLock.ExitUpgradeableReadLock(); }
public bool AddPersonaje(Personaje personaje, int idUser, int idPartida) { var per = _personaje.AddPersonaje(personaje); PUP pup = new PUP(); PersonajesCapacidades personajesCapacidades = new PersonajesCapacidades(); pup.PersonajeId = per.PersonajeId; pup.UserId = idUser; pup.PartidaId = idPartida; var classCharacterCpacidades = _classCharacterCpacidadesData.GetClassCharacterCapacidades(per.ClassCharacterId.GetValueOrDefault()); foreach (var clases in classCharacterCpacidades) { personajesCapacidades.CapacidadId = clases.CapacidadId; personajesCapacidades.PersonajeId = per.PersonajeId; personajesCapacidades.Nivel = 1; _personajesCapacidadesData.AddPersonajesCapacidades(personajesCapacidades); } _pupdata.Add(pup); return(true); }
/// <summary> /// Routes a PUP out to the world. /// </summary> /// <param name="p"></param> private void RouteOutgoingPacket(PUP p) { // // Check the destination network. If it's 0 (meaning the sender doesn't know // what network it's on, or wants it to go out to whatever network it's currently // connected to) or it's destined for our network, we send it out directly through // the local network interface. // if (p.DestinationPort.Network == 0 || p.DestinationPort.Network == DirectoryServices.Instance.LocalNetwork) { _pupPacketInterface.Send(p); } else { // // Not for our network -- see if we know what network this is going to. // RoutePacketExternally(p); } }
/// <summary> /// Sends data to the channel (i.e. to the client). Will block (waiting for an ACK) if an ACK is requested. /// </summary> /// <param name="data">The data to be sent</param> /// <param name="flush">Whether to flush data out immediately or to wait for enough for a full PUP first.</param> public void Send(byte[] data, int length, bool flush) { if (length > data.Length) { throw new InvalidOperationException("Length must be less than or equal to the size of data."); } if (_destroyed) { return; } // Add output data to output queue. // Again, this is really inefficient for (int i = 0; i < length; i++) { _outputQueue.Enqueue(data[i]); } if (flush || _outputQueue.Count >= PUP.MAX_PUP_SIZE) { // Send data until all is used (for a flush) or until we have less than a full PUP (non-flush). while (_outputQueue.Count >= (flush ? 1 : PUP.MAX_PUP_SIZE)) { byte[] chunk = new byte[Math.Min(PUP.MAX_PUP_SIZE, _outputQueue.Count)]; // Ugh. for (int i = 0; i < chunk.Length; i++) { chunk[i] = _outputQueue.Dequeue(); } // Send the data. PUP dataPup = new PUP(flush ? PupType.AData : PupType.Data, _sendPos, _clientConnectionPort, _serverConnectionPort, chunk); SendDataPup(dataPup); } } }
/// <summary> /// Worker thread for UDP packet receipt. /// </summary> private void GatewayReceiveThread() { // Just call Receive forever, that's it. This will never return. // (probably need to make this more elegant so we can tear down the thread // properly.) Log.Write(LogComponent.Routing, "Gateway UDP Receiver thread started for port {0}.", _gatewayUdpPort); IPEndPoint groupEndPoint = new IPEndPoint(IPAddress.Any, Configuration.UDPPort); while (true) { byte[] data = null; try { data = _gatewayUdpClient.Receive(ref groupEndPoint); } catch (Exception e) { // // This can happen on occasion for reasons I don't quite understand. // We will log the failure and attempt to continue. // Log.Write(LogType.Error, LogComponent.Routing, "Gateway UDP client receive failed, error {0}. Continuing.", e.Message); continue; } // 1) validate that the packet came in on the right port // 2) validate packet // 3) get a PUP out of it // 4) send to RouteIncomingPacket. // 5) do it again. if (groupEndPoint.Port == _gatewayUdpPort) { if (data.Length < PUP.PUP_HEADER_SIZE + PUP.PUP_CHECKSUM_SIZE || data.Length > PUP.MAX_PUP_SIZE + PUP.PUP_HEADER_SIZE + PUP.PUP_CHECKSUM_SIZE) { Log.Write(LogType.Error, LogComponent.Routing, "External PUP has an invalid size ({0}). Dropping.", data.Length); continue; } try { // // See if we can get a PUP out of this. // PUP externalPUP = new PUP(new MemoryStream(data), data.Length); // // TODO: should technically bump the PUP's TransportControl field up; // really need to rewrite the PUP class to make this possible without // building up an entirely new PUP. // RouteIncomingExternalPacket(externalPUP); Log.Write(LogType.Verbose, LogComponent.Routing, "<- External PUP received from {0}:{1}, type {2} source {3} destination {4}. Routing to local network.", groupEndPoint.Address, groupEndPoint.Port, externalPUP.Type, externalPUP.SourcePort, externalPUP.DestinationPort); } catch (Exception e) { Log.Write(LogType.Error, LogComponent.Routing, "Error handling external PUP: {0}", e.Message); } } else { Log.Write(LogType.Verbose, LogComponent.Routing, "Packet from {0} received on wrong port ({1}), expected {2}.", groupEndPoint.Address, groupEndPoint.Port, _gatewayUdpPort); } } }