parseMessage function

IncomingMessage? parseMessage(
  1. String data,
  2. PitelUA? ua
)

Parse SIP Message

Implementation

IncomingMessage? parseMessage(String data, PitelUA? ua) {
  IncomingMessage message;
  int bodyStart;
  int headerEnd = data.indexOf('\r\n');

  if (headerEnd == -1) {
    logger.error('parseMessage() | no CRLF found, not a SIP message');
    return null;
  }

  // Parse first line. Check if it is a Request or a Reply.
  String firstLine = data.substring(0, headerEnd);
  dynamic parsed;
  try {
    parsed = Grammar.parse(firstLine, 'Request_Response');
  } catch (FormatException) {
    // Catch exception and fake the expected -1 result
    parsed = -1;
  }

  if (parsed == -1) {
    logger.error(
        'parseMessage() | error parsing first line of SIP message: "$firstLine"');

    return null;
  } else if (parsed.status_code == null) {
    IncomingRequest incomingRequest = IncomingRequest(ua);
    incomingRequest.method = parsed.method;
    incomingRequest.ruri = parsed.uri;
    message = incomingRequest;
  } else {
    message = IncomingResponse();
    message.status_code = parsed.status_code;
    message.reason_phrase = parsed.reason_phrase;
  }

  message.data = data;
  int headerStart = headerEnd + 2;

  /* Loop over every line in data. Detect the end of each header and parse
  * it or simply add to the headers collection.
  */
  while (true) {
    headerEnd = getHeader(data, headerStart);

    // The SIP message has normally finished.
    if (headerEnd == -2) {
      bodyStart = headerStart + 2;
      break;
    }
    // Data.indexOf returned -1 due to a malformed message.
    else if (headerEnd == -1) {
      logger.error('parseMessage() | malformed message');

      return null;
    }

    parsed = parseHeader(message, data, headerStart, headerEnd);

    if (parsed != true) {
      logger.error('parseMessage() |' + parsed['error']);
      return null;
    }

    headerStart = headerEnd + 2;
  }

  /* RFC3261 18.3.
   * If there are additional bytes in the transport packet
   * beyond the end of the body, they MUST be discarded.
   */
  if (message.hasHeader('content-length')) {
    dynamic contentLength = message.getHeader('content-length');

    if (contentLength is String) {
      contentLength = int.tryParse(contentLength) ?? 0;
    }
    contentLength ??= 0;
    if (contentLength > 0) {
      List<int> encoded = utf8.encode(data);
      List<int> content =
          encoded.sublist(bodyStart, bodyStart + contentLength as int);
      message.body = utf8.decode(content);
    }
  } else {
    message.body = data.substring(bodyStart);
  }

  return message;
}