public static void Subscribe(this DataLinkCollection dlc, string channel, Action <DataLink, string, Memory <byte> > action) => dlc.Subscribe( channel, (d, s, m) => { action(d, s, m); return(new ValueTask <bool>(true)); });
public static void Subscribe(this DataLinkCollection dlc, string channel, Func <DataLink, string, Memory <byte>, ValueTask> action) => dlc.Subscribe( channel, async(d, s, m) => { await action(d, s, m); return(true); });
public override async void OnHealthyChanged(DataLinkCollection sender, DataLink dataLink) { if (!dataLink.IsHealthy) { await dataLink.Disconnect(); _ = _dlf.ConnectAsync(dataLink.RemoteName, dataLink.RemoteListenPort, sender); } }
public static async Task <bool> BroadcastWithAckWithTrackAsync(this DataLinkCollection dlc, string group, string content) { var length = Encoding.UTF8.GetByteCount(content); using (var owner = ExactSizeMemoryPool.Shared.Rent(length)) { Encoding.UTF8.GetBytes(content, owner.Memory.Span); return(await dlc.BroadcastWithAckWithTrackAsync(group, owner.Memory)); } }
public static async ValueTask SendTo(this DataLinkCollection dlc, string peer, string group, string content) { var length = Encoding.UTF8.GetByteCount(content); using (var owner = ExactSizeMemoryPool.Shared.Rent(length)) { Encoding.UTF8.GetBytes(content, owner.Memory.Span); await dlc.SendTo(peer, group, owner.Memory); } }
public Program(string name, ushort port, X509Certificate2 certificate) { _dlcs = new DataLinkCollectionStore(port); _dlf = new DataLinkFactory(_dlcs, this, port, certificate); _dlcs.Add(nameof(Program), this, name); _dlc = _dlcs.Get(nameof(Program)); _dlc.Subscribe(BroadcastChannel, OnBroadcast); _dlc.Subscribe(P2PChannel, OnP2P); _dlc.Subscribe(PerfChannel, OnPerf); _ = StartAutoSync(); }
internal DataLink(DataLinkCollection dlc, IPEndPoint remote, Stream stream, IDataLinkHandler handler, DataLinkDecoder decoder, DCConnectMessage connectMessage, ReadOnlyMemory <byte> memory) { _dlc = dlc; _stream = stream; _handler = handler; _decoder = decoder; Remote = remote; RemoteName = connectMessage.InstanceName; RemoteListenPort = connectMessage.Port; _inPipe.Writer.WriteAsync(memory); _inPipe.Writer.FlushAsync(); }
public async Task ConnectAsync(string hostname, int port, DataLinkCollection dlc, ReadOnlyMemory <byte> args = default) { Socket socket = null; bool success = false; try { socket = new Socket(SocketType.Stream, ProtocolType.Tcp); await socket.ConnectAsync(hostname, port); var stream = new SslStream(new NetworkStream(socket, true)); await stream.AuthenticateAsClientAsync( new SslClientAuthenticationOptions { AllowRenegotiation = true, CertificateRevocationCheckMode = X509RevocationMode.NoCheck, ClientCertificates = new X509CertificateCollection { _certificate }, EnabledSslProtocols = SslProtocols.Tls12, EncryptionPolicy = EncryptionPolicy.RequireEncryption, RemoteCertificateValidationCallback = (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) => certificate.Equals(_certificate), TargetHost = nameof(DataLink), }); if (await CreateDataLinkAsClientAsync(socket.RemoteEndPoint as IPEndPoint, stream, dlc, args) != null) { success = true; } } finally { if (!success) { socket?.Close(); } } }
public override void OnReplySyncNode(DataLinkCollection sender, string host, ushort port, string name) { _ = _dlf.ConnectAsync(host, port, sender); }
public virtual void OnHealthyChanged(DataLinkCollection sender, DataLink dataLink) { }
public virtual void OnReplySyncNode(DataLinkCollection sender, string host, ushort port, string name) { }
public static void Subscribe(this DataLinkCollection dlc, string channel, Func <DataLink, string, Memory <byte>, bool> action) => dlc.Subscribe( channel, (d, s, m) => new ValueTask <bool>(action(d, s, m)));
private async Task <DataLink> CreateDataLinkAsClientAsync(IPEndPoint remote, Stream stream, DataLinkCollection dlc, ReadOnlyMemory <byte> args) { using (var cm = DataLinkEncoder.Encode(new DCConnectMessage(dlc.ServiceName, dlc.Name, LocalPort, args))) { await stream.WriteAsync(cm.Memory); await stream.FlushAsync(); } var decoder = new DataLinkDecoder(); // 1024 is enough for current connect message. using (var owner = MemoryPool <byte> .Shared.Rent(1024)) { int count = 0; while (true) { count += await stream.ReadAsync(owner.Memory.Slice(count)); if (decoder.TryParseTransportMessage(new ReadOnlySequence <byte>(owner.Memory.Slice(0, count)), out var tm)) { if (tm.Type != DataLinkMessageType.Connect) { stream.Close(); return(null); } var connect = decoder.ParseConnect(tm.Content); if (connect.ServiceName != dlc.ServiceName) { stream.Close(); return(null); } if (connect.InstanceName == dlc.Name) { stream.Close(); return(null); } var moreData = owner.Memory.Slice(tm.Length, count - tm.Length); return(dlc.CreateInternal(remote, stream, decoder, connect, moreData)); } } } }