blob: 06dd56dbbd05468c78eeac14efbf2ec0b389c4c6 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009 Nokia and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Nokia - Initial API and implementation
*******************************************************************************/
/*******************************************************************************
* Copyright (c) 2008 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.debug.edc.tcf.extension;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.tm.tcf.core.AbstractPeer;
import org.eclipse.tm.tcf.core.ChannelTCP;
import org.eclipse.tm.tcf.protocol.IPeer;
import org.eclipse.tm.tcf.protocol.Protocol;
/**
* ServerTCP is a TCP server that is listening for incoming connection requests
* and creates TCF communication channels over TCP sockets for such requests.
*
* Clients may create objects of this class to become a TCF server.
*/
public class ServerTCP extends ServerSocket {
private static class ServerPeer extends AbstractPeer {
ServerPeer(Map<String, String> attrs) {
super(attrs);
}
}
private static class RemotePeer extends AbstractPeer {
RemotePeer(Map<String, String> attrs) {
super(attrs);
}
}
private final String name;
private List<ServerPeer> peers;
private Thread thread;
public ServerTCP(String name, int port) throws IOException {
super(port);
this.name = name;
peers = new ArrayList<ServerPeer>();
Enumeration<NetworkInterface> e = NetworkInterface.getNetworkInterfaces();
while (e.hasMoreElements()) {
NetworkInterface f = e.nextElement();
Enumeration<InetAddress> n = f.getInetAddresses();
while (n.hasMoreElements()) {
InetAddress addr = n.nextElement();
if (shouldCreatePeerOnAddress(addr))
getLocalPeer(addr.getHostAddress());
}
}
thread = new Thread() {
@Override
public void run() {
while (true) {
try {
final Socket socket = accept();
Protocol.invokeLater(new Runnable() {
public void run() {
try {
new ChannelTCP(getLocalPeer(socket), getRemotePeer(socket), socket);
} catch (final Throwable x) {
Protocol.log("TCF Server: failed to create a channel", x);
}
}
});
} catch (final Throwable x) {
Protocol.invokeLater(new Runnable() {
public void run() {
Protocol.log("TCF Server thread aborted", x);
}
});
break;
}
}
}
};
thread.setName(name);
thread.setDaemon(true);
thread.start();
}
/**
* Check if we want to create a server peer on the given local address. Note
* a network host may have several net addresses. By default we create a
* peer on each of them. This method is to allow subclass to do certain
* filtering, for instance not to create peer on loopback address.
*
* @param localAddr
* @return
*/
protected boolean shouldCreatePeerOnAddress(InetAddress localAddr) {
return true;
}
/**
* This is to allow subclass to specify customized attributes for creating
* new server peer.
*
* @return
*/
protected Map<String, String> getCustomPeerAttributes() {
Map<String, String> attrs = new HashMap<String, String>();
return attrs;
}
private ServerPeer getLocalPeer(String addr) {
for (ServerPeer p : peers) {
if (addr.equals(p.getAttributes().get(IPeer.ATTR_IP_HOST)))
return p;
}
// Standard attributes
//
Map<String, String> attrs = new HashMap<String, String>();
attrs.put(IPeer.ATTR_ID, "TCP:" + addr + ":" + getLocalPort());
attrs.put(IPeer.ATTR_NAME, name);
attrs.put(IPeer.ATTR_OS_NAME, System.getProperty("os.name"));
attrs.put(IPeer.ATTR_TRANSPORT_NAME, "TCP");
attrs.put(IPeer.ATTR_IP_HOST, addr);
attrs.put(IPeer.ATTR_IP_PORT, Integer.toString(getLocalPort()));
attrs.put(IPeer.ATTR_PROXY, "");
// Custom attributes
//
attrs.putAll(getCustomPeerAttributes());
ServerPeer p = new ServerPeer(attrs);
peers.add(p);
return p;
}
private IPeer getLocalPeer(Socket socket) {
return getLocalPeer(socket.getLocalAddress().getHostAddress());
}
private IPeer getRemotePeer(Socket socket) {
String addr = socket.getInetAddress().getHostAddress();
for (IPeer p : Protocol.getLocator().getPeers().values()) {
if (addr.equals(p.getAttributes().get(IPeer.ATTR_IP_HOST)))
return p;
}
Map<String, String> attrs = new HashMap<String, String>();
attrs.put(IPeer.ATTR_ID, "TCP:" + addr + ":");
attrs.put(IPeer.ATTR_TRANSPORT_NAME, "TCP");
attrs.put(IPeer.ATTR_IP_HOST, addr);
return new RemotePeer(attrs);
}
@Override
public void close() throws IOException {
if (peers != null) {
for (ServerPeer s : peers)
s.dispose();
peers = null;
}
super.close();
if (thread != null) {
try {
thread.join();
thread = null;
} catch (InterruptedException e) {
throw new InterruptedIOException();
}
}
}
}