Socket problem (buffer overflow?) 
Author Message
 Socket problem (buffer overflow?)

Hello all,

i recently had a strange problem regarding the socket class. I am writing a
newsreader and therefor i am developing an NNTP-control which requires a
socket connection. I read the description in the MSDN about how to use the
socket class and did my own implementation.

Now everything is working fine, except of...

...i receive invalid data if the size of the incoming data block reaches the
upper edge of the receive buffer. I detected it by decoding an yenc-encoded
file which failed due to CRC-errors. Most of the incoming data blocks are
only a view KB, but sometimes they hit the upper bound of the buffer what
causes that error.

My temporary solution is to increase the buffer size to over 100 KB, but i
think this cannot be the final solution.

Does anyone had the same problem or know how to fix this?

Below is the code of my SocketClient class.

Thank you for any help!

Best regards,
Uwe

---------------------------------------------------------------

Imports System.Net
Imports System.Net.Sockets

Public Class SocketsClient
    Const BUFSIZE = 131072
    Dim Buffer(BUFSIZE - 1) As Byte
    Dim Client As Socket 'socket object

    'Events
    Public Event OnConnect() 'when client gets connected to server
    Public Event OnDataArrival(ByRef Data As Byte(), ByRef TotalBytes As
Integer) 'when data is received from the server
    Public Event OnDisconnect() 'when the client gets disconnected from the
server
    Public Event OnSendComplete(ByRef DataSize As Integer) 'when sending
data to the server is complete
    Public Event OnError(ByRef Err As ErrObject) 'when an error occurs in
the socket

    Public Sub Connect(ByRef RemoteHostName As String, ByRef RemotePort As
Integer)
        Try
            'set information for connection
            Dim IpHostInfo As IPHostEntry = Dns.Resolve(RemoteHostName)
            Dim IpAddress As IpAddress = IpHostInfo.AddressList(0)
            Dim RemoteEP As New IPEndPoint(IpAddress, RemotePort)
            'create client
            Client = New Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp) 'Client object
            'Connect and trigger sub 'sockConnected' when connected.
            Client.BeginConnect(RemoteEP, AddressOf SockConnected, Client)
        Catch
            'notify about any error
            RaiseEvent OnError(Err)
        End Try
    End Sub
    Public Sub Send(ByRef Data() As Byte)
        Try
            'send the data and trigger the sub 'sockSendEnd' when completed
sending
            Client.BeginSend(Data, 0, Data.Length, SocketFlags.None,
AddressOf SockSendEnd, Client)
        Catch
            'Notify host if an error occurs.
            RaiseEvent OnError(Err)
        End Try
    End Sub
    Public Sub Disconnect()
        Try
            Client.Shutdown(SocketShutdown.Both) 'kill any data being sent
or received
            Client.Close() 'kill socket connection
            RaiseEvent OnDisconnect()
        Catch
            RaiseEvent OnError(Err)
        End Try
    End Sub

    Private Sub SockConnected(ByVal ar As IAsyncResult)
        If Client.Connected Then 'check if actually connected
            Try
                Client.BeginReceive(Buffer, 0, BUFSIZE, SocketFlags.None,
AddressOf SockDataArrival, Nothing)
                RaiseEvent OnConnect()
            Catch
                RaiseEvent OnError(Err)
            End Try
        Else 'connection remotely rejected
            Err.Number = 1 'not connected
            Err.Description = "Connection remotely rejected"
            RaiseEvent OnError(Err)
        End If
    End Sub
    Private Sub SockDataArrival(ByVal ar As IAsyncResult)
        'get the data from the server
        Try
            If Client.Connected Then 'do not continue if connection lost

                'get number of received bytes
                Dim BytesRead As Integer = Client.EndReceive(ar)

                'The .NET framework will send useless 0kb packets at high
speed in order to
                'show a connection loss. Therefore, if the packet size is
0kb, the
                'connection will be closed. This method of detecting a
disconnection
                'is not very effective, but may be the only solution for
now.
                If BytesRead = 0 Then
                    Disconnect()

                Else
                    'notify owner that data has been received
                    RaiseEvent OnDataArrival(Buffer, BytesRead)

                    'now continue listening if still connected
                    If Client.Connected Then
                        Client.BeginReceive(Buffer, 0, BUFSIZE,
SocketFlags.None, AddressOf SockDataArrival, Nothing)
                    End If
                End If
            End If
        Catch
            'Notify host if an error occurs.
            RaiseEvent OnError(Err)
        End Try
    End Sub
    Private Sub SockSendEnd(ByVal ar As IAsyncResult)
        Try
            'Dim Client As Socket = CType(ar.AsyncState, Socket)
            Dim BytesSent As Integer = Client.EndSend(ar)
            'notify the host that the data has completed to be sent.
            RaiseEvent OnSendComplete(BytesSent)
        Catch
            RaiseEvent OnError(Err)
        End Try
    End Sub

End Class



Sun, 11 Dec 2005 13:22:16 GMT  
 Socket problem (buffer overflow?)
Quote:

> Hello all,

> i recently had a strange problem regarding the socket class. I am writing a
> newsreader and therefor i am developing an NNTP-control which requires a
> socket connection. I read the description in the MSDN about how to use the
> socket class and did my own implementation.

> Now everything is working fine, except of...

> ...i receive invalid data if the size of the incoming data block reaches the
> upper edge of the receive buffer. I detected it by decoding an yenc-encoded
> file which failed due to CRC-errors. Most of the incoming data blocks are
> only a view KB, but sometimes they hit the upper bound of the buffer what
> causes that error.

Uwe -

    You don't show how you handle the data after it is received by
your socket class. Is it possible that data is being overwritten
somewhere along the line when the data is being put together? You
define a large BUFSIZE value, and allow the BeqginReceive() method to
accept that much data if possible. As new chunks of data are received,
does the program place these chunks into a larger buffer?

    Another issue (I'm not sure if it is contributing to your problem
or not) is that you are not using the Asynchronous socket classes
properly. When you call the Beginxxx() async method, you should pass
the socket object instead of the Nothing object. This enables the
Endxxx() method to reference the original socket when the call is
completed:

    Client.BeginReceive(Buffer, 0, BUFSIZE, SocketFlags.None,
AddressOf SockDataArrival, Client)

  then use --
    Private Sub SockDataArrival(ByVal ar as IAsyncfResult)
        Dim sock as Socket = CType(ar.AsyncState, Socket)
        Dim BytesRead as Integer = sock.EndReceive(ar)

    This is the preferred way to reference the socket for the
asynchronous calls. Hope this makes sense.

Rich Blum
Author of "C# Network Programming" (Sybex)
http://www.sybex.com/sybexbooks.nsf/Booklist/4176



Mon, 12 Dec 2005 04:06:47 GMT  
 Socket problem (buffer overflow?)

Quote:

>My temporary solution is to increase the buffer size to over 100 KB, but i
>think this cannot be the final solution.

>Does anyone had the same problem or know how to fix this?

I think you should reorient your view of the problem such that you make the code
work with any sized buffer, including 1kb.  To do that you will need to read the
incoming data a buffer-sized chunk at a time and stash it somewhere until you
reach the end of whatever data you're reading; which in the case of an nntp
message will be "CRLF.CRLF".

--
           Abderaware
    Fine Components For .NET
   Turn on, tune in, download.



Mon, 12 Dec 2005 06:01:53 GMT  
 Socket problem (buffer overflow?)

Quote:
> I think you should reorient your view of the problem such that you make
the code
> work with any sized buffer, including 1kb.

Yes, i agree it should work with any buffer size.

Quote:
> To do that you will need to read the
> incoming data a buffer-sized chunk at a time and stash it somewhere until
you
> reach the end of whatever data you're reading; which in the case of an
nntp
> message will be "CRLF.CRLF".

I fire the OnDataArrival event immediately after the data is received. In
the superior nntp-control i store the data line-wise into an arraylist.
After completing the event, the next BeginReceive command continues
listening for new data. That should work, but does not :-(

Uwe



Mon, 12 Dec 2005 17:55:18 GMT  
 Socket problem (buffer overflow?)
Rich,

thank you for your reply!

Quote:
>     You don't show how you handle the data after it is received by
> your socket class.

In the superior nntp control, i store the data line-wise into an array list.
After that, the next BeginReceive command sends the next data request.

Quote:
> Is it possible that data is being overwritten
> somewhere along the line when the data is being put together? You
> define a large BUFSIZE value, and allow the BeqginReceive() method to
> accept that much data if possible. As new chunks of data are received,
> does the program place these chunks into a larger buffer?

It is used the same buffer for each data chunk (may be that's the problem).
I did it in that way, because i raise an OnDataArrival event for each chunk
where the data can be processed. The next chunk will not be received before
the next BeginReceive command is fired (true?).

Quote:
>     Another issue (I'm not sure if it is contributing to your problem
> or not) is that you are not using the Asynchronous socket classes
> properly. When you call the Beginxxx() async method, you should pass
> the socket object instead of the Nothing object. This enables the
> Endxxx() method to reference the original socket when the call is
> completed:

I really do not understand that! Why do i have to hand over the clients
socket? I have the original reference to the socket by the variable defined
in the socket-class itself, right? Btw, i do not use a shared socket as
shown in MSDN sample, because i use my socket class in several instances
simultaneously.

Any ideas?

Best regards,
Uwe



Mon, 12 Dec 2005 18:06:19 GMT  
 Socket problem (buffer overflow?)

Quote:

>After completing the event, the next BeginReceive command continues
>listening for new data.

Couple things:

o  The Connected property is not usable.  If EndReceive returns something > 0
then you have data otherwise the connection has been closed.

o  When you retrieve a message using nntp the text of the message will be
returned followed by "CRLF.CRLF" - if you do not recognize that sequence and
blindly invoke BeginReceive again you will not receive any more data.

--
           Abderaware
    Fine Components For .NET
   Turn on, tune in, download.



Tue, 13 Dec 2005 03:55:45 GMT  
 Socket problem (buffer overflow?)
Thank you again for your reply!

I see i have to play around with that. I am curious about to see what
happen, if i send a BeginReceive after a CRLF.CRLF. At the moment, i do so
because the END OF DATA will be recognized in my NNTP control. If you are
interested in my NNTP control, i can send a copy to you. Pls let me know.

Best regards,
Uwe



Quote:

> >After completing the event, the next BeginReceive command continues
> >listening for new data.

> Couple things:

> o  The Connected property is not usable.  If EndReceive returns something
> 0
> then you have data otherwise the connection has been closed.

> o  When you retrieve a message using nntp the text of the message will be
> returned followed by "CRLF.CRLF" - if you do not recognize that sequence
and
> blindly invoke BeginReceive again you will not receive any more data.

> --
>            Abderaware
>     Fine Components For .NET
>    Turn on, tune in, download.




Tue, 13 Dec 2005 17:56:24 GMT  
 Socket problem (buffer overflow?)

Quote:

>I see i have to play around with that. I am curious about to see what
>happen, if i send a BeginReceive after a CRLF.CRLF.

Unless you send another command you will not receive any more data after the
termination message-end sequence is received.

Quote:
>If you are
>interested in my NNTP control, i can send a copy to you. Pls let me know.

That's ok, I've written VBX, MFC, ATL, and .NET versions in the past.  :-)

--
           Abderaware
    Fine Components For .NET
   Turn on, tune in, download.



Wed, 14 Dec 2005 03:42:48 GMT  
 
 [ 8 post ] 

 Relevant Pages 

1. Access97->Word97 merge, buffer overflow?

2. comm-buffer overflow

3. How can I prevent a communications buffer overflow?

4. Buffer overflow

5. Keyboard Buffer Overflow Question

6. Help with Byte buffers and stack overflows

7. stop buffer overflow attacks

8. Buffer overflow?

9. Winsock receive buffer overflow error 10040

10. MSComm overflowing buffer

11. Buffer overrun on UDP socket

12. Changing Sockets Buffer Size

 

 
Powered by phpBB® Forum Software