// Broadcast an event-specific protocol message across subscribed clients // Returns true if it sent the message to at least one endpoint. Returns false if the message couldn't be sent to any endpoints /// <summary> /// Broadcasts an event message to all clients who are subscribed to receive the specific event type and wallet address. /// </summary> /// <remarks> /// Events are filtered by type and address. A client must subscribe to the specifif type for specific addresses in order to receive this data. /// The payload `data` should be properly formatted for the given `code` - this function will not ensure that this is so and /// the caller must provide a valid message to this function. /// The `skipEndpoint` parameter is useful when re-broadcasting a message received from a specific endpoint and do not wish to echo the same /// data back to the sender. /// </remarks> /// <param name="type">Type of the event message - used to filter subscribers</param> /// <param name="address">Address, which triggered the event.</param> /// <param name="code">Ixian protocol code.</param> /// <param name="data">Payload data.</param> /// <param name="helper_data">Optional additional data, as required by `code`.</param> /// <param name="skipEndpoint">Endpoint to skip when broadcasting.</param> /// <returns>True, if at least one message was sent to at least one remote endpoint. False if no messages were sent.</returns> public static bool broadcastEventDataMessage(NetworkEvents.Type type, byte[] address, ProtocolMessageCode code, byte[] data, byte[] helper_data, RemoteEndpoint skipEndpoint = null) { // Send it to subscribed C nodes bool f_result = NetworkServer.broadcastEventData(type, code, data, address, helper_data, skipEndpoint); return(f_result); }
// Check if the remote endpoint is subscribed to an event for a specific address // Returns true if subscribed public bool isSubscribedToEvent(NetworkEvents.Type type, byte[] address) { if (address == null) { return(false); } lock (subscribedAddresses) { foreach (var entry in subscribedAddresses) { // Check for the specific event type if (entry.Value != type) { continue; } // Use the address matcher to see if this address qualifies if (AddressMatcher.matches(entry.Key, address, CoreConfig.matcherBytesPerAddress)) { return(true); } } } return(false); }
// Unsubscribe from event public bool detachEventType(NetworkEvents.Type type) { lock (subscribedFilters) { // Check if we're subscribed already to this address if (subscribedFilters.ContainsKey(type) == true) { subscribedFilters.Remove(type); } } return(true); }
/// <summary> /// Sends the specified event to all connected clients. /// The information is only sent to those clients who have previously subscribed to this event type /// </summary> /// <param name="type">Types of the event that has occurred.</param> /// <param name="code">Type of the protocol message being sent.</param> /// <param name="data">Byte-field of the data, appropriate for the specific `code` used.</param> /// <param name="address">Ixian Wallet Address which triggered the event</param> /// <param name="helper_data">Optional, additional data to transmit after `data`.</param> /// <param name="skipEndpoint">If given, the message will not be sent to this remote endpoint. This prevents echoing the message to the originating node.</param> /// <returns>True, if at least one message was sent to at least one client.</returns> public static bool broadcastEventData(NetworkEvents.Type type, ProtocolMessageCode code, byte[] data, byte[] address, byte[] helper_data, RemoteEndpoint skipEndpoint = null) { bool result = false; try { QueueMessage queue_message = RemoteEndpoint.getQueueMessage(code, data, helper_data); lock (connectedClients) { foreach (RemoteEndpoint endpoint in connectedClients) { if (skipEndpoint != null) { if (endpoint == skipEndpoint) { continue; } } if (!endpoint.isConnected()) { continue; } if (endpoint.helloReceived == false) { continue; } if (endpoint.presenceAddress == null || (endpoint.presenceAddress.type != 'C' && endpoint.presenceAddress.type != 'R')) { continue; } // Finally, check if the endpoint is subscribed to this event and address if (endpoint.isSubscribedToAddress(type, address)) { endpoint.sendData(queue_message); result = true; } } } }catch (Exception e) { Logging.error("Exception occured in NetworkServer.broadcastEventData: " + e); } return(result); }
public bool detachEventAddress(NetworkEvents.Type type, byte[] address) { if (address == null) { return(true); } lock (subscribedFilters) { if (subscribedFilters.ContainsKey(type) == true) { subscribedFilters[type].Delete(address); } } return(true); }
// Subscribe to event public bool attachEvent(NetworkEvents.Type type, byte[] filter) { if (address == null) { return(false); } lock (subscribedFilters) { // Check the quota int num_subscribed_addresses = subscribedFilters.Values.Aggregate(0, (acc, f) => acc + f.numItems); if (num_subscribed_addresses > CoreConfig.maximumSubscribableEvents) { return(false); } } Cuckoo cuckoo_filter = null; try { cuckoo_filter = new Cuckoo(filter); } catch (Exception) { Logging.warn("Error while attempting to replace {0} filter for endpoint {1}", type.ToString(), getFullAddress() ); return(false); } if (cuckoo_filter == null) { Logging.warn("Cannot attach event {0} to Remote Endpoint {1}, cuckoo filter is null.", type.ToString(), getFullAddress() ); return(false); } lock (subscribedFilters) { // Subscribing a new cuckoo for a particular event type will replace the old one subscribedFilters.AddOrReplace(type, cuckoo_filter); } return(true); }
// Check if the remote endpoint is subscribed to an event for a specific address // Returns true if subscribed public bool isSubscribedToAddress(NetworkEvents.Type type, byte[] address) { if (address == null) { return(false); } lock (subscribedFilters) { if (subscribedFilters.ContainsKey(type) == true) { return(subscribedFilters[type].Contains(address)); } } return(false); }
// Unsubscribe from event public bool detachEvent(NetworkEvents.Type type, byte[] address) { if (address == null) { return(false); } lock (subscribedAddresses) { // Check if we're subscribed already to this address if (subscribedAddresses.ContainsKey(address) == true) { subscribedAddresses.Remove(address); } } return(true); }
// Sends event data to all subscribed clients public static bool broadcastEventData(NetworkEvents.Type type, ProtocolMessageCode code, byte[] data, byte[] address, byte[] helper_data, RemoteEndpoint skipEndpoint = null) { bool result = false; lock (connectedClients) { foreach (RemoteEndpoint endpoint in connectedClients) { if (skipEndpoint != null) { if (endpoint == skipEndpoint) { continue; } } if (!endpoint.isConnected()) { continue; } if (endpoint.helloReceived == false) { continue; } if (endpoint.presenceAddress == null || endpoint.presenceAddress.type != 'C') { continue; } // Finally, check if the endpoint is subscribed to this event and address if (endpoint.isSubscribedToEvent(type, address)) { endpoint.sendData(code, data, helper_data); result = true; } } } return(result); }
// Unsubscribe multiple events public bool detachEvents(NetworkEvents.Type type) { lock (subscribedAddresses) { // remove all types if (type == NetworkEvents.Type.all) { subscribedAddresses = new Dictionary <byte[], NetworkEvents.Type>(); return(true); } foreach (var entry in subscribedAddresses) { if (entry.Value == type) { subscribedAddresses.Remove(entry.Key); } } } return(true); }
// Subscribe to event public bool attachEvent(NetworkEvents.Type type, byte[] address) { if (address == null) { return(false); } lock (subscribedAddresses) { // Check the quota if (subscribedAddresses.Count > CoreConfig.maximumSubscribableEvents) { return(false); } // Check if we're subscribed already to this address if (subscribedAddresses.ContainsKey(address) == false) { subscribedAddresses.Add(address, type); } } return(true); }