Example #1
0
 private IEnumerable <CommunicationToken> GetMessageTokens(CommunicationRequest communicationRequest)
 {
     return(communicationRequest.Tokens
            .Where(token =>
                   token.Key != CommunicationTokens.RecipientEmailAddress &&
                   token.Key != CommunicationTokens.CandidateMobileNumber));
 }
Example #2
0
        public static CommunicationRequest GetCommunicationMessage(Candidate candidate, List <ExpiringApprenticeshipApplicationDraft> candidateDailyDigest)
        {
            var communicationMessage = new CommunicationRequest
            {
                EntityId    = candidate.EntityId,
                MessageType = MessageTypes.DailyDigest
            };

            var commTokens = new List <CommunicationToken>
            {
                new CommunicationToken(CommunicationTokens.CandidateFirstName, candidate.RegistrationDetails.FirstName),
                new CommunicationToken(CommunicationTokens.RecipientEmailAddress, candidate.RegistrationDetails.EmailAddress),
                new CommunicationToken(CommunicationTokens.CandidateMobileNumber, candidate.RegistrationDetails.PhoneNumber),
                new CommunicationToken(CommunicationTokens.ExpiringDraftsCount, candidateDailyDigest.Count().ToString(CultureInfo.InvariantCulture))
            };

            //todo: for review. consider dealing with raw data here, not custom serialisation
            var drafts = string.Join("~", candidateDailyDigest
                                     .OrderBy(p => p.ClosingDate)
                                     .Select(d => string.Join("|", d.VacancyId, WebUtility.UrlEncode(d.Title), WebUtility.UrlEncode(d.EmployerName), d.ClosingDate.ToLongDateString())));

            commTokens.Add(new CommunicationToken(CommunicationTokens.ExpiringDrafts, drafts));

            communicationMessage.Tokens = commTokens;

            return(communicationMessage);
        }
        private IEnumerable <CommunicationMessage> GenerateCommunicationMessages(
            CommunicationRequest request,
            string originatingService,
            List <CommunicationDataItem> dataItems,
            IEnumerable <Participant> filteredParticipants)
        {
            var messages = filteredParticipants.SelectMany(p =>
            {
                var channels = p.Preferences.Channels.ToDeliveryChannels();

                return(channels.Select(channel => new CommunicationMessage
                {
                    Id = Guid.NewGuid(),
                    RequestDateTime = request.RequestDateTime,
                    ParticipantsResolverName = request.ParticipantsResolverName,
                    OriginatingServiceName = originatingService,
                    Recipient = p.User,
                    DataItems = dataItems,
                    RequestType = request.RequestType,
                    Channel = channel,
                    Frequency = p.Preferences.Frequency,
                    Status = CommunicationMessageStatus.Pending
                }
                                       ));
            });

            return(messages.ToArray());
        }
        public async Task <IEnumerable <CommunicationUser> > GetParticipantsAsync(CommunicationRequest request)
        {
            _logger.LogDebug($"Resolving participants for RequestType: '{request.RequestType}'");

            var entityId = request.Entities.Single(e => e.EntityType == CommunicationConstants.EntityTypes.Vacancy).EntityId.ToString();

            if (long.TryParse(entityId, out var vacancyReference) == false)
            {
                return(Array.Empty <CommunicationUser>());
            }

            var vacancy = await _vacancyRepository.GetVacancyAsync(vacancyReference);

            List <User> users = null;

            if (vacancy.OwnerType == OwnerType.Employer)
            {
                users = await _userRepository.GetEmployerUsersAsync(vacancy.EmployerAccountId);
            }
            else
            {
                users = await _userRepository.GetProviderUsersAsync(vacancy.TrainingProvider.Ukprn.GetValueOrDefault());
            }

            var primaryUserIdamsId = vacancy.Status == VacancyStatus.Rejected ? vacancy.ReviewByUser?.UserId : vacancy.SubmittedByUser?.UserId;

            return(ParticipantResolverPluginHelper.ConvertToCommunicationUsers(users, primaryUserIdamsId));
        }
Example #5
0
        public void Request(CommunicationRequest parameter)
        {
            Thread t = new Thread(new ParameterizedThreadStart(AsyncRequest));

            parameter.threadId = t.ManagedThreadId;
            t.Start(parameter);
        }
Example #6
0
        protected override void HandleSmsMessage(Candidate candidate, CommunicationRequest communicationRequest)
        {
            var mobileNumber = communicationRequest.GetToken(CommunicationTokens.CandidateMobileNumber);

            HandleExpiringDraftSmsMessages(candidate, mobileNumber, communicationRequest);
            HandleApplicationStatusAlertSmsMessages(candidate, mobileNumber, communicationRequest);
        }
        /// <summary>
        /// Deserialize JSON into a FHIR CommunicationRequest
        /// </summary>
        public static void DeserializeJson(this CommunicationRequest current, ref Utf8JsonReader reader, JsonSerializerOptions options)
        {
            string propertyName;

            while (reader.Read())
            {
                if (reader.TokenType == JsonTokenType.EndObject)
                {
                    return;
                }

                if (reader.TokenType == JsonTokenType.PropertyName)
                {
                    propertyName = reader.GetString();
                    if (Hl7.Fhir.Serialization.FhirSerializerOptions.Debug)
                    {
                        Console.WriteLine($"CommunicationRequest >>> CommunicationRequest.{propertyName}, depth: {reader.CurrentDepth}, pos: {reader.BytesConsumed}");
                    }
                    reader.Read();
                    current.DeserializeJsonProperty(ref reader, options, propertyName);
                }
            }

            throw new JsonException($"CommunicationRequest: invalid state! depth: {reader.CurrentDepth}, pos: {reader.BytesConsumed}");
        }
        private static string BuildRequestBody(CommunicationRequest communicationRequest)
        {
            var serializer = new FhirJsonSerializer();
            var json       = serializer.SerializeToString(communicationRequest);

            return(json);
        }
        public async Task <IEnumerable <CommunicationMessage> > CreateMessagesAsync(CommunicationRequest request)
        {
            _logger.LogInformation($"Starting to create messages for request id: '{request.RequestId}' of type: '{request.RequestType}'");
            var recipientsTask = GetPotentialRecipientsAsync(request);
            var dataItemsTask  = GetEntityDataItemsAsync(request);
            await Task.WhenAll(recipientsTask, dataItemsTask);

            var recipients = recipientsTask.Result;
            var dataItems  = dataItemsTask.Result;

            _logger.LogInformation($"{dataItems.Count} data items found for request id: '{request.RequestId}'");

            var participants = await GetPreferencesForParticipantsAsync(request.RequestType, recipients);

            _logger.LogInformation($"Retrieved {participants.Count()} participants for request id: '{request.RequestId}'");

            var optedInParticipants = GetOptedInParticipants(participants);

            _logger.LogInformation($"{optedInParticipants.Count()} participants have opted in for request id: '{request.RequestId}'");

            var messages = GenerateCommunicationMessages(request, request.TemplateProviderName, dataItems, optedInParticipants);

            _logger.LogInformation($"{messages.Count()} messages generated for request id: '{request.RequestId}'");

            await SetMessageTemplateIdsAsync(messages);

            return(messages);
        }
        private void AddCommonTokens(CommunicationRequest communicationRequest)
        {
            var tokens = communicationRequest.Tokens.ToList();

            AddCandidateSiteDomainNameToken(tokens);

            communicationRequest.Tokens = tokens;
        }
        private static Guid GetCandidateId(CommunicationRequest communicationRequest)
        {
            if (!communicationRequest.EntityId.HasValue)
            {
                throw new InvalidOperationException("Candidate Id is null.");
            }

            return(communicationRequest.EntityId.Value);
        }
Example #12
0
        public override bool CanHandle(CommunicationRequest communicationRequest)
        {
            var messageTypes = new[]
            {
                MessageTypes.SendEmployerApplicationLinks
            };

            return(messageTypes.Contains(communicationRequest.MessageType));
        }
Example #13
0
        public override CommunicationResponse Request(CommunicationRequest parameter)
        {
            CommunicationResponse response = new CommunicationResponse();

            try {
                string         requestUrl = parameter.GetURL();
                HttpWebRequest request    = HttpWebRequest.Create(requestUrl) as HttpWebRequest;
                request.Accept        = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
                request.ContentType   = "application/x-AsyncWebClient";
                request.Method        = parameter.methodName;
                request.KeepAlive     = false;
                request.ContentLength = parameter.dataLength;
                request.UserAgent     = this.userAgent.Create();
                request.Timeout       = HttpCommunicationClient.TIME_OUT;
                if (parameter.methodName.Equals("POST"))
                {
                    Stream streamRequest = request.GetRequestStream();
                    using (BinaryWriter byteWriter = new BinaryWriter(streamRequest)) {
                        byteWriter.Write(parameter.GetQueryString());
                        byteWriter.Flush();
                        byteWriter.Close();
                    }
                }
                using (System.Net.HttpWebResponse webresponse = (HttpWebResponse)request.GetResponse()) {
                    using (System.IO.Stream stream = webresponse.GetResponseStream()) {
                        if (Regex.IsMatch(requestUrl, @"(\.html$|\.js$|\.xml|\.css|\.txt$)"))
                        {
                            using (System.IO.StreamReader reader = new System.IO.StreamReader(stream, System.Text.Encoding.UTF8)) {
                                string text = reader.ReadToEnd();
                                response.data = text;
                                reader.Close();
                            }
                        }
                        else
                        {
                            using (System.IO.BinaryReader reader = new System.IO.BinaryReader(stream)) {
                                response.data = reader.ReadBytes(1024 * 1000 * 10);
                                reader.Close();
                            }
                        }
                        stream.Close();
                    }
                    webresponse.Close();
                }
                response.status  = CommunicationResponse.ResponseStatus.SUCCESS;
                response.request = parameter;
                return(response);
            } catch (WebException we) {
                response.data    = null;
                response.status  = CommunicationResponse.ResponseStatus.FAILD;
                response.request = parameter;
                response.message = we.Message;
                Debug.LogError(we.Message);
            }
            return(response);
        }
Example #14
0
        public override bool CanHandle(CommunicationRequest communicationRequest)
        {
            var messageTypes = new[]
            {
                MessageTypes.SendProviderUserEmailVerificationCode,
                MessageTypes.ProviderContactUsMessage
            };

            return messageTypes.Contains(communicationRequest.MessageType);
        }
 public override async Task GetAllStream(
     CommunicationRequest request,
     IServerStreamWriter <CommunicationModel> responseStream,
     ServerCallContext context)
 {
     foreach (var model in mockModel)
     {
         await responseStream.WriteAsync(model);
     }
 }
        public VacancyReferredDomainEventHandlerTests()
        {
            _mockCommunicationQueueService = new Mock <ICommunicationQueueService>();
            _mockCommunicationQueueService.Setup(x => x.AddMessageAsync(It.IsAny <CommunicationRequest>()))
            .Returns(Task.CompletedTask)
            .Callback <CommunicationRequest>(cr => _sentCommRequest = cr);

            _sut = new VacancyReferredDomainEventHandler(Mock.Of <ILogger <VacancyReferredDomainEventHandler> >(),
                                                         _mockCommunicationQueueService.Object);
        }
Example #17
0
        public override CommunicationResponse Request(CommunicationRequest parameter)
        {
            CommunicationResponse response = new CommunicationResponse();
            Random random    = new System.Random();
            int    sleepTime = random.Next(500, 4000);

            Thread.Sleep(sleepTime);
            response.request = parameter;
            return(response);
        }
        public void Send(Guid?userId, MessageTypes messageType, IEnumerable <CommunicationToken> tokens)
        {
            var request = new CommunicationRequest
            {
                EntityId    = userId,
                MessageType = messageType,
                Tokens      = tokens
            };

            _messageBus.PublishMessage(request);
        }
Example #19
0
        private void HandleApplicationStatusAlertSmsMessages(
            Candidate candidate, string mobileNumber, CommunicationRequest communicationRequest)
        {
            var applicationStatusAlertsJson = communicationRequest.GetToken(CommunicationTokens.ApplicationStatusAlerts);

            var applicationStatusAlerts = string.IsNullOrWhiteSpace(applicationStatusAlertsJson)
                ? new List <ApplicationStatusAlert>()
                : JsonConvert.DeserializeObject <List <ApplicationStatusAlert> >(applicationStatusAlertsJson);

            QueueApplicationStatusAlertSmsMessages(candidate, mobileNumber, applicationStatusAlerts);
        }
        private Task <IEnumerable <CommunicationUser> > GetPotentialRecipientsAsync(CommunicationRequest request)
        {
            if (!_participantResolvers.ContainsKey(request.ParticipantsResolverName))
            {
                throw new UnknownRecipientResolverTypeException($"Unable to resolve recipient resolver named '{request.ParticipantsResolverName}'");
            }

            var resolver = _participantResolvers[request.ParticipantsResolverName];

            return(resolver.GetParticipantsAsync(request));
        }
        public override Task <CommunicationResponse> GetAllChannels(CommunicationRequest request, ServerCallContext context)
        {
            var model = new CommunicationResponse();

            model.Response.AddRange(mockModel);
            model.Total = mockModel.Count;

            context.Status = new Status(StatusCode.OK, $"ok");

            return(Task.FromResult(model));
        }
Example #22
0
        private CommunicationRequest GetVacancyWithdrawnByQaCommunicationRequest(long vacancyReference)
        {
            var communicationRequest = new CommunicationRequest(
                CommunicationConstants.RequestType.VacancyWithdrawnByQa,
                CommunicationConstants.ParticipantResolverNames.VacancyParticipantsResolverName,
                CommunicationConstants.ServiceName);

            communicationRequest.AddEntity(CommunicationConstants.EntityTypes.Vacancy, vacancyReference);
            communicationRequest.AddEntity(CommunicationConstants.EntityTypes.ApprenticeshipServiceUrl, vacancyReference);
            return(communicationRequest);
        }
Example #23
0
        private Task RequestProviderCommunicationAsync(long ukprn)
        {
            var communicationRequest = new CommunicationRequest(
                CommunicationConstants.RequestType.ProviderBlockedProviderNotification,
                CommunicationConstants.ParticipantResolverNames.ProviderParticipantsResolverName,
                CommunicationConstants.ServiceName);

            communicationRequest.AddEntity(CommunicationConstants.EntityTypes.Provider, ukprn);
            communicationRequest.AddEntity(CommunicationConstants.EntityTypes.ApprenticeshipServiceConfig, null);

            return(_communicationQueueService.AddMessageAsync(communicationRequest));
        }
Example #24
0
        public async Task GetAllStreams(CommunicationRequest request)
        {
            using (var call = _communicationGrpcClient.GetAllStream(request))
            {
                while (await call.ResponseStream.MoveNext())
                {
                    var currentDummyGrpc = call.ResponseStream.Current;

                    Console.WriteLine($"{ currentDummyGrpc.ChannelId }: { currentDummyGrpc.Channel }");
                }
            }
        }
Example #25
0
        protected void SendSmsMessage(CommunicationRequest message)
        {
            var toMobile = message.Tokens.First(t => t.Key == CommunicationTokens.CandidateMobileNumber).Value;
            var request  = new SmsRequest
            {
                ToNumber    = toMobile,
                MessageType = message.MessageType,
                Tokens      = GetMessageTokens(message),
            };

            _messageBus.PublishMessage(request);
        }
Example #26
0
        protected void SendEmailMessage(CommunicationRequest message)
        {
            var toEmail = message.Tokens.First(t => t.Key == CommunicationTokens.RecipientEmailAddress).Value;
            var request = new EmailRequest
            {
                ToEmail     = toEmail,
                MessageType = message.MessageType,
                Tokens      = GetMessageTokens(message),
            };

            _messageBus.PublishMessage(request);
        }
        protected virtual void HandleSmsMessage(Candidate candidate, CommunicationRequest communicationRequest)
        {
            var sendMessage = candidate.ShouldSendMessageViaChannel(CommunicationChannels.Sms, communicationRequest.MessageType);

            LogSendMessageResult(sendMessage, CommunicationChannels.Sms, candidate, communicationRequest);

            if (sendMessage)
            {
                AddCommonTokens(communicationRequest);
                QueueSmsMessage(communicationRequest);
            }
        }
        private CommunicationRequest GetRejectedVacancyCommunicationRequest(long vacancyReference, long?providerUkprn)
        {
            var communicationRequest = new CommunicationRequest(
                CommunicationConstants.RequestType.VacancyRejectedByEmployer,
                CommunicationConstants.ParticipantResolverNames.VacancyParticipantsResolverName,
                CommunicationConstants.ServiceName);

            communicationRequest.AddEntity(CommunicationConstants.EntityTypes.Vacancy, vacancyReference);
            communicationRequest.AddEntity(CommunicationConstants.EntityTypes.ApprenticeshipServiceUrl, vacancyReference);
            communicationRequest.AddEntity(CommunicationConstants.EntityTypes.Provider, providerUkprn);
            return(communicationRequest);
        }
        public void Send(MessageTypes messageType, IEnumerable <CommunicationToken> tokens)
        {
            var request = new CommunicationRequest
            {
                //TODO: Might be an issue nulling this
                EntityId    = null,
                MessageType = messageType,
                Tokens      = tokens
            };

            _serviceBus.PublishMessage(request);
        }
Example #30
0
        public static CommunicationRequest GetProviderBlockedEmployerNotificationForLiveVacanciesRequest(long ukprn, string employerAccountId)
        {
            var communicationRequest = new CommunicationRequest(
                CommunicationConstants.RequestType.ProviderBlockedEmployerNotificationForLiveVacancies,
                CommunicationConstants.ParticipantResolverNames.EmployerParticipantsResolverName,
                CommunicationConstants.ServiceName);

            communicationRequest.AddEntity(CommunicationConstants.EntityTypes.Provider, ukprn);
            communicationRequest.AddEntity(CommunicationConstants.EntityTypes.Employer, employerAccountId);
            communicationRequest.AddEntity(CommunicationConstants.EntityTypes.ApprenticeshipServiceConfig, null);
            return(communicationRequest);
        }
Example #31
0
 public udp_req_cpacket(CommunicationRequest request, Mode connectionMode = Mode.Unspecified, int port = -1)
 {
     this.ConnectionMode = connectionMode;
     this.Request = request;
     this.port = port;
 }
Example #32
0
        /// <summary>
        /// Enqueue communication request and wait for reply.
        /// </summary>
        /// 
        /// <param name="request">Array of bytes (command) to send to SRV-1 Blackfin robot/camera.</param>
        /// <param name="responseBuffer">Buffer to read response into.</param>
        /// 
        /// <returns>Returns total bytes read into the response buffer.</returns>
        /// 
        /// <remarks><para>The method puts specified command into communication queue and waits until
        /// the command is sent to SRV-1 Blackfin robot and reply is received.</para>
        /// 
        /// <para><note>If SRV-1 responds with more data than response buffer can fit, then
        /// the response buffer will take all the data it can store, but the rest of response
        /// will be discarded. The only exception is image request - if response buffer is too
        /// small to fit image response, then <see cref="IndexOutOfRangeException"/> exception
        /// is thrown. It is user's responsibility to provide response buffer of the correct
        /// size. Check definition of the <a href="http://www.surveyor.com/SRV_protocol.html">SRV-1
        /// Control Protocol</a> for information about supported commands and responses.</note></para>
        /// </remarks>
        /// 
        /// <exception cref="NotConnectedException">Not connected to SRV-1.</exception>
        /// <exception cref="ConnectionLostException">Connection lost or communicaton failure.</exception>
        /// <exception cref="IndexOutOfRangeException">Response buffer is too small.</exception>
        /// 
        public int SendAndReceive( byte[] request, byte[] responseBuffer )
        {
            lock ( sync )
            {
                if ( socket == null )
                {
                    // handle error
                    throw new NotConnectedException( "Not connected to SRV-1." );
                }

                lock ( communicationQueue )
                {
                    communicationQueue.Enqueue( new CommunicationRequest( request, responseBuffer ) );
                }
                requestIsAvailable.Set( );

                // waiting for reply
                replyIsAvailable.WaitOne( );

                // no reply since we got disconnect request from user - background thread is exiting
                if ( lastRequestWithReply == null )
                    return 0;

                // get number of bytes read
                int bytesRead = lastRequestWithReply.BytesRead;

                // clean the last reply
                lastRequestWithReply = null;

                if ( bytesRead == -1 )
                {
                    // handle error
                    throw new ConnectionLostException( "Connection lost or communicaton failure." );
                }
                if ( bytesRead == -2 )
                {
                    // handle error
                    throw new IndexOutOfRangeException( "Response buffer is too small." );
                }
                return bytesRead;
            }
        }
Example #33
0
        // Communication thread
        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( );
                        }
                    }
                }
            }
        }