private SecureMessageVerifierImpl(File keyFile, String keyBase32, PublicKey pubKey, String name) { if (name == null) { QUEUE = ExecutorsHelper.newProcessingQueue("SecureMessageVerifier"); } else { QUEUE = ExecutorsHelper.newProcessingQueue(name + "-SecureMessageVerifier"); } if (pubKey == null && (keyFile == null) == (keyBase32 == null)) throw new IllegalArgumentException("must have only one source of key"); this.pubKey = pubKey; this.keyFile = keyFile; this.keyBase32 = keyBase32; }
private class TestExecutor implements Executor { private List<Runnable> runners = new ArrayList<Runnable>(); private ExecutorService service = ExecutorsHelper.newProcessingQueue("DHT-TestExecutor"); public List<Runnable> getRunners() { return runners; } public void execute(Runnable command) { runners.add(command); service.execute(command); } }
@Override public void setUp() throws Exception { RUDPMessageFactory factory = new DefaultMessageFactory(); stubService = new UDPServiceStub(factory); Executor executor = ExecutorsHelper.newProcessingQueue("TestEventThread"); udpSelectorProvider = new UDPSelectorProvider( new DefaultRUDPContext( factory, NIODispatcher.instance().getTransportListener(), stubService, new DefaultRUDPSettings()), new AsynchronousMulticasterImpl<UDPSocketChannelConnectionEvent>(executor)); udpMultiplexor = udpSelectorProvider.openSelector(); stubService.setUDPMultiplexor(udpMultiplexor); NIODispatcher.instance() .registerSelector(udpMultiplexor, udpSelectorProvider.getUDPSocketChannelClass()); // Add some simulated connections to the UDPServiceStub stubService.addReceiver(PORT_1, PORT_2, 10, 0); stubService.addReceiver(PORT_2, PORT_1, 10, 0); }
@Singleton public class LocalHTTPAcceptor extends BasicHttpAcceptor { private static final Log LOG = LogFactory.getLog(LocalHTTPAcceptor.class); private static final String[] SUPPORTED_METHODS = new String[] { "GET", "HEAD", }; private final Executor magnetExecutor = ExecutorsHelper.newProcessingQueue("magnet-handler"); /** Magnet request for a default action on parameters */ // private static final String MAGNET_DEFAULT = "/magnet10/default.js?"; /** Magnet request for a paused response */ // private static final String MAGNET_PAUSE = "/magnet10/pause"; /** Start of Magnet URI */ private static final String MAGNET = "magnet:?"; /** Magnet detail command */ private static final String MAGNET_DETAIL = "magcmd/detail?"; private static final String LIBRARY_URL = "/library/"; private String lastCommand; private long lastCommandTime; private long MIN_REQUEST_INTERVAL = 1500; private final ExternalControl externalControl; private LibraryManager libraryManager; @Inject public LocalHTTPAcceptor( ExternalControl externalControl, LibraryManager libraryManager, AuthenticationInterceptor requestAuthenticator) { super( createDefaultParams(LimeWireUtils.getHttpServer(), Constants.TIMEOUT), requestAuthenticator, SUPPORTED_METHODS); this.externalControl = externalControl; this.libraryManager = libraryManager; registerHandler("magnet:", new MagnetCommandRequestHandler()); registerHandler("/magnet10/default.js", new MagnetCommandRequestHandler()); registerHandler("/magnet10/pause", new MagnetPauseRequestHandler()); registerHandler("/magcmd/detail", new MagnetDetailRequestHandler()); registerHandler("/script/asset/*", new FileRequestHandler()); registerHandler("/library/*", new LibraryRequestHandler()); registerHandler("/crossdomain.xml", new CrossDomainRequestHandler()); // TODO figure out which files we want to serve from the local file system // registerHandler("*", new FileRequestHandler(new File("root"), new BasicMimeTypeProvider())); } @Inject void register(org.limewire.lifecycle.ServiceRegistry registry) { registry.register(this); } @Override public String getServiceName() { return org.limewire.i18n.I18nMarker.marktr("Magnet Processor"); } private class MagnetCommandRequestHandler extends SimpleNHttpRequestHandler { public ConsumingNHttpEntity entityRequest( HttpEntityEnclosingRequest request, HttpContext context) throws HttpException, IOException { return null; } @Override public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException { final String uri = request.getRequestLine().getUri(); magnetExecutor.execute( new Runnable() { public void run() { try { triggerMagnetHandling(uri); } catch (IOException ignored) { } } }); } } private class MagnetPauseRequestHandler extends SimpleNHttpRequestHandler { public ConsumingNHttpEntity entityRequest( HttpEntityEnclosingRequest request, HttpContext context) throws HttpException, IOException { return null; } @Override public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException { response.setStatusCode(HttpStatus.SC_NO_CONTENT); magnetExecutor.execute( new Runnable() { public void run() { try { Thread.sleep(2500); } catch (InterruptedException e) { } } }); } } private class MagnetDetailRequestHandler extends SimpleNHttpRequestHandler { public ConsumingNHttpEntity entityRequest( HttpEntityEnclosingRequest request, HttpContext context) throws HttpException, IOException { return null; } @Override public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException { String uri = request.getRequestLine().getUri(); int i = uri.indexOf(MAGNET_DETAIL); String command = uri.substring(i + MAGNET_DETAIL.length()); String page = MagnetHTML.buildMagnetDetailPage(command); NStringEntity entity = new NStringEntity(page); entity.setContentType("text/html"); response.setEntity(entity); } } private class CrossDomainRequestHandler extends SimpleNHttpRequestHandler { public ConsumingNHttpEntity entityRequest( HttpEntityEnclosingRequest request, HttpContext context) throws HttpException, IOException { return null; } @Override public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException { String page = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; page += "<cross-domain-policy xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://www.adobe.com/xml/schemas/PolicyFile.xsd\">"; page += "<allow-access-from domain=\"*.opentape.fm\" />"; page += "</cross-domain-policy>"; NStringEntity entity = new NStringEntity(page); entity.setContentType("text/html"); response.setEntity(entity); } } private class FileRequestHandler extends SimpleNHttpRequestHandler { public ConsumingNHttpEntity entityRequest( HttpEntityEnclosingRequest request, HttpContext context) throws HttpException, IOException { return null; } @Override public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException { String uri = request.getRequestLine().getUri(); int i = uri.indexOf("/script/asset/"); String filepath = uri.substring(i + "/script/asset/".length()); i = filepath.lastIndexOf('/'); String filename = filepath.substring(i + 1); i = filename.lastIndexOf('.'); String extension = filename.substring(i + 1); System.out.println(extension); System.out.println(filepath); File file = new File("../../core/com/limegroup/scripting/resources/assets/" + filepath); NFileEntity entity = new NFileEntity(file, "application/binary"); if (extension.contentEquals("js")) { entity.setContentType("text/javascript"); } else if (extension.contentEquals("css")) { entity.setContentType("text/css"); } else if (extension.contentEquals("swf")) { entity.setContentType("application/x-shockwave-flash"); } else if (extension.contentEquals("html")) { entity.setContentType("text/html"); } else { entity.setContentType("application/binary"); } response.setEntity(entity); } } private class LibraryRequestHandler extends SimpleNHttpRequestHandler { public ConsumingNHttpEntity entityRequest( HttpEntityEnclosingRequest request, HttpContext context) throws HttpException, IOException { return null; } @Override public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException { AbstractHttpEntity entity; String uri = request.getRequestLine().getUri(); int i = uri.indexOf(LIBRARY_URL); String sha1 = uri.substring(i + LIBRARY_URL.length()); if (sha1.indexOf("?") != -1) { sha1 = sha1.substring(0, sha1.indexOf("?")); } System.out.println("sha1:" + sha1); URN urn = new URNImpl(com.limegroup.gnutella.URN.createSHA1Urn(sha1)); if (libraryManager.getLibraryManagedList().contains(urn)) { FileDesc fileDesc = libraryManager.getLibraryManagedList().getFileDescsByURN(urn).get(0); entity = new NFileEntity(fileDesc.getFile(), "application/binary"); entity.setContentType("application/binary"); response.setHeader( "Content-disposition", "attachment; filename=\"" + fileDesc.getFileName() + "\";"); } else { entity = new NStringEntity("File not found: " + sha1); entity.setContentType("text/plain"); } response.setEntity(entity); } } private synchronized void triggerMagnetHandling(String uri) throws IOException { int i = uri.indexOf("?"); if (i == -1) { throw new IOException("Invalid command"); } String command = uri.substring(i + 1); // suppress duplicate requests from some browsers long currentTime = System.currentTimeMillis(); if (!command.equals(lastCommand) || (currentTime - lastCommandTime) >= MIN_REQUEST_INTERVAL) { // trigger an operation externalControl.handleMagnetRequest(MAGNET + command); lastCommand = command; lastCommandTime = currentTime; } else { LOG.warn("Ignoring duplicate request: " + command); } } }
@Override protected void configure() { EventMulticaster<FriendEvent> knownMulticaster = new EventMulticasterImpl<FriendEvent>(FriendEvent.class); EventMulticaster<FriendEvent> availMulticaster = new EventMulticasterImpl<FriendEvent>(); EventMulticaster<FriendPresenceEvent> presenceMulticaster = new EventMulticasterImpl<FriendPresenceEvent>(); EventMulticaster<FeatureEvent> featureMulticaster = new EventMulticasterImpl<FeatureEvent>(); bind(new TypeLiteral<ListenerSupport<FriendEvent>>() {}) .annotatedWith(Names.named("known")) .toInstance(knownMulticaster); bind(new TypeLiteral<EventBroadcaster<FriendEvent>>() {}) .annotatedWith(Names.named("known")) .toInstance(knownMulticaster); bind(new TypeLiteral<ListenerSupport<FriendEvent>>() {}) .annotatedWith(Names.named("available")) .toInstance(availMulticaster); bind(new TypeLiteral<EventBroadcaster<FriendEvent>>() {}) .annotatedWith(Names.named("available")) .toInstance(availMulticaster); bind(new TypeLiteral<ListenerSupport<FriendPresenceEvent>>() {}) .toInstance(presenceMulticaster); bind(new TypeLiteral<EventBroadcaster<FriendPresenceEvent>>() {}) .toInstance(presenceMulticaster); bind(new TypeLiteral<ListenerSupport<FeatureEvent>>() {}).toInstance(featureMulticaster); bind(new TypeLiteral<EventMulticaster<FeatureEvent>>() {}).toInstance(featureMulticaster); bind(new TypeLiteral<EventBroadcaster<FeatureEvent>>() {}).toInstance(featureMulticaster); Executor executor = ExecutorsHelper.newProcessingQueue("FriendConnectionEventThread"); AsynchronousCachingEventMulticasterImpl<FriendConnectionEvent> asyncConnectionMulticaster = new AsynchronousCachingEventMulticasterImpl<FriendConnectionEvent>( executor, BroadcastPolicy.IF_NOT_EQUALS, LogFactory.getLog(FriendConnectionEvent.class)); bind(new TypeLiteral<EventBean<FriendConnectionEvent>>() {}) .toInstance(asyncConnectionMulticaster); bind(new TypeLiteral<EventMulticaster<FriendConnectionEvent>>() {}) .toInstance(asyncConnectionMulticaster); bind(new TypeLiteral<AsynchronousEventMulticaster<FriendConnectionEvent>>() {}) .toInstance(asyncConnectionMulticaster); bind(new TypeLiteral<AsynchronousEventBroadcaster<FriendConnectionEvent>>() {}) .toInstance(asyncConnectionMulticaster); bind(new TypeLiteral<ListenerSupport<FriendConnectionEvent>>() {}) .toInstance(asyncConnectionMulticaster); EventMulticaster<LibraryChangedEvent> libraryChangedMulticaster = new EventMulticasterImpl<LibraryChangedEvent>(); bind(new TypeLiteral<EventBroadcaster<LibraryChangedEvent>>() {}) .toInstance(libraryChangedMulticaster); bind(new TypeLiteral<ListenerSupport<LibraryChangedEvent>>() {}) .toInstance(libraryChangedMulticaster); // bind eagerly, so it registers itself with SocketsManager bind(FriendAddressResolver.class).asEagerSingleton(); // ditto bind(FriendAddressSerializer.class).asEagerSingleton(); bind(FriendAddressRegistry.class); }
/** Contains a collection of SSL-related utilities. */ public class SSLUtils { private SSLUtils() {} private static final Executor TLS_PROCESSOR = ExecutorsHelper.newProcessingQueue("TLSProcessor"); private static final Provider<SSLContext> TLS_CONTEXT = new AbstractLazySingletonProvider<SSLContext>() { @Override protected SSLContext createObject() { try { SSLContext context = SSLContext.getInstance("TLS"); context.init(null, null, null); // TODO: Set the SSLSessionContext cache size, or timeout? return context; } catch (NoSuchAlgorithmException e) { throw new IllegalStateException(e); } catch (KeyManagementException e) { throw new IllegalStateException(e); } } }; /** Returns the TLS cipher suites this generally supports. */ public static String[] getTLSCipherSuites() { return new String[] {"TLS_DH_anon_WITH_AES_128_CBC_SHA"}; } /** Returns the shared Executor for processing tasks from the SSLEngine. */ public static Executor getExecutor() { return TLS_PROCESSOR; } /** Returns the shared TLS context. */ public static SSLContext getTLSContext() { return TLS_CONTEXT.get(); } /** Returns <code>true</code> is the given socket is already using TLS. */ public static boolean isTLSEnabled(Socket socket) { return socket instanceof TLSNIOSocket; } /** * Returns <code>true</code> if you are capable of performing a {@link #startTLS(Socket, * ByteBuffer)} operation on this <code>socket</code>. */ public static boolean isStartTLSCapable(Socket socket) { return socket instanceof AbstractNBSocket; } /** * Wraps an existing socket in a TLS-enabled socket. Any data within 'data' will be pushed into * the TLS layer. * * <p>This currently only works for creating server-side TLS sockets. * * <p>You must ensure that <code>isTLSCapable</code> returns true for the socket, otherwise an * <code>IllegalArgumentException</code> is thrown. */ public static TLSNIOSocket startTLS(Socket socket, ByteBuffer data) throws IOException { if (socket instanceof AbstractNBSocket) { TLSNIOSocket tlsSocket = new TLSNIOSocket(socket); // Tell the channel to read in the buffered data. if (data.hasRemaining()) { SSLReadWriteChannel sslChannel = tlsSocket.getSSLChannel(); InterestReadableByteChannel oldReader = sslChannel.getReadChannel(); sslChannel.setReadChannel(new BufferReader(data)); sslChannel.read(BufferUtils.getEmptyBuffer()); if (data.hasRemaining()) throw new IllegalStateException("unable to read all prebuffered data in one pass!"); sslChannel.setReadChannel(oldReader); } return tlsSocket; } else { throw new IllegalArgumentException("cannot wrap non AbstractNBSocket"); } } /** * Returns a tracker for the given socket. If no SSL exchanges are performed on the socket, the * returned tracker will always report 0 bytes produced and consumed. */ public static ProtocolBandwidthTracker getSSLBandwidthTracker(Socket socket) { if (socket instanceof TLSNIOSocket) { return new SSLChannelTracker(((TLSNIOSocket) socket).getSSLChannel()); } else { return EmptyTracker.instance(); } } /** * Provides an implementation for the {@link ProtocolBandwidthTracker} interface where each "get" * method returns zero. Using an empty tracker as the default value of a <code>SSLBandwidthTracker * </code> avoids <code>NullPointerExceptions</code>. */ public static class EmptyTracker implements ProtocolBandwidthTracker { private static final EmptyTracker instance = new EmptyTracker(); public static final EmptyTracker instance() { return instance; } private EmptyTracker() {} public long getReadBytesConsumed() { return 0; } public long getReadBytesProduced() { return 0; } public long getWrittenBytesConsumed() { return 0; } public long getWrittenBytesProduced() { return 0; } } private static class SSLChannelTracker implements ProtocolBandwidthTracker { private final SSLReadWriteChannel channel; SSLChannelTracker(SSLReadWriteChannel channel) { this.channel = channel; } public long getReadBytesConsumed() { return channel.getReadBytesConsumed(); } public long getReadBytesProduced() { return channel.getReadBytesProduced(); } public long getWrittenBytesConsumed() { return channel.getWrittenBytesConsumed(); } public long getWrittenBytesProduced() { return channel.getWrittenBytesProduced(); } } }