/// <summary> /// Add a new subscription for a certain service /// </summary> /// <param name="tag">The TypeTag for which to add the listener</param> /// <param name="listener">Listener to add (must be an instance of ServiceListener)</param> /// <returns>Returns a ServiceSubscription, which can be used to manage your subscription</returns> public ServiceSubscription AddServiceSubscription(TypeTag tag, ServiceListenerBase listener) { // Try to get the list of listeners, then add it. If it doesn't exist, create one first List<ServiceListenerBase> listenerList; // Try to get the list if it exists (and add the listener to it) if (serviceSubscriptions.TryGetValue(tag, out listenerList)) listenerList.Add(listener); else { // Otherwise create a new list and add it listenerList = new List<ServiceListenerBase> { listener }; serviceSubscriptions.Add(tag, listenerList); } // Now create an Action which can later be invoked by the user to cancel his subscription Action remover = () => { // Try to remove it from the list of listeners (categorized by TypeTag) // If it's the only element left in the list, just remove the entry as a whole List<ServiceListenerBase> listenerList_; if (serviceSubscriptions.TryGetValue(tag, out listenerList_)) if (listenerList.Count > 1) listenerList_.Remove(listener); else serviceSubscriptions.Remove(tag); }; // Now return an instance of ServiceSubscription so the user can manage his subscription return new ServiceSubscription(remover); }
/// <summary> /// Add a new service to the list of imported services. /// Will trigger the ServiceDisconnectedEvent or ServiceReconnectedEvent (whichever is appropriate) /// Will also ignore any service if it has already been imported /// </summary> /// <param name="serviceIdentifier">The identifier of the service</param> /// <param name="sourceAddress">The address which exported the service</param> /// <param name="serviceImplementation">The actual exported service</param> public void AddService(TypeTag typeTag, Guid serviceIdentifier, string sourceAddress, object serviceImplementation) { // If the service has already been imported - ignore it if (this.importedServices.ContainsKey(serviceIdentifier)) return; this.importedServices.Add(serviceIdentifier, serviceImplementation); this.importedServiceTypeTags.Add(serviceIdentifier, typeTag); // Check if we have already imported other services from this particular client. If yes, add this particular service to the list of his services. // Otherwise add an entirely new set (containing only one service for now - until we discover more of his services). if (this.importedServiceAddresses.ContainsKey(sourceAddress)) this.importedServiceAddresses[sourceAddress].Add(serviceIdentifier); else this.importedServiceAddresses.Add(sourceAddress, new List<Guid>() { serviceIdentifier }); // Check if the service has previously been disconnected from the network // If yes, trigger the reconnected event - otherwise trigger the discovered event if(this.diconnectedServices.Contains(serviceIdentifier)) { if(this.ServiceReconnectedEvent != null) this.ServiceReconnectedEvent(this, new ServiceNotificationEventArgs(serviceIdentifier, sourceAddress, typeTag, serviceImplementation)); this.diconnectedServices.Remove(serviceIdentifier); } else { if(this.ServiceDiscoveredEvent != null) this.ServiceDiscoveredEvent(this, new ServiceNotificationEventArgs(serviceIdentifier, sourceAddress, typeTag, serviceImplementation)); } }
/// <summary> /// Export a certain service. This service will link the given serviceImplementation to the provided TypeTag. /// When the ServiceImplementation implements the UObject interface, a RemoteReference will be returned. /// Otherwise the ServiceImplementation itself will be returned. /// When the same object is exported twice, it will be handled as a new service. The instance will be stored as if it was new. /// This will also generate a new RemoteReference. /// </summary> /// <param name="tag">TypeTag which identifies the service which needs to be exported</param> /// <param name="serviceImplementation">Service implementation to export (make available on the network)</param> /// <param name="identifier">Output parameter which will give you the identifier associated with the service implementation</param> /// <returns>Returns an object which can be used to transmit to other devices (either the ServiceImplementation itself or a RemoteReference)</returns> public object ExportService(TypeTag tag, object serviceImplementation, out Guid identifier) { // Check if the typetag already has exported service implementations identifier = Guid.NewGuid(); if (!services.ContainsKey(tag)) services.Add(tag, new List<Guid>() { identifier }); else { // If an implementation already exists - add a new implementation to the existing list List<Guid> _services; if (services.TryGetValue(tag, out _services)) _services.Add(identifier); } // Now add the service implementation to the list of exported services this.exportedObjects.Add(identifier, serviceImplementation); // If the service is a UObject, we should refer to it with a remote reference. Store this too! (and return a RemoteReference) if (serviceImplementation is UObject) { RemoteReference remoteReference = new RemoteReference(tag, identifier); this.AddRemoteReference(identifier, remoteReference); // Returns the RemoteReference as "exportable object" return remoteReference; } // Otherwise just return the implementation itself return serviceImplementation; }
public RemoteReference AddParameterReferencedObject(object obj) { TypeTag typeTag = new TypeTag(""); Guid identifier = Guid.NewGuid(); RemoteReference remoteReference = new RemoteReference(typeTag, identifier); // Change the typetag to something unique - to make sure it wouldn't be found as a service when looking up the object this remoteReference belongs to //remoteReference.serviceTag.tag = identifier.ToString(); this.exportedObjects.Add(identifier, obj); this.remoteReferences.Add(identifier, remoteReference); return remoteReference; }
public MainPage() { this.InitializeComponent(); UIDispatcher = (Windows.UI.Core.DispatchedHandler a) => this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, a); this.chatServiceTag = new TypeTag("chat"); MyChatUsersViewModel = (ChatUsersViewModel)Resources["ChatUsersViewModel"]; this.chatUsers = new Dictionary<Guid, RemoteReference>(); // Set up our own name string nickname = "User" + new Random().Next(1, 99); ui_nickname.Text = nickname; ui_nickname.IsEnabled = false; // Set up our own user and all callbacks myChatUser = new ChatUser(nickname, this.UIDispatcher); myChatUser.PartnerLeftChatEvent += PartnerLeftChat; myChatUser.InviteReceivedEvent += InviteReceivedFromUser; myChatUser.AcceptInviteEvent += AcceptInviteByUser; myChatUser.RejectInviteEvent += RejectInviteByUser; myChatUser.InviteAcceptedEvent += InviteAcceptedByUser; myChatUser.InviteRejectedEvent += InviteRejectedByUser; // Set up the listener callbacks for joining/leaving of users this.userListener = new ServiceListener<RemoteReference>(); userListener.IsDiscovered += UserListener_IsDiscovered; userListener.IsDisconnected += UserListener_IsDisconnected; userListener.IsReconnected += UserListener_IsDiscovered; EventLoop.Instance.Whenever(chatServiceTag, userListener); // Export our service myServicePublication = EventLoop.Instance.Broadcast(chatServiceTag, myChatUser); // Go online on the network NetPOC.Network.NetworkControl.Network networkObj = EventLoop.Instance.GoOnline(); }
public RemoteReference(TypeTag service, Guid guid) { this.serviceTag = service; this.guid = guid; }
/// <summary> /// Get all ServiceListeners for a given service (identified by TypeTag) /// If no listeners are registered (or the typetag is unknown), the empty list will be returned. /// </summary> /// <param name="tag">Service to get the listeners for. Will return an empty list if typetag isn't know or has no listeners</param> public List<ServiceListenerBase> GetServiceListeners(TypeTag tag) { List<ServiceListenerBase> listeners; if (this.serviceSubscriptions.TryGetValue(tag, out listeners)) return listeners; else return new List<ServiceListenerBase>(); }
/// <summary> /// Disconnect a certain service from the network /// </summary> /// <param name="serviceIdentifier">The identifier of the service you're disconnecting</param> /// <param name="typetag">TypeTag by which the service is identified on the network</param> /// <param name="service">Service which has previously been broadcast on the network</param> /// <returns></returns> public void DisconnectService(Guid serviceIdentifier, TypeTag typetag, object service) { PeerConnector.Instance.BroadcastNetworkObject(new NetworkDisconnectService(serviceIdentifier, typetag, service)); }
/// <summary> /// Given a TypeTag (to identify the service), get a list of all exported services linked to this typetag. /// The "exported service" may be a RemoteReference (if the service implementation is a UObject), but it can also be the actual service implementation itself. /// The returned services are what's exported to other devices. /// </summary> /// <param name="service">TypeTag which identifies the required service</param> /// <param name="serviceIdentifiers">Output parameters which gives you the list of identifiers associated with the returned list of service implementations</param> /// <returns>Returns a list of objects which can be sent to other devices. The objects in this list are what's exported when exporting a service (RemoteReference, string, int, etc)</returns> public List<object> GetExportedServices(TypeTag service, out List<Guid> serviceIdentifiers) { List<object> _services = new List<object>(); List<Guid> exportedServices; if (this.services.TryGetValue(service, out exportedServices)) { foreach (Guid serviceGuid in exportedServices) { // First - try to get a RemoteReference. If this doesn't exist - export the service implementation RemoteReference remoteRef; object _service; if (remoteReferences.TryGetValue(serviceGuid, out remoteRef)) _services.Add(remoteRef); else if (exportedObjects.TryGetValue(serviceGuid, out _service)) _services.Add(_service); } } serviceIdentifiers = exportedServices; return _services; }
/// <summary> /// Install a ServiceListener to listen for all services on the network of a particular TypeTag. /// </summary> /// <param name="serviceTag">TypeTag which identifies the service</param> /// <param name="listener">The ServiceListener to install for this particular TypeTag</param> /// <returns>Returns a ServiceSubscription, which can be used to manage this subscription to a service (and for example cancel it)</returns> public ServiceSubscription Whenever(TypeTag serviceTag, ServiceListenerBase listener) { System.Diagnostics.Debug.WriteLine("Installing service listener for TypeTag " + serviceTag.tag); return discoveryManager.serviceManager.subscriptionManager.AddServiceSubscription(serviceTag, listener); }
/// <summary> /// Broadcast a service to the entire network /// </summary> /// <param name="serviceTag">label (TypeTag) which the service is announced as</param> /// <param name="serviceImplementation">Implementation of the service</param> /// <returns>Returns a ServicePublication, which can be used to control your publication of this particular service (and perhaps cancel it)</returns> public ServicePublication Broadcast(TypeTag serviceTag, object serviceImplementation) { ServiceManager serviceManager = discoveryManager.serviceManager; Guid identifier; // Export the service, which gets us an object which can be tranfered over the network. object transferableService = serviceManager.exportedServiceManager.ExportService(serviceTag, serviceImplementation, out identifier); // If we're connected to a network - broadcast the service if (this.connectedToNetwork) { // Now construct a new data packet to send over the network NetworkJoinService dataPacket = new NetworkJoinService(identifier, serviceTag, transferableService); // Broadcast the service over the network PeerConnector.Instance.BroadcastNetworkObject(dataPacket); } // Return a ServicePublication (also pass an anonymous function which removes the service again, so the user is capable of cancelling it) return new ServicePublication(identifier, () => { serviceManager.exportedServiceManager.RemoveExportedService(identifier); this.discoveryManager.DisconnectService(identifier, serviceTag, transferableService); }); }
/// <summary> /// /// </summary> /// <param name="serviceIdentifier">Identifier of the referenced service</param> /// <param name="sourceAddress">The address of the device who exported the service</param> /// <param name="typetag">Typetag (or "category") the service is exported as</param> /// <param name="service">The service implementation of the service</param> public ServiceNotificationEventArgs(Guid serviceIdentifier, string sourceAddress, TypeTag typetag, object service) { this.serviceIdentifier = serviceIdentifier; this.sourceAddress = sourceAddress; this.typetag = typetag; this.service = service; }