/// <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); }
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; } }
/// <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); }
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; } } }
public static bool IsReserved(PacketIdentifier identifier) { ushort sid = (ushort)identifier; return(sid >= 0x04 && sid <= 0x0F || sid >= 0x0017 && sid <= 0x001B); }
public bool HasPacketType(PacketIdentifier identifier) { return(_packetTypes.ContainsKey(identifier)); }
/// <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); } } }
public RakNetServer(IPEndPoint endPoint, PacketIdentifier identifier) { Socket = new RakNetSocket(endPoint, identifier); Init(); }
public Type RetrievePacketType(PacketIdentifier identifier) { return(_packetTypes[identifier]); }
public void Display(PacketIdentifier packetId, float time) { _link.AddGameObject(PacketFactory.Create(packetId).gameObject, time); }
/// <summary>Registers a new handler for a packet.</summary> protected void RegisterHandler(PacketIdentifier packet, IPacketHandler <T> handler) { this.InsertHandlerForPacket(packet, handler); }
/// <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()); }
/// <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)) { }
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); } } }
public PacketType this[PacketIdentifier packetId] => _packetTypes.Lookup(packetId).OrElseDefault();
private void CompleteTransmission(PacketIdentifier packetId, LinkIdentifier linkId) { commandQueue.Enqueue(new NetworkCommand.CompleteTransmission(packetId, linkId)); }
public static bool IsUserDefined(PacketIdentifier identifier) { ushort sid = (ushort)identifier; //Encompass ASTCMetaData? return(sid >= 0x20 && sid <= 0x1FFA || sid >= 0x1FFC && sid <= 0x1FFE); }
public PacketReceiveEventArgs(PacketIdentifier packetId, DataStream packetStream) { PacketId = packetId; PacketStream = packetStream; }
public static bool IsDVBMetaData(PacketIdentifier identifier) { ushort sid = (ushort)identifier; return(sid >= 16 || sid <= Common.Binary.FiveBitMaxValue); }
public RakNetSocket(IPEndPoint endPoint, PacketIdentifier identifier) : base(endPoint) { EndPoint = endPoint; PacketIdentifier = identifier; }
/// <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); }
protected bool IsPacketDoubleReceived(PacketIdentifier identifier, DateTimeOffset now) => receivedPacketTimes.TryGetValue(identifier, out var lastReceivedTime) && lastReceivedTime + InvalidationTime > now;
public RakNetSocket(IPEndPoint endPoint) : base(endPoint) { EndPoint = endPoint; PacketIdentifier = new PacketIdentifier(); }
public MinecraftServer(IPEndPoint endPoint, PacketIdentifier identifier) : base(endPoint, identifier) { }