00001 /* 00002 * Copyright (C) 2011 Google Inc. 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 00005 * use this file except in compliance with the License. You may obtain a copy of 00006 * the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 00013 * License for the specific language governing permissions and limitations under 00014 * the License. 00015 */ 00016 00017 package org.ros.internal.transport.tcp; 00018 00019 import com.google.common.base.Preconditions; 00020 00021 import org.apache.commons.logging.Log; 00022 import org.apache.commons.logging.LogFactory; 00023 import org.jboss.netty.bootstrap.ServerBootstrap; 00024 import org.jboss.netty.buffer.HeapChannelBufferFactory; 00025 import org.jboss.netty.channel.Channel; 00026 import org.jboss.netty.channel.ChannelFactory; 00027 import org.jboss.netty.channel.group.ChannelGroup; 00028 import org.jboss.netty.channel.group.DefaultChannelGroup; 00029 import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; 00030 import org.ros.address.AdvertiseAddress; 00031 import org.ros.address.BindAddress; 00032 import org.ros.internal.node.service.ServiceManager; 00033 import org.ros.internal.node.topic.TopicParticipantManager; 00034 00035 import java.net.InetSocketAddress; 00036 import java.nio.ByteOrder; 00037 import java.util.concurrent.Callable; 00038 import java.util.concurrent.ScheduledExecutorService; 00039 00050 public class TcpRosServer { 00051 00052 private static final boolean DEBUG = false; 00053 private static final Log log = LogFactory.getLog(TcpRosServer.class); 00054 00055 private final BindAddress bindAddress; 00056 private final AdvertiseAddress advertiseAddress; 00057 private final TopicParticipantManager topicParticipantManager; 00058 private final ServiceManager serviceManager; 00059 private final ScheduledExecutorService executorService; 00060 00061 private ChannelFactory channelFactory; 00062 private ServerBootstrap bootstrap; 00063 private Channel outgoingChannel; 00064 private ChannelGroup incomingChannelGroup; 00065 00066 public TcpRosServer(BindAddress bindAddress, AdvertiseAddress advertiseAddress, 00067 TopicParticipantManager topicParticipantManager, ServiceManager serviceManager, 00068 ScheduledExecutorService executorService) { 00069 this.bindAddress = bindAddress; 00070 this.advertiseAddress = advertiseAddress; 00071 this.topicParticipantManager = topicParticipantManager; 00072 this.serviceManager = serviceManager; 00073 this.executorService = executorService; 00074 } 00075 00076 public void start() { 00077 Preconditions.checkState(outgoingChannel == null); 00078 channelFactory = new NioServerSocketChannelFactory(executorService, executorService); 00079 bootstrap = new ServerBootstrap(channelFactory); 00080 bootstrap.setOption("child.bufferFactory", 00081 new HeapChannelBufferFactory(ByteOrder.LITTLE_ENDIAN)); 00082 bootstrap.setOption("child.keepAlive", true); 00083 incomingChannelGroup = new DefaultChannelGroup(); 00084 bootstrap.setPipelineFactory(new TcpServerPipelineFactory(incomingChannelGroup, 00085 topicParticipantManager, serviceManager)); 00086 00087 outgoingChannel = bootstrap.bind(bindAddress.toInetSocketAddress()); 00088 advertiseAddress.setPortCallable(new Callable<Integer>() { 00089 @Override 00090 public Integer call() throws Exception { 00091 return ((InetSocketAddress) outgoingChannel.getLocalAddress()).getPort(); 00092 } 00093 }); 00094 if (DEBUG) { 00095 log.info("Bound to: " + bindAddress); 00096 log.info("Advertising: " + advertiseAddress); 00097 } 00098 } 00099 00106 public void shutdown() { 00107 if (DEBUG) { 00108 log.info("Shutting down: " + getAddress()); 00109 } 00110 if (outgoingChannel != null) { 00111 outgoingChannel.close().awaitUninterruptibly(); 00112 } 00113 incomingChannelGroup.close().awaitUninterruptibly(); 00114 // NOTE(damonkohler): We are purposely not calling 00115 // channelFactory.releaseExternalResources() or 00116 // bootstrap.releaseExternalResources() since only external resources are 00117 // the ExecutorService and control of that must remain with the overall 00118 // application. 00119 outgoingChannel = null; 00120 } 00121 00126 public InetSocketAddress getAddress() { 00127 return advertiseAddress.toInetSocketAddress(); 00128 } 00129 00133 public AdvertiseAddress getAdvertiseAddress() { 00134 return advertiseAddress; 00135 } 00136 }