private void CommunicationThread( )
{
bool lastRequestFailed = false;
while ( !stopEvent.WaitOne( 0, false ) )
{
// wait for any request
requestIsAvailable.WaitOne( );
while ( !stopEvent.WaitOne( 0, false ) )
{
// get next communication request from queue
CommunicationRequest cr = null;
lock ( communicationQueue )
{
if ( communicationQueue.Count == 0 )
break;
cr = communicationQueue.Dequeue( );
}
try
{
// try to reconnect if we had communication issues on the last request
if ( lastRequestFailed )
{
Reconnect( );
lastRequestFailed = false;
}
if ( cr.Request[0] != (byte) 'I' )
{
// System.Diagnostics.Debug.WriteLine( ">> " +
// System.Text.ASCIIEncoding.ASCII.GetString( cr.Request ) );
}
// send request
socket.Send( cr.Request );
// read response
if ( cr.ResponseBuffer != null )
{
int bytesToRead = Math.Min( readSize, cr.ResponseBuffer.Length );
// receive first portion
cr.BytesRead = socket.Receive( cr.ResponseBuffer, 0, bytesToRead, SocketFlags.None );
// check if response contains image
if ( ( cr.BytesRead > 10 ) &&
( cr.ResponseBuffer[0] == (byte) '#' ) &&
( cr.ResponseBuffer[1] == (byte) '#' ) &&
( cr.ResponseBuffer[2] == (byte) 'I' ) &&
( cr.ResponseBuffer[3] == (byte) 'M' ) &&
( cr.ResponseBuffer[4] == (byte) 'J' ) )
{
// extract image size
int imageSize = System.BitConverter.ToInt32( cr.ResponseBuffer, 6 );
bytesToRead = imageSize + 10 - cr.BytesRead;
if ( bytesToRead > cr.ResponseBuffer.Length - cr.BytesRead )
{
// response buffer is too small
throw new IndexOutOfRangeException( );
}
// read the rest
while ( !stopEvent.WaitOne( 0, false ) )
{
int read = socket.Receive( cr.ResponseBuffer, cr.BytesRead,
Math.Min( readSize, bytesToRead ), SocketFlags.None );
cr.BytesRead += read;
bytesToRead -= read;
if ( bytesToRead == 0 )
break;
}
}
else
{
// commenting check for new line presence, because not all replies
// which start with '##' have new line in the end.
// this SRV-1 text based protocol drives me crazy.
/*
if ( ( cr.BytesRead >= 2 ) &&
( cr.ResponseBuffer[0] == (byte) '#' ) &&
( cr.ResponseBuffer[1] == (byte) '#' ) )
{
int bytesChecked = 2;
while ( cr.BytesRead != cr.ResponseBuffer.Length )
{
// ensure we got end of line for variable length replies
bool endLineWasFound = false;
for ( int n = cr.BytesRead - 1; bytesChecked < n; bytesChecked++ )
{
if ( ( ( cr.ResponseBuffer[bytesChecked] == '\n' ) &&
( cr.ResponseBuffer[bytesChecked + 1] == '\r' ) ) ||
( ( cr.ResponseBuffer[bytesChecked] == '\r' ) &&
( cr.ResponseBuffer[bytesChecked + 1] == '\n' ) ) )
{
endLineWasFound = true;
break;
}
}
if ( ( endLineWasFound ) || stopEvent.WaitOne( 0, false ) )
break;
// read more
bytesToRead = Math.Min( readSize, cr.ResponseBuffer.Length - cr.BytesRead );
cr.BytesRead += socket.Receive( cr.ResponseBuffer, cr.BytesRead,
bytesToRead, SocketFlags.None );
}
}
*/
}
// check if there is still something to read
// because of small buffer given by user
if ( socket.Available != 0 )
{
DiscardIncomingData( socket, stopEvent );
}
// System.Diagnostics.Debug.WriteLine( "<< (" + cr.BytesRead + ") " +
// System.Text.ASCIIEncoding.ASCII.GetString( cr.ResponseBuffer, 0, Math.Min( 5, cr.BytesRead ) ) );
}
else
{
// read reply and throw it away, since nobody wants it
DiscardIncomingData( socket, stopEvent );
}
}
catch ( IndexOutOfRangeException )
{
cr.BytesRead = -2; // too small buffer
}
catch
{
if ( lastRequestFailed )
{
// wait a bit if we have 2 consequent failures
Thread.Sleep( 500 );
}
lastRequestFailed = true;
cr.BytesRead = -1; // communication failure
}
finally
{
// signal about available response to the waiting caller
if ( ( stopEvent != null ) && ( !stopEvent.WaitOne( 0, false ) ) && ( cr.ResponseBuffer != null ) )
{
lastRequestWithReply = cr;
replyIsAvailable.Set( );
}
}
}
}
}