/// <summary> /// Registers this client with the server to listen for simias events. /// </summary> public void Register() { // Don't let registration happen multiple times. if (state == ClientState.Initializing) { // Set the states to registering. state = ClientState.Registering; regThreadState = RegThreadState.Initializing; // Start a thread which will process the registration request. Thread thread = new Thread(new ThreadStart(RegistrationService)); thread.Name = "IProc Event Client Registration"; thread.Priority = ThreadPriority.BelowNormal; thread.IsBackground = true; thread.Start(); } }
/// <summary> /// Thread service routine that registers with the event service and then dies. /// </summary> private void RegistrationService() { try { // Start monitoring the configuration file for changes. StartMonitorConfigFileChange(); try { // Sit here until we connect. while (socketDisconnected && (state != ClientState.Shutdown)) { // Connect to the event service and send an initialization message. IPEndPoint host = GetHostAddress(); // Make sure that the thread was not told to shutdown. if (state != ClientState.Shutdown) { try { // Connect to the server. eventSocket.Connect(host); socketDisconnected = false; // Get the local end point information localEndPoint = eventSocket.LocalEndPoint as IPEndPoint; // Post the received before the registration message is sent. eventSocket.BeginReceive(receiveBuffer, 0, receiveBuffer.Length, SocketFlags.None, new AsyncCallback(MessageHandler), null); // Register our client. SendMessage(new IProcEventRegistration(localEndPoint, true).ToBuffer()); // Process the queues within the lock so that any new actions or filters // are sent to the server and not just queued and forgotten. lock ( subscribeLock ) { // Check to see if any set filter items have been queue. ProcessEventFilterQueue(); // Check to see if any set event actions have been queued. ProcessEventActionQueue(); // Set the state as running. state = ClientState.Running; } } catch (SocketException e) { // See if this is a case of the server not listening on the socket anymore. // It may have gone down hard and left the configuration file with an invalid // socket. Keep watching the file until the socket changes and it can be // connected. if (e.ErrorCode == WSAECONNREFUSED) { // Wait for the configuration file to change before continuing. WaitForConfigFileChange(); } else { throw e; } } } } } finally { // Don't watch for anymore changes. EndMonitorConfigFileChange(); } // This thread is going away. regThreadState = RegThreadState.Terminated; } catch (SocketException e) { ReportError(new ApplicationException("Error registering with the event service.", e)); RestartClient(); } }
/// <summary> /// Processes messages from the event server. /// </summary> /// <param name="result">The result of the asynchronous operation.</param> private void MessageHandler(IAsyncResult result) { // Make sure that the client is not shutting down. if (state != ClientState.Shutdown) { try { // End the pending read operation. int bytesReceived = eventSocket.EndReceive(result); if (bytesReceived > 0) { try { // Keep track of how much data is in the buffer. bufferLength += bytesReceived; int bytesToProcess = bufferLength; int msgIndex = 0; // Process as much as is available. while (bytesToProcess > 0) { // There needs to be atleast 4 bytes for the message length. if (bytesToProcess >= 4) { // Get the length of the message, add in the prepended length. int msgLength = BitConverter.ToInt32(receiveBuffer, msgIndex) + 4; // See if the entire message is represented in the buffer. if (bytesToProcess >= msgLength) { // Process the message received from the client. Skip the message length. ProcessMessage(new UTF8Encoding().GetString(receiveBuffer, msgIndex + 4, msgLength - 4)); msgIndex += msgLength; bytesToProcess -= msgLength; } else { break; } } else { break; } } // Update how much data is left in the buffer. bufferLength = bytesToProcess; // If any data has been processed at the beginning of the buffer, the unprocessed // data needs to be moved to the front. if ((bytesToProcess > 0) && (msgIndex > 0)) { // Move any existing data up. Buffer.BlockCopy(receiveBuffer, msgIndex, receiveBuffer, 0, bytesToProcess); } // Repost the buffer. eventSocket.BeginReceive(receiveBuffer, bufferLength, receiveBuffer.Length - bufferLength, SocketFlags.None, new AsyncCallback(MessageHandler), null); } catch (SocketException e) { throw e; } catch (Exception e) { ReportError(new ApplicationException("Error processing event message from server.", e)); } } else { // The server has gone away or has terminated our connection. throw new SocketException(WSAEHOSTDOWN); } } catch (SocketException e) { // Check to see if this exception was caused by the registration thread going away. // If it was, just repost the receive. if ((e.ErrorCode == ownerThreadTerminated) && (regThreadState == RegThreadState.Terminated)) { regThreadState = RegThreadState.TerminationAck; eventSocket.BeginReceive(receiveBuffer, 0, receiveBuffer.Length, SocketFlags.None, new AsyncCallback(MessageHandler), null); } else { ReportError(new ApplicationException("Error processing event message from server.", e)); RestartClient(); } } } }