Пример #1
0
        /// <summary>
        /// Sends a Netbios Name Service request to a unicast address and returns the respective response
        /// </summary>
        /// <param name="packet">Netbios Name Service packet to send</param>
        /// <param name="address">Target address to send the packet to</param>
        /// <param name="timeOutMilliseconds">
        /// If after this timeout following sending the request packet no response has been received, the request is sent again.
        /// This is tried <see cref="numRetries"/> times. We intentionally use the "wrong" timeout value here. For unicast
        /// requests RFC 1002 defines a UCAST_REQ_RETRY_TIMEOUT of 5 seconds. However, with the default retry count of 3, this
        /// results in a maximum time of 15 seconds until we can be sure that no response was sent. This is extremely long and
        /// tests have shown that even in a WLan, computers respond to requests withing less than 100 ms. We therefore by default
        /// use the BCAST_REQ_RETRY_TIMEOUT of 250ms, which is meant for broadcast requests, also for unicast requests.
        /// </param>
        /// <param name="numRetries">Number of retries. Default is 3.</param>
        /// <returns>
        /// A <see cref="Task"/> that completes when either (a) the respective response was received (in which case the result value
        /// of the Task contains the response packet) or (b) when the send operation was not successful or (c) when after <see cref="numRetries"/>
        /// retries no response was received (in the latter two cases the result value of the Task is <c>null</c>).
        /// </returns>
        public async Task <NbNsPacketBase> SendUnicastRequestAsync(NbNsPacketBase packet, IPAddress address, int timeOutMilliseconds = BCAST_REQ_RETRY_TIMEOUT, int numRetries = BCAST_REQ_RETRY_COUNT)
        {
            if (packet == null)
            {
                throw new ArgumentNullException("packet");
            }
            if (address == null)
            {
                throw new ArgumentNullException("address");
            }
            var identifier = new PacketIdentifier(packet.Header.NameTrnId, address);

            // If there is a request pending with the same transaction Id and the same target IP address, we do not
            // send the request again, but simply return the Task representing the already pending request.
            var newTcs = new TaskCompletionSource <NbNsPacketBase>();
            var tcs    = _pendingUnicastRequests.GetOrAdd(identifier, newTcs);

            if (tcs != newTcs)
            {
                return(await tcs.Task);
            }

            for (var retryCount = 1; retryCount <= numRetries; retryCount++)
            {
                // If the send operation was not successful (most likely the given IP address does not exist in the local subnet)
                // we immediately return null.
                if (!await SendPacketAsync(packet, address))
                {
                    _pendingUnicastRequests.TryRemove(identifier, out newTcs);
                    return(null);
                }

                // If we received a response within the given timeout, we return the response; if not, we resend the request
                if (await Task.WhenAny(tcs.Task, Task.Delay(timeOutMilliseconds)) == tcs.Task)
                {
                    _pendingUnicastRequests.TryRemove(identifier, out newTcs);
                    return(await tcs.Task);
                }
            }

            _pendingUnicastRequests.TryRemove(identifier, out newTcs);
            return(null);
        }
Пример #2
0
        public virtual void Send(SocketStateObject state, PacketIdentifier packetId, GamePacket packet)
        {
            switch (packetId.PacketType)
            {
            case PacketType.ServerPacket:
            case PacketType.ClientPacket:
                Send(state, packetId.PacketId, packet.Serialize(new DataStream {
                    IsLittleEndian = false
                }));
                return;

            case PacketType.ServerContainer:
                Send(state, new ServerContainerS00(new[] { new PacketEventArgs(packetId, packet) }));
                return;

            case PacketType.ClientContainer:
                Send(state, new ClientContainerC22(packetId.PacketId, packet));
                return;
            }
        }
Пример #3
0
        /// <summary>
        /// Convert a data packet to a FingerPrintProtocol oject
        /// </summary>
        /// <param name="pack"></param>
        /// <returns></returns>
        public static FingerPrintProtocol Parse(byte[] pack)
        {
            try
            {
                List <byte>      data       = new List <byte>();
                int              startIndex = FindStartIndex(pack);
                PacketIdentifier pid        = (PacketIdentifier)pack[startIndex + TYPE_INDEX];
                byte             cmd        = pack[startIndex + COMAND_INDEX];

                int length = (pack[startIndex + LENGTH_INDEX] << 8) | (pack[startIndex + LENGTH_INDEX + 1] & 0xff);

                for (int n = (startIndex + DATA_INDEX); n < (startIndex + OVERHEAD + length - 5); n++)
                {
                    data.Add(pack[n]);
                }
                return(new FingerPrintProtocol(pid, cmd, data.ToArray()));
            }
            catch
            {
            }
            return(null);
        }
Пример #4
0
        private void InsertHandlerForPacket(PacketIdentifier packet, IPacketHandler <T> handler)
        {
            // TODO: Throw improved exception (show conflicting packets)
            var identifier = packet.Identifier;

            var handlers = this.packetHandlers;

            for (int i = 0; i < identifier.Count; i++)
            {
                bool isLastIdentifier = i == identifier.Count - 1;
                bool identifierExists = handlers.ContainsKey(identifier[i]);

                if (isLastIdentifier)
                {
                    if (identifierExists)
                    {
                        throw new ConflictingPacketHandlersException(packet);
                    }

                    var value = OneOf <PacketToHandlerDictionary, IPacketHandler <T> > .FromT1(handler);

                    handlers.Add(identifier[i], value);
                }
                else if (identifierExists)
                {
                    handlers = handlers[identifier[i]].Match(
                        dictionary => dictionary,
                        _ => throw new ConflictingPacketHandlersException(packet));
                }
                else
                {
                    var nestedHandlers = new PacketToHandlerDictionary();
                    handlers.Add(identifier[i], nestedHandlers);
                    handlers = nestedHandlers;
                }
            }
        }
Пример #5
0
        public static bool IsReserved(PacketIdentifier identifier)
        {
            ushort sid = (ushort)identifier;

            return(sid >= 0x04 && sid <= 0x0F || sid >= 0x0017 && sid <= 0x001B);
        }
Пример #6
0
 public bool HasPacketType(PacketIdentifier identifier)
 {
     return(_packetTypes.ContainsKey(identifier));
 }
Пример #7
0
        /// <summary>
        /// Method used in <see cref="_receiverTask"/> to receive Netbios Name Service packets
        /// </summary>
        /// <returns>Task that completes when the <see cref="_receiverTask"/> stops receiving packets</returns>
        private async Task Receive()
        {
            var      buffer        = new byte[RECEIVE_BUFFER_SIZE];
            EndPoint localEndPoint = new IPEndPoint(0, 0);

            while (true)
            {
                var tcs = new TaskCompletionSource <EndPoint>();
                try
                {
                    _socket.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref localEndPoint, asynchronousResult =>
                    {
                        var t       = (TaskCompletionSource <EndPoint>)asynchronousResult.AsyncState;
                        EndPoint ep = new IPEndPoint(0, 0);
                        try
                        {
                            _socket.EndReceiveFrom(asynchronousResult, ref ep);
                            t.TrySetResult(ep);
                        }
                        catch (Exception)
                        {
                            t.TrySetResult(null);
                        }
                    }, tcs);
                }
                catch (Exception)
                {
                    if (_endReceive.Task.IsCompleted)
                    {
                        return;
                    }
                    continue;
                }

                // Wait until a new packet has been received or NbNsClient is disposed
                if (await Task.WhenAny(tcs.Task, _endReceive.Task) == _endReceive.Task)
                {
                    return;
                }

                // RemoteEndPoint is null when there was an exception in EndReceive. In that case, discard the packet.
                var remoteEndPoint = (await tcs.Task) as IPEndPoint;
                if (remoteEndPoint == null)
                {
                    continue;
                }

                // If we cannot parse the received packet, discard it.
                NbNsPacketBase packet;
                if (!NbNsPacketBase.TryParse(buffer, out packet))
                {
                    continue;
                }

                // If the received packet is the response to a known request, set the request task result to the received packet.
                var identifier = new PacketIdentifier(packet.Header.NameTrnId, remoteEndPoint.Address);
                TaskCompletionSource <NbNsPacketBase> result;
                if (_pendingUnicastRequests.TryGetValue(identifier, out result))
                {
                    result.TrySetResult(packet);
                }
            }
        }
Пример #8
0
 public RakNetServer(IPEndPoint endPoint, PacketIdentifier identifier)
 {
     Socket = new RakNetSocket(endPoint, identifier);
     Init();
 }
Пример #9
0
 public Type RetrievePacketType(PacketIdentifier identifier)
 {
     return(_packetTypes[identifier]);
 }
Пример #10
0
 public void Display(PacketIdentifier packetId, float time)
 {
     _link.AddGameObject(PacketFactory.Create(packetId).gameObject, time);
 }
Пример #11
0
 /// <summary>Registers a new handler for a packet.</summary>
 protected void RegisterHandler(PacketIdentifier packet, IPacketHandler <T> handler)
 {
     this.InsertHandlerForPacket(packet, handler);
 }
Пример #12
0
 /// <summary>
 /// Generate an encoded packet header string using only the packet identifier.
 /// </summary>
 /// <param name="identifier">Packet identifier to use.</param>
 /// <returns>A packet header string.</returns>
 protected static string EncodeHeader(PacketIdentifier identifier)
 {
     return(((char)identifier).ToString());
 }
Пример #13
0
 /// <summary>
 /// Generate an encoded packet header string using the packet identifier and player index.
 /// </summary>
 /// <param name="identifier">Packet identifier to use.</param>
 /// <param name="player">Player to include in the header, if not null.</param>
 /// <param name="tail">Payload string to include in the packet.</param>
 /// <returns>A whole packet encoded-string.</returns>
 protected static string EncodePacket(PacketIdentifier identifier, Player player, string tail)
 {
     return(EncodeHeader(identifier, player) + SEPARATOR + tail);
 }
 private static string BuildMessage(PacketIdentifier packet) =>
 new StringBuilder()
 .AppendLine("Conflicting packet handlers")
 .Append("Packet: ").AppendLine(packet.Name)
 .Append("Identifier: ").AppendLine(packet.Identifier.ToHexString())
 .ToString();
 /// <summary>Initializes a new instance of the <see cref="ConflictingPacketHandlersException"/> class.</summary>
 public ConflictingPacketHandlersException(PacketIdentifier packet)
     : base(BuildMessage(packet))
 {
 }
Пример #16
0
        public async Task SendWeatherDataAsync(Packet packet, DateTime receivedTime)
        {
            if (packet.type != PacketTypes.Weather)
            {
                throw new InvalidOperationException();
            }

            var now = new DateTimeOffset(receivedTime).ToUniversalTime();

            var subPackets     = packet.packetData as IList <SingleWeatherData>;
            var groupedPackets = subPackets.GroupBy(p => p.sendingStation);

            foreach (var grp in groupedPackets.Where(grp => grp.Count() > 1))
            {
                byte spaceAfter(SingleWeatherData d)
                {
                    if (grp.Count() == 1)
                    {
                        return(255);
                    }
                    var otherPackets = grp.Where(p => p != d);
                    var nextId       = otherPackets.Where(p => p.uniqueID > d.uniqueID)
                                       .Min(p => (byte?)p.uniqueID);

                    if (nextId != null)
                    {
                        return((byte)(nextId - d.uniqueID));
                    }
                    var firstId = otherPackets.Min(p => p.uniqueID);

                    return((byte)(firstId + (255 - d.uniqueID)));
                }

                var      lastId             = grp.OrderBy(p => spaceAfter(p)).Last().uniqueID;
                TimeSpan timeBetweenPackets = TimeSpan.FromSeconds(4);
                foreach (var subPacket in grp)
                {
                    byte idSpace    = (byte)(lastId - subPacket.uniqueID);
                    var  packetTime = now - idSpace * timeBetweenPackets;
                    subPacket.calculatedTime = packetTime;
                }
            }

            foreach (var subPacket in subPackets.OrderBy(p => p.calculatedTime ?? now))
            {
                var identifier = new PacketIdentifier()
                {
                    packetType = 'W',
                    stationID  = subPacket.sendingStation,
                    uniqueID   = subPacket.uniqueID
                };

                if (IsPacketDoubleReceived(identifier, now))
                {
                    continue;
                }
                receivedPacketTimes[identifier] = now;

                var toSerialize = new
                {
                    timestamp      = (subPacket.calculatedTime ?? now).ToUnixTimeSeconds(),
                    wind_speed     = subPacket.windSpeed,
                    wind_direction = subPacket.windDirection,
                    battery        = subPacket.batteryLevelH,
                    external_temp  = subPacket.externalTemp,
                    internal_temp  = subPacket.internalTemp,
                    wind_gust      = subPacket.gust,
                    pwm            = subPacket.pwmValue,
                    current        = subPacket.current,
                };
                var json    = JsonConvert.SerializeObject(toSerialize);
                var content = new StringContent(json, Encoding.UTF8, "application/json");
                var url     = _url + $"/api/station/{subPacket.sendingStation + Offset}/data";
                var uri     = new Uri(url);

                try
                {
                    var response = await _client.PostAsync(uri, content);

                    if (response.IsSuccessStatusCode)
                    {
                        OutputWriter.WriteLine($"Succesfully posted {subPacket.sendingStation}/{(char)packet.type}{subPacket.uniqueID} to {url}.");
                    }
                    else
                    {
                        OutputWriter.WriteLine($"Post of {packet.sendingStation}/{(char)packet.type}{packet.uniqueID} to {url} failed ({response.StatusCode}): {response.ReasonPhrase}");
                        OutputWriter.WriteLine($"Content: {response.Content.ReadAsStringAsync().Result}");
                        OutputWriter.WriteLine($"JSON: {json}");
                    }
                }
                catch (Exception ex)
                {
                    OnException?.Invoke(this, ex);
                }
            }
        }
Пример #17
0
 public PacketType this[PacketIdentifier packetId]
 => _packetTypes.Lookup(packetId).OrElseDefault();
Пример #18
0
 private void CompleteTransmission(PacketIdentifier packetId, LinkIdentifier linkId)
 {
     commandQueue.Enqueue(new NetworkCommand.CompleteTransmission(packetId, linkId));
 }
Пример #19
0
        public static bool IsUserDefined(PacketIdentifier identifier)
        {
            ushort sid = (ushort)identifier; //Encompass ASTCMetaData?

            return(sid >= 0x20 && sid <= 0x1FFA || sid >= 0x1FFC && sid <= 0x1FFE);
        }
Пример #20
0
 public PacketReceiveEventArgs(PacketIdentifier packetId, DataStream packetStream)
 {
     PacketId     = packetId;
     PacketStream = packetStream;
 }
Пример #21
0
        public static bool IsDVBMetaData(PacketIdentifier identifier)
        {
            ushort sid = (ushort)identifier;

            return(sid >= 16 || sid <= Common.Binary.FiveBitMaxValue);
        }
Пример #22
0
 public RakNetSocket(IPEndPoint endPoint, PacketIdentifier identifier) : base(endPoint)
 {
     EndPoint         = endPoint;
     PacketIdentifier = identifier;
 }
Пример #23
0
 /// <summary>Registers a new handler for a packet type.</summary>
 protected void RegisterHandler <TPacket>(IPacketHandler <T> handler)
     where TPacket : IPacket
 {
     this.InsertHandlerForPacket(PacketIdentifier.Get <TPacket>(), handler);
 }
Пример #24
0
 protected bool IsPacketDoubleReceived(PacketIdentifier identifier, DateTimeOffset now)
 => receivedPacketTimes.TryGetValue(identifier, out var lastReceivedTime) &&
 lastReceivedTime + InvalidationTime > now;
Пример #25
0
 public RakNetSocket(IPEndPoint endPoint) : base(endPoint)
 {
     EndPoint         = endPoint;
     PacketIdentifier = new PacketIdentifier();
 }
Пример #26
0
 public MinecraftServer(IPEndPoint endPoint, PacketIdentifier identifier) : base(endPoint, identifier)
 {
 }