pni_protocol_type_t pni_sniff_header()

in c/src/core/autodetect.c [80:121]


pni_protocol_type_t pni_sniff_header(const char *buf, size_t len)
{
  if (len < 3) return PNI_PROTOCOL_INSUFFICIENT;
  bool isSSL3Handshake = buf[0]==22 &&            // handshake
                         buf[1]==3  && buf[2]<=3; // SSL 3.0 & TLS 1.0-1.2 (v3.1-3.3)
  if (isSSL3Handshake) return PNI_PROTOCOL_SSL;

  bool isFirst3AMQP = buf[0]=='A' && buf[1]=='M' && buf[2]=='Q';
  bool isFirst3SSL2CLientHello = buf[2]==1;       // Client Hello
  if (!isFirst3AMQP && !isFirst3SSL2CLientHello) return PNI_PROTOCOL_UNKNOWN;


  if (len < 4) return PNI_PROTOCOL_INSUFFICIENT;
  bool isAMQP = isFirst3AMQP && buf[3]=='P';
  bool isFirst4SSL2ClientHello = isFirst3SSL2CLientHello && (buf[3]==2 || buf[3]==3);
  if (!isAMQP && !isFirst4SSL2ClientHello) return PNI_PROTOCOL_UNKNOWN;

  if (len < 5) return PNI_PROTOCOL_INSUFFICIENT;
  bool isSSL2Handshake = buf[2] == 1 &&   // MSG-CLIENT-HELLO
      ((buf[3] == 3 && buf[4] <= 3) ||    // SSL 3.0 & TLS 1.0-1.2 (v3.1-3.3)
       (buf[3] == 2 && buf[4] == 0));     // SSL 2
  if (isSSL2Handshake) return PNI_PROTOCOL_SSL;

  bool isFirst5OldAMQP = isAMQP && buf[4]==1;
  bool isFirst5AMQP = isAMQP && (buf[4]==0 || buf[4]==2 || buf[4]==3);
  if (!isFirst5AMQP && !isFirst5OldAMQP) return PNI_PROTOCOL_UNKNOWN;

  if (len < 6) return PNI_PROTOCOL_INSUFFICIENT;

  // Both old and new versions of AMQP have 1 in byte 5
  if (buf[5]!=1) return PNI_PROTOCOL_UNKNOWN;

  // From here on it must be some sort of AMQP
  if (len < 8) return PNI_PROTOCOL_INSUFFICIENT;
  if (buf[6]==0 && buf[7]==0) {
    // AM<QP 1.0
      if (buf[4]==0) return PNI_PROTOCOL_AMQP1;
      if (buf[4]==2) return PNI_PROTOCOL_AMQP_SSL;
      if (buf[4]==3) return PNI_PROTOCOL_AMQP_SASL;
  }
  return PNI_PROTOCOL_AMQP_OTHER;
}