diff --git a/SMBLibrary/Client/SMB1Client.cs b/SMBLibrary/Client/SMB1Client.cs index d083f89..63ebcc7 100644 --- a/SMBLibrary/Client/SMB1Client.cs +++ b/SMBLibrary/Client/SMB1Client.cs @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2023 Tal Aloni . All rights reserved. +/* Copyright (C) 2014-2024 Tal Aloni . All rights reserved. * * You can redistribute this program and/or modify it under the terms of * the GNU Lesser Public License as published by the Free Software Foundation, @@ -172,7 +172,10 @@ namespace SMBLibrary.Client { m_clientSocket.Disconnect(false); m_clientSocket.Close(); - m_connectionState.ReceiveBuffer.Dispose(); + lock (m_connectionState.ReceiveBuffer) + { + m_connectionState.ReceiveBuffer.Dispose(); + } m_isConnected = false; m_userID = 0; } @@ -424,63 +427,66 @@ namespace SMBLibrary.Client ConnectionState state = (ConnectionState)ar.AsyncState; Socket clientSocket = state.ClientSocket; - if (!clientSocket.Connected) + lock (state.ReceiveBuffer) { - state.ReceiveBuffer.Dispose(); - return; - } - - int numberOfBytesReceived = 0; - try - { - numberOfBytesReceived = clientSocket.EndReceive(ar); - } - catch (ArgumentException) // The IAsyncResult object was not returned from the corresponding synchronous method on this class. - { - state.ReceiveBuffer.Dispose(); - return; - } - catch (ObjectDisposedException) - { - Log("[ReceiveCallback] EndReceive ObjectDisposedException"); - state.ReceiveBuffer.Dispose(); - return; - } - catch (SocketException ex) - { - Log("[ReceiveCallback] EndReceive SocketException: " + ex.Message); - state.ReceiveBuffer.Dispose(); - return; - } - - if (numberOfBytesReceived == 0) - { - m_isConnected = false; - state.ReceiveBuffer.Dispose(); - } - else - { - NBTConnectionReceiveBuffer buffer = state.ReceiveBuffer; - buffer.SetNumberOfBytesReceived(numberOfBytesReceived); - ProcessConnectionBuffer(state); - - if (clientSocket.Connected) + if (!clientSocket.Connected) { - try + state.ReceiveBuffer.Dispose(); + return; + } + + int numberOfBytesReceived = 0; + try + { + numberOfBytesReceived = clientSocket.EndReceive(ar); + } + catch (ArgumentException) // The IAsyncResult object was not returned from the corresponding synchronous method on this class. + { + state.ReceiveBuffer.Dispose(); + return; + } + catch (ObjectDisposedException) + { + Log("[ReceiveCallback] EndReceive ObjectDisposedException"); + state.ReceiveBuffer.Dispose(); + return; + } + catch (SocketException ex) + { + Log("[ReceiveCallback] EndReceive SocketException: " + ex.Message); + state.ReceiveBuffer.Dispose(); + return; + } + + if (numberOfBytesReceived == 0) + { + m_isConnected = false; + state.ReceiveBuffer.Dispose(); + } + else + { + NBTConnectionReceiveBuffer buffer = state.ReceiveBuffer; + buffer.SetNumberOfBytesReceived(numberOfBytesReceived); + ProcessConnectionBuffer(state); + + if (clientSocket.Connected) { - clientSocket.BeginReceive(buffer.Buffer, buffer.WriteOffset, buffer.AvailableLength, SocketFlags.None, new AsyncCallback(OnClientSocketReceive), state); - } - catch (ObjectDisposedException) - { - m_isConnected = false; - buffer.Dispose(); - Log("[ReceiveCallback] BeginReceive ObjectDisposedException"); - } - catch (SocketException ex) - { - m_isConnected = false; - buffer.Dispose(); - Log("[ReceiveCallback] BeginReceive SocketException: " + ex.Message); + try + { + clientSocket.BeginReceive(buffer.Buffer, buffer.WriteOffset, buffer.AvailableLength, SocketFlags.None, new AsyncCallback(OnClientSocketReceive), state); + } + catch (ObjectDisposedException) + { + m_isConnected = false; + buffer.Dispose(); + Log("[ReceiveCallback] BeginReceive ObjectDisposedException"); + } + catch (SocketException ex) + { + m_isConnected = false; + buffer.Dispose(); + Log("[ReceiveCallback] BeginReceive SocketException: " + ex.Message); + } } } } diff --git a/SMBLibrary/Client/SMB2Client.cs b/SMBLibrary/Client/SMB2Client.cs index 827a705..d90cc0c 100644 --- a/SMBLibrary/Client/SMB2Client.cs +++ b/SMBLibrary/Client/SMB2Client.cs @@ -182,7 +182,10 @@ namespace SMBLibrary.Client { m_clientSocket.Disconnect(false); m_clientSocket.Close(); - m_connectionState.ReceiveBuffer.Dispose(); + lock (m_connectionState.ReceiveBuffer) + { + m_connectionState.ReceiveBuffer.Dispose(); + } m_isConnected = false; m_messageID = 0; m_sessionID = 0; @@ -357,63 +360,66 @@ namespace SMBLibrary.Client ConnectionState state = (ConnectionState)ar.AsyncState; Socket clientSocket = state.ClientSocket; - if (!clientSocket.Connected) + lock (state.ReceiveBuffer) { - state.ReceiveBuffer.Dispose(); - return; - } - - int numberOfBytesReceived = 0; - try - { - numberOfBytesReceived = clientSocket.EndReceive(ar); - } - catch (ArgumentException) // The IAsyncResult object was not returned from the corresponding synchronous method on this class. - { - state.ReceiveBuffer.Dispose(); - return; - } - catch (ObjectDisposedException) - { - Log("[ReceiveCallback] EndReceive ObjectDisposedException"); - state.ReceiveBuffer.Dispose(); - return; - } - catch (SocketException ex) - { - Log("[ReceiveCallback] EndReceive SocketException: " + ex.Message); - state.ReceiveBuffer.Dispose(); - return; - } - - if (numberOfBytesReceived == 0) - { - m_isConnected = false; - state.ReceiveBuffer.Dispose(); - } - else - { - NBTConnectionReceiveBuffer buffer = state.ReceiveBuffer; - buffer.SetNumberOfBytesReceived(numberOfBytesReceived); - ProcessConnectionBuffer(state); - - if (clientSocket.Connected) + if (!clientSocket.Connected) { - try + state.ReceiveBuffer.Dispose(); + return; + } + + int numberOfBytesReceived = 0; + try + { + numberOfBytesReceived = clientSocket.EndReceive(ar); + } + catch (ArgumentException) // The IAsyncResult object was not returned from the corresponding synchronous method on this class. + { + state.ReceiveBuffer.Dispose(); + return; + } + catch (ObjectDisposedException) + { + Log("[ReceiveCallback] EndReceive ObjectDisposedException"); + state.ReceiveBuffer.Dispose(); + return; + } + catch (SocketException ex) + { + Log("[ReceiveCallback] EndReceive SocketException: " + ex.Message); + state.ReceiveBuffer.Dispose(); + return; + } + + if (numberOfBytesReceived == 0) + { + m_isConnected = false; + state.ReceiveBuffer.Dispose(); + } + else + { + NBTConnectionReceiveBuffer buffer = state.ReceiveBuffer; + buffer.SetNumberOfBytesReceived(numberOfBytesReceived); + ProcessConnectionBuffer(state); + + if (clientSocket.Connected) { - clientSocket.BeginReceive(buffer.Buffer, buffer.WriteOffset, buffer.AvailableLength, SocketFlags.None, new AsyncCallback(OnClientSocketReceive), state); - } - catch (ObjectDisposedException) - { - m_isConnected = false; - Log("[ReceiveCallback] BeginReceive ObjectDisposedException"); - buffer.Dispose(); - } - catch (SocketException ex) - { - m_isConnected = false; - Log("[ReceiveCallback] BeginReceive SocketException: " + ex.Message); - buffer.Dispose(); + try + { + clientSocket.BeginReceive(buffer.Buffer, buffer.WriteOffset, buffer.AvailableLength, SocketFlags.None, new AsyncCallback(OnClientSocketReceive), state); + } + catch (ObjectDisposedException) + { + m_isConnected = false; + Log("[ReceiveCallback] BeginReceive ObjectDisposedException"); + buffer.Dispose(); + } + catch (SocketException ex) + { + m_isConnected = false; + Log("[ReceiveCallback] BeginReceive SocketException: " + ex.Message); + buffer.Dispose(); + } } } } diff --git a/SMBLibrary/NetBios/NBTConnectionReceiveBuffer.cs b/SMBLibrary/NetBios/NBTConnectionReceiveBuffer.cs index 6cec8be..c013fd1 100644 --- a/SMBLibrary/NetBios/NBTConnectionReceiveBuffer.cs +++ b/SMBLibrary/NetBios/NBTConnectionReceiveBuffer.cs @@ -13,11 +13,11 @@ using Utilities; namespace SMBLibrary.NetBios { + /// + /// NBTConnectionReceiveBuffer is not thread-safe. + /// public class NBTConnectionReceiveBuffer : IDisposable { -#if NETSTANDARD2_0 - private object m_bufferSyncLock = new object(); -#endif private byte[] m_buffer; private int m_readOffset = 0; private int m_bytesInBuffer = 0; @@ -131,13 +131,10 @@ namespace SMBLibrary.NetBios public void Dispose() { #if NETSTANDARD2_0 - lock (m_bufferSyncLock) + if (m_buffer != null) { - if (m_buffer != null) - { - ArrayPool.Shared.Return(m_buffer); - m_buffer = null; - } + ArrayPool.Shared.Return(m_buffer); + m_buffer = null; } #else m_buffer = null; diff --git a/SMBLibrary/Server/ConnectionManager.cs b/SMBLibrary/Server/ConnectionManager.cs index acafe36..cef64a1 100644 --- a/SMBLibrary/Server/ConnectionManager.cs +++ b/SMBLibrary/Server/ConnectionManager.cs @@ -42,7 +42,10 @@ namespace SMBLibrary.Server connection.SendQueue.Stop(); SocketUtils.ReleaseSocket(connection.ClientSocket); connection.CloseSessions(); - connection.ReceiveBuffer.Dispose(); + lock (connection.ReceiveBuffer) + { + connection.ReceiveBuffer.Dispose(); + } RemoveConnection(connection); } diff --git a/SMBLibrary/Server/SMBServer.cs b/SMBLibrary/Server/SMBServer.cs index 578760f..bcd3c39 100644 --- a/SMBLibrary/Server/SMBServer.cs +++ b/SMBLibrary/Server/SMBServer.cs @@ -230,63 +230,66 @@ namespace SMBLibrary.Server ConnectionState state = (ConnectionState)result.AsyncState; Socket clientSocket = state.ClientSocket; - if (!m_listening) + lock (state.ReceiveBuffer) { - clientSocket.Close(); - return; - } - - int numberOfBytesReceived; - try - { - numberOfBytesReceived = clientSocket.EndReceive(result); - } - catch (ObjectDisposedException) - { - state.LogToServer(Severity.Debug, "The connection was terminated"); - m_connectionManager.ReleaseConnection(state); - return; - } - catch (SocketException ex) - { - const int WSAECONNRESET = 10054; - if (ex.ErrorCode == WSAECONNRESET) + if (!m_listening) { - state.LogToServer(Severity.Debug, "The connection was forcibly closed by the remote host"); + clientSocket.Close(); + return; } - else - { - state.LogToServer(Severity.Debug, "The connection was terminated, Socket error code: {0}", ex.ErrorCode); - } - m_connectionManager.ReleaseConnection(state); - return; - } - if (numberOfBytesReceived == 0) - { - state.LogToServer(Severity.Debug, "The client closed the connection"); - m_connectionManager.ReleaseConnection(state); - return; - } - - state.UpdateLastReceiveDT(); - NBTConnectionReceiveBuffer receiveBuffer = state.ReceiveBuffer; - receiveBuffer.SetNumberOfBytesReceived(numberOfBytesReceived); - ProcessConnectionBuffer(ref state); - - if (clientSocket.Connected) - { + int numberOfBytesReceived; try { - clientSocket.BeginReceive(state.ReceiveBuffer.Buffer, state.ReceiveBuffer.WriteOffset, state.ReceiveBuffer.AvailableLength, 0, ReceiveCallback, state); + numberOfBytesReceived = clientSocket.EndReceive(result); } catch (ObjectDisposedException) { + state.LogToServer(Severity.Debug, "The connection was terminated"); m_connectionManager.ReleaseConnection(state); + return; } - catch (SocketException) + catch (SocketException ex) { + const int WSAECONNRESET = 10054; + if (ex.ErrorCode == WSAECONNRESET) + { + state.LogToServer(Severity.Debug, "The connection was forcibly closed by the remote host"); + } + else + { + state.LogToServer(Severity.Debug, "The connection was terminated, Socket error code: {0}", ex.ErrorCode); + } m_connectionManager.ReleaseConnection(state); + return; + } + + if (numberOfBytesReceived == 0) + { + state.LogToServer(Severity.Debug, "The client closed the connection"); + m_connectionManager.ReleaseConnection(state); + return; + } + + state.UpdateLastReceiveDT(); + NBTConnectionReceiveBuffer receiveBuffer = state.ReceiveBuffer; + receiveBuffer.SetNumberOfBytesReceived(numberOfBytesReceived); + ProcessConnectionBuffer(ref state); + + if (clientSocket.Connected) + { + try + { + clientSocket.BeginReceive(state.ReceiveBuffer.Buffer, state.ReceiveBuffer.WriteOffset, state.ReceiveBuffer.AvailableLength, 0, ReceiveCallback, state); + } + catch (ObjectDisposedException) + { + m_connectionManager.ReleaseConnection(state); + } + catch (SocketException) + { + m_connectionManager.ReleaseConnection(state); + } } } }