/* * Copyright (C) 2005-2008 Alfresco, Inc. * * Licensed under the Mozilla Public License version 1.1 * with a permitted attribution clause. You may obtain a * copy of the License at * * http://www.alfresco.org/legal/license.txt * * 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.alfresco.jlan.smb.server; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Vector; import org.alfresco.jlan.debug.Debug; import org.alfresco.jlan.netbios.win32.Win32NetBIOS; import org.alfresco.jlan.server.SessionHandlerInterface; import org.alfresco.jlan.server.SessionHandlerList; import org.alfresco.jlan.server.SocketSessionHandler; import org.alfresco.jlan.server.config.InvalidConfigurationException; import org.alfresco.jlan.smb.mailslot.HostAnnouncer; import org.alfresco.jlan.smb.mailslot.TcpipNetBIOSHostAnnouncer; import org.alfresco.jlan.smb.mailslot.win32.Win32NetBIOSHostAnnouncer; import org.alfresco.jlan.smb.server.win32.LanaListener; import org.alfresco.jlan.smb.server.win32.Win32NetBIOSLanaMonitor; import org.alfresco.jlan.smb.server.win32.Win32NetBIOSSessionSocketHandler; /** * Threaded CIFS Connectins Handler Class * * <p>Create a seperate thread for each enabled CIFS session handler. * * @author gkspencer */ public class ThreadedCifsConnectionsHandler implements CifsConnectionsHandler { // Constants // // Default LANA offline polling interval public static final long LANAPollingInterval = 5000; // 5 seconds // List of session handlers that are waiting for incoming requests private SessionHandlerList m_handlerList; // List of host announcers private Vector<HostAnnouncer> m_hostAnnouncers; // SMB server private SMBServer m_server; // Debug output private boolean m_debug; /** * Class constructor */ public ThreadedCifsConnectionsHandler() { m_handlerList = new SessionHandlerList(); m_hostAnnouncers = new Vector<HostAnnouncer>(); } /** * Check if debug output is enabled * * @return boolean */ public final boolean hasDebug() { return m_debug; } /** * Initialize the connections handler * * @param srv SMBServer * @param config CIFSConfigSection * @exception InvalidConfigurationException */ public void initializeHandler( SMBServer srv, CIFSConfigSection config) throws InvalidConfigurationException { // Save the server m_server = srv; // Check if the socket connection debug flag is enabled if ( (config.getSessionDebugFlags() & SMBSrvSession.DBG_SOCKET) != 0) m_debug = true; // Create the NetBIOS session socket handler, if enabled if ( config.hasNetBIOSSMB()) { // Create the TCP/IP NetBIOS SMB/CIFS session handler(s), and host announcer(s) SocketSessionHandler sessHandler = new NetBIOSSessionSocketHandler( srv, config.getSessionPort(), config.getSMBBindAddress(), hasDebug()); sessHandler.setSocketTimeout( config.getSocketTimeout()); try { // Initialize the NetBIOS session handler sessHandler.initializeSessionHandler( srv); m_handlerList.addHandler( sessHandler); // DEBUG if ( Debug.EnableError && hasDebug()) Debug.println("[SMB] TCP NetBIOS session handler created"); // Check if a host announcer should be created if ( config.hasEnableAnnouncer()) { // Create the TCP NetBIOS host announcer TcpipNetBIOSHostAnnouncer announcer = new TcpipNetBIOSHostAnnouncer(); // Set the host name to be announced announcer.addHostName(config.getServerName()); announcer.setDomain(config.getDomainName()); announcer.setComment(config.getComment()); announcer.setBindAddress(config.getSMBBindAddress()); if ( config.getHostAnnouncerPort() != 0) announcer.setPort(config.getHostAnnouncerPort()); // Check if there are alias names to be announced if ( config.hasAliasNames()) announcer.addHostNames(config.getAliasNames()); // Set the announcement interval if ( config.getHostAnnounceInterval() > 0) announcer.setInterval(config.getHostAnnounceInterval()); try { announcer.setBroadcastAddress(config.getBroadcastMask()); } catch (Exception ex) { } // Set the server type flags announcer.setServerType(config.getServerType()); // Enable debug output if ( config.hasHostAnnounceDebug()) announcer.setDebug(true); // Add the announcer to the list m_hostAnnouncers.add( announcer); // DEBUG if ( Debug.EnableError && hasDebug()) Debug.println("[SMB] TCP NetBIOS host announcer created"); } } catch (IOException ex) { } } // Create the TCP/IP SMB session socket handler, if enabled if ( config.hasTcpipSMB()) { // Create the TCP/IP native SMB session handler(s) SocketSessionHandler sessHandler = new TcpipSMBSessionSocketHandler( srv, config.getTcpipSMBPort(), config.getSMBBindAddress(), hasDebug()); sessHandler.setSocketTimeout( config.getSocketTimeout()); try { // Initialize the native SMB handler sessHandler.initializeSessionHandler( srv); m_handlerList.addHandler( sessHandler); // DEBUG if ( Debug.EnableError && hasDebug()) Debug.println("[SMB] Native SMB TCP session handler created"); } catch ( IOException ex) { throw new InvalidConfigurationException( "Error initializing session handler, " + ex.getMessage()); } } // Create the Win32 NetBIOS session handler, if enabled if ( config.hasWin32NetBIOS()) { // Only enable if running under Windows if ( isWindowsNTOnwards()) { // DEBUG if ( Debug.EnableInfo && hasDebug()) { int[] lanas = Win32NetBIOS.LanaEnumerate(); StringBuffer lanaStr = new StringBuffer(); if ( lanas != null && lanas.length > 0) { for (int i = 0; i < lanas.length; i++) { lanaStr.append(Integer.toString(lanas[i])); lanaStr.append(" "); } } Debug.println("[SMB] Win32 NetBIOS Available LANAs: " + lanaStr.toString()); } // Check if the Win32 NetBIOS session handler should use a particular LANA/network adapter // or should use all available LANAs/network adapters (that have NetBIOS enabled). Win32NetBIOSSessionSocketHandler sessHandler = null; List<Win32NetBIOSSessionSocketHandler> lanaListeners = new ArrayList<Win32NetBIOSSessionSocketHandler>(); if ( config.getWin32LANA() != -1) { // Create a single Win32 NetBIOS session handler using the specified LANA sessHandler = new Win32NetBIOSSessionSocketHandler(srv, config.getWin32LANA(), hasDebug()); try { // Initialize the Win32 JNI session handler sessHandler.initializeSessionHandler( srv); m_handlerList.addHandler( sessHandler); // DEBUG if ( Debug.EnableInfo && hasDebug()) Debug.println("[SMB] Win32 NetBIOS created session handler on LANA " + config.getWin32LANA()); } catch (Exception ex) { // DEBUG if ( Debug.EnableError && hasDebug()) { Debug.println("[SMB] Win32 NetBIOS failed to create session handler for LANA " + config.getWin32LANA()); Debug.println(" " + ex.getMessage()); } } // Check if a host announcer should be enabled if ( config.hasWin32EnableAnnouncer()) { // Create a host announcer Win32NetBIOSHostAnnouncer hostAnnouncer = new Win32NetBIOSHostAnnouncer(sessHandler, config.getDomainName(), config.getWin32HostAnnounceInterval()); hostAnnouncer.setDebug( hasDebug()); // Add the host announcer to the SMB/CIFS server list m_hostAnnouncers.add( hostAnnouncer); // DEBUG if ( Debug.EnableInfo && hasDebug()) Debug.println("[SMB] Win32 NetBIOS host announcer enabled on LANA " + config.getWin32LANA()); } // Check if the session handler implements the LANA listener interface if ( sessHandler instanceof LanaListener) lanaListeners.add(sessHandler); } else { // Get a list of the available LANAs int[] lanas = Win32NetBIOS.LanaEnumerate(); if ( lanas != null && lanas.length > 0) { // Create a session handler for each available LANA for (int i = 0; i < lanas.length; i++) { // Get the current LANA int lana = lanas[i]; // Create a session handler sessHandler = new Win32NetBIOSSessionSocketHandler( srv, lana, hasDebug()); try { // Initialize the Win32 JNI session handler sessHandler.initializeSessionHandler( srv); m_handlerList.addHandler( sessHandler); // DEBUG if ( Debug.EnableError && hasDebug()) Debug.println("[SMB] Win32 NetBIOS created session handler on LANA " + lana); } catch (Exception ex) { // DEBUG if ( Debug.EnableError && hasDebug()) { Debug.println("[SMB] Win32 NetBIOS failed to create session handler for LANA " + lana); Debug.println(" " + ex.getMessage()); } } // Check if a host announcer should be enabled if ( config.hasWin32EnableAnnouncer()) { // Create a host announcer Win32NetBIOSHostAnnouncer hostAnnouncer = new Win32NetBIOSHostAnnouncer(sessHandler, config.getDomainName(), config.getWin32HostAnnounceInterval()); hostAnnouncer.setDebug( hasDebug()); // Add the host announcer to the SMB/CIFS server list m_hostAnnouncers.add( hostAnnouncer); // DEBUG if ( Debug.EnableInfo && hasDebug()) Debug.println("[SMB] Win32 NetBIOS host announcer enabled on LANA " + lana); } // Check if the session handler implements the LANA listener interface if ( sessHandler instanceof LanaListener) lanaListeners.add(sessHandler); } } // Create a LANA monitor to check for new LANAs becoming available Win32NetBIOSLanaMonitor lanaMonitor = new Win32NetBIOSLanaMonitor( srv, lanas, LANAPollingInterval, hasDebug()); // Register any session handlers that are LANA listeners if ( lanaListeners.size() > 0) { for (int i = 0; i < lanaListeners.size(); i++) { // Get the current LANA listener Win32NetBIOSSessionSocketHandler handler = lanaListeners.get(i); // Register the LANA listener lanaMonitor.addLanaListener(handler.getLANANumber(), handler); } } } } } } /** * Return the count of active session handlers * * @return int */ public int numberOfSessionHandlers() { return m_handlerList.numberOfHandlers(); } /** * Start the connection handler thread */ public void startHandler() { // Start each session handler in a seperate thread for ( int idx = 0; idx < m_handlerList.numberOfHandlers(); idx++) { SessionHandlerInterface sessHandler = m_handlerList.getHandlerAt( idx); if ( sessHandler instanceof Runnable) { // Start the session handler in a seperate thread Thread handlerThread = new Thread(( Runnable) sessHandler); handlerThread.setName( "CIFSSessHandler_" + sessHandler.getHandlerName()); handlerThread.start(); // DEBUG if ( Debug.EnableInfo && hasDebug()) Debug.println("[SMB] Created session handler thread " + handlerThread.getName()); } } // Start the host announcer(s) if ( m_hostAnnouncers.size() > 0) { for ( int idx = 0; idx < m_hostAnnouncers.size(); idx++) { // Get the current host announcer HostAnnouncer hostAnnouncer = (HostAnnouncer) m_hostAnnouncers.get( idx); hostAnnouncer.startAnnouncer(); // DEBUG if ( Debug.EnableInfo && hasDebug()) Debug.println( "[SMB] Started host announcer " + hostAnnouncer.getName()); } } } /** * Stop the connections handler */ public void stopHandler() { // Stop each session handler for ( int idx = 0; idx < m_handlerList.numberOfHandlers(); idx++) { SessionHandlerInterface sessHandler = m_handlerList.getHandlerAt( idx); sessHandler.closeSessionHandler( m_server); // DEBUG if ( Debug.EnableInfo && hasDebug()) Debug.println("[SMB] Shutting down session handler thread " + sessHandler.getHandlerName()); } // Stop the host announcer(s) if ( m_hostAnnouncers.size() > 0) { for ( int idx = 0; idx < m_hostAnnouncers.size(); idx++) { // Get the current host announcer HostAnnouncer hostAnnouncer = (HostAnnouncer) m_hostAnnouncers.get( idx); hostAnnouncer.shutdownAnnouncer(); // DEBUG if ( Debug.EnableInfo && hasDebug()) Debug.println( "[SMB] Shutting down host announcer " + hostAnnouncer.getName()); } } } /** * Determine if we are running under Windows NT onwards * * @return boolean */ private final boolean isWindowsNTOnwards() { // Get the operating system name property String osName = System.getProperty("os.name"); if ( osName.startsWith("Windows")) { if ( osName.endsWith("95") || osName.endsWith("98") || osName.endsWith("ME")) { // Windows 95-ME return false; } // Looks like Windows NT onwards return true; } // Not Windows return false; } }