public static async Task HandleData(Campaign campaign, AckHandler ackHandler, NackHandler nackHandler) { if (VERBOSE) { Console.WriteLine($" [-] Campaign {campaign.Id} RECEIVED at {DateTime.Now.ToShortDateString()} {DateTime.Now.ToShortTimeString()}."); } var indexingResult = await _campaignIndexer.IndexCampaignAsync(campaign); if (indexingResult.Notifications.Any()) { if (VERBOSE) { foreach (var notification in indexingResult.Notifications) { Console.WriteLine($" [-] {notification.Message} at {DateTime.Now.ToShortDateString()} {DateTime.Now.ToShortTimeString()}."); } } if (indexingResult.IsInvalid) { nackHandler(requeue: false); return; } } if (VERBOSE) { Console.WriteLine($" [x] Campaign {campaign.Id} DONE indexing at {DateTime.Now.ToShortDateString()} {DateTime.Now.ToShortTimeString()}."); } ackHandler(); }
public static async Task HandleData(Visit visit, AckHandler ackHandler, NackHandler nackHandler) { if (VERBOSE) { Console.WriteLine($" [-] Vist {visit.Id} RECEIVED at {DateTime.Now.ToShortDateString()} {DateTime.Now.ToShortTimeString()}."); } var pushingResult = await _campaignPusher.PushCampaignAsync(visit); if (pushingResult.Notifications.Any()) { if (VERBOSE) { foreach (var notification in pushingResult.Notifications) { Console.WriteLine($" [-] {notification.Message} at {DateTime.Now.ToShortDateString()} {DateTime.Now.ToShortTimeString()}."); } } if (pushingResult.IsInvalid) { nackHandler(requeue: false); return; } } if (VERBOSE) { Console.WriteLine($" [x] Visit {visit.Id} DONE pushing campaign at {DateTime.Now.ToShortDateString()} {DateTime.Now.ToShortTimeString()}."); } ackHandler(); }
public void UnregisteredAcksCantBeTriggered() { var ackHandler = new AckHandler(cancelAcksOnTimeout: false, ackThreshold: TimeSpan.Zero, ackInterval: TimeSpan.Zero); Assert.False(ackHandler.TriggerAck("foo")); }
public async Task AcksLastingLongerThanThresholdAreCompleted() { var ackHandler = new AckHandler(completeAcksOnTimeout: true, ackThreshold: TimeSpan.FromSeconds(1), ackInterval: TimeSpan.FromSeconds(1)); await Assert.ThrowsAsync <TaskCanceledException>(() => ackHandler.CreateAck("foo").OrTimeout()); }
public void UnregisteredAcksCantBeTriggered() { var ackHandler = new AckHandler(completeAcksOnTimeout: false, ackThreshold: TimeSpan.Zero, ackInterval: TimeSpan.Zero); Assert.False(ackHandler.TriggerAck("foo")); }
public void cant_ack_without_message_id() { var frame = new BasicFrame("ACK"); var client = Substitute.For <IStompClient>(); var sut = new AckHandler(); Action actual = () => sut.Process(client, frame); actual.ShouldThrow <BadRequestException>(); }
public P2PAckMessageEventArgs(P2PMessage p2pMessage, AckHandler ackHandler, int timeoutSec) : base(p2pMessage) { this.ackHandler = ackHandler; this.deleteTick = timeoutSec; if (timeoutSec != 0) { AddSeconds(timeoutSec); } }
public void TriggeredAcksAreCompleted() { var ackHandler = new AckHandler(cancelAcksOnTimeout: false, ackThreshold: TimeSpan.Zero, ackInterval: TimeSpan.Zero); Task task = ackHandler.CreateAck("foo"); Assert.True(ackHandler.TriggerAck("foo")); Assert.True(task.IsCompleted); }
public void TriggeredAcksAreCompleted() { var ackHandler = new AckHandler(completeAcksOnTimeout: false, ackThreshold: TimeSpan.Zero, ackInterval: TimeSpan.Zero); Task task = ackHandler.CreateAck("foo"); Assert.True(ackHandler.TriggerAck("foo")); Assert.True(task.IsCompleted); }
public void Send(P2PMessage p2pMessage, int ackTimeout, AckHandler ackHandler) { ResetTimeoutTimer(); if (p2pBridge == null) { MigrateToOptimalBridge(); } p2pBridge.Send(this, Remote, RemoteContactEndPointID, p2pMessage, ackTimeout, ackHandler); }
public RedisHubLifetimeManager(ILogger <RedisHubLifetimeManager <THub> > logger, IOptions <RedisOptions> options, IHubProtocolResolver hubProtocolResolver) { _logger = logger; _options = options.Value; _ackHandler = new AckHandler(); _channels = new RedisChannels(typeof(THub).FullName); _protocol = new RedisProtocol(hubProtocolResolver.AllProtocols); RedisLog.ConnectingToEndpoints(_logger, options.Value.Options.EndPoints, _serverName); }
public RedisHubLifetimeManager(ILogger <RedisHubLifetimeManager <THub> > logger, IOptions <RedisOptions> options, IHubProtocolResolver hubProtocolResolver) { _logger = logger; _options = options.Value; _ackHandler = new AckHandler(); _channels = new RedisChannels(typeof(THub).FullName); _protocol = new RedisProtocol(hubProtocolResolver.AllProtocols); var writer = new LoggerTextWriter(logger); RedisLog.ConnectingToEndpoints(_logger, options.Value.Options.EndPoints, _serverName); _redisServerConnection = _options.Connect(writer); _redisServerConnection.ConnectionRestored += (_, e) => { // We use the subscription connection type // Ignore messages from the interactive connection (avoids duplicates) if (e.ConnectionType == ConnectionType.Interactive) { return; } RedisLog.ConnectionRestored(_logger); }; _redisServerConnection.ConnectionFailed += (_, e) => { // We use the subscription connection type // Ignore messages from the interactive connection (avoids duplicates) if (e.ConnectionType == ConnectionType.Interactive) { return; } RedisLog.ConnectionFailed(_logger, e.Exception); }; if (_redisServerConnection.IsConnected) { RedisLog.Connected(_logger); } else { RedisLog.NotConnected(_logger); } _bus = _redisServerConnection.GetSubscriber(); SubscribeToAll(); SubscribeToGroupManagementChannel(); SubscribeToAckChannel(); }
public void AcksLastingLongerThanThresholdAreCancelled() { var ackHandler = new AckHandler(cancelAcksOnTimeout: true, ackThreshold: TimeSpan.FromSeconds(1), ackInterval: TimeSpan.FromSeconds(1)); Task task = ackHandler.CreateAck("foo"); Thread.Sleep(TimeSpan.FromSeconds(5)); Assert.True(task.IsCanceled); }
public ShardingRedisHubLifetimeManager(ILogger <RedisHubLifetimeManager <THub> > logger, IOptions <ShardingRedisOptions> options, IHubProtocolResolver hubProtocolResolver) { _logger = logger; _options = options.Value; _ackHandler = new AckHandler(); _channels = new RedisChannels(typeof(THub).FullName); _protocol = new RedisProtocol(hubProtocolResolver.AllProtocols); _ = EnsureRedisServerConnection(); }
public RedisHubLifetimeManager(ILogger <RedisHubLifetimeManager <THub> > logger, IOptions <RedisOptions> options) { _logger = logger; _options = options.Value; _ackHandler = new AckHandler(); var writer = new LoggerTextWriter(logger); _logger.ConnectingToEndpoints(options.Value.Options.EndPoints); _redisServerConnection = _options.Connect(writer); _redisServerConnection.ConnectionRestored += (_, e) => { // We use the subscription connection type // Ignore messages from the interactive connection (avoids duplicates) if (e.ConnectionType == ConnectionType.Interactive) { return; } _logger.ConnectionRestored(); }; _redisServerConnection.ConnectionFailed += (_, e) => { // We use the subscription connection type // Ignore messages from the interactive connection (avoids duplicates) if (e.ConnectionType == ConnectionType.Interactive) { return; } _logger.ConnectionFailed(e.Exception); }; if (_redisServerConnection.IsConnected) { _logger.Connected(); } else { _logger.NotConnected(); } _bus = _redisServerConnection.GetSubscriber(); SubscribeToHub(); SubscribeToAllExcept(); SubscribeToInternalGroup(); SubscribeToInternalServerName(); }
public void cant_ack_if_message_Was_not_found() { var frame = new BasicFrame("ACK"); frame.Headers["id"] = "aa"; var client = Substitute.For <IStompClient>(); client.IsFramePending("aa").Returns(false); var sut = new AckHandler(); Action actual = () => sut.Process(client, frame); actual.ShouldThrow <BadRequestException>(); }
/// <summary> /// Sends a message with the specified <see cref="P2PMessage"/> and <see cref="AckHandler"/>. /// </summary> public virtual void SendMessage(P2PMessage p2pMessage, int ackTimeout, AckHandler ackHandler) { Debug.Assert(p2pMessage.Version == version); p2pMessage.Header.SessionId = p2pSession.SessionId; // If not an ack, set the footer (p2pv1 only) if (p2pMessage.Version == P2PVersion.P2PV1 && (p2pMessage.V1Header.Flags & P2PFlag.Acknowledgement) != P2PFlag.Acknowledgement) { p2pMessage.Footer = ApplicationId; } p2pSession.Send(p2pMessage, ackTimeout, ackHandler); }
public MsmqHubLifetimeManager( ILogger <MsmqHubLifetimeManager <THub> > logger, IOptions <MsmqOptions> options, IHubProtocolResolver hubProtocolResolver, IMsmqBus msmqBus) { this.logger = logger; this.options = options.Value; this.protocol = new MsmqProtocol(hubProtocolResolver.AllProtocols); this.msmqBus = msmqBus; this.queues = new MsmqQueues(this.options.ApplicationName); this.ackHandler = new AckHandler(); MsmqLog.ConnectingToEndpoints(this.logger, this.options.ConnectionString, this.options.ApplicationName); _ = this.EnsureMsmqServerConnection(); }
public void ack() { var frame = new BasicFrame("ACK"); frame.Headers["id"] = "aa"; var client = Substitute.For <IStompClient>(); var subscription = Substitute.For <Subscription>(client, "aa"); client.IsFramePending("aa").Returns(true); client.GetSubscription("aa").Returns(subscription); var sut = new AckHandler(); sut.Process(client, frame); subscription.Received().Ack("aa"); }
public void enqueue_if_transaction_was_specified() { var frame = new BasicFrame("ACK"); frame.Headers["id"] = "aa"; frame.Headers["transaction"] = "sdfsd"; var client = Substitute.For <IStompClient>(); var subscription = Substitute.For <Subscription>(client, "aa"); client.IsFramePending("aa").Returns(true); client.GetSubscription("aa").Returns(subscription); var sut = new AckHandler(); sut.Process(client, frame); client.Received().EnqueueInTransaction("sdfsd", Arg.Any <Action>(), Arg.Any <Action>()); subscription.DidNotReceive().Ack("aa"); }
/// <summary> /// Constructs the <see cref="RedisHubLifetimeManager{THub}"/> with types from Dependency Injection. /// </summary> /// <param name="logger">The logger to write information about what the class is doing.</param> /// <param name="options">The <see cref="RedisOptions"/> that influence behavior of the Redis connection.</param> /// <param name="hubProtocolResolver">The <see cref="IHubProtocolResolver"/> to get an <see cref="IHubProtocol"/> instance when writing to connections.</param> /// <param name="globalHubOptions">The global <see cref="HubOptions"/>.</param> /// <param name="hubOptions">The <typeparamref name="THub"/> specific options.</param> public RedisHubLifetimeManager(ILogger <RedisHubLifetimeManager <THub> > logger, IOptions <RedisOptions> options, IHubProtocolResolver hubProtocolResolver, IOptions <HubOptions>?globalHubOptions, IOptions <HubOptions <THub> >?hubOptions) { _logger = logger; _options = options.Value; _ackHandler = new AckHandler(); _channels = new RedisChannels(typeof(THub).FullName !); if (globalHubOptions != null && hubOptions != null) { _protocol = new RedisProtocol(new DefaultHubMessageSerializer(hubProtocolResolver, globalHubOptions.Value.SupportedProtocols, hubOptions.Value.SupportedProtocols)); } else { var supportedProtocols = hubProtocolResolver.AllProtocols.Select(p => p.Name).ToList(); _protocol = new RedisProtocol(new DefaultHubMessageSerializer(hubProtocolResolver, supportedProtocols, null)); } RedisLog.ConnectingToEndpoints(_logger, options.Value.Configuration.EndPoints, _serverName); _ = EnsureRedisServerConnection(); }
/// <summary> /// Send a P2P Message to the specified P2PSession. /// </summary> /// <param name="session"> /// The application layer, which is a <see cref="P2PSession"/> /// </param> /// <param name="remote"> /// he receiver <see cref="Contact"/> /// </param> /// <param name="remoteGuid"> /// A <see cref="Guid"/> /// </param> /// <param name="msg"> /// he <see cref="P2PMessage"/> to be sent. /// </param> /// <param name="ackTimeout"> /// The maximum time to wait for an ACK. <see cref="System.Int32"/> /// </param> /// <param name="ackHandler"> /// The <see cref="AckHandler"/> to handle the ACK. /// </param> public virtual void Send(P2PSession session, Contact remote, Guid remoteGuid, P2PMessage msg, int ackTimeout, AckHandler ackHandler) { if (remote == null) { throw new ArgumentNullException("remote"); } P2PMessage[] msgs = SetSequenceNumberAndRegisterAck(session, remote, msg, ackHandler, ackTimeout); if (session == null) { if (!IsOpen) { Trace.WriteLineIf(Settings.TraceSwitch.TraceError, "Send called with no session on a closed bridge", GetType().Name); return; } // Bypass queueing foreach (P2PMessage m in msgs) { SendOnePacket(null, remote, remoteGuid, m); } return; } if (!SuitableFor(session)) { Trace.WriteLineIf(Settings.TraceSwitch.TraceError, "Send called with a session this bridge is not suitable for", GetType().Name); return; } lock (sendQueues) { if (!sendQueues.ContainsKey(session)) { sendQueues[session] = new P2PSendQueue(); } } lock (sendQueues[session]) { foreach (P2PMessage m in msgs) { sendQueues[session].Enqueue(remote, remoteGuid, m); } } ProcessSendQueues(); }
public void Send(P2PMessage p2pMessage, AckHandler ackHandler) { Send(p2pMessage, P2PBridge.DefaultTimeout, ackHandler); }
public TestServiceConnectionContainer(List <IServiceConnection> serviceConnections, HubServiceEndpoint endpoint = null, AckHandler ackHandler = null, IServiceConnectionFactory factory = null, ILogger logger = null) : base(factory, 0, endpoint, serviceConnections, ackHandler: ackHandler, logger: logger ?? NullLogger.Instance) { }
private void SendChunk() { if (!_sendingData) { return; } P2PDataMessage p2pChunk = new P2PDataMessage(P2PVersion); long offset = _dataStream.Position; // First chunk if (offset == 0) { if (P2PVersion == P2PVersion.P2PV1) { P2PSession.IncreaseLocalIdentifier(); p2pChunk.V1Header.TotalSize = (ulong)_dataStream.Length; } else if (P2PVersion == P2PVersion.P2PV2) { p2pChunk.V2Header.TFCombination = TFCombination.First; } } p2pChunk.Header.Identifier = P2PSession.LocalIdentifier; p2pChunk.WriteBytes(_dataStream, P2PSession.Bridge.MaxDataSize); AckHandler ackHandler = null; int ackTimeout = P2PBridge.MaxTimeout; if (P2PVersion == P2PVersion.P2PV1) { p2pChunk.V1Header.Flags = P2PFlag.FileData; } else if (P2PVersion == P2PVersion.P2PV2) { p2pChunk.V2Header.PackageNumber = packNum; p2pChunk.V2Header.TFCombination |= TFCombination.FileTransfer; if (p2pv2NextRAK < DateTime.Now) { _sendingData = false; // Activate when ack received. p2pChunk.V2Header.OperationCode |= (byte)OperationCode.RAK; p2pv2NextRAK = DateTime.Now.AddSeconds(8); ackTimeout = P2PBridge.DefaultTimeout; ackHandler = delegate(P2PMessage ack) { _sendingData = true; // Ack received, continue sending... SendChunk(); }; } } if (_dataStream.Position == _dataStream.Length) { _sendingData = false; SendMessage(p2pChunk); // This is the last chunk of data, register the ACKHandler P2PMessage rak = new P2PMessage(P2PVersion); SendMessage(rak, P2PBridge.DefaultTimeout, delegate(P2PMessage ack) { Abort(); OnTransferFinished(EventArgs.Empty); }); } else { SendMessage(p2pChunk, ackTimeout, ackHandler); } OnProgressed(EventArgs.Empty); }
private P2PMessage[] SetSequenceNumberAndRegisterAck(P2PSession session, Contact remote, P2PMessage p2pMessage, AckHandler ackHandler, int timeout) { if (p2pMessage.Header.Identifier == 0) { if (p2pMessage.Version == P2PVersion.P2PV1) { p2pMessage.Header.Identifier = ++sequenceId; } else if (p2pMessage.Version == P2PVersion.P2PV2) { p2pMessage.V2Header.Identifier = sequenceId; } } if (p2pMessage.Version == P2PVersion.P2PV1 && p2pMessage.V1Header.AckSessionId == 0) { p2pMessage.V1Header.AckSessionId = (uint)new Random().Next(50000, int.MaxValue); } if (p2pMessage.Version == P2PVersion.P2PV2 && p2pMessage.V2Header.PackageNumber == 0) { p2pMessage.V2Header.PackageNumber = packageNo; } P2PMessage[] msgs = p2pMessage.SplitMessage(MaxDataSize); if (p2pMessage.Version == P2PVersion.P2PV2) { // Correct local sequence no P2PMessage lastMsg = msgs[msgs.Length - 1]; SequenceId = lastMsg.V2Header.Identifier + lastMsg.V2Header.MessageSize; } if (ackHandler != null) { P2PMessage firstMessage = msgs[0]; RegisterAckHandler(new P2PAckMessageEventArgs(firstMessage, ackHandler, timeout)); } if (session != null) { session.LocalIdentifier = SequenceId; } return msgs; }
public RedisHubLifetimeManager(ILogger <RedisHubLifetimeManager <THub> > logger, IOptions <RedisOptions> options) { _logger = logger; _options = options.Value; _ackHandler = new AckHandler(); var writer = new LoggerTextWriter(logger); _logger.LogInformation("Connecting to redis endpoints: {endpoints}", string.Join(", ", options.Value.Options.EndPoints.Select(e => EndPointCollection.ToString(e)))); _redisServerConnection = _options.Connect(writer); if (_redisServerConnection.IsConnected) { _logger.LogInformation("Connected to redis"); } else { // TODO: We could support reconnecting, like old SignalR does. throw new InvalidOperationException("Connection to redis failed."); } _bus = _redisServerConnection.GetSubscriber(); var previousBroadcastTask = Task.CompletedTask; var channelName = _channelNamePrefix; _logger.LogInformation("Subscribing to channel: {channel}", channelName); _bus.Subscribe(channelName, async(c, data) => { await previousBroadcastTask; _logger.LogTrace("Received message from redis channel {channel}", channelName); var message = DeserializeMessage <HubMessage>(data); // TODO: This isn't going to work when we allow JsonSerializer customization or add Protobuf var tasks = new List <Task>(_connections.Count); foreach (var connection in _connections) { tasks.Add(WriteAsync(connection, message)); } previousBroadcastTask = Task.WhenAll(tasks); }); var allExceptTask = Task.CompletedTask; channelName = _channelNamePrefix + ".AllExcept"; _logger.LogInformation("Subscribing to channel: {channel}", channelName); _bus.Subscribe(channelName, async(c, data) => { await allExceptTask; _logger.LogTrace("Received message from redis channel {channel}", channelName); var message = DeserializeMessage <RedisExcludeClientsMessage>(data); var excludedIds = message.ExcludedIds; // TODO: This isn't going to work when we allow JsonSerializer customization or add Protobuf var tasks = new List <Task>(_connections.Count); foreach (var connection in _connections) { if (!excludedIds.Contains(connection.ConnectionId)) { tasks.Add(WriteAsync(connection, message)); } } allExceptTask = Task.WhenAll(tasks); }); channelName = _channelNamePrefix + ".internal.group"; _bus.Subscribe(channelName, async(c, data) => { var groupMessage = DeserializeMessage <GroupMessage>(data); if (groupMessage.Action == GroupAction.Remove) { if (!await RemoveGroupAsyncCore(groupMessage.ConnectionId, groupMessage.Group)) { // user not on this server return; } } if (groupMessage.Action == GroupAction.Add) { if (!await AddGroupAsyncCore(groupMessage.ConnectionId, groupMessage.Group)) { // user not on this server return; } } // Sending ack to server that sent the original add/remove await PublishAsync($"{_channelNamePrefix}.internal.{groupMessage.Server}", new GroupMessage { Action = GroupAction.Ack, ConnectionId = groupMessage.ConnectionId, Group = groupMessage.Group, Id = groupMessage.Id }); }); // Create server specific channel in order to send an ack to a single server var serverChannel = $"{_channelNamePrefix}.internal.{_serverName}"; _bus.Subscribe(serverChannel, (c, data) => { var groupMessage = DeserializeMessage <GroupMessage>(data); if (groupMessage.Action == GroupAction.Ack) { _ackHandler.TriggerAck(groupMessage.Id); } }); }
public PulledMessage(BaseMessage message, AckHandler handler) : base(message) { _handler = handler ?? throw new ArgumentNullException(nameof(handler)); _pulledTime = DateTime.Now.ToTime(); }
public TestBaseServiceConnectionContainer(List <IServiceConnection> serviceConnections, HubServiceEndpoint endpoint = null, AckHandler ackHandler = null) : base(null, 0, endpoint, serviceConnections, ackHandler: ackHandler) { }
public void Send(P2PMessage p2pMessage, int ackTimeout, AckHandler ackHandler) { ResetTimeoutTimer(); if (p2pBridge == null) MigrateToOptimalBridge(); p2pBridge.Send(this, Remote, RemoteContactEndPointID, p2pMessage, ackTimeout, ackHandler); }
/// <summary> /// Send a P2P Message to the specified P2PSession. /// </summary> /// <param name="session"> /// The application layer, which is a <see cref="P2PSession"/> /// </param> /// <param name="remote"> /// he receiver <see cref="Contact"/> /// </param> /// <param name="remoteGuid"> /// A <see cref="Guid"/> /// </param> /// <param name="msg"> /// he <see cref="P2PMessage"/> to be sent. /// </param> /// <param name="ackTimeout"> /// The maximum time to wait for an ACK. <see cref="System.Int32"/> /// </param> /// <param name="ackHandler"> /// The <see cref="AckHandler"/> to handle the ACK. /// </param> public virtual void Send(P2PSession session, Contact remote, Guid remoteGuid, P2PMessage msg, int ackTimeout, AckHandler ackHandler) { if (remote == null) throw new ArgumentNullException("remote"); P2PMessage[] msgs = SetSequenceNumberAndRegisterAck(session, remote, msg, ackHandler, ackTimeout); if (session == null) { if (!IsOpen) { Trace.WriteLineIf(Settings.TraceSwitch.TraceError, "Send called with no session on a closed bridge", GetType().Name); return; } // Bypass queueing foreach (P2PMessage m in msgs) { SendOnePacket(null, remote, remoteGuid, m); } return; } if (!SuitableFor(session)) { Trace.WriteLineIf(Settings.TraceSwitch.TraceError, "Send called with a session this bridge is not suitable for", GetType().Name); return; } lock (sendQueues) { if (!sendQueues.ContainsKey(session)) sendQueues[session] = new P2PSendQueue(); } lock (sendQueues[session]) { foreach (P2PMessage m in msgs) sendQueues[session].Enqueue(remote, remoteGuid, m); } ProcessSendQueues(); }
/// <summary> /// Sends a message with the specified <see cref="P2PMessage"/> and <see cref="AckHandler"/>. /// </summary> public virtual void SendMessage(P2PMessage p2pMessage, int ackTimeout, AckHandler ackHandler) { Debug.Assert(p2pMessage.Version == version); p2pMessage.Header.SessionId = p2pSession.SessionId; // If not an ack, set the footer (p2pv1 only) if (p2pMessage.Version == P2PVersion.P2PV1 && (p2pMessage.V1Header.Flags & P2PFlag.Acknowledgement) != P2PFlag.Acknowledgement) p2pMessage.Footer = ApplicationId; p2pSession.Send(p2pMessage, ackTimeout, ackHandler); }
private CustomizedPingTimerFactory(IServiceConnectionFactory serviceConnectionFactory, int minConnectionCount, HubServiceEndpoint endpoint, IReadOnlyList <IServiceConnection> initialConnections = null, ILogger logger = null, AckHandler ackHandler = null) : base(serviceConnectionFactory, minConnectionCount, endpoint, initialConnections, logger, ackHandler) { }
/// <summary> /// Emits an event on the socket which gets sent to the server and listens to an acknowledgement from the server /// </summary> /// <param name="ev">The name of the event</param> /// <param name="ackHandler">The delegate to be executed upon acknowledgement</param> /// <param name="data">The data to be serialized/sent</param> public void Emit(string ev, Action <JArray> ackHandler, params object[] data) { socketConnection.Send(Packet.Event(ev, data, nextEventID)); ackHandlers[nextEventID] = new AckHandler(ackHandler); nextEventID++; }
private P2PMessage[] SetSequenceNumberAndRegisterAck(P2PSession session, Contact remote, P2PMessage p2pMessage, AckHandler ackHandler, int timeout) { if (p2pMessage.Header.Identifier == 0) { if (p2pMessage.Version == P2PVersion.P2PV1) { p2pMessage.Header.Identifier = ++sequenceId; } else if (p2pMessage.Version == P2PVersion.P2PV2) { p2pMessage.V2Header.Identifier = sequenceId; } } if (p2pMessage.Version == P2PVersion.P2PV1 && p2pMessage.V1Header.AckSessionId == 0) { p2pMessage.V1Header.AckSessionId = (uint)new Random().Next(50000, int.MaxValue); } if (p2pMessage.Version == P2PVersion.P2PV2 && p2pMessage.V2Header.PackageNumber == 0) { p2pMessage.V2Header.PackageNumber = packageNo; } P2PMessage[] msgs = p2pMessage.SplitMessage(MaxDataSize); if (p2pMessage.Version == P2PVersion.P2PV2) { // Correct local sequence no P2PMessage lastMsg = msgs[msgs.Length - 1]; SequenceId = lastMsg.V2Header.Identifier + lastMsg.V2Header.MessageSize; } if (ackHandler != null) { P2PMessage firstMessage = msgs[0]; RegisterAckHandler(new P2PAckMessageEventArgs(firstMessage, ackHandler, timeout)); } if (session != null) { session.LocalIdentifier = SequenceId; } return(msgs); }