mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Moving to root below branch label
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2005 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2005 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.filesys.smb.server.win32;
|
||||
|
||||
/**
|
||||
* LANA Listener Class
|
||||
*
|
||||
* <p>Receive status change events for a particular NetBIOS LANA.
|
||||
*
|
||||
* @author GKSpencer
|
||||
*/
|
||||
public interface LanaListener
|
||||
{
|
||||
/**
|
||||
* LANA status change callback
|
||||
*
|
||||
* @param lana int
|
||||
* @param online boolean
|
||||
*/
|
||||
public void lanaStatusChange( int lana, boolean online);
|
||||
}
|
@@ -0,0 +1,423 @@
|
||||
/*
|
||||
* Copyright (C) 2005 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.filesys.smb.server.win32;
|
||||
|
||||
import java.util.BitSet;
|
||||
|
||||
import org.alfresco.filesys.netbios.win32.NetBIOSSocket;
|
||||
import org.alfresco.filesys.netbios.win32.Win32NetBIOS;
|
||||
import org.alfresco.filesys.netbios.win32.WinsockNetBIOSException;
|
||||
import org.alfresco.filesys.server.config.ServerConfiguration;
|
||||
import org.alfresco.filesys.smb.mailslot.Win32NetBIOSHostAnnouncer;
|
||||
import org.alfresco.filesys.smb.server.SMBServer;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Win32 NetBIOS LANA Monitor Class
|
||||
* <p>
|
||||
* Monitors the available NetBIOS LANAs to check for new network interfaces coming online. A session
|
||||
* socket handler will be created for new LANAs as they appear.
|
||||
*/
|
||||
public class Win32NetBIOSLanaMonitor extends Thread
|
||||
{
|
||||
// Constants
|
||||
//
|
||||
// Initial LANA listener array size
|
||||
|
||||
private static final int LanaListenerArraySize = 16;
|
||||
|
||||
// Debug logging
|
||||
|
||||
private static final Log logger = LogFactory.getLog("org.alfresco.smb.protocol");
|
||||
|
||||
// Global LANA monitor
|
||||
|
||||
private static Win32NetBIOSLanaMonitor _lanaMonitor;
|
||||
|
||||
// Available LANA list and current status
|
||||
|
||||
private BitSet m_lanas;
|
||||
private BitSet m_lanaSts;
|
||||
|
||||
// LANA status listeners
|
||||
|
||||
private LanaListener[] m_listeners;
|
||||
|
||||
// SMB/CIFS server to add new session handlers to
|
||||
|
||||
private SMBServer m_server;
|
||||
|
||||
// Wakeup interval
|
||||
|
||||
private long m_wakeup;
|
||||
|
||||
// Shutdown request flag
|
||||
|
||||
private boolean m_shutdown;
|
||||
|
||||
// Debug output enable
|
||||
|
||||
private boolean m_debug;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* @param server SMBServer
|
||||
* @param lanas int[]
|
||||
* @param wakeup long
|
||||
* @param debug boolean
|
||||
*/
|
||||
Win32NetBIOSLanaMonitor(SMBServer server, int[] lanas, long wakeup, boolean debug)
|
||||
{
|
||||
|
||||
// Set the SMB server and wakeup interval
|
||||
|
||||
m_server = server;
|
||||
m_wakeup = wakeup;
|
||||
|
||||
m_debug = debug;
|
||||
|
||||
// Set the current LANAs in the available LANAs list
|
||||
|
||||
m_lanas = new BitSet();
|
||||
m_lanaSts = new BitSet();
|
||||
|
||||
if (lanas != null)
|
||||
{
|
||||
|
||||
// Set the currently available LANAs
|
||||
|
||||
for (int i = 0; i < lanas.length; i++)
|
||||
m_lanas.set(lanas[i]);
|
||||
}
|
||||
|
||||
// Initialize the online LANA status list
|
||||
|
||||
int[] curLanas = Win32NetBIOS.LanaEnumerate();
|
||||
|
||||
if ( curLanas != null)
|
||||
{
|
||||
for ( int i = 0; i < curLanas.length; i++)
|
||||
m_lanaSts.set(curLanas[i], true);
|
||||
}
|
||||
|
||||
// Set the global LANA monitor, if not already set
|
||||
|
||||
if (_lanaMonitor == null)
|
||||
_lanaMonitor = this;
|
||||
|
||||
// Start the LANA monitor thread
|
||||
|
||||
setDaemon(true);
|
||||
start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the global LANA monitor
|
||||
*
|
||||
* @return Win32NetBIOSLanaMonitor
|
||||
*/
|
||||
public static Win32NetBIOSLanaMonitor getLanaMonitor()
|
||||
{
|
||||
return _lanaMonitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a LANA listener
|
||||
*
|
||||
* @param lana int
|
||||
* @param listener LanaListener
|
||||
*/
|
||||
public synchronized final void addLanaListener(int lana, LanaListener l)
|
||||
{
|
||||
// Range check the LANA id
|
||||
|
||||
if ( lana < 0 || lana > 255)
|
||||
return;
|
||||
|
||||
// Check if the listener array has been allocated
|
||||
|
||||
if ( m_listeners == null)
|
||||
{
|
||||
int len = LanaListenerArraySize;
|
||||
if ( lana > len)
|
||||
len = (lana + 3) & 0x00FC;
|
||||
|
||||
m_listeners = new LanaListener[len];
|
||||
}
|
||||
else if ( lana > m_listeners.length)
|
||||
{
|
||||
// Extend the LANA listener array
|
||||
|
||||
LanaListener[] newArray = new LanaListener[(lana + 3) & 0x00FC];
|
||||
|
||||
// Copy the existing array to the extended array
|
||||
|
||||
System.arraycopy(m_listeners, 0, newArray, 0, m_listeners.length);
|
||||
m_listeners = newArray;
|
||||
}
|
||||
|
||||
// Add the LANA listener
|
||||
|
||||
m_listeners[lana] = l;
|
||||
|
||||
// DEBUG
|
||||
|
||||
if (logger.isDebugEnabled() && hasDebug())
|
||||
logger.debug("[SMB] Win32 NetBIOS register listener for LANA " + lana);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a LANA listener
|
||||
*
|
||||
* @param lana int
|
||||
*/
|
||||
public synchronized final void removeLanaListener(int lana)
|
||||
{
|
||||
// Validate the LANA id
|
||||
|
||||
if ( m_listeners == null || lana < 0 || lana >= m_listeners.length)
|
||||
return;
|
||||
|
||||
m_listeners[lana] = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread method
|
||||
*/
|
||||
public void run()
|
||||
{
|
||||
// Clear the shutdown flag
|
||||
|
||||
m_shutdown = false;
|
||||
|
||||
// If Winsock NetBIOS is not enabled then initialize the sockets interface
|
||||
|
||||
ServerConfiguration config = m_server.getConfiguration();
|
||||
|
||||
if ( config.useWinsockNetBIOS() == false)
|
||||
{
|
||||
try
|
||||
{
|
||||
NetBIOSSocket.initializeSockets();
|
||||
}
|
||||
catch (WinsockNetBIOSException ex)
|
||||
{
|
||||
// DEBUG
|
||||
|
||||
if (logger.isDebugEnabled() && hasDebug())
|
||||
logger.debug("[SMB] Win32 NetBIOS initialization error", ex);
|
||||
|
||||
// Shutdown the LANA monitor thread
|
||||
|
||||
m_shutdown = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Loop until shutdown
|
||||
|
||||
BitSet curLanas = new BitSet();
|
||||
|
||||
while (m_shutdown == false)
|
||||
{
|
||||
|
||||
// Wait for a network address change event
|
||||
|
||||
Win32NetBIOS.waitForNetworkAddressChange();
|
||||
|
||||
// Check if the monitor has been closed
|
||||
|
||||
if ( m_shutdown == true)
|
||||
continue;
|
||||
|
||||
// Clear the current active LANA bit set
|
||||
|
||||
curLanas.clear();
|
||||
|
||||
// Get the available LANA list
|
||||
|
||||
int[] lanas = Win32NetBIOS.LanaEnumerate();
|
||||
if (lanas != null)
|
||||
{
|
||||
|
||||
// Check if there are any new LANAs available
|
||||
|
||||
Win32NetBIOSSessionSocketHandler sessHandler = null;
|
||||
|
||||
for (int i = 0; i < lanas.length; i++)
|
||||
{
|
||||
|
||||
// Get the current LANA id, check if it's a known LANA
|
||||
|
||||
int lana = lanas[i];
|
||||
curLanas.set(lana, true);
|
||||
|
||||
if (m_lanas.get(lana) == false)
|
||||
{
|
||||
|
||||
// DEBUG
|
||||
|
||||
if (logger.isDebugEnabled() && hasDebug())
|
||||
logger.debug("[SMB] Win32 NetBIOS found new LANA, " + lana);
|
||||
|
||||
// Create a single Win32 NetBIOS session handler using the specified LANA
|
||||
|
||||
sessHandler = new Win32NetBIOSSessionSocketHandler(m_server, lana, hasDebug());
|
||||
|
||||
try
|
||||
{
|
||||
sessHandler.initialize();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
// DEBUG
|
||||
|
||||
if (logger.isDebugEnabled() && hasDebug())
|
||||
logger.debug("[SMB] Win32 NetBIOS failed to create session handler for LANA " + lana,
|
||||
ex);
|
||||
|
||||
// Clear the session handler
|
||||
|
||||
sessHandler = null;
|
||||
}
|
||||
|
||||
// If the session handler was initialized successfully add it to the
|
||||
// SMB/CIFS server
|
||||
|
||||
if (sessHandler != null)
|
||||
{
|
||||
|
||||
// Add the session handler to the SMB/CIFS server
|
||||
|
||||
m_server.addSessionHandler(sessHandler);
|
||||
|
||||
// Run the NetBIOS session handler in a seperate thread
|
||||
|
||||
Thread nbThread = new Thread(sessHandler);
|
||||
nbThread.setName("Win32NB_Handler_" + lana);
|
||||
nbThread.start();
|
||||
|
||||
// DEBUG
|
||||
|
||||
if (logger.isDebugEnabled() && hasDebug())
|
||||
logger.debug("[SMB] Win32 NetBIOS created session handler on LANA " + lana);
|
||||
|
||||
// Check if a host announcer should be enabled
|
||||
|
||||
if (config.hasWin32EnableAnnouncer())
|
||||
{
|
||||
|
||||
// Create a host announcer
|
||||
|
||||
Win32NetBIOSHostAnnouncer hostAnnouncer = new Win32NetBIOSHostAnnouncer(sessHandler,
|
||||
config.getDomainName(), config.getWin32HostAnnounceInterval());
|
||||
|
||||
// Add the host announcer to the SMB/CIFS server list
|
||||
|
||||
m_server.addHostAnnouncer(hostAnnouncer);
|
||||
hostAnnouncer.start();
|
||||
|
||||
// DEBUG
|
||||
|
||||
if (logger.isDebugEnabled() && hasDebug())
|
||||
logger.debug("[SMB] Win32 NetBIOS host announcer enabled on LANA " + lana);
|
||||
}
|
||||
|
||||
// Set the LANA in the available LANA list, and set the current status to online
|
||||
|
||||
m_lanas.set(lana);
|
||||
m_lanaSts.set(lana, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check if the LANA has just come back online
|
||||
|
||||
if ( m_lanaSts.get(lana) == false)
|
||||
{
|
||||
// Change the LANA status to indicate the LANA is back online
|
||||
|
||||
m_lanaSts.set(lana, true);
|
||||
|
||||
// Inform the listener that the LANA is back online
|
||||
|
||||
if ( m_listeners != null && lana < m_listeners.length &&
|
||||
m_listeners[lana] != null)
|
||||
m_listeners[lana].lanaStatusChange(lana, true);
|
||||
|
||||
// DEBUG
|
||||
|
||||
if (logger.isDebugEnabled() && hasDebug())
|
||||
logger.debug("[SMB] Win32 NetBIOS LANA online - " + lana);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if there are any LANAs that have gone offline
|
||||
|
||||
for ( int i = 0; i < m_lanaSts.length(); i++)
|
||||
{
|
||||
if ( curLanas.get(i) == false && m_lanaSts.get(i) == true)
|
||||
{
|
||||
// DEBUG
|
||||
|
||||
if (logger.isDebugEnabled() && hasDebug())
|
||||
logger.debug("[SMB] Win32 NetBIOS LANA offline - " + i);
|
||||
|
||||
// Change the LANA status
|
||||
|
||||
m_lanaSts.set(i, false);
|
||||
|
||||
// Check if there is an associated listener for the LANA
|
||||
|
||||
if ( m_listeners != null && m_listeners[i] != null)
|
||||
{
|
||||
// Notify the LANA listener that the LANA is now offline
|
||||
|
||||
m_listeners[i].lanaStatusChange(i, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if debug output is enabled
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public final boolean hasDebug()
|
||||
{
|
||||
return m_debug;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request the LANA monitor thread to shutdown
|
||||
*/
|
||||
public final void shutdownRequest()
|
||||
{
|
||||
m_shutdown = true;
|
||||
|
||||
// If Winsock NetBIOS is being used shutdown the Winsock interface
|
||||
|
||||
if ( m_server.getConfiguration().useWinsockNetBIOS())
|
||||
NetBIOSSocket.shutdownSockets();
|
||||
}
|
||||
}
|
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Copyright (C) 2005 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.filesys.smb.server.win32;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.alfresco.filesys.netbios.RFCNetBIOSProtocol;
|
||||
import org.alfresco.filesys.netbios.win32.NetBIOS;
|
||||
import org.alfresco.filesys.netbios.win32.Win32NetBIOS;
|
||||
import org.alfresco.filesys.smb.server.PacketHandler;
|
||||
import org.alfresco.filesys.smb.server.SMBSrvPacket;
|
||||
|
||||
/**
|
||||
* Win32 NetBIOS Packet Handler Class
|
||||
*
|
||||
* <p>Uses the Win32 Netbios() call to provide the low level session layer for better integration with
|
||||
* Windows.
|
||||
*
|
||||
* @author GKSpencer
|
||||
*/
|
||||
public class Win32NetBIOSPacketHandler extends PacketHandler
|
||||
{
|
||||
|
||||
// Constants
|
||||
//
|
||||
// Receive error encoding and length masks
|
||||
|
||||
private static final int ReceiveErrorMask = 0xFF000000;
|
||||
private static final int ReceiveLengthMask = 0x0000FFFF;
|
||||
|
||||
// Network LAN adapter to use
|
||||
|
||||
private int m_lana;
|
||||
|
||||
// NetBIOS session id
|
||||
|
||||
private int m_lsn;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* @param lana int
|
||||
* @param lsn int
|
||||
* @param callerName String
|
||||
*/
|
||||
public Win32NetBIOSPacketHandler(int lana, int lsn, String callerName)
|
||||
{
|
||||
super(SMBSrvPacket.PROTOCOL_WIN32NETBIOS, "Win32NB", "WNB", callerName);
|
||||
|
||||
m_lana = lana;
|
||||
m_lsn = lsn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the LANA number
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public final int getLANA()
|
||||
{
|
||||
return m_lana;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the NetBIOS session id
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public final int getLSN()
|
||||
{
|
||||
return m_lsn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a packet from the client
|
||||
*
|
||||
* @param pkt SMBSrvPacket
|
||||
* @return int
|
||||
* @throws IOException
|
||||
*/
|
||||
public int readPacket(SMBSrvPacket pkt) throws IOException
|
||||
{
|
||||
|
||||
// Wait for a packet on the Win32 NetBIOS session
|
||||
//
|
||||
// As Windows is handling the NetBIOS session layer we only receive the SMB packet. In order
|
||||
// to be compatible with the other packet handlers we allow for the 4 byte header.
|
||||
|
||||
int pktLen = pkt.getBuffer().length;
|
||||
if (pktLen > NetBIOS.MaxReceiveSize)
|
||||
pktLen = NetBIOS.MaxReceiveSize;
|
||||
|
||||
int rxLen = Win32NetBIOS.Receive(m_lana, m_lsn, pkt.getBuffer(), 4, pktLen - 4);
|
||||
|
||||
if ((rxLen & ReceiveErrorMask) != 0)
|
||||
{
|
||||
|
||||
// Check for an incomplete message status code
|
||||
|
||||
int sts = (rxLen & ReceiveErrorMask) >> 24;
|
||||
|
||||
if (sts == NetBIOS.NRC_Incomp)
|
||||
{
|
||||
|
||||
// Check if the packet buffer is already at the maximum size (we assume the maximum
|
||||
// size is the maximum that RFC NetBIOS can send which is 17bits)
|
||||
|
||||
if (pkt.getBuffer().length < RFCNetBIOSProtocol.MaxPacketSize)
|
||||
{
|
||||
|
||||
// Allocate a new buffer
|
||||
|
||||
byte[] newbuf = new byte[RFCNetBIOSProtocol.MaxPacketSize];
|
||||
|
||||
// Copy the first part of the received data to the new buffer
|
||||
|
||||
System.arraycopy(pkt.getBuffer(), 4, newbuf, 4, pktLen - 4);
|
||||
|
||||
// Move the new buffer in as the main packet buffer
|
||||
|
||||
pkt.setBuffer(newbuf);
|
||||
|
||||
// DEBUG
|
||||
|
||||
// Debug.println("readPacket() extended buffer to " + pkt.getBuffer().length);
|
||||
}
|
||||
|
||||
// Set the original receive size
|
||||
|
||||
rxLen = (rxLen & ReceiveLengthMask);
|
||||
|
||||
// Receive the remaining data
|
||||
//
|
||||
// Note: If the second read request is issued with a size of 64K or 64K-4 it returns
|
||||
// with another incomplete status and returns no data.
|
||||
|
||||
int rxLen2 = Win32NetBIOS.Receive(m_lana, m_lsn, pkt.getBuffer(), rxLen + 4, 32768);
|
||||
|
||||
if ((rxLen2 & ReceiveErrorMask) != 0)
|
||||
{
|
||||
sts = (rxLen2 & ReceiveErrorMask) >> 24;
|
||||
throw new IOException("Win32 NetBIOS multi-part receive failed, sts=0x" + sts + ", err="
|
||||
+ NetBIOS.getErrorString(sts));
|
||||
}
|
||||
|
||||
// Set the total received data length
|
||||
|
||||
rxLen += rxLen2;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// Indicate that the session has closed
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the received data length
|
||||
|
||||
return rxLen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a packet to the client
|
||||
*
|
||||
* @param pkt SMBSrvPacket
|
||||
* @param len int
|
||||
* @throws IOException
|
||||
*/
|
||||
public void writePacket(SMBSrvPacket pkt, int len) throws IOException
|
||||
{
|
||||
|
||||
// Output the packet on the Win32 NetBIOS session
|
||||
//
|
||||
// As Windows is handling the NetBIOS session layer we do not send the 4 byte header that is
|
||||
// used by the NetBIOS over TCP/IP and native SMB packet handlers.
|
||||
|
||||
int sts = Win32NetBIOS.Send(m_lana, m_lsn, pkt.getBuffer(), 4, len);
|
||||
|
||||
// Do not check the status, if the session has been closed the next receive will fail
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the Win32 NetBIOS packet handler. Hangup the NetBIOS session
|
||||
*/
|
||||
public void closeHandler()
|
||||
{
|
||||
super.closeHandler();
|
||||
|
||||
// Hangup the Win32 NetBIOS session
|
||||
|
||||
Win32NetBIOS.Hangup(m_lana, m_lsn);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright (C) 2005 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.filesys.smb.server.win32;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.alfresco.filesys.netbios.RFCNetBIOSProtocol;
|
||||
import org.alfresco.filesys.netbios.win32.NetBIOSSocket;
|
||||
import org.alfresco.filesys.netbios.win32.WinsockError;
|
||||
import org.alfresco.filesys.netbios.win32.WinsockNetBIOSException;
|
||||
import org.alfresco.filesys.smb.server.PacketHandler;
|
||||
import org.alfresco.filesys.smb.server.SMBSrvPacket;
|
||||
|
||||
/**
|
||||
* Winsock NetBIOS Packet Handler Class
|
||||
*
|
||||
* <p>Uses a Windows Winsock NetBIOS socket to provide the low level session layer for better integration
|
||||
* with Windows.
|
||||
*
|
||||
* @author GKSpencer
|
||||
*/
|
||||
public class WinsockNetBIOSPacketHandler extends PacketHandler
|
||||
{
|
||||
// Constants
|
||||
//
|
||||
// Receive error indicating a receive buffer error
|
||||
|
||||
private static final int ReceiveBufferSizeError = 0x80000000;
|
||||
|
||||
// Network LAN adapter to use
|
||||
|
||||
private int m_lana;
|
||||
|
||||
// NetBIOS session socket
|
||||
|
||||
private NetBIOSSocket m_sessSock;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* @param lana int
|
||||
* @param sock NetBIOSSocket
|
||||
*/
|
||||
public WinsockNetBIOSPacketHandler(int lana, NetBIOSSocket sock)
|
||||
{
|
||||
super(SMBSrvPacket.PROTOCOL_WIN32NETBIOS, "WinsockNB", "WSNB", sock.getName().getName());
|
||||
|
||||
m_lana = lana;
|
||||
m_sessSock = sock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the LANA number
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public final int getLANA()
|
||||
{
|
||||
return m_lana;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the NetBIOS socket
|
||||
*
|
||||
* @return NetBIOSSocket
|
||||
*/
|
||||
public final NetBIOSSocket getSocket()
|
||||
{
|
||||
return m_sessSock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a packet from the client
|
||||
*
|
||||
* @param pkt SMBSrvPacket
|
||||
* @return int
|
||||
* @throws IOException
|
||||
*/
|
||||
public int readPacket(SMBSrvPacket pkt) throws IOException
|
||||
{
|
||||
// Receive an SMB/CIFS request packet via the Winsock NetBIOS socket
|
||||
|
||||
int rxlen = 0;
|
||||
|
||||
try {
|
||||
|
||||
// Read a pakcet of data
|
||||
|
||||
rxlen = m_sessSock.read(pkt.getBuffer(), 4, pkt.getBufferLength() - 4);
|
||||
|
||||
// Check if the buffer is not big enough to receive the entire packet, extend the buffer
|
||||
// and read the remaining part of the packet
|
||||
|
||||
if (rxlen == ReceiveBufferSizeError)
|
||||
{
|
||||
|
||||
// Check if the packet buffer is already at the maximum size (we assume the maximum
|
||||
// size is the maximum that RFC NetBIOS can send which is 17bits)
|
||||
|
||||
if (pkt.getBuffer().length < RFCNetBIOSProtocol.MaxPacketSize)
|
||||
{
|
||||
// Set the initial receive size, assume a full read
|
||||
|
||||
rxlen = pkt.getBufferLength() - 4;
|
||||
|
||||
// Allocate a new buffer, copy the existing data to the new buffer
|
||||
|
||||
byte[] newbuf = new byte[RFCNetBIOSProtocol.MaxPacketSize];
|
||||
System.arraycopy(pkt.getBuffer(), 4, newbuf, 4, rxlen);
|
||||
pkt.setBuffer( newbuf);
|
||||
|
||||
// Receive the packet
|
||||
|
||||
int rxlen2 = m_sessSock.read(pkt.getBuffer(), rxlen + 4, pkt.getBufferLength() - (rxlen + 4));
|
||||
|
||||
if ( rxlen2 == ReceiveBufferSizeError)
|
||||
throw new WinsockNetBIOSException(WinsockError.WsaEMsgSize);
|
||||
|
||||
rxlen += rxlen2;
|
||||
}
|
||||
else
|
||||
throw new WinsockNetBIOSException(WinsockError.WsaEMsgSize);
|
||||
}
|
||||
}
|
||||
catch ( WinsockNetBIOSException ex)
|
||||
{
|
||||
// Check if the remote client has closed the socket
|
||||
|
||||
if ( ex.getErrorCode() == WinsockError.WsaEConnReset)
|
||||
{
|
||||
// Indicate that the socket has been closed
|
||||
|
||||
rxlen = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Rethrow the exception
|
||||
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the received packet length
|
||||
|
||||
return rxlen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a packet to the client
|
||||
*
|
||||
* @param pkt SMBSrvPacket
|
||||
* @param len int
|
||||
* @throws IOException
|
||||
*/
|
||||
public void writePacket(SMBSrvPacket pkt, int len) throws IOException
|
||||
{
|
||||
// Output the packet via the Winsock NetBIOS socket
|
||||
//
|
||||
// As Windows is handling the NetBIOS session layer we do not send the 4 byte header that is
|
||||
// used by the NetBIOS over TCP/IP and native SMB packet handlers.
|
||||
|
||||
int txlen = m_sessSock.write(pkt.getBuffer(), 4, len);
|
||||
|
||||
// Do not check the status, if the session has been closed the next receive will fail
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the Winsock NetBIOS packet handler.
|
||||
*/
|
||||
public void closeHandler()
|
||||
{
|
||||
super.closeHandler();
|
||||
|
||||
// Close the session socket
|
||||
|
||||
if ( m_sessSock != null)
|
||||
m_sessSock.closeSocket();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user