indexing description: "JXTA platform (World peer group)" author: "Beat Strasser " date: "$Date$" revision: "$Revision$" class P2P_PLATFORM inherit P2P_GENERIC_PEERGROUP export {NONE} load_module_by_specification redefine init, start_with_arguments, stop end P2P_ID_CREATOR create make feature {NONE} -- Initialization make (a_cache_directory_path: STRING; a_logger: L4E_LOGGER) is -- Create JXTA platform (world peer group) require Path_valid: a_cache_directory_path /= Void Logger_valid: a_logger /= Void do -- general module and peer group initialization logger := a_logger id := worldgroup_id module_id := id name := world_peergroup_name description := "Standard World Group implementation" peer_group := Current parent_group := Current implementation_advertisement := default_implementation_advertisement (ref_platform_msid, "P2P_PLATFORM", "Standard World Group Platform") logger.debugging ("platform: Initializing platform") -- peer group module manager create modules_hashed.make (1) -- get configuration and initialize if possible create cache_manager.make (a_cache_directory_path, logger) if not cache_manager.has_failed then logger.debugging ("platform: Cache directory initialized") configuration := cache_manager.configuration_advertisement if is_configured then initialize_platform end else logger.fatal ("platform: Error initializing cache directory") module_status := init_failed end end init (group: P2P_PEERGROUP; an_id: P2P_ID; advertisement: like implementation_advertisement) is -- Unused method in this special peer group. Use `make' instead. do ensure then False -- yes, don't call it end feature -- Access standard_net_peergroup: P2P_PEERGROUP is -- Create standard net peer group instance indexing once_status: global require Configuration_valid: is_configured local npg_mia: P2P_MODULE_IMPLEMENTATION_ADVERTISEMENT once -- look for implementation advertisement if not cache_manager.has_module_implementation_advertisement (ref_net_peergroup_msid) then logger.info ("platform: Creating new standard net peer group module implementation advertisement") npg_mia := peergroup_implementation_advertisement (ref_net_peergroup_msid, "P2P_GENERIC_PEERGROUP", "Standard Net Peer Group") cache_manager.store_module_implementation_advertisement (npg_mia) end -- create net peer group instance Result ?= load_net_peergroup (netgroup_id, ref_net_peergroup_msid) if Result /= Void and Result.module_status /= init_failed then -- set net peer group name and description Result.group_advertisement.set_name (net_peergroup_name) Result.group_advertisement.set_description ("Standard Net Peer Group implementation") cache_manager.store_peergroup_advertisement (Result.group_advertisement) logger.info ("platform: Standard net peer group initialized") end end peergroup_implementation_advertisement (a_msid: P2P_MODULE_SPECIFICATION_ID; a_code, a_description: STRING): P2P_MODULE_IMPLEMENTATION_ADVERTISEMENT is -- A net peer group implementation advertisement containing all standard modules' implementation advertisements indexing once_status: global require Msid_valid: a_msid /= Void and a_msid.is_valid Code_valid: a_code /= Void and not a_code.is_empty Description_valid: a_description /= Void and not a_description.is_empty local mia: P2P_MODULE_IMPLEMENTATION_ADVERTISEMENT npg_params: P2P_UNKNOWN_ADVERTISEMENT npg_params_doc: P2P_XML_DOCUMENT once create npg_params_doc.make_with_jxta_root ("Parm") -- Endpoint Service mia := default_implementation_advertisement (ref_endpoint_msid, "P2P_ENDPOINT_SERVICE", "Standard Endpoint Service") npg_params_doc.create_root_child_element ("Svc", namespace_empty) npg_params_doc.add_child_element (npg_params_doc.last_element, mia.document.document.root_element) -- TCP Transport mia := default_implementation_advertisement (ref_transport_tcp_msid, "P2P_TCP_TRANSPORT", "Standard TCP Transport") npg_params_doc.create_root_child_element ("Proto", namespace_empty) npg_params_doc.add_child_element (npg_params_doc.last_element, mia.document.document.root_element) -- Router Transport mia := default_implementation_advertisement (ref_transport_router_msid, "P2P_ENDPOINT_ROUTER", "Standard Endpoint Router") npg_params_doc.create_root_child_element ("Proto", namespace_empty) npg_params_doc.add_child_element (npg_params_doc.last_element, mia.document.document.root_element) -- Discovery Service mia := default_implementation_advertisement (ref_discovery_msid, "P2P_DISCOVERY_SERVICE", "Standard Discovery Service") npg_params_doc.create_root_child_element ("Svc", namespace_empty) npg_params_doc.add_child_element (npg_params_doc.last_element, mia.document.document.root_element) -- Rendezvous Service mia := default_implementation_advertisement (ref_rendezvous_msid, "P2P_RENDEZVOUS_SERVICE", "Standard Rendezvous Service") npg_params_doc.create_root_child_element ("Svc", namespace_empty) npg_params_doc.add_child_element (npg_params_doc.last_element, mia.document.document.root_element) -- Peer Group Result := default_implementation_advertisement (a_msid, a_code, a_description) create npg_params.make_from_element (npg_params_doc.document.root_element) Result.set_parameter (npg_params) ensure Result_set: Result /= Void and Result.is_valid Result_id_set: Result.specification_id.is_equal (a_msid) end default_configuration: P2P_CONFIGURATION is -- Create new platform configuration with new peer id and default service parameters local pid: P2P_PEER_ID npg_id: P2P_NETGROUP_ID do -- Create new peer id in standard net peer group create npg_id.make create pid.make_new_peer (npg_id.uuid) -- Create configuration advertisement create Result.make_with_id (pid) -- TCP parameter Result.add_service_parameter (transport_tcp_mcid, default_tcp_configuration) -- Rendezvous parameter Result.add_service_parameter (rendezvous_mcid, default_rendezvous_configuration) -- Router parameter -- Result.add_service_parameter (transport_relay_mcid, default_router_configuration) -- Membership parameter -- Proxy parameter -- HTTP parameter ensure Result_set: Result /= Void and Result.is_valid end default_tcp_configuration: P2P_TCP_ADVERTISEMENT is -- Create default configuration for the tcp transport module do -- ip is updated during platform's initialization create Result.make ("0.0.0.0", 9701) ensure Result_set: Result /= Void and Result.is_valid end default_rendezvous_configuration: P2P_RENDEZVOUS_CONFIGURATION is -- Create default configuration for the rendezvous service do create Result.make Result.add_seed_uri ("http://rdv.jxtahosts.net/cgi-bin/rendezvous.cgi?2") ensure Result_set: Result /= Void and Result.is_valid end -- default_router_configuration: P2P_ROUTER_ADVERTISEMENT is -- -- Create default configuration for the router transport -- do -- ensure -- Result_set: Result /= Void and Result.is_valid -- end feature -- Status report is_configured: BOOLEAN is -- Is platform configured do Result := configuration /= Void end feature -- Basic operations configure (config: like configuration) is -- Configure platform with given `config' require Config_valid: config /= Void and config.is_valid do configuration := config configuration.make_reconfigured cache_manager.store_configuration_advertisement (configuration) initialize_platform ensure Config_set: is_configured and configuration.is_reconfigured end load_net_peergroup (an_id: P2P_PEERGROUP_ID; specification_id: P2P_MODULE_SPECIFICATION_ID): P2P_MODULE is -- Load a peer group require No_npg_loaded: lookup_module (net_peergroup_name) = Void Id_valid: an_id /= Void and an_id.is_valid Msid_valid: specification_id /= Void and specification_id.is_valid do Result := load_module_by_specification (an_id, specification_id, net_peergroup_name) if Result = Void or Result.module_status = init_failed then module_status := init_failed logger.fatal ("platform: Error loading net peer group module") end ensure Registered_if_successful: (Result /= Void and Result.module_status /= init_failed) implies lookup_module (net_peergroup_name) = Result end start_with_arguments (args: ARRAY [STRING_8]) is -- Start registered net peer group local npg: P2P_MODULE do npg := lookup_module (net_peergroup_name) if npg /= Void then npg.start (args) module_status := npg.module_status if module_status = start_ok then logger.info ("platform: Net peer group module successfully started") else logger.fatal ("platform: Error starting net peer group module") end else module_status := start_failed logger.fatal ("platform: Error looking for net peer group module during start") end end stop is -- Stop registered net peer group local npg: P2P_MODULE do npg := lookup_module (net_peergroup_name) if npg /= Void then npg.stop logger.info ("platform: Net peer group module successfully stopped") else logger.fatal ("platform: Error looking for net peer group module during stop") end module_status := stop_ok end feature {NONE} -- Implementation initialize_platform is -- Initialize platform with current configuration require Configuration_valid: is_configured do logger.debugging ("platform: Initializing world peer group") -- World group advertisement if not configuration.is_reconfigured then group_advertisement := cache_manager.peergroup_advertisement (id) end if group_advertisement = Void then logger.info ("platform: Creating new world peer group advertisement") create group_advertisement.make (id, ref_platform_msid) group_advertisement.set_name (name) group_advertisement.set_description (description) cache_manager.store_peergroup_advertisement (group_advertisement) end -- Peer advertisement peer_id := configuration.peer_id peer_name := configuration.name if not configuration.is_reconfigured then peer_advertisement := cache_manager.peer_advertisement (id, peer_id) end if peer_advertisement = Void then logger.info ("platform: Creating new peer advertisement for world peer group") create peer_advertisement.make (configuration.peer_id, id) if configuration.name /= Void then peer_advertisement.set_name (configuration.name) end if configuration.description /= Void then peer_advertisement.set_description (configuration.description) end end -- fetch rendezvous seeds and update local ip in peer's route advertisement and in tcp configuration update_local_ip -- Create list with standard modules to load create modules_list.make modules_list.extend (["EndpointService", endpoint_mcid, ref_endpoint_msid, parent_is_owner_if_available]) modules_list.extend (["TCPTransport", transport_tcp_mcid, ref_transport_tcp_msid, parent_is_owner_if_available]) modules_list.extend (["DiscoveryService", discovery_mcid, ref_discovery_msid, parent_is_owner_if_available]) modules_list.extend (["EndpointRouter", transport_router_mcid, ref_transport_router_msid, parent_is_owner_if_available]) modules_list.extend (["RendezvousService", rendezvous_mcid, ref_rendezvous_msid, parent_is_owner_if_available]) remove_disabled_modules -- Create wire message creator create wire_message_creator end default_implementation_advertisement (a_msid: P2P_MODULE_SPECIFICATION_ID; a_code, a_description: STRING): P2P_MODULE_IMPLEMENTATION_ADVERTISEMENT is -- Create default implementation advertisement require Msid_valid: a_msid /= Void and a_msid.is_valid Code_valid: a_code /= Void Description_valid: a_description /= Void do create Result.make (a_msid, standard_module_compatibility, standard_module_code_prefix + a_code) Result.set_description (a_description) Result.set_package_uri (standard_module_package_uri) Result.set_provider (standard_module_provider) ensure Result_set: Result /= Void and Result.is_valid Result_id_set: Result.specification_id.is_equal (a_msid) end local_ip: STRING update_local_ip is -- Update local ip in peers route advertisement and in tcp configuration local route_adv: P2P_ROUTE_ADVERTISEMENT ap_adv: P2P_ACCESSPOINT_ADVERTISEMENT ea: P2P_ENDPOINT_ADDRESS tcp_conf: P2P_TCP_ADVERTISEMENT update_ip: BOOLEAN do -- create a connection to get the local IP... very nice, indeed ;) resolve_rendezvous_seed_uris -- update tcp configuration tcp_conf ?= configuration.service_parameter (transport_tcp_mcid) if tcp_conf = Void then -- no tcp configuration set yet if local_ip = Void then local_ip := "127.0.0.1" logger.warn ("platform: Could not detect local ip, set it to: " + local_ip) end create tcp_conf.make (local_ip, 9701) configuration.add_service_parameter (transport_tcp_mcid, tcp_conf) update_ip := True elseif local_ip /= Void and not tcp_conf.interface_address.is_equal (local_ip) then -- ip has changed since last run tcp_conf.set_interface_address (local_ip) configuration.renew_document update_ip := True elseif local_ip = Void and tcp_conf.interface_address.is_equal ("0.0.0.0") then -- we don't know our ip local_ip := "127.0.0.1" logger.warn ("platform: Could not detect local ip, set it to: " + local_ip) tcp_conf.set_interface_address (local_ip) configuration.renew_document update_ip := True end if update_ip then cache_manager.store_configuration_advertisement (configuration) -- create access point advertisement create ea.make ("tcp", local_ip + ":" + tcp_conf.port.out) create ap_adv.make ap_adv.add_address (ea) -- update peer's route advertisement create route_adv.make (ap_adv) peer_advertisement.replace_service_parameter (endpoint_mcid, route_adv) cache_manager.store_peer_advertisement (peer_advertisement) end end resolve_rendezvous_seed_uris is -- Fetch rendezvous seeds and update the rendezvous configuration. -- During this, we save also our local ip local failed: BOOLEAN seed_resolver: P2P_SEED_RESOLVER conf: P2P_RENDEZVOUS_CONFIGURATION seed_cursor: DS_LIST_CURSOR [STRING] do if not failed then conf ?= configuration.service_parameter (rendezvous_mcid) if conf /= Void and conf.is_valid then create seed_resolver -- loop through all seed uris from seed_cursor := conf.seed_uris.new_cursor seed_cursor.start until seed_cursor.after loop -- open http connection to get the seeds seed_resolver.resolve (seed_cursor.item) if not seed_resolver.has_failed then local_ip := seed_resolver.local_host_address -- store results in rendezvous configuration conf.add_seed_addresses (seed_resolver.found_seeds) end seed_cursor.forth end end else logger.error ("platform: Unable to resolve rendezvous seeds") end rescue failed := True retry end end