Search in sources :

Example 1 with CRLFLineReader

use of org.apache.commons.net.io.CRLFLineReader in project opennms by OpenNMS.

the class SmtpMonitor method poll.

/**
 * {@inheritDoc}
 *
 * <P>
 * Poll the specified address for SMTP service availability.
 * </P>
 *
 * <P>
 * During the poll an attempt is made to connect on the specified port (by
 * default TCP port 25). If the connection request is successful, the banner
 * line generated by the interface is parsed and if the extracted return
 * code indicates that we are talking to an SMTP server we continue. Next,
 * an SMTP 'HELO' command is sent to the interface. Again the response is
 * parsed and a return code extracted and verified. Finally, an SMTP 'QUIT'
 * command is sent. Provided that the interface's response is valid we set
 * the service status to SERVICE_AVAILABLE and return.
 * </P>
 */
@Override
public PollStatus poll(MonitoredService svc, Map<String, Object> parameters) {
    TimeoutTracker tracker = new TimeoutTracker(parameters, DEFAULT_RETRY, DEFAULT_TIMEOUT);
    int port = ParameterMap.getKeyedInteger(parameters, "port", DEFAULT_PORT);
    InetAddress ipAddr = svc.getAddress();
    final String hostAddress = InetAddressUtils.str(ipAddr);
    LOG.debug("poll: address = {}, port = {}, {}", hostAddress, port, tracker);
    PollStatus serviceStatus = PollStatus.unavailable();
    for (tracker.reset(); tracker.shouldRetry() && !serviceStatus.isAvailable(); tracker.nextAttempt()) {
        Socket socket = null;
        try {
            // create a connected socket
            // 
            tracker.startAttempt();
            socket = new Socket();
            socket.connect(new InetSocketAddress(ipAddr, port), tracker.getConnectionTimeout());
            socket.setSoTimeout(tracker.getSoTimeout());
            LOG.debug("SmtpMonitor: connected to host: {} on port: {}", ipAddr, port);
            // We're connected, so upgrade status to unresponsive
            serviceStatus = PollStatus.unresponsive();
            // Forcing to check for CRLF instead of any other line terminator as per RFC specification
            CRLFLineReader rdr = new CRLFLineReader(new InputStreamReader(socket.getInputStream(), "ASCII"));
            // 
            // Tokenize the Banner Line, and check the first
            // line for a valid return.
            // 
            String banner = sendMessage(socket, rdr, null);
            LOG.debug("poll: banner = {}", banner);
            StringTokenizer t = new StringTokenizer(banner);
            int rc = Integer.parseInt(t.nextToken());
            if (rc == 220) {
                // 
                // Send the HELO command
                // 
                String cmd = "HELO " + LOCALHOST_NAME + "\r\n";
                socket.getOutputStream().write(cmd.getBytes());
                // 
                // get the returned string, tokenize, and
                // verify the correct output.
                // 
                String response = rdr.readLine();
                double responseTime = tracker.elapsedTimeInMillis();
                if (response == null) {
                    continue;
                }
                if (MULTILINE.matcher(response).find()) {
                    // Ok we have a multi-line response...first three
                    // chars of the response line are the return code.
                    // The last line of the response will start with
                    // return code followed by a space.
                    String multiLineRC = new String(response.getBytes("ASCII"), 0, 3, "ASCII");
                    // Create new regExp to look for last line
                    // of this multi line response
                    Pattern endMultiline = null;
                    try {
                        endMultiline = Pattern.compile(multiLineRC);
                    } catch (PatternSyntaxException ex) {
                        throw new java.lang.reflect.UndeclaredThrowableException(ex);
                    }
                    // response
                    do {
                        response = rdr.readLine();
                    } while (response != null && !endMultiline.matcher(response).find());
                    if (response == null) {
                        continue;
                    }
                }
                t = new StringTokenizer(response);
                rc = Integer.parseInt(t.nextToken());
                if (rc == 250) {
                    response = sendMessage(socket, rdr, "QUIT\r\n");
                    t = new StringTokenizer(response);
                    rc = Integer.parseInt(t.nextToken());
                    if (rc == 221) {
                        serviceStatus = PollStatus.available(responseTime);
                    }
                }
            } else if (rc == 554) {
                String response = sendMessage(socket, rdr, "QUIT\r\n");
                serviceStatus = PollStatus.unavailable("Server rejecting transactions with 554");
            }
            // checking or HELO/QUIT comand process.
            if (!serviceStatus.isAvailable()) {
                serviceStatus = PollStatus.unavailable(serviceStatus.getReason());
            }
        } catch (NumberFormatException e) {
            String reason = "NumberFormatException while polling address " + hostAddress;
            LOG.debug(reason, e);
            serviceStatus = PollStatus.unavailable(reason);
        } catch (NoRouteToHostException e) {
            String reason = "No route to host exception for address " + hostAddress;
            LOG.debug(reason, e);
            serviceStatus = PollStatus.unavailable(reason);
            // Break out of for(;;)
            break;
        } catch (InterruptedIOException e) {
            String reason = "Did not receive expected response within timeout " + tracker;
            LOG.debug(reason);
            serviceStatus = PollStatus.unavailable(reason);
        } catch (ConnectException e) {
            String reason = "Unable to connect to address " + hostAddress;
            LOG.debug(reason, e);
            serviceStatus = PollStatus.unavailable(reason);
        } catch (IOException e) {
            String reason = "IOException while polling address " + hostAddress;
            LOG.debug(reason, e);
            serviceStatus = PollStatus.unavailable(reason);
        } finally {
            try {
                // Close the socket
                if (socket != null) {
                    socket.close();
                }
            } catch (IOException e) {
                e.fillInStackTrace();
                LOG.debug("poll: Error closing socket.", e);
            }
        }
    }
    // 
    return serviceStatus;
}
Also used : Pattern(java.util.regex.Pattern) InterruptedIOException(java.io.InterruptedIOException) PollStatus(org.opennms.netmgt.poller.PollStatus) InputStreamReader(java.io.InputStreamReader) InetSocketAddress(java.net.InetSocketAddress) CRLFLineReader(org.apache.commons.net.io.CRLFLineReader) IOException(java.io.IOException) InterruptedIOException(java.io.InterruptedIOException) NoRouteToHostException(java.net.NoRouteToHostException) StringTokenizer(java.util.StringTokenizer) TimeoutTracker(org.opennms.core.utils.TimeoutTracker) InetAddress(java.net.InetAddress) Socket(java.net.Socket) PatternSyntaxException(java.util.regex.PatternSyntaxException) ConnectException(java.net.ConnectException)

Aggregations

IOException (java.io.IOException)1 InputStreamReader (java.io.InputStreamReader)1 InterruptedIOException (java.io.InterruptedIOException)1 ConnectException (java.net.ConnectException)1 InetAddress (java.net.InetAddress)1 InetSocketAddress (java.net.InetSocketAddress)1 NoRouteToHostException (java.net.NoRouteToHostException)1 Socket (java.net.Socket)1 StringTokenizer (java.util.StringTokenizer)1 Pattern (java.util.regex.Pattern)1 PatternSyntaxException (java.util.regex.PatternSyntaxException)1 CRLFLineReader (org.apache.commons.net.io.CRLFLineReader)1 TimeoutTracker (org.opennms.core.utils.TimeoutTracker)1 PollStatus (org.opennms.netmgt.poller.PollStatus)1