void ARTSPConnection::onSendRequest(const sp<AMessage> &msg) { sp<AMessage> reply; CHECK(msg->findMessage("reply", &reply)); if (mState != CONNECTED) { reply->setInt32("result", -ENOTCONN); reply->post(); return; } AString request; CHECK(msg->findString("request", &request)); // Just in case we need to re-issue the request with proper authentication // later, stash it away. reply->setString("original-request", request.c_str(), request.size()); addAuthentication(&request); addUserAgent(&request); // Find the boundary between headers and the body. ssize_t i = request.find("\r\n\r\n"); CHECK_GE(i, 0); int32_t cseq = mNextCSeq++; AString cseqHeader = "CSeq: "; cseqHeader.append(cseq); cseqHeader.append("\r\n"); request.insert(cseqHeader, i + 2); LOGV("request: '%s'", request.c_str()); size_t numBytesSent = 0; while (numBytesSent < request.size()) { ssize_t n = send(mSocket, request.c_str() + numBytesSent, request.size() - numBytesSent, 0); if (n < 0 && errno == EINTR) { continue; } if (n <= 0) { performDisconnect(); if (n == 0) { // Server closed the connection. LOGE("Server unexpectedly closed the connection."); reply->setInt32("result", ERROR_IO); reply->post(); } else { LOGE("Error sending rtsp request. (%s)", strerror(errno)); reply->setInt32("result", -errno); reply->post(); } return; } numBytesSent += (size_t)n; } mPendingRequests.add(cseq, reply); }
bool ARTSPConnection::receiveRTSPReponse() { AString statusLine; if (!receiveLine(&statusLine)) { return false; } if (statusLine == "$") { sp<ABuffer> buffer = receiveBinaryData(); if (buffer == NULL) { return false; } if (mObserveBinaryMessage != NULL) { sp<AMessage> notify = mObserveBinaryMessage->dup(); notify->setObject("buffer", buffer); notify->post(); } else { LOGW("received binary data, but no one cares."); } return true; } sp<ARTSPResponse> response = new ARTSPResponse; response->mStatusLine = statusLine; LOGI("status: %s", response->mStatusLine.c_str()); ssize_t space1 = response->mStatusLine.find(" "); if (space1 < 0) { return false; } ssize_t space2 = response->mStatusLine.find(" ", space1 + 1); if (space2 < 0) { return false; } bool isRequest = false; if (!IsRTSPVersion(AString(response->mStatusLine, 0, space1))) { CHECK(IsRTSPVersion( AString( response->mStatusLine, space2 + 1, response->mStatusLine.size() - space2 - 1))); isRequest = true; response->mStatusCode = 0; } else { AString statusCodeStr( response->mStatusLine, space1 + 1, space2 - space1 - 1); if (!ParseSingleUnsignedLong( statusCodeStr.c_str(), &response->mStatusCode) || response->mStatusCode < 100 || response->mStatusCode > 999) { return false; } } AString line; ssize_t lastDictIndex = -1; for (;;) { if (!receiveLine(&line)) { break; } if (line.empty()) { break; } LOGV("line: '%s'", line.c_str()); if (line.c_str()[0] == ' ' || line.c_str()[0] == '\t') { // Support for folded header values. if (lastDictIndex < 0) { // First line cannot be a continuation of the previous one. return false; } AString &value = response->mHeaders.editValueAt(lastDictIndex); value.append(line); continue; } ssize_t colonPos = line.find(":"); if (colonPos < 0) { // Malformed header line. return false; } AString key(line, 0, colonPos); key.trim(); key.tolower(); line.erase(0, colonPos + 1); lastDictIndex = response->mHeaders.add(key, line); } for (size_t i = 0; i < response->mHeaders.size(); ++i) { response->mHeaders.editValueAt(i).trim(); } unsigned long contentLength = 0; ssize_t i = response->mHeaders.indexOfKey("content-length"); if (i >= 0) { AString value = response->mHeaders.valueAt(i); if (!ParseSingleUnsignedLong(value.c_str(), &contentLength)) { return false; } } if (contentLength > 0) { response->mContent = new ABuffer(contentLength); if (receive(response->mContent->data(), contentLength) != OK) { return false; } } if (response->mStatusCode == 401) { if (mAuthType == NONE && mUser.size() > 0 && parseAuthMethod(response)) { ssize_t i; CHECK_EQ((status_t)OK, findPendingRequest(response, &i)); CHECK_GE(i, 0); sp<AMessage> reply = mPendingRequests.valueAt(i); mPendingRequests.removeItemsAt(i); AString request; CHECK(reply->findString("original-request", &request)); sp<AMessage> msg = new AMessage(kWhatSendRequest, id()); msg->setMessage("reply", reply); msg->setString("request", request.c_str(), request.size()); LOGI("re-sending request with authentication headers..."); onSendRequest(msg); return true; } } return isRequest ? handleServerRequest(response) : notifyResponseListener(response); }
virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override { LOGD("Error while connecting HTTP: %d (%s)", a_ErrorCode, a_ErrorMsg.c_str()); m_Event.Set(); }
void ARTSPConnection::onConnect(const sp<AMessage> &msg) { ++mConnectionID; if (mState != DISCONNECTED) { if (mUIDValid) { HTTPBase::UnRegisterSocketUserTag(mSocket); } close(mSocket); mSocket = -1; flushPendingRequests(); } mState = CONNECTING; AString url; CHECK(msg->findString("url", &url)); sp<AMessage> reply; CHECK(msg->findMessage("reply", &reply)); AString host, path; unsigned port; if (!ParseURL(url.c_str(), &host, &port, &path, &mUser, &mPass) || (mUser.size() > 0 && mPass.size() == 0)) { // If we have a user name but no password we have to give up // right here, since we currently have no way of asking the user // for this information. LOGE("Malformed rtsp url %s", url.c_str()); reply->setInt32("result", ERROR_MALFORMED); reply->post(); mState = DISCONNECTED; return; } if (mUser.size() > 0) { LOGV("user = '******', pass = '******'", mUser.c_str(), mPass.c_str()); } struct hostent *ent = gethostbyname(host.c_str()); if (ent == NULL) { LOGE("Unknown host %s", host.c_str()); reply->setInt32("result", -ENOENT); reply->post(); mState = DISCONNECTED; return; } mSocket = socket(AF_INET, SOCK_STREAM, 0); if (mUIDValid) { HTTPBase::RegisterSocketUserTag(mSocket, mUID, (uint32_t)*(uint32_t*) "RTSP"); } MakeSocketBlocking(mSocket, false); union { struct sockaddr_in remote; struct sockaddr remote_generic; }; memset(remote.sin_zero, 0, sizeof(remote.sin_zero)); remote.sin_family = AF_INET; remote.sin_addr.s_addr = *(in_addr_t *)ent->h_addr; remote.sin_port = htons(port); int err = ::connect( mSocket, &remote_generic, sizeof(remote)); reply->setInt32("server-ip", ntohl(remote.sin_addr.s_addr)); if (err < 0) { if (errno == EINPROGRESS) { sp<AMessage> msg = new AMessage(kWhatCompleteConnection, id()); msg->setMessage("reply", reply); msg->setInt32("connection-id", mConnectionID); msg->post(); return; } reply->setInt32("result", -errno); mState = DISCONNECTED; if (mUIDValid) { HTTPBase::UnRegisterSocketUserTag(mSocket); } close(mSocket); mSocket = -1; } else { reply->setInt32("result", OK); mState = CONNECTED; mNextCSeq = 1; postReceiveReponseEvent(); } reply->post(); }
bool ASessionDescription::getDurationUs(int64_t *durationUs) const { *durationUs = 0; CHECK(mIsValid); AString value; if (!findAttribute(0, "a=range", &value)) { return false; } #ifndef ANDROID_DEFAULT_CODE if (strncmp(value.c_str(), "npt=", 4) && strncmp(value.c_str(), "npt:", 4)) { #else if (strncmp(value.c_str(), "npt=", 4)) { #endif // #ifndef ANDROID_DEFAULT_CODE return false; } float from, to; if (!parseNTPRange(value.c_str() + 4, &from, &to)) { return false; } *durationUs = (int64_t)((to - from) * 1E6); return true; } // static void ASessionDescription::ParseFormatDesc( const char *desc, int32_t *timescale, int32_t *numChannels) { const char *slash1 = strchr(desc, '/'); CHECK(slash1 != NULL); const char *s = slash1 + 1; char *end; unsigned long x = strtoul(s, &end, 10); CHECK_GT(end, s); CHECK(*end == '\0' || *end == '/'); *timescale = x; *numChannels = 1; if (*end == '/') { s = end + 1; unsigned long x = strtoul(s, &end, 10); CHECK_GT(end, s); CHECK_EQ(*end, '\0'); *numChannels = x; } } // static bool ASessionDescription::parseNTPRange( const char *s, float *npt1, float *npt2) { if (s[0] == '-') { return false; // no start time available. } if (!strncmp("now", s, 3)) { return false; // no absolute start time available } char *end; *npt1 = strtof(s, &end); if (end == s || *end != '-') { // Failed to parse float or trailing "dash". return false; } s = end + 1; // skip the dash. if (!strncmp("now", s, 3)) { return false; // no absolute end time available } *npt2 = strtof(s, &end); #ifndef ANDROID_DEFAULT_CODE //We support range string as "Range: npt=1.0000-" return true; #else if (end == s || *end != '\0') { return false; } return *npt2 > *npt1; #endif } #ifndef ANDROID_DEFAULT_CODE bool ASessionDescription::getBitrate(size_t index, int32_t* bitrate) const { char key[] = "b=AS"; AString value; if (!findAttribute(index, key, &value)) return false; int32_t b = atoi(value.c_str()); b *= 1000; if (b < 0) return false; *bitrate = b; return true; }
bool ASessionDescription::parse(const void *data, size_t size) { mTracks.clear(); mFormats.clear(); mTracks.push(Attribs()); mFormats.push(AString("[root]")); AString desc((const char *)data, size); #ifndef ANDROID_DEFAULT_CODE int rtpmapNum = 0; bool unsupported = false; #endif // #ifndef ANDROID_DEFAULT_CODE size_t i = 0; for (;;) { #ifndef ANDROID_DEFAULT_CODE if (i >= desc.size()) { break; } #endif // #ifndef ANDROID_DEFAULT_CODE ssize_t eolPos = desc.find("\n", i); if (eolPos < 0) { #ifndef ANDROID_DEFAULT_CODE eolPos = desc.size(); #else break; #endif // #ifndef ANDROID_DEFAULT_CODE } AString line; if ((size_t)eolPos > i && desc.c_str()[eolPos - 1] == '\r') { // We accept both '\n' and '\r\n' line endings, if it's // the latter, strip the '\r' as well. line.setTo(desc, i, eolPos - i - 1); } else { line.setTo(desc, i, eolPos - i); } if (line.empty()) { i = eolPos + 1; continue; } if (line.size() < 2 || line.c_str()[1] != '=') { return false; } #ifndef ANDROID_DEFAULT_CODE if (unsupported && line.c_str()[0] != 'm') { ALOGI("skip %s in unsupported media description", line.c_str()); i = eolPos + 1; continue; } else #endif // #ifndef ANDROID_DEFAULT_CODE ALOGI("%s", line.c_str()); switch (line.c_str()[0]) { case 'v': { if (strcmp(line.c_str(), "v=0")) { return false; } break; } case 'a': case 'b': { AString key, value; ssize_t colonPos = line.find(":", 2); if (colonPos < 0) { key = line; } else { key.setTo(line, 0, colonPos); if (key == "a=fmtp" || key == "a=rtpmap" || key == "a=framesize") { ssize_t spacePos = line.find(" ", colonPos + 1); if (spacePos < 0) { return false; } #ifndef ANDROID_DEFAULT_CODE if (key == "a=rtpmap") { if (rtpmapNum > 0) { mTracks.pop(); mFormats.pop(); unsupported = true; ALOGW("ASessionDescription: multiple rtpmap" " for one media is not supported yet"); break; } else { rtpmapNum++; } } #endif // #ifndef ANDROID_DEFAULT_CODE key.setTo(line, 0, spacePos); colonPos = spacePos; } value.setTo(line, colonPos + 1, line.size() - colonPos - 1); } key.trim(); value.trim(); ALOGV("adding '%s' => '%s'", key.c_str(), value.c_str()); mTracks.editItemAt(mTracks.size() - 1).add(key, value); break; } case 'm': { ALOGV("new section '%s'", AString(line, 2, line.size() - 2).c_str()); #ifndef ANDROID_DEFAULT_CODE rtpmapNum = 0; unsupported = false; #endif // #ifndef ANDROID_DEFAULT_CODE mTracks.push(Attribs()); mFormats.push(AString(line, 2, line.size() - 2)); break; } default: { AString key, value; ssize_t equalPos = line.find("="); key = AString(line, 0, equalPos + 1); value = AString(line, equalPos + 1, line.size() - equalPos - 1); key.trim(); value.trim(); ALOGV("adding '%s' => '%s'", key.c_str(), value.c_str()); mTracks.editItemAt(mTracks.size() - 1).add(key, value); break; } } i = eolPos + 1; } return true; }
bool ASessionDescription::getDimensions( size_t index, unsigned long PT, int32_t *width, int32_t *height) const { *width = 0; *height = 0; char key[20]; sprintf(key, "a=framesize:%lu", PT); AString value; if (!findAttribute(index, key, &value)) { #ifndef ANDROID_DEFAULT_CODE // try to get dimensions from cliprect if no framesize strcpy(key, "a=cliprect"); if (!findAttribute(index, key, &value)) { ALOGW("no framesize and cliprect, try Width/Height"); strcpy(key, "a=Width"); if (!findAttribute(index, key, &value)) { return false; } int w = parseString(value.c_str()); strcpy(key, "a=Height"); if (!findAttribute(index, key, &value)) { return false; } int h = parseString(value.c_str()); if (w > 0 && h > 0) { *width = w; *height = h; return true; } return false; } const char *s = value.c_str(); int a = -1, b = -1, c = -1, d = -1; sscanf(s, "%d,%d,%d,%d", &a, &b, &c, &d); if (a == -1 || b == -1 || c == -1 || d == -1) return false; *height = c - a; *width = d - b; return true; #else return false; #endif // #ifndef ANDROID_DEFAULT_CODE } const char *s = value.c_str(); char *end; *width = strtoul(s, &end, 10); CHECK_GT(end, s); CHECK_EQ(*end, '-'); s = end + 1; *height = strtoul(s, &end, 10); CHECK_GT(end, s); CHECK_EQ(*end, '\0'); return true; }
// StoreVariableToVariable //------------------------------------------------------------------------------ bool BFFParser::StoreVariableToVariable( const AString & dstName, BFFIterator & varNameSrcStart, const BFFIterator & operatorIter, BFFStackFrame * dstFrame ) { AStackString< MAX_VARIABLE_NAME_LENGTH > srcName; bool srcParentScope = false; if ( ParseVariableName( varNameSrcStart, srcName, srcParentScope ) == false ) { return false; } // find src var const BFFVariable * varSrc = nullptr; BFFStackFrame * const srcFrame = ( srcParentScope ) ? BFFStackFrame::GetParentDeclaration( srcName, nullptr, varSrc ) : nullptr; if ( !srcParentScope ) { varSrc = BFFStackFrame::GetVar( srcName, nullptr ); } if ( ( srcParentScope && nullptr == srcFrame ) || ( nullptr == varSrc ) ) { Error::Error_1009_UnknownVariable( varNameSrcStart, nullptr ); return false; } // find dst var const BFFVariable * varDst = BFFStackFrame::GetVar( dstName, dstFrame ); const bool concat = ( *operatorIter == BFF_VARIABLE_CONCATENATION ); // concatenation? if ( concat ) { // can only concatenate to existing vars if ( varDst == nullptr ) { Error::Error_1026_VariableNotFoundForConcatenation( operatorIter, dstName ); return false; } } // if dst exists, types must match BFFVariable::VarType srcType = varSrc->GetType(); BFFVariable::VarType dstType = BFFVariable::VAR_ANY; if ( varDst ) { dstType = varDst->GetType(); } else { ASSERT( concat == false ); dstType = srcType; } // handle supported types if ( srcType != dstType ) { // Mismatched - is there a supported conversion? // String to ArrayOfStrings if ( ( dstType == BFFVariable::VAR_ARRAY_OF_STRINGS ) && ( srcType == BFFVariable::VAR_STRING ) ) { uint32_t num = (uint32_t)( 1 + ( concat ? varDst->GetArrayOfStrings().GetSize() : 0 ) ); Array< AString > values( num, false ); if ( concat ) { values.Append( varDst->GetArrayOfStrings() ); } values.Append( varSrc->GetString() ); BFFStackFrame::SetVarArrayOfStrings( dstName, values, dstFrame ); FLOG_INFO( "Registered <ArrayOfStrings> variable '%s' with %u elements", dstName.Get(), num ); return true; } // Struct to ArrayOfStructs if ( ( dstType == BFFVariable::VAR_ARRAY_OF_STRUCTS ) && ( srcType == BFFVariable::VAR_STRUCT ) ) { uint32_t num = (uint32_t)( 1 + ( concat ? varDst->GetArrayOfStructs().GetSize() : 0 ) ); Array< const BFFVariable * > values( num, false ); if ( concat ) { values.Append( varDst->GetArrayOfStructs() ); } values.Append( varSrc ); BFFStackFrame::SetVarArrayOfStructs( dstName, values, dstFrame ); FLOG_INFO( "Registered <ArrayOfStructs> variable '%s' with %u elements", dstName.Get(), num ); return true; } } else { // Matching Src and Dst if ( srcType == BFFVariable::VAR_STRING ) { AStackString< 2048 > finalValue; if ( concat ) { finalValue = varDst->GetString(); } finalValue += varSrc->GetString(); BFFStackFrame::SetVarString( dstName, finalValue, dstFrame ); FLOG_INFO( "Registered <string> variable '%s' with value '%s'", dstName.Get(), finalValue.Get() ); return true; } if ( srcType == BFFVariable::VAR_ARRAY_OF_STRINGS ) { if ( concat ) { const unsigned int num = (unsigned int)( varSrc->GetArrayOfStrings().GetSize() + varDst->GetArrayOfStrings().GetSize() ); Array< AString > values( num, false ); values.Append( varDst->GetArrayOfStrings() ); values.Append( varSrc->GetArrayOfStrings() ); BFFStackFrame::SetVarArrayOfStrings( dstName, values, dstFrame ); FLOG_INFO( "Registered <ArrayOfStrings> variable '%s' with %u elements", dstName.Get(), num ); } else { BFFStackFrame::SetVarArrayOfStrings( dstName, varSrc->GetArrayOfStrings(), dstFrame ); FLOG_INFO( "Registered <ArrayOfStrings> variable '%s' with %u elements", dstName.Get(), (unsigned int)varSrc->GetArrayOfStrings().GetSize() ); } return true; } if ( srcType == BFFVariable::VAR_ARRAY_OF_STRUCTS ) { if ( concat ) { const unsigned int num = (unsigned int)( varSrc->GetArrayOfStructs().GetSize() + varDst->GetArrayOfStructs().GetSize() ); Array< const BFFVariable * > values( num, false ); values.Append( varDst->GetArrayOfStructs() ); values.Append( varSrc->GetArrayOfStructs() ); BFFStackFrame::SetVarArrayOfStructs( dstName, values, dstFrame ); FLOG_INFO( "Registered <ArrayOfStructs> variable '%s' with %u elements", dstName.Get(), num ); } else { BFFStackFrame::SetVarArrayOfStructs( dstName, varSrc->GetArrayOfStructs(), dstFrame ); FLOG_INFO( "Registered <ArrayOfStructs> variable '%s' with %u elements", dstName.Get(), (unsigned int)varSrc->GetArrayOfStructs().GetSize() ); } return true; } if ( srcType == BFFVariable::VAR_INT ) { int newVal( varSrc->GetInt() ); if ( concat ) { newVal += varDst->GetInt(); } return StoreVariableInt( dstName, newVal, dstFrame ); } if ( srcType == BFFVariable::VAR_BOOL ) { // only assignment is supported if ( concat == false ) { return StoreVariableBool( dstName, varSrc->GetBool(), dstFrame ); } } if ( srcType == BFFVariable::VAR_STRUCT ) { const Array< const BFFVariable * > & srcMembers = varSrc->GetStructMembers(); if ( concat ) { BFFVariable *const newVar = BFFStackFrame::ConcatVars( dstName, varSrc, varDst, dstFrame ); FLOG_INFO( "Registered <struct> variable '%s' with %u members", dstName.Get(), newVar->GetStructMembers().GetSize() ); } else { // Register this variable BFFStackFrame::SetVarStruct( dstName, srcMembers, dstFrame ); FLOG_INFO( "Registered <struct> variable '%s' with %u members", dstName.Get(), srcMembers.GetSize() ); } return true; } } Error::Error_1034_OperationNotSupported( varNameSrcStart, varDst ? varDst->GetType() : varSrc->GetType(), varSrc->GetType(), operatorIter ); return false; }
// StoreVariableArray //------------------------------------------------------------------------------ bool BFFParser::StoreVariableArray( const AString & name, const BFFIterator & valueStart, const BFFIterator & valueEnd, const BFFIterator & operatorIter, BFFStackFrame * frame ) { Array< AString > values( 32, true ); Array< const BFFVariable * > structValues( 32, true ); // are we concatenating? if ( *operatorIter == BFF_VARIABLE_CONCATENATION ) { // find existing const BFFVariable * var = BFFStackFrame::GetVar( name, frame ); if ( var == nullptr ) { Error::Error_1026_VariableNotFoundForConcatenation( operatorIter, name ); return false; } // make sure existing is an array if ( var->IsArrayOfStrings() ) { // get values to start with values = var->GetArrayOfStrings(); } else if ( var->IsArrayOfStructs() ) { // get values to start with structValues = var->GetArrayOfStructs(); } else { // TODO:B Improve this error to handle ArrayOfStructs case Error::Error_1027_CannotConcatenate( operatorIter, name, var->GetType(), BFFVariable::VAR_ARRAY_OF_STRINGS ); return false; } } // Parse array of variables BFFIterator iter( valueStart ); for (;;) { iter.SkipWhiteSpaceAndComments(); // end? if ( iter.GetCurrent() == valueEnd.GetCurrent() ) { break; } const char c = *iter; if ( ( c == '"' ) || ( c == '\'' ) ) { // a quoted string // detect mistmatches if ( structValues.IsEmpty() == false ) { // Mixed types in vector Error::Error_1034_OperationNotSupported( iter, BFFVariable::VAR_ARRAY_OF_STRUCTS, BFFVariable::VAR_STRING, operatorIter ); return false; } // a string BFFIterator elementValueStart( iter ); iter.SkipString( c ); ASSERT( iter.GetCurrent() <= valueEnd.GetCurrent() ); // should not be in this function if string is not terminated elementValueStart++; // move to start of actual content AStackString< 2048 > elementValue; // unescape and subsitute embedded variables if ( PerformVariableSubstitutions( elementValueStart, iter, elementValue ) == false ) { return false; } values.Append( elementValue ); iter++; // pass closing quote } else if ( c == BFF_DECLARE_VAR_INTERNAL || c == BFF_DECLARE_VAR_PARENT ) { const BFFIterator elementStartValue = iter; // a variable AStackString< MAX_VARIABLE_NAME_LENGTH > varName; bool parentScope = false; // ignored, the behavior is the same if ( ParseVariableName( iter, varName, parentScope ) == false ) { return false; } // get the variable const BFFVariable * var = BFFStackFrame::GetVar( varName, frame ); if ( var == nullptr ) { Error::Error_1026_VariableNotFoundForConcatenation( operatorIter, varName ); return false; } if ( var->IsString() || var->IsArrayOfStrings() ) { // dest is consistent? if ( structValues.IsEmpty() == false ) { // inconsistency Error::Error_1034_OperationNotSupported( elementStartValue, BFFVariable::VAR_ARRAY_OF_STRUCTS, var->GetType(), operatorIter ); return false; } if ( var->IsString() ) { values.Append( var->GetString() ); } else { values.Append( var->GetArrayOfStrings() ); } } else if ( var->IsStruct() || var->IsArrayOfStructs() ) { // dest is consistent? if ( values.IsEmpty() == false ) { // inconsistency Error::Error_1034_OperationNotSupported( elementStartValue, BFFVariable::VAR_ARRAY_OF_STRINGS, var->GetType(), operatorIter ); return false; } if ( var->IsStruct() ) { structValues.Append( var ); } else { structValues.Append( var->GetArrayOfStructs() ); } } else { Error::Error_1050_PropertyMustBeOfType( iter, nullptr, name.Get(), var->GetType(), BFFVariable::VAR_STRING, BFFVariable::VAR_STRUCT ); return false; } } else { Error::Error_1001_MissingStringStartToken( iter, nullptr ); return false; } iter.SkipWhiteSpaceAndComments(); if ( *iter == ',' ) // comma seperators are optional { iter++; } // continue looking for more vars... } // should only have one populated array ASSERT( values.IsEmpty() || structValues.IsEmpty() ); // Register this variable if ( structValues.IsEmpty() == false ) { // structs BFFStackFrame::SetVarArrayOfStructs( name, structValues, frame ); FLOG_INFO( "Registered <ArrayOfStructs> variable '%s' with %u elements", name.Get(), structValues.GetSize() ); } else { // strings (or unknown, so default to strings) BFFStackFrame::SetVarArrayOfStrings( name, values, frame ); FLOG_INFO( "Registered <ArrayOfStrings> variable '%s' with %u elements", name.Get(), values.GetSize() ); } return true; }
int cProtocol132::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata) { // Uncompress the GZIPped data: AString Uncompressed; if (UncompressStringGZIP(a_Metadata.data(), a_Metadata.size(), Uncompressed) != Z_OK) { AString HexDump; CreateHexDump(HexDump, a_Metadata.data(), a_Metadata.size(), 16); LOG("Cannot unGZIP item metadata:\n%s", HexDump.c_str()); return PARSE_ERROR; } // Parse into NBT: cParsedNBT NBT(Uncompressed.data(), Uncompressed.size()); if (!NBT.IsValid()) { AString HexDump; CreateHexDump(HexDump, Uncompressed.data(), Uncompressed.size(), 16); LOG("Cannot parse NBT item metadata:\n%s", HexDump.c_str()); return PARSE_ERROR; } // Load enchantments from the NBT: for (int tag = NBT.GetFirstChild(NBT.GetRoot()); tag >= 0; tag = NBT.GetNextSibling(tag)) { if ( (NBT.GetType(tag) == TAG_List) && ( (NBT.GetName(tag) == "ench") || (NBT.GetName(tag) == "StoredEnchantments") ) ) { EnchantmentSerializer::ParseFromNBT(a_Item.m_Enchantments, NBT, tag); } } return PARSE_OK; }
bool ARTSPConnection::receiveRTSPRequest() { AString requestLine; LOGI(LOG_TAG,"start receiveLine ......\n"); if (!receiveLine(&requestLine)) { return false; } // LOGI(LOG_TAG,"receiveLine OK\n"); sp<AMessage> request = new AMessage(kWhatRequest,mhandlerID); request->setInt32("SessionID",mSessionID); LOGI(LOG_TAG,"request->setInt32 SessionID %d\n",mSessionID); LOGI(LOG_TAG,"request: %s\n", requestLine.c_str()); ssize_t space1 = requestLine.find(" ");//寻找空格 if (space1 < 0) { return false; } ssize_t space2 = requestLine.find(" ", space1 + 1); if (space2 < 0) { return false; } AString Method(requestLine.c_str(), space1); request->setString("Method",Method.c_str()); AString URI(requestLine,space1+1,space2-space1-1); request->setString("URI",URI.c_str()); AString line; for (;;) { if (!receiveLine(&line)) { break; } if (line.empty()) { break; } ssize_t colonPos = line.find(":"); if (colonPos < 0) { // Malformed header line. return false; } AString key(line, 0, colonPos); key.trim(); // key.tolower(); line.erase(0, colonPos + 1); line.trim(); LOGI(LOG_TAG,"line: %s:%s\n", key.c_str(),line.c_str()); request->setString(key.c_str(),line.c_str()); } LOGI(LOG_TAG,"Post the request to handler\n"); request->post();//将请求消息发送给uplayer 处理 return OK; }