package plugins.CENO.Client; import java.net.MalformedURLException; import plugins.CENO.CENOL10n; import plugins.CENO.Configuration; import plugins.CENO.Version; import plugins.CENO.Client.Signaling.ChannelMaker; import plugins.CENO.Common.URLtoUSKTools; import plugins.CENO.FreenetInterface.NodeInterface; import freenet.keys.FreenetURI; import freenet.pluginmanager.FredPlugin; import freenet.pluginmanager.FredPluginHTTP; import freenet.pluginmanager.FredPluginRealVersioned; import freenet.pluginmanager.FredPluginThreadless; import freenet.pluginmanager.FredPluginVersioned; import freenet.pluginmanager.PluginHTTPException; import freenet.pluginmanager.PluginRespirator; import freenet.support.Logger; import freenet.support.api.HTTPRequest; /** * CENO Client plugin * * Implements the Local Cache Server (LCS) and Request Sender (RS) * CENO agents. */ public class CENOClient implements FredPlugin, FredPluginVersioned, FredPluginRealVersioned, FredPluginHTTP, FredPluginThreadless { // Interface objects with fred public static NodeInterface nodeInterface; private static final ClientHandler clientHandler = new ClientHandler(); private static String bridgeKey; // Plugin-specific configuration public static final String PLUGIN_URI = "/plugins/plugins.CENO.CENO"; public static final String PLUGIN_NAME = "CENO"; private static final Version VERSION = new Version(Version.PluginType.CLIENT); public static Configuration initConfig; private static final String CONFIGPATH = ".CENO/client.properties"; public static ChannelMaker channelMaker; private Thread channelMakerThread; // Default bridge key (for the CENO bridge running on Deflect) private static final String BRIDGE_KEY = "SSK@skyVcFU3qUK7lM-Ye2SGUwG1kQi1GPnI7tuiHttIOJA,d0aDf-qB~x7q7amxT935Kgju0Nw6TVfiIjZnPptmAF8,AQACAAE/"; private static Long feedsLastVersion; /** * {@inheritDoc} */ @Override public void runPlugin(PluginRespirator pr) { // Initialize interfaces with Freenet node //TODO initialized within NodeInterface, do not expose HLSC but only via nodeInterface nodeInterface = new NodeInterface(pr.getNode(), pr); CENOL10n.getInstance().setLanguageFromEnvVar("CENOLANG"); // Initialize LCS ULPRManager.init(); initConfig = new Configuration(CONFIGPATH); initConfig.readProperties(); String confBridgeKey = initConfig.getProperty("bridgeKey"); try { FreenetURI bridgeURI = new FreenetURI(confBridgeKey); if (!bridgeURI.isSSK()) { throw new MalformedURLException(); } bridgeKey = confBridgeKey; } catch (MalformedURLException e) { bridgeKey = BRIDGE_KEY; } catch (NullPointerException e) { bridgeKey = BRIDGE_KEY; } bridgeKey = bridgeKey.endsWith("/") ? bridgeKey : bridgeKey + "/"; Logger.normal(this, "CENO will make requests to the bridge with key: " + bridgeKey); // Initialize RS - Make a new class ChannelManager that handles ChannelMaker channelMaker = new ChannelMaker(initConfig.getProperty("signalSSK"), Long.parseLong(initConfig.getProperty("lastSynced", "0"))); channelMakerThread = new Thread(channelMaker); channelMakerThread.start(); try { feedsLastVersion = Long.parseLong(initConfig.getProperty("feedsLastVersion", "0")); } catch (NumberFormatException e) { feedsLastVersion = 0L; } // Subscribe to updates of the CENO Portal feeds.json try { DistFetchHelper.fetchDist(URLtoUSKTools.getPortalFeedsUSK(BRIDGE_KEY).setSuggestedEdition(feedsLastVersion), "Fetched CENO Portal feeds.json from the distributed cache", "Failed to fetch feeds.json from the distributed cache"); } catch (MalformedURLException e) { Logger.error(this, "MalformedURLException while trying to fetch CENO Portal feeds.json: " + e.getMessage()); terminate(); return; } USKUpdateFetcher.subscribeToBridgeFeeds(); } /** * {@inheritDoc} */ @Override public String getVersion() { return VERSION.getVersion(); } /** * {@inheritDoc} */ @Override public long getRealVersion() { return VERSION.getRealVersion(); } public static String getBridgeKey() { return bridgeKey; } public static Long getFeedsLastVersion() { return feedsLastVersion; } static void setFeedsLastVersion(Long feedsLastVersionPar) { feedsLastVersion = feedsLastVersionPar; } /** * Method called before termination of the CENO plugin */ @Override public void terminate() { if(channelMaker != null && channelMaker.canSend()) { initConfig.setProperty("signalSSK", channelMaker.getSignalSSK()); initConfig.setProperty("lastSynced", String.valueOf(channelMaker.getLastSynced())); } initConfig.setProperty("feedsLastVersion", Long.toString(feedsLastVersion)); initConfig.storeProperties(); if(channelMakerThread != null) { channelMakerThread.interrupt(); } RequestSender.getInstance().stopTimerTasks(); //TODO Release ULPRs' resources Logger.normal(this, PLUGIN_NAME + " terminated."); } @Override public String handleHTTPGet(HTTPRequest request) throws PluginHTTPException { return clientHandler.handleHTTPGet(request); } @Override public String handleHTTPPost(HTTPRequest request) throws PluginHTTPException { return clientHandler.handleHTTPPost(request); } }