Brn XmlParserBasic::Find(const Brx& aTag, const Brx& aDocument, Brn& aRemaining) { EParserState state = eSearchOpen; TInt ignoreClose = 0; Brn namesp; Brn name; Brn attributes; Brn ns; TUint index; Brn doc(Ascii::Trim(aDocument)); Brn remaining(Ascii::Trim(aDocument)); Brn retStart; ETagType tagType; for (;;) { NextTag(doc, name, attributes, ns, index, remaining, tagType); if (Ascii::CaseInsensitiveEquals(name, aTag)) { if (state == eSearchOpen) { if (tagType == eTagClose) { if (--ignoreClose < 0) THROW(XmlError); } else if (tagType == eTagOpenClose) { return Brn(Brx::Empty()); } namesp.Set(ns); retStart.Set(remaining); state = eSearchClose; } else { // eSearchClose if (tagType == eTagOpen) { ++ignoreClose; } else if (tagType == eTagClose) { if (ignoreClose == 0) { if (namesp != ns) { THROW(XmlError); } aRemaining.Set(remaining); const TUint retBytes = (TUint)(doc.Ptr() - retStart.Ptr()) + index; Brn ret(retStart.Ptr(), retBytes); return ret; } ignoreClose--; } } } if (remaining.Bytes() == 0) { THROW(XmlError); } doc.Set(remaining); } }
void HeaderAcceptLanguage::Process(const Brx& aValue) { SetReceived(); ClearLanguageList(); iLanguages.Set(aValue); std::vector<PrioritisedLanguage> prioritisedList; Parser parser(iLanguages); while (parser.Remaining().Bytes() > 0) { Brn langBuf = parser.Next(','); Parser parser2(langBuf); Brn lang = parser2.Next(';'); parser2.Set(parser2.Remaining()); Brn qualityBuf = parser2.Next('='); if (qualityBuf.Bytes() > 0) { qualityBuf.Set(parser2.Remaining()); } TUint quality = ParseQualityValue(qualityBuf); PrioritisedLanguage prioritisedLang; prioritisedLang.iLanguage = (char*)malloc(lang.Bytes()+1); (void)memcpy(prioritisedLang.iLanguage, lang.Ptr(), lang.Bytes()); prioritisedLang.iLanguage[lang.Bytes()] = '\0'; prioritisedLang.iPriority = quality; AddPrioritisedLanguage(prioritisedList, prioritisedLang); } for (TUint i=0; i<(TUint)prioritisedList.size(); i++) { iLanguageList.push_back(prioritisedList[i].iLanguage); } }
Brn ReaderUntil::ReadProtocol(TUint aBytes) { ASSERT(aBytes <= iMaxBytes); TByte* start = Ptr() + iOffset; TByte* p = start; if (aBytes <= iBytes - iOffset) { iOffset += aBytes; if (iOffset == iBytes) { iBytes = 0; iOffset = 0; } return Brn(start, aBytes); } if (iBytes > 0) { iBytes -= iOffset; start = Ptr(); (void)memmove(start, start + iOffset, iBytes); p = start + iBytes; iOffset = 0; aBytes -= iBytes; } TUint remaining = aBytes; while (remaining > 0) { Brn buf = iReader.Read(remaining); (void)memcpy(p, buf.Ptr(), buf.Bytes()); p += buf.Bytes(); } iBytes = 0; iOffset = 0; return Brn(start, (TUint)(p - start)); }
void DviProtocolUpnp::WriteResource(const Brx& aUriTail, TIpAddress aAdapter, std::vector<char*>& aLanguageList, IResourceWriter& aResourceWriter) { if (aUriTail == kDeviceXmlName) { Brh xml; Brn xmlBuf; AutoMutex _(iLock); const TInt index = FindListenerForInterface(aAdapter); if (index == -1) { return; } if (iDevice.IsRoot()) { const Brx& cachedXml = iAdapters[index]->DeviceXml(); if (cachedXml.Bytes() > 0) { xmlBuf.Set(cachedXml); } } if (xmlBuf.Bytes() == 0) { GetDeviceXml(xml, aAdapter); if (iDevice.IsRoot()) { iAdapters[index]->SetDeviceXml(xml); xmlBuf.Set(iAdapters[index]->DeviceXml()); } else { xmlBuf.Set(xml); } } aResourceWriter.WriteResourceBegin(xmlBuf.Bytes(), kOhNetMimeTypeXml); aResourceWriter.WriteResource(xmlBuf.Ptr(), xmlBuf.Bytes()); aResourceWriter.WriteResourceEnd(); } else { Parser parser(aUriTail); Brn buf = parser.Next('/'); Brn rem = parser.Remaining(); if (buf == DviDevice::kResourceDir) { IResourceManager* resMgr = iDevice.ResourceManager(); if (resMgr != NULL) { resMgr->WriteResource(rem, aAdapter, aLanguageList, aResourceWriter); } } else if (rem == kServiceXmlName) { iLock.Wait(); DviService* service = 0; const TUint count = iDevice.ServiceCount(); for (TUint i=0; i<count; i++) { DviService& s = iDevice.Service(i); if (s.ServiceType().PathUpnp() == buf) { service = &s; break; } } iLock.Signal(); if (service == 0) { THROW(ReaderError); } DviProtocolUpnpServiceXmlWriter::Write(*service, *this, aResourceWriter); } } }
void CpiDeviceUpnp::GetServiceUri(Uri& aUri, const TChar* aType, const ServiceType& aServiceType) { Brn root = XmlParserBasic::Find("root", iXml); Brn device = XmlParserBasic::Find("device", root); Brn udn = XmlParserBasic::Find("UDN", device); if (!CpiDeviceUpnp::UdnMatches(udn, Udn())) { Brn deviceList = XmlParserBasic::Find("deviceList", device); do { Brn remaining; device.Set(XmlParserBasic::Find("device", deviceList, remaining)); udn.Set(XmlParserBasic::Find("UDN", device)); deviceList.Set(remaining); } while (!CpiDeviceUpnp::UdnMatches(udn, Udn())); } Brn serviceList = XmlParserBasic::Find("serviceList", device); Brn service; Brn serviceType; Brn devServiceTypeNoVer; const Brx& targServiceType = aServiceType.FullName(); // Must have backwards compatibility. Need to compare service type and version separately. Parser serviceParser = targServiceType; serviceParser.Next(':'); // urn serviceParser.Next(':'); // schema url serviceParser.Next(':'); // service serviceParser.Next(':'); // name Brn targServiceTypeNoVer(targServiceType.Ptr(), serviceParser.Index()); // full name minus ":x" (where x is version) do { Brn remaining; service.Set(XmlParserBasic::Find("service", serviceList, remaining)); serviceType.Set(XmlParserBasic::Find("serviceType", service)); serviceList.Set(remaining); // Parse service type and version separately. serviceParser.Set(serviceType); serviceParser.Next(':'); // urn serviceParser.Next(':'); // schema url serviceParser.Next(':'); // service serviceParser.Next(':'); // name devServiceTypeNoVer.Set(serviceType.Ptr(), serviceParser.Index()); // full name minus ":x" (where x is version) // MUST allow use of device with version >= target version } while (devServiceTypeNoVer != targServiceTypeNoVer); Brn path = XmlParserBasic::Find(aType, service); if (path.Bytes() == 0) { // no event url => service doesn't have any evented state variables THROW(XmlError); } // now create a uri using the scheme/host/port of the device xml location // plus the path we've just constructed Bws<40> base; // just need space for http://xxx.xxx.xxx.xxx:xxxxx aUri.Replace(iLocation); base.Append(aUri.Scheme()); base.Append("://"); base.Append(aUri.Host()); base.Append(':'); Ascii::AppendDec(base, aUri.Port()); aUri.Replace(base, path); }
TUint CpiDeviceUpnp::Version(const TChar* aDomain, const TChar* aName, TUint /*aProxyVersion*/) const { ServiceType serviceType(iDevice->GetCpStack().Env(), aDomain, aName, 0); const Brx& targServiceType = serviceType.FullName(); // Must have backwards compatibility. Need to compare service type and version separately. Parser serviceParser = targServiceType; serviceParser.Next(':'); // urn serviceParser.Next(':'); // schema url serviceParser.Next(':'); // service serviceParser.Next(':'); // name Brn targServiceTypeNoVer(targServiceType.Ptr(), serviceParser.Index()); // full name minus ":x" (where x is version) try { Brn root = XmlParserBasic::Find("root", iXml); Brn device = XmlParserBasic::Find("device", root); Brn udn = XmlParserBasic::Find("UDN", device); if (!CpiDeviceUpnp::UdnMatches(udn, Udn())) { Brn deviceList = XmlParserBasic::Find("deviceList", device); do { Brn remaining; device.Set(XmlParserBasic::Find("device", deviceList, remaining)); udn.Set(XmlParserBasic::Find("UDN", device)); deviceList.Set(remaining); } while (!CpiDeviceUpnp::UdnMatches(udn, Udn())); } Brn serviceList = XmlParserBasic::Find("serviceList", device); Brn service; Brn serviceType; Brn devServiceTypeNoVer; for (;;) { Brn remaining; service.Set(XmlParserBasic::Find("service", serviceList, remaining)); serviceType.Set(XmlParserBasic::Find("serviceType", service)); serviceList.Set(remaining); // Parse service type and version separately. serviceParser.Set(serviceType); serviceParser.Next(':'); // urn serviceParser.Next(':'); // schema url serviceParser.Next(':'); // service serviceParser.Next(':'); // name devServiceTypeNoVer.Set(serviceType.Ptr(), serviceParser.Index()); // full name minus ":x" (where x is version) if (devServiceTypeNoVer == targServiceTypeNoVer) { Brn devVersionBuf = serviceParser.NextToEnd(); // version try { return Ascii::Uint(devVersionBuf); } catch (AsciiError&) { THROW(XmlError); } } } } catch (XmlError&) { return 0; } }
void ShellSession::Run() { FunctorMsg logger = MakeFunctorMsg(*this, &OpenHome::Net::ShellSession::Log); FunctorMsg oldLogger = Log::SwapOutput(logger); iShutdownSem.Wait(); for (;;) { try { Brn buf = iReadBuffer->ReadUntil('\n'); TUint bytes = buf.Bytes(); if (bytes > 0 && buf[bytes - 1] == '\r') { // strip any trailing LF buf.Set(buf.Ptr(), bytes-1); } Parser parser(buf); Brn command = parser.Next(' '); if (command == kCmdExit) { break; } std::vector<Brn> args; for (;;) { Brn arg = parser.Next(' '); if (arg.Bytes() == 0) { break; } args.push_back(arg); } iCommandHandler.HandleShellCommand(command, args, *iWriterResponse); } catch (ReaderError&) { break; } catch (WriterError&) { break; } catch (Exception& e) { Log::Print("Unexpected exception: %s from %s:%u\n", e.Message(), e.File(), e.Line()); break; } } (void)Log::SwapOutput(oldLogger); iShutdownSem.Signal(); }
void WriterRingBuffer::Write(const Brx& aBuffer) { const Brn tail = Tail(aBuffer, iBytes); // tail.Bytes() <= iBytes const TByte* ptr = tail.Ptr(); const TUint bytes = tail.Bytes(); const TUint bytesToEnd = iBytes - iCursor; if (bytes <= bytesToEnd) { // single write memcpy(&(iData[iCursor]), ptr, bytes); iCursor += bytes; if (iCursor == iBytes) { iCursor = 0; iWrapped = true; } } else { // double write memcpy( &(iData[iCursor]), ptr, bytesToEnd); memcpy( &(iData[0]), ptr + bytesToEnd, bytes - bytesToEnd); iCursor = bytes - bytesToEnd; iWrapped = true; } }
void CpiDeviceLpec::LpecThread() { try { iSocket.Open(iCpStack.Env()); iSocket.Connect(iLocation, iCpStack.Env().InitParams()->TcpConnectTimeoutMs()); TBool starting = true; for (;;) { Brn line = iReadBuffer->ReadUntil(Ascii::kLf); if (line.Bytes() > 0 && line[line.Bytes()-1] == Ascii::kCr) { line.Set(line.Ptr(), line.Bytes()-1); } Parser parser(line); Brn method = parser.Next(' '); if (starting) { if (method != Lpec::kMethodAlive) { LOG2(kLpec, kError, "LPEC: unable to find device "); LOG2(kLpec, kError, iLpecName); LOG2(kLpec, kError, ", exiting thread\n"); if (iStateChanged) { iStateChanged(); } THROW(ReaderError); } Brn name = parser.Next(' '); if (name == iLpecName) { starting = false; Brn udn = parser.Remaining(); iDevice = new CpiDevice(iCpStack, udn, *this, *this, NULL); iConnected = true; if (iStateChanged) { iStateChanged(); } } } if (method == Lpec::kMethodAlive) { LOG(kLpec, "LPEC: Alive - "); LOG(kLpec, parser.Remaining()); LOG(kLpec, "\n"); } else if (method == Lpec::kMethodByeBye) { Brn name = parser.Next(' '); if (name == iLpecName) { iConnected = false; { if (iStateChanged) { iStateChanged(); } } iExiting = true; THROW(ReaderError); } } else if (method == Lpec::kMethodEvent) { HandleEventedUpdate(parser.Remaining()); } else if (iResponseHandler == NULL || !iResponseHandler->HandleLpecResponse(method, parser.Remaining())) { LOG2(kLpec, kError, "Unexpected LPEC message: "); LOG2(kLpec, kError, line); LOG2(kLpec, kError, "\n"); } } } catch (NetworkError&) { LogError("NetworkError"); } catch (NetworkTimeout&) { LogError("NetworkTimeout"); } catch (WriterError&) { LogError("WriterError"); } catch (ReaderError&) { if (!iExiting) { LogError("ReaderError"); } } }
void XmlParserBasic::NextTag(const Brx& aDocument, Brn& aName, Brn& aAttributes, Brn& aNamespace, TUint& aIndex, Brn& aRemaining, ETagType& aType) { aName.Set(Brx::Empty()); aAttributes.Set(Brx::Empty()); aNamespace.Set(Brx::Empty()); aRemaining.Set(Brx::Empty()); Parser parser(aDocument); for (;;) { Brn item = parser.Next('>'); TUint bytes = item.Bytes(); if (bytes > 0 && item[0] != '<') { Parser valueParser(item); Brn value = valueParser.Next('<'); bytes -= value.Bytes(); item.Set(item.Split(value.Bytes(), bytes)); item.Set(Ascii::Trim(item)); bytes = item.Bytes(); } if (bytes < 2 || item[0] != '<') { THROW(XmlError); } aIndex = (TUint)(item.Ptr() - aDocument.Ptr()); if (item[1] == '?') { if (bytes < 3) { // catch special case of <?> THROW(XmlError); } if (item[bytes - 1] == '?') { // processing instruction continue; } THROW(XmlError); } aRemaining.Set(parser.Remaining()); TUint start = 1; // skip opening '<' TUint len = bytes-1; if (item[1] == '/') { aType = eTagClose; start++; len--; } else if (item[bytes-1] == '/') { aType = eTagOpenClose; len--; } else { aType = eTagOpen; } parser.Set(item.Split(start, len)); aName.Set(parser.NextWhiteSpace()); aAttributes.Set(parser.Remaining()); if (Ascii::Contains(aName, ':')) { // collect the namespace parser.Set(aName); aNamespace.Set(parser.Next(':')); if (!aNamespace.Bytes()) { THROW(XmlError); } aName.Set(parser.Remaining()); } else { aNamespace.Set(Brx::Empty()); } if (!aName.Bytes()) { THROW(XmlError); } return; } }