package promauto.jroboplc;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.TreeMap;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelException;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.group.ChannelGroup;
import org.jboss.netty.channel.group.ChannelGroupFuture;
import org.jboss.netty.channel.group.DefaultChannelGroup;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import promauto.utils.RpHyperstring;
public class SvcTcpServer extends Service implements IConsoleCmd {
// private static Logger logger = Logger.getLogger(SvcTcpServerHandlerAscii.class);
public static final ChannelGroup allTcpServerChannels = new DefaultChannelGroup("svctcpserver");
public static final int FRAME_LENGHT_ASCII = 16384;
private ServerBootstrap bootstrapAscii;
// private ServerBootstrap bootstrapRtu;
// private ServerBootstrap bootstrapRaw;
private ChannelFactory channelFactory;
// <tcpport, port>
public HashMap<Integer, TcpServerPort> ports = new HashMap<Integer, TcpServerPort>();
@Override
public String getServiceName() {
return "tcpserver";
}
@Override
public boolean load() {
super.load();
String tmpl = getServiceName() + ".port";
try {
TreeMap<Integer, ArrayList<String>> a = RpHyperstring.getPropertyBunch(JRoboPLC.props, tmpl);
for (Integer num: a.keySet()) {
TcpServerPort port = new TcpServerPort();
port.portnum = num;
for (String s: a.get(num)) {
String[] ss = s.split("\\s*=\\s*");
if (ss[0].endsWith("port")) {
port.tcpport = Integer.parseInt(ss[1]);
ports.put(port.tcpport, port);
} else
if (ss[0].endsWith("maxcon")) {
port.connMax = Integer.parseInt(ss[1]);
} else
// if (ss[0].endsWith("protobase")) {
// port.protoBase = TcpServerProtocolBase.valueOf(ss[1].toUpperCase());
// } else
if (ss[0].endsWith("ipfilter")) {
String[] sp = ss[1].split("\\s*,\\s*");
port.ipfilter = new String[sp.length];
for (int i=0; i<sp.length; i++) {
port.ipfilter[i] = sp[i].replace(".","\\.").replace("*", ".*");
}
}
}
}
} catch (NumberFormatException e) {
JRoboUtils.logError(JRoboStrings.BAD_TCPSERVER_CFG, e);
return false;
}
return true;
}
public TcpServerPort getPort(int portnum) {
for (TcpServerPort port: ports.values())
if (port.portnum == portnum)
return port;
return null;
}
@Override
public boolean initialize() {
super.initialize();
// // getting subscribers among services
// for (Service svc: JRoboPLC.services)
// if (svc instanceof ITcpServerSubscriber)
// addSubscriber((ITcpServerSubscriber)svc);
//
// // getting subscribers among modules
// for (Module mdl: JRoboPLC.modules)
// if (mdl instanceof ITcpServerSubscriber)
// addSubscriber((ITcpServerSubscriber)mdl);
// setting up tcp server
channelFactory = new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool());
bootstrapAscii = new ServerBootstrap( channelFactory );
bootstrapAscii.setPipelineFactory(new SvcTcpServerPipelineFactoryAscii(this));
// bootstrapRtu = new ServerBootstrap( channelFactory );
// bootstrapRtu.setPipelineFactory(new SvcTcpServerPipelineFactoryRtu(this));
return true;
}
// private void addSubscriber(ITcpServerSubscriber subscriber) {
// for (TcpServerPort port: ports.values())
// if (subscriber.isSubscriber(port))
// if (port.subscriber == null)
// port.subscriber = subscriber;
// }
@Override
public boolean start() {
super.start();
try {
// Bind and start to accept incoming connections.
for (TcpServerPort port: ports.values()) {
Channel channel = null;
switch (port.protoBase) {
case ASCII:
JRoboUtils.println(JRoboStrings.TCPSVR_BIND_PORT + port.tcpport);
channel = bootstrapAscii.bind(new InetSocketAddress(port.tcpport));
break;
// case RTU:
// channel = bootstrapRtu.bind(new InetSocketAddress(port.tcpport));
// break;
}
if (channel!=null)
allTcpServerChannels.add(channel);
}
return true;
} catch (ChannelException e) {
JRoboUtils.logError(JRoboStrings.CAN_T_BIND_TCP_PORT, e);
return false;
}
}
@Override
public boolean closedown() {
if (!loaded)
return true;
super.closedown();
ChannelGroupFuture future = allTcpServerChannels.close();
future.awaitUninterruptibly();
if (channelFactory!=null)
channelFactory.releaseExternalResources();
allTcpServerChannels.clear();
ports.clear();
return true;
}
@Override
public int getStatus() {
// TODO Auto-generated method stub
return 0;
}
@Override
public String getStatusStr() {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean processConsoleCommand(SvcConsole svcConsole, int reqId,
String[] cmd) throws Exception {
boolean result = super.processConsoleCommand( svcConsole, reqId, cmd );
if (result) {
// Command - list
if (cmd[1].equals("list") || cmd[1].equals("l")) {
for (TcpServerPort port: ports.values()) {
svcConsole.write(
"port"+port.portnum + " tcpport="+ port.tcpport + " " + port.protoBase +
"\n" );
for (String ip: port.clients.keySet())
svcConsole.write(
" " + ip + " / " + port.clients.get(ip) + "\n" );
}
} else
// somebody else's command
result = false;
}
return result;
}
@Override
public void writeConsoleHelp(SvcConsole svcConsole) {
svcConsole.write(
" " + getServiceName() + " l|list\n" +
""
);
}
}