A C program to check if a 3M SIP2 Protocol server is alive by sending the SC Status message.

Home   »   A C program to check if a 3M SIP2 Protocol server is alive by sending the SC Status message.

/*
 * Copyright © 2021 Jason J.A. Stephenson 
 *
 * This program is free software: you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation, either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see
 * .
 */
#include 
#include 
#include 
#include 
#include 
#include 
#include 

/* 
 * This program is meant to be used as a health check for 3M SIP2
 * Protocol servers with ldirectord or haproxy.  It is specifically
 * written to be used with the F/OSS Evergreen ILS SIPServer program.
 * It *may* work with other SIP server implementations, but none have
 * been tested.
 *
 * It sends a 3M SIP2 Protocol SC Status message (99) to the SIP
 * server without logging in.  The SIP server, therefore, must allow
 * the SC Status message before login.  This is accomplished for the
 * Evergreen ILS SIPServer by adding allow_sc_status_then_login="true"
 * to the configuration for the RAW transport service in the
 * oils_sip.xml configuration file.
 *
 * NOTE: This program does NOT send the sequence nor checksum fields,
 * as checksums are redundant over TCP connections.  If your SIP
 * server requires checksums, then you will have to add the code to
 * generate the sequence and checksum and add them to the message.
 *
 * The program returns 0, which both ldirectord and haproxy accept as
 * OK, if it can connect to the SIP server, send the SC Status message
 * and receives the ACS Status message (98) from the server
 * indicating the on-line status of the SIP server is OK, i.e. the
 * message begins 98Y.  If the connection fails, the SIP server
 * doesn't respond or responds with a different message, then the
 * program returns 1, which both ldirectord and haproxy interpret as
 * failure.  The load balancer/proxy will then follow its
 * configuration for what to do with a failed server.
 *
 * The two load balancers both pass 4 arguments to the program, but
 * the program only uses the 3rd and 4th arguments which correspond to
 * the SIP server's real IP address and real port, respectively.
 * These are used to connect to the SIP server and send the SC Status
 * message.
 *
 * To install the program, you would first compile it (see below),
 * then copy it to an accessible location on your load balancer or
 * proxy servers (/usr/local/bin is common or a chroot is setup for
 * haproxy), and adjust your load balancer or proxy configuration as
 * appropriate to use the program to check the status of your SIP
 * servers (see your software's documentation).
 *
 * compile (on Debian or Ubuntu GNU/Linux):
 * cc -O2 -o sip2status sip2status.c
 */

int main(int argc, char *argv[]) {
  int rv = 1; // Assume failure.

  /* ldirectord/haproxy give us four or five arguments.  We only care about 3 and 4. */
  char *remoteIP = argv[3];
  char *remotePort = argv[4];

  char *message = "9902552.00\r";
  
  int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  struct sockaddr_in remoteAddr;
  memset(&remoteAddr, 0, sizeof(struct sockaddr_in));
  remoteAddr.sin_family = AF_INET;
  remoteAddr.sin_port = htons((uint16_t) atoi(remotePort));
  inet_pton(AF_INET, remoteIP, &remoteAddr.sin_addr);
  if (connect(sockfd, (struct sockaddr *)&remoteAddr, sizeof(remoteAddr)) != -1) {
    if (write(sockfd, (void *)message, strlen(message)) != -1) {
      char response[512]; // Certainly big enough...
      memset(response, 0, 512);
      if (read(sockfd, (void *)response, 511) != -1) {
        if (strncmp(response, "98Y", 3) == 0)
          rv = 0; // Success!
      }
    }
    close(sockfd);
  }

  return rv;
}

Leave a Reply

Your email address will not be published. Required fields are marked *