/// <summary> /// Parse a message value. /// </summary> /// <param name="reader">Reader containing the string that should be parsed.</param> /// <returns>Newly created header.</returns> /// <exception cref="ParseException">Header value is malformed.</exception> /// <example> /// sip:[email protected]:5060 /// [email protected]:5060 /// jonas:[email protected] /// sip:[email protected] /// mailto:[email protected] /// </example> public static SipUri Parse(ITextReader reader) { string first = reader.ReadUntil("@:"); string scheme = null; string userName; string password = null; string domain; int port = 0; bool containsAt = reader.Contains('@'); // scheme:domain:port // scheme:domain // domain:port if (reader.Current == ':' && !containsAt) { reader.Consume(); //scheme:domain:port or scheme:domain if (IsValidScheme(first)) { scheme = first; domain = reader.ReadToEnd(":"); if (reader.EOF) return new SipUri(scheme, domain, 0); //scheme:domain:port reader.Consume(':'); first = reader.ReadToEnd(); } else // domain:port or just domain { domain = first; first = reader.ReadToEnd(":"); } if (!int.TryParse(first, out port)) throw new ParseException("Port is not a number: " + first); return new SipUri(scheme, domain, port); } // Can either be "scheme:username" // or "username:password" // or "scheme:username:password" else if (reader.Current == ':') { reader.Consume(); // Check if we got another colon (scheme:username:password) string second = reader.ReadUntil(":@"); if (reader.Current == ':') { scheme = first; userName = second; reader.Consume(); password = reader.ReadUntil('@'); } // it's "scheme:username" or "username:password" else { //TODO: Create a ProtocolProvider singleton if (first == "tel" || first == "sip" || first == "sips" || first == "mailto") { scheme = first; userName = second; } else { userName = first; password = second; } } } // only username else userName = first; reader.Consume(); // eat delimiter. domain = reader.ReadToEnd(":;"); if (reader.Current == '\r' || userName == null) return null; // domain was not specified. // We got a port. if (reader.Current == ':') { reader.Consume(); string portStr = reader.ReadToEnd(';'); if (portStr != null) { if (!int.TryParse(portStr, out port)) return null; } } // parse parameters var values = new KeyValueCollection(); if (reader.Current == ';') ParseParameters(values, reader); return new SipUri(scheme, userName, password, domain, port, values); }