SipMessage.parse constructor

SipMessage.parse(
  1. String raw
)

Parse a wire message.

Implementation

factory SipMessage.parse(String raw) {
  final eoh = raw.indexOf('\r\n\r\n');
  final headPart = eoh < 0 ? raw : raw.substring(0, eoh);
  final body = eoh < 0 ? '' : raw.substring(eoh + 4);
  final lines = headPart.split('\r\n');
  if (lines.isEmpty) {
    throw const FormatException('empty SIP message');
  }
  final start = lines.first;
  final headers = <MapEntry<String, String>>[];
  for (var i = 1; i < lines.length; i++) {
    final line = lines[i];
    if (line.isEmpty) continue;
    final colon = line.indexOf(':');
    if (colon <= 0) continue;
    final name = line.substring(0, colon).trim();
    var value = line.substring(colon + 1);
    if (value.isNotEmpty && (value[0] == ' ' || value[0] == '\t')) {
      value = value.substring(1);
    }
    headers.add(MapEntry(name, value));
  }

  if (start.startsWith('SIP/2.0 ')) {
    final rest = start.substring(8);
    final sp = rest.indexOf(' ');
    final code = int.tryParse(sp < 0 ? rest : rest.substring(0, sp)) ?? 0;
    final reason = sp < 0 ? '' : rest.substring(sp + 1);
    return SipMessage._(
      statusCode: code,
      reasonPhrase: reason,
      headers: headers,
      body: body,
    );
  }
  final parts = start.split(' ');
  if (parts.length < 3) {
    throw FormatException('bad start line: $start');
  }
  return SipMessage._(
    method: parts[0],
    requestUri: parts.sublist(1, parts.length - 1).join(' '),
    headers: headers,
    body: body,
  );
}