text: "use strict";
  /**
   * @fileoverview Incoming SIP Message Sanity Check
   */
  
  /**
   * SIP message sanity check.
   * @augments SIP
   * @function
   * @param {SIP.IncomingMessage} message
   * @param {SIP.UA} ua
   * @param {SIP.Transport} transport
   * @returns {Boolean}
   */
  module.exports = function(SIP) {
      var sanityCheck,
          logger,
          message, ua, transport,
          requests = [],
          responses = [],
          all = [];
  
      // Reply
      function reply(status_code) {
          var to,
              response = SIP.Utils.buildStatusLine(status_code),
              vias = message.getHeaders('via'),
              length = vias.length,
              idx = 0;
  
          for (idx; idx < length; idx++) {
              response += "Via: " + vias[idx] + "\r\n";
          }
  
          to = message.getHeader('To');
  
          if (!message.to_tag) {
              to += ';tag=' + SIP.Utils.newTag();
          }
  
          response += "To: " + to + "\r\n";
          response += "From: " + message.getHeader('From') + "\r\n";
          response += "Call-ID: " + message.call_id + "\r\n";
          response += "CSeq: " + message.cseq + " " + message.method + "\r\n";
          response += "\r\n";
  
          transport.send(response);
      }
  
      /*
       * Sanity Check for incoming Messages
       *
       * Requests:
       *  - _rfc3261_8_2_2_1_ Receive a Request with a non supported URI scheme
       *  - _rfc3261_16_3_4_ Receive a Request already sent by us
       *   Does not look at via sent-by but at sipjsId, which is inserted as
       *   a prefix in all initial requests generated by the ua
       *  - _rfc3261_18_3_request_ Body Content-Length
       *  - _rfc3261_8_2_2_2_ Merged Requests
       *
       * Responses:
       *  - _rfc3261_8_1_3_3_ Multiple Via headers
       *  - _rfc3261_18_1_2_ sent-by mismatch
       *  - _rfc3261_18_3_response_ Body Content-Length
       *
       * All:
       *  - Minimum headers in a SIP message
       */
  
      // Sanity Check functions for requests
      function rfc3261_8_2_2_1() {
          if (!message.ruri || message.ruri.scheme !== 'sip') {
              logger.warn('message.ruri: ' + message.ruri);
              reply(416);
              return false;
          }
      }
  
      function rfc3261_16_3_4() {
          if (!message.to_tag) {
              if (message.call_id.substr(0, 5) === ua.configuration.sipjsId) {
                  reply(482);
                  return false;
              }
          }
      }
  
      function rfc3261_18_3_request() {
          var len = SIP.Utils.str_utf8_length(message.body),
              contentLength = message.getHeader('content-length');
  
          if (len < contentLength) {
              reply(400);
              return false;
          }
      }
  
      function rfc3261_8_2_2_2() {
          var tr, idx,
              fromTag = message.from_tag,
              call_id = message.call_id,
              cseq = message.cseq;
  
          if (!message.to_tag) {
              if (message.method === SIP.C.INVITE) {
                  tr = ua.transactions.ist[message.via_branch];
                  if (tr) {
                      return;
                  } else {
                      for (idx in ua.transactions.ist) {
                          tr = ua.transactions.ist[idx];
                          if (tr.request.from_tag === fromTag && tr.request.call_id === call_id && tr.request.cseq === cseq) {
                              reply(482);
                              return false;
                          }
                      }
                  }
              } else {
                  tr = ua.transactions.nist[message.via_branch];
                  if (tr) {
                      return;
                  } else {
                      for (idx in ua.transactions.nist) {
                          tr = ua.transactions.nist[idx];
                          if (tr.request.from_tag === fromTag && tr.request.call_id === call_id && tr.request.cseq === cseq) {
                              reply(482);
                              return false;
                          }
                      }
                  }
              }
          }
      }
  
      // Sanity Check functions for responses
      function rfc3261_8_1_3_3() {
          if (message.getHeaders('via').length > 1) {
              logger.warn('More than one Via header field present in the response. Dropping the response');
              return false;
          }
      }
  
      function rfc3261_18_1_2() {
          var viaHost = ua.configuration.viaHost;
          if (message.via.host !== viaHost || message.via.port !== undefined) {
              logger.warn('Via sent-by in the response does not match UA Via host value. Dropping the response');
              return false;
          }
      }
  
      function rfc3261_18_3_response() {
          var
              len = SIP.Utils.str_utf8_length(message.body),
              contentLength = message.getHeader('content-length');
  
          if (len < contentLength) {
              logger.warn('Message body length is lower than the value in Content-Length header field. Dropping the response');
              return false;
          }
      }
  
      // Sanity Check functions for requests and responses
      function minimumHeaders() {
          var
              mandatoryHeaders = ['from', 'to', 'call_id', 'cseq', 'via'],
              idx = mandatoryHeaders.length;
  
          while (idx--) {
              if (!message.hasHeader(mandatoryHeaders[idx])) {
                  logger.warn('Missing mandatory header field : ' + mandatoryHeaders[idx] + '. Dropping the response');
                  return false;
              }
          }
      }
  
      requests.push(rfc3261_8_2_2_1);
      requests.push(rfc3261_16_3_4);
      requests.push(rfc3261_18_3_request);
      requests.push(rfc3261_8_2_2_2);
  
      responses.push(rfc3261_8_1_3_3);
      responses.push(rfc3261_18_1_2);
      responses.push(rfc3261_18_3_response);
  
      all.push(minimumHeaders);
  
      sanityCheck = function(m, u, t) {
          var len, pass;
  
          message = m;
          ua = u;
          transport = t;
  
          logger = ua.getLogger('sip.sanitycheck');
  
          len = all.length;
          while (len--) {
              pass = all[len](message);
              if (pass === false) {
                  console.log('sanityCheck return 1');
                  return false;
              }
          }
  
          if (message instanceof SIP.IncomingRequest) {
              len = requests.length;
              while (len--) {
                  pass = requests[len](message);
                  if (pass === false) {
                      logger.warn('requests[len]: ' + requests[len]);
                      logger.warn('sanityCheck return 2');
                      return false;
                  }
              }
          } else if (message instanceof SIP.IncomingResponse) {
              len = responses.length;
              while (len--) {
                  pass = responses[len](message);
                  if (pass === false) {
                      console.log('sanityCheck return 3');
                      return false;
                  }
              }
          }
  
  
          //Everything is OK
          return true;
      };
  
      SIP.sanityCheck = sanityCheck;
  };