bool String::StartsWith(const String& string) const { for (std::size_t i = 0; i < string.Length(); ++i) { if (this->CharAt(i) != string.CharAt(i)) { return false; } } return true; }
/// Fetches target section in string using given start and end-tokens. Returns the first occurance, if any, or an empty string if none such exist. String GetSection(String inString, char withStartToken, char andEndToken){ int startIndex = -1, endIndex = -1; for (int i = 0; i < inString.Length(); ++i){ char c = inString.CharAt(i); if (c == withStartToken) startIndex = i+1; if (c == andEndToken) endIndex = i; if (startIndex >= 0 && endIndex >= 0) break; } if (startIndex < 0 && endIndex < 0) return String(); String newString; for (int i = startIndex; i < endIndex; ++i){ newString.Add(inString.CharAt(i)); } std::cout<<"newString: "<<newString<<" length: "<<newString.Length(); return newString; }
bool String::EndsWith(const String& string) const { for (std::size_t i = 1; i <= string.Length(); ++i) { if (this->CharAt(this->Length() - i) != string.CharAt(string.Length() - i)) { return false; } } return true; }
// Fetches type-integer from the header-data. See above for RFC details. void SIPPacket::ParseHeader(){ // std::cout << "SIPPacket::ParseHeader called."; String line; List<String> tokens; sipType = SIP_NULL; // Evaluate basic type of the packet, first need to get the first valid line... String firstLine; int firstLineIndex; for (int i = 0; i < header.Size(); ++i){ firstLine = header[i]; if (firstLine.Length()){ firstLineIndex = i; break; } } // Determine type from first line for (int i = 0; i < SIP_PACKET_TYPES; ++i){ String typeName = PacketTypeName(i); if (firstLine.Contains(typeName)){ sipType = i; break; } } // Try and see if it's a numerical response-code we don't know? if (sipType == SIP_NULL){ // Split using white-space, get first element, try and parse numberrr! String firstPart = firstLine.Tokenize(" \t\n\r")[0]; int number = firstPart.ParseInt(); if (number >= 700) sipType = SIP_NULL; else if (number >= 600) sipType = SIP_GLOBAL_FAILURE; else if (number >= 500) sipType = SIP_SERVER_INTERNAL_ERROR; else if (number >= 400) sipType = SIP_BAD_REQUEST; else if (number >= 300) sipType = SIP_REDIRECTION; else if (number >= 200) sipType = SIP_OK; // Should not even get here, but eh.. else if (number >= 100) sipType = SIP_PROVISIONAL; } // If still bad type, don't parse anymore? :| if (sipType == SIP_NULL){ // std::cout <<"Type of packet could not be determined in SIPPacket::ParseHeader, firstline: "<<firstLine; return; } // Evaluate the rest of the lines for (int i = firstLineIndex+1; i < header.Size(); ++i){ line = header[i]; // Split using all white-space characters and the colon for header-fields! // First find where attribute name and value start/end (the first colon) String attributeName = String(); String attributeValue = String(); // Remove only up to the first colon? int firstColonIndex = -1; for(int i = 0; i < line.Length(); ++i){ if (line.CharAt(i) == ':'){ firstColonIndex = i; break; } } attributeName = line.Part(0, firstColonIndex); attributeValue = line.Part(firstColonIndex+1); attributeName.RemoveInitialWhitespaces(); attributeValue.RemoveInitialWhitespaces(); // Macro for the comparison, getting tired of this... // First macro checks if they are lexicographically the same (i.e. identical), except not case sensitive #define IsAttributeName(a) (attributeName == a) // And the second macros does the same but compares if it is either the same to a OR b, inclusive. #define IsAttributeName2(a,b) (IsAttributeName(a) || IsAttributeName(b)) // Set comparison mode to not case sensitive. attributeName.SetComparisonMode(String::NOT_CASE_SENSITIVE); // Apparently all fields can have compact forms too, so spam all the comparisons.. if (IsAttributeName2("Call-ID","i")){ callID = attributeValue; } else if (IsAttributeName2("Content-Length","l")){ String s = attributeValue; contentLength = s.ParseInt(); } else if (IsAttributeName2("Content-Type","c")){ contentType = attributeValue; } else if (IsAttributeName("CSeq")){ cSeq = attributeValue; } else if (IsAttributeName("Expires")){ String s = attributeValue; expirationTime = s.ParseInt(); } else if (IsAttributeName2("From","f")){ senderData = attributeValue; } else if (IsAttributeName("Require")){ // Although an optional header field, the Require MUST NOT be // ignored if it is present. assert(false && "Not implemented, sorry. ):"); } else if (IsAttributeName2("To","t")){ recipientData = attributeValue; } else if (IsAttributeName("Warning")){ String warning = attributeValue; // std::cout<<"Warning attribute found on packet: "<<attributeValue; } else if (IsAttributeName("Script")){ event = attributeValue; } else { // std::cout << "Could not find anything relevant in line: "<<line; } } if (type == SIP_REGISTER && !cSeq.Length()){ std::cout << "WARNING: Lacking CSeq in Register message!"; } // Set default packet type? if (type == SIP_NULL) std::cout <<"WARNING: Packet of type SIP_NULL. Either the packet lacks a proper header or this function (SIPPacket::ParseHeader) requires expansion."; }