2012-03-07 18:44:43 +00:00
|
|
|
// Copyright 2011, 2012 Tony Garnock-Jones <tonygarnockjones@gmail.com>.
|
|
|
|
//
|
|
|
|
// This file is part of Hop.
|
|
|
|
//
|
|
|
|
// Hop 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 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// Hop 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. See the GNU General Public
|
|
|
|
// License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with Hop. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
//
|
2012-03-06 23:08:18 +00:00
|
|
|
package hop;
|
|
|
|
|
|
|
|
import java.io.*;
|
|
|
|
import java.net.Socket;
|
|
|
|
|
|
|
|
/**
|
|
|
|
*/
|
|
|
|
public class Relay implements Runnable, Node, Flushable {
|
|
|
|
NodeContainer _container;
|
|
|
|
String _remoteName;
|
|
|
|
Socket _sock;
|
|
|
|
String _hostname;
|
|
|
|
int _port;
|
|
|
|
SexpReader _r;
|
|
|
|
OutputStream _output;
|
|
|
|
SexpWriter _w;
|
|
|
|
|
|
|
|
public Relay(NodeContainer container, String hostname) throws IOException, InterruptedException {
|
|
|
|
this(container, hostname, 5671);
|
|
|
|
}
|
|
|
|
|
|
|
|
public Relay(NodeContainer container, String hostname, int port) throws IOException, InterruptedException {
|
|
|
|
_container = container;
|
|
|
|
_remoteName = null;
|
|
|
|
_hostname = hostname;
|
|
|
|
_port = port;
|
|
|
|
_connect();
|
|
|
|
}
|
|
|
|
|
|
|
|
public String getRemoteName() {
|
|
|
|
return _remoteName;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void _connect() throws IOException, InterruptedException {
|
|
|
|
_sock = new Socket(_hostname, _port);
|
|
|
|
_sock.setTcpNoDelay(true);
|
|
|
|
_r = new SexpReader(new BufferedInputStream(_sock.getInputStream()));
|
|
|
|
_output = new BufferedOutputStream(_sock.getOutputStream());
|
|
|
|
_w = new SexpWriter(_output);
|
|
|
|
_login();
|
|
|
|
new Thread(this).start();
|
|
|
|
synchronized (this) {
|
|
|
|
while (_remoteName == null) {
|
|
|
|
this.wait();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void _login() throws IOException {
|
|
|
|
SexpList greeting = _r.readList();
|
|
|
|
if (!greeting.getBytes(0).getDataString().equals("hop")) {
|
|
|
|
throw new InvalidGreetingException(greeting);
|
|
|
|
}
|
|
|
|
|
|
|
|
_w.write(SexpMessage.subscribe(_container.getName(), null, null, null, null));
|
|
|
|
}
|
|
|
|
|
|
|
|
public void handle(Object message) {
|
|
|
|
try {
|
|
|
|
_w.write(message);
|
|
|
|
} catch (IOException ioe) {
|
|
|
|
ioe.printStackTrace();
|
|
|
|
System.err.print("Message to be written was: ");
|
|
|
|
try {
|
|
|
|
SexpWriter.write(System.err, message);
|
|
|
|
} catch (IOException ioe2) {
|
|
|
|
ioe2.printStackTrace();
|
|
|
|
}
|
|
|
|
System.err.println();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void flush() throws IOException {
|
|
|
|
_output.flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void run() {
|
|
|
|
SexpList m = null;
|
|
|
|
try {
|
|
|
|
while (true) {
|
|
|
|
m = _r.readList();
|
|
|
|
if (m == null) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
//System.err.println("Received: " + m);
|
|
|
|
String selector = m.getBytes(0).getDataString();
|
|
|
|
if (selector.equals("post") && m.size() == 4) {
|
|
|
|
_container.send(m.getBytes(1).getDataString(), m.get(2));
|
|
|
|
} else if (selector.equals("subscribe") && m.size() == 6) {
|
|
|
|
if (_remoteName != null) {
|
|
|
|
System.err.println("Double bind attempted");
|
|
|
|
} else {
|
|
|
|
_remoteName = m.getBytes(1).getDataString();
|
|
|
|
synchronized (this) {
|
|
|
|
this.notifyAll();
|
|
|
|
}
|
|
|
|
if (_container.bind(_remoteName, this)) {
|
|
|
|
String replySink = m.getBytes(4).getDataString();
|
|
|
|
if (replySink.length() > 0) {
|
|
|
|
_container.post(replySink, m.get(5), SexpMessage.subscribe_ok(_remoteName), null);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
System.err.println("Bind failed: " + _remoteName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (selector.equals("unsubscribe") && m.size() == 2) {
|
|
|
|
if (!m.getBytes(1).getDataString().equals(_remoteName)) {
|
|
|
|
System.err.println("Unknown unbind attempted");
|
|
|
|
} else {
|
|
|
|
if (!_container.unbind(m.getBytes(1).getDataString())) {
|
|
|
|
System.err.println("Unbind failed: " + m.get(1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
System.err.print("Unknown message: ");
|
|
|
|
SexpWriter.write(System.err, m);
|
|
|
|
System.err.println();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (IOException ioe) {
|
|
|
|
ioe.printStackTrace();
|
|
|
|
System.err.print("Most recent received message: ");
|
|
|
|
try {
|
|
|
|
SexpWriter.write(System.err, m);
|
|
|
|
} catch (IOException ioe2) {
|
|
|
|
ioe2.printStackTrace();
|
|
|
|
}
|
|
|
|
System.err.println();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|