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->setBuffer("buffer", buffer); notify->post(); } else { ALOGW("received binary data, but no one cares."); } return true; } sp<ARTSPResponse> response = new ARTSPResponse; response->mStatusLine = statusLine; ALOGI("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; } ALOGV("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()); ALOGI("re-sending request with authentication headers..."); onSendRequest(msg); return true; } } return isRequest ? handleServerRequest(response) : notifyResponseListener(response); }
void WebSocketAdapter::onSocketRecv(const MutableBuffer& buffer, const net::Address& peerAddress) { TraceLS(this) << "On recv: " << buffer.size() << endl; // << ": " << buffer //assert(buffer.position() == 0); if (framer.handshakeComplete()) { // Note: The spec wants us to buffer partial frames, but our // software does not require this feature, and furthermore // it goes against our nocopy where possible policy. // This may need to change in the future, but for now // we just parse and emit packets as they arrive. // // Incoming frames may be joined, so we parse them // in a loop until the read buffer is empty. BitReader reader(buffer); int total = reader.available(); int offset = reader.position(); while (offset < total) { char* payload = nullptr; UInt64 payloadLength = 0; try { // Restore buffer state for next read //reader.position(offset); //reader.limit(total); #if 0 TraceLS(this) << "Read frame at: " << "\n\tinputPosition: " << offset << "\n\tinputLength: " << total << "\n\tbufferPosition: " << reader.position() << "\n\tbufferAvailable: " << reader.available() << "\n\tbufferLimit: " << reader.limit() << "\n\tbuffer: " << std::string(reader.current(), reader.limit()) << endl; #endif // Parse a frame to throw //int payloadLength = framer.readFrame(reader); payloadLength = framer.readFrame(reader, payload); assert(payload); // Update the next frame offset offset = reader.position(); // + payloadLength; if (offset < total) DebugLS(this) << "Splitting joined packet at " << offset << " of " << total << endl; // Drop empty packets if (!payloadLength) { DebugLS(this) << "Dropping empty frame" << endl; continue; } } catch (std::exception& exc) { WarnL << "Parser error: " << exc.what() << endl; socket->setError(exc.what()); return; } // Emit the result packet assert(payload); assert(payloadLength); SocketAdapter::onSocketRecv(mutableBuffer(payload, (std::size_t)payloadLength), peerAddress); } assert(offset == total); } else { try { if (framer.mode() == ws::ClientSide) handleClientResponse(buffer); else handleServerRequest(buffer); } catch (std::exception& exc) { WarnL << "Read error: " << exc.what() << endl; socket->setError(exc.what()); } return; } }