/* * Copyright (c) 1998-2015 Caucho Technology -- all rights reserved * * This file is part of Baratine(TM) * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Baratine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Baratine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Baratine; if not, write to the * * Free Software Foundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * * @author Scott Ferguson */ package com.caucho.v5.bartender.hamp; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.SocketException; import java.util.logging.Level; import java.util.logging.Logger; import com.caucho.v5.amp.ServicesAmp; import com.caucho.v5.amp.ServiceRefAmp; import com.caucho.v5.amp.remote.ChannelAmp; import com.caucho.v5.amp.remote.ChannelServerLinkImpl; import com.caucho.v5.amp.remote.ClientAmpBase; import com.caucho.v5.amp.remote.OutAmp; import com.caucho.v5.amp.remote.OutAmpFactory; import com.caucho.v5.amp.spi.ShutdownModeAmp; import com.caucho.v5.ramp.hamp.InHamp; import io.baratine.service.ServiceRef; /** * HMTP client protocol */ public class LinkHamp extends ClientAmpBase implements Runnable { private static final Logger log = Logger.getLogger(LinkHamp.class.getName()); private InputStream _is; private OutputStream _os; private String _address; private boolean _isClosed; private InHamp _in; private ChannelServerLinkImpl _channel; private OutHampImpl _out; public LinkHamp(InputStream is, OutputStream os) { this(ServicesAmp.newManager().start(), "remote://", is, os); } public LinkHamp(ServicesAmp manager, String peerAddress, InputStream is, OutputStream os) { super(manager, "remote:"); _is = is; _os = os; // RampServiceRef readService = RampClientReadActor.create(manager); /* ChannelManagerService sessionManager = new ChannelManagerServiceImpl(manager); String podName = null; ChannelServerFactory channelFactory = new RegistryAmpInServerFactoryImpl(manager, sessionManager, podName); */ //_conn = new HampWriteConnection(_os, brokerFactory, peerAddress); _out = new OutHampImpl(_os); _channel = new ChannelServerLinkImpl(()->manager, _out); // _channel.onLogin("link"); // XXX: need remote ServiceRefAmp channelRef = _channel.getServiceRefOut(); // make remote:// available for callers channelRef.bind(peerAddress); // make remote:// available for remote reply _channel.bind(peerAddress, channelRef); _in = new InHamp(manager, _channel); _in.init(_is); } @Override protected void bindRemote() { } public String getAddress() { return _address; } public void setAddress(String address) { _address = address; } public ServicesAmp getManager() { return (ServicesAmp) delegate(); } @Override public String getUrl() { return "remote:///link"; } @Override public LinkHamp connect() { return this; } /* @Override public <T> T lookup(String address, Class<T> api) { return getManager().lookup(address).as(api); } @Override public void publish(String address, Object actor) { getManager().service(actor).bind(address); } */ protected OutAmpFactory getOutFactory() { return new OutAmpFactoryImpl(); } private class OutAmpFactoryImpl implements OutAmpFactory { @Override public boolean isUp() { return ! isClosed(); } @Override public OutAmp getOut(ChannelAmp registry) { return _out; } } public boolean isClosed() { return _isClosed; } /** * Receive messages from the client */ @Override public void run() { try { while (! isClosed() && _is.read() > 0 && _in.readMessage(_is)) { ServiceRef.flushOutbox(); } } catch (EOFException e) { log.finer(this + " end of file"); if (log.isLoggable(Level.ALL)) { log.log(Level.ALL, e.toString(), e); } } catch (SocketException e) { e.printStackTrace(); log.finer(this + " socket closed:" + e); if (log.isLoggable(Level.ALL)) { log.log(Level.ALL, e.toString(), e); } } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(e); } catch (Throwable e) { e.printStackTrace(); throw e; } finally { close(); } } @Override public void close() { _isClosed = true; _channel.shutdown(ShutdownModeAmp.GRACEFUL); _out.close(); try { _is.close(); } catch (Exception e) { log.log(Level.FINEST, e.toString(), e); } try { _os.close(); } catch (Exception e) { log.log(Level.FINEST, e.toString(), e); } } }