private async Task StartInternal() { while (!cancel.IsCancellationRequested) { var rec = await client.ReceiveAsync().WithCancellation(cancel.Token); Debug.Assert(rec.Buffer.Length > 0); try { DiscoveryAnnounceMessage messageReq; messageReq = settings.MessageSerializer.Deserialize <DiscoveryAnnounceMessage>(rec.Buffer); var endpoint = new IPEndPoint(rec.RemoteEndPoint.Address, messageReq.ServicePort); if (!compatibilityChecker.IsCompatibleWith(endpoint, messageReq.Version)) { continue; } PeerDiscoveryMode mode = PeerDiscoveryMode.UdpDiscovery; bool isLoopback = messageReq.PeerId.Equals(announce.PeerId); if (isLoopback) { mode |= PeerDiscoveryMode.Loopback; } registry.UpdatePeers(new PeerUpdateInfo[] { new PeerUpdateInfo(endpoint, mode, TimeSpan.Zero) }); logger.LogTrace($"Received request from {rec.RemoteEndPoint.Address}."); } catch (OperationCanceledException) { return; } catch (Exception e) { logger.LogDebug($"Cannot read message from {rec.RemoteEndPoint}. Reason: {e.Message}"); continue; } try { await client.SendAsync(announceBytes, announceBytes.Length, rec.RemoteEndPoint).WithCancellation(cancel.Token); } catch (OperationCanceledException) { return; } catch (SocketException) { logger.LogTrace($"Client {rec.RemoteEndPoint} closed connection befory reply."); } catch (Exception e) { logger.LogDebug($"Error sending response to client {rec.RemoteEndPoint}: {e.Message}"); } } }
public async Task Discover() { using (client = new UdpClient()) { var ip = new IPEndPoint(IPAddress.Broadcast, settings.UdpAnnouncePort); Debug.Assert(announceBytes.Length > 0); var lengthSent = await client.SendAsync(announceBytes, announceBytes.Length, ip); if (lengthSent != announceBytes.Length) { throw new InvalidOperationException("Cannot send discovery datagram."); } var timeout = new CancellationTokenSource(settings.UdpDiscoveryTimeout); while (!timeout.IsCancellationRequested) { DiscoveryAnnounceMessage response = null; try { var responseData = await client.ReceiveAsync().WithCancellation(timeout.Token); response = settings.MessageSerializer.Deserialize <DiscoveryAnnounceMessage>(responseData.Buffer); var endpoint = new IPEndPoint(responseData.RemoteEndPoint.Address, response.ServicePort); if (!compatibilityChecker.IsCompatibleWith(endpoint, response.Version)) { continue; } PeerDiscoveryMode mode = PeerDiscoveryMode.UdpDiscovery; bool isLoopback = response.PeerId.Equals(announce.PeerId); if (isLoopback) { mode |= PeerDiscoveryMode.Loopback; } registry.UpdatePeers(new PeerUpdateInfo[] { new PeerUpdateInfo(endpoint, mode, TimeSpan.Zero) }); } catch (OperationCanceledException) { break; } catch (Exception e) { logger.LogDebug($"Cannot deserialize discovery response: {e}"); } } } }
public void OnActionExecuting(ActionExecutingContext context) { if (!context.HttpContext.Request.Headers.TryGetValue(VersionHeaderName, out StringValues valueString)) { ProcessInvalidVersion(context, $"Missing header {VersionHeaderName}"); return; } if (!ClientVersion.TryParse(valueString, out ClientVersion version)) { ProcessInvalidVersion(context, $"Invalid value of header {VersionHeaderName}"); return; } if (!CompatibilityChecker.IsCompatibleWith(CompatibilitySet.Network, context.HttpContext.Connection.RemoteIpAddress.ToString(), version)) { ProcessInvalidVersion(context, $"Server is incompatible with version defined in header {VersionHeaderName}"); return; } // validate if this is not request from myself if (!context.HttpContext.Request.Headers.TryGetValue(InstanceHeaderName, out valueString)) { ProcessInvalidVersion(context, $"Missing header {InstanceHeaderName}"); return; } if (!Hash.TryParse(valueString, out Hash hash)) { ProcessInvalidVersion(context, $"Invalid value of header {InstanceHeaderName}"); return; } // validate input type header if (!context.HttpContext.Request.Headers.TryGetValue(TypeHeaderName, out StringValues _)) { ProcessInvalidVersion(context, $"Missing header {TypeHeaderName}"); return; } var controller = (IHttpApiController)context.Controller; controller.RemoteIpAddress = context.HttpContext.Connection.RemoteIpAddress; controller.PeerId = hash; controller.IsLoopback = hash.Equals(InstanceHash.Hash); }