/* * RED5 Open Source Flash Server - http://code.google.com/p/red5/ * * Copyright 2006-2012 by respective authors (see below). All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.red5.server.net.mrtmp; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.util.HashSet; import java.util.Set; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.buffer.SimpleBufferAllocator; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.filter.logging.LoggingFilter; import org.apache.mina.transport.socket.SocketAcceptor; import org.apache.mina.transport.socket.SocketSessionConfig; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Steven Gong (steven.gong@gmail.com) */ public class MRTMPMinaTransport { private static final int DEFAULT_EVENT_THREADS_CORE = 16; private static final int DEFAULT_EVENT_THREADS_KEEPALIVE = 60; private static final int DEFAULT_EVENT_THREADS_MAX = 32; private static final int DEFAULT_EVENT_THREADS_QUEUE = -1; private static final int DEFAULT_IO_THREADS = Runtime.getRuntime() .availableProcessors(); private static final int DEFAULT_PORT = 1935; private static final int DEFAULT_RECEIVE_BUFFER_SIZE = 256 * 1024; private static final int DEFAULT_SEND_BUFFER_SIZE = 64 * 1024; private static final boolean DEFAULT_TCP_NO_DELAY = false; private static final boolean DEFAULT_USE_HEAP_BUFFERS = true; private static final Logger log = LoggerFactory.getLogger(MRTMPMinaTransport.class); private SocketAcceptor acceptor; private String address = null; private int eventThreadsCore = DEFAULT_EVENT_THREADS_CORE; private int eventThreadsKeepalive = DEFAULT_EVENT_THREADS_KEEPALIVE; private int eventThreadsMax = DEFAULT_EVENT_THREADS_MAX; private int eventThreadsQueue = DEFAULT_EVENT_THREADS_QUEUE; private IoHandlerAdapter ioHandler; private int ioThreads = DEFAULT_IO_THREADS; private boolean isLoggingTraffic = false; private int port = DEFAULT_PORT; private int receiveBufferSize = DEFAULT_RECEIVE_BUFFER_SIZE; private int sendBufferSize = DEFAULT_SEND_BUFFER_SIZE; private boolean tcpNoDelay = DEFAULT_TCP_NO_DELAY; private boolean useHeapBuffers = DEFAULT_USE_HEAP_BUFFERS; private void initIOHandler() { if (ioHandler == null) { log.info("No rtmp IO Handler associated - using defaults"); ioHandler = new OriginMRTMPHandler(); } } public void setAddress(String address) { if ("*".equals(address) || "0.0.0.0".equals(address)) { address = null; } this.address = address; } public void setEventThreadsCore(int eventThreadsCore) { this.eventThreadsCore = eventThreadsCore; } public void setEventThreadsKeepalive(int eventThreadsKeepalive) { this.eventThreadsKeepalive = eventThreadsKeepalive; } public void setEventThreadsMax(int eventThreadsMax) { this.eventThreadsMax = eventThreadsMax; } public void setEventThreadsQueue(int eventThreadsQueue) { this.eventThreadsQueue = eventThreadsQueue; } public void setIoHandler(IoHandlerAdapter rtmpIOHandler) { this.ioHandler = rtmpIOHandler; } public void setIoThreads(int ioThreads) { this.ioThreads = ioThreads; } public void setIsLoggingTraffic(boolean isLoggingTraffic) { this.isLoggingTraffic = isLoggingTraffic; } public void setPort(int port) { this.port = port; } public void setReceiveBufferSize(int receiveBufferSize) { this.receiveBufferSize = receiveBufferSize; } public void setSendBufferSize(int sendBufferSize) { this.sendBufferSize = sendBufferSize; } public void setTcpNoDelay(boolean tcpNoDelay) { this.tcpNoDelay = tcpNoDelay; } public void setUseHeapBuffers(boolean useHeapBuffers) { this.useHeapBuffers = useHeapBuffers; } public void start() throws Exception { initIOHandler(); IoBuffer.setUseDirectBuffer(!useHeapBuffers); // this is global, oh well. if (useHeapBuffers) { IoBuffer.setAllocator(new SimpleBufferAllocator()); // dont pool for heap buffers. } log.info("MRTMP Mina Transport Settings"); log.info("IO Threads: {}", ioThreads); log.info("Event Threads:" + " core: " + eventThreadsCore + "+1" + " max: " + eventThreadsMax + "+1" + " queue: " + eventThreadsQueue + " keepalive: " + eventThreadsKeepalive); // Executors.newCachedThreadPool() is always preferred by IoService // See http://mina.apache.org/configuring-thread-model.html for details acceptor = new NioSocketAcceptor(ioThreads); acceptor.setHandler(ioHandler); acceptor.setBacklog(100); log.info("TCP No Delay: {}", tcpNoDelay); log.info("Receive Buffer Size: {}", receiveBufferSize); log.info("Send Buffer Size: {}", sendBufferSize); SocketSessionConfig sessionConf = acceptor.getSessionConfig(); sessionConf.setReuseAddress(true); sessionConf.setTcpNoDelay(tcpNoDelay); // XXX ignore the config of buffer settings // sessionConf.setReceiveBufferSize(receiveBufferSize); // sessionConf.setSendBufferSize(sendBufferSize); if (isLoggingTraffic) { log.info("Configuring traffic logging filter"); IoFilter filter = new LoggingFilter(); acceptor.getFilterChain().addFirst("LoggingFilter", filter); } Set<SocketAddress> addresses = new HashSet<SocketAddress>(); SocketAddress socketAddress = (address == null) ? new InetSocketAddress(port) : new InetSocketAddress(address, port); addresses.add(socketAddress); acceptor.bind(addresses); log.info("MRTMP Mina Transport bound to {}", socketAddress.toString()); } public void stop() { log.info("MRTMP Mina Transport unbind"); acceptor.unbind(); } public String toString() { return "MRTMP Mina Transport [port=" + port + "]"; } }