void VolumeManager::OnLineRead(int aFd, nsDependentCSubstring& aMessage) { MOZ_ASSERT(aFd == mSocket.get()); char* endPtr; int responseCode = strtol(aMessage.Data(), &endPtr, 10); if (*endPtr == ' ') { endPtr++; } // Now fish out the rest of the line after the response code nsDependentCString responseLine(endPtr, aMessage.Length() - (endPtr - aMessage.Data())); DBG("Rcvd: %d '%s'", responseCode, responseLine.Data()); if (responseCode >= ::ResponseCode::UnsolicitedInformational) { // These are unsolicited broadcasts. We intercept these and process // them ourselves HandleBroadcast(responseCode, responseLine); } else { // Everything else is considered to be part of the command response. if (mCommands.size() > 0) { VolumeCommand* cmd = mCommands.front(); cmd->HandleResponse(responseCode, responseLine); if (responseCode >= ::ResponseCode::CommandOkay) { // That's a terminating response. We can remove the command. mCommands.pop(); mCommandPending = false; // Start the next command, if there is one. WriteCommandData(); } } else { ERR("Response with no command"); } } }
const char* HttpResponse::parseResponse(const char* buffer, size_t size) { const char* curPos = buffer; const char* endline = (const char*)memmem(curPos, size - (curPos - buffer), "\r\n", 2); if (endline == 0) throw ParseError("HTTP response doesn't end with \\r\\n"); string responseLine(curPos, endline - curPos); size_t posFirstSpace = responseLine.find(" "); size_t posSecondSpace = responseLine.find(" ", posFirstSpace + 1); if (posFirstSpace == string::npos || posSecondSpace == string::npos) throw ParseError("Incorrectly formatted response"); // 1. HTTP version if (responseLine.compare(0, 5, "HTTP/") != 0) throw ParseError("Incorrectly formatted HTTP response"); string version = responseLine.substr(5, posFirstSpace - 5); // TRACE(version); setVersion(version); // 2. Response code string code = responseLine.substr(posFirstSpace + 1, posSecondSpace - posFirstSpace - 1); // TRACE(code); setStatusCode(code); string msg = responseLine.substr(posSecondSpace + 1, responseLine.size() - posSecondSpace - 1); // TRACE(msg); setStatusMsg(msg); curPos = endline + 2; return parseHeaders(curPos, size - (curPos - buffer)); }
void VolumeManager::OnFileCanReadWithoutBlocking(int aFd) { MOZ_ASSERT(aFd == mSocket.get()); while (true) { ssize_t bytesRemaining = read(aFd, &mRcvBuf[mRcvIdx], sizeof(mRcvBuf) - mRcvIdx); if (bytesRemaining < 0) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { return; } if (errno == EINTR) { continue; } ERR("Unknown read error: %d (%s) - restarting", errno, strerror(errno)); Restart(); return; } if (bytesRemaining == 0) { // This means that vold probably crashed ERR("Vold appears to have crashed - restarting"); Restart(); return; } // We got some data. Each line is terminated by a null character DBG("Read %ld bytes", bytesRemaining); while (bytesRemaining > 0) { bytesRemaining--; if (mRcvBuf[mRcvIdx] == '\0') { // We found a line terminator. Each line is formatted as an // integer response code followed by the rest of the line. // Fish out the response code. char *endPtr; int responseCode = strtol(mRcvBuf, &endPtr, 10); if (*endPtr == ' ') { endPtr++; } // Now fish out the rest of the line after the response code nsDependentCString responseLine(endPtr, &mRcvBuf[mRcvIdx] - endPtr); DBG("Rcvd: %d '%s'", responseCode, responseLine.Data()); if (responseCode >= ResponseCode::UnsolicitedInformational) { // These are unsolicited broadcasts. We intercept these and process // them ourselves HandleBroadcast(responseCode, responseLine); } else { // Everything else is considered to be part of the command response. if (mCommands.size() > 0) { VolumeCommand *cmd = mCommands.front(); cmd->HandleResponse(responseCode, responseLine); if (responseCode >= ResponseCode::CommandOkay) { // That's a terminating response. We can remove the command. mCommands.pop(); mCommandPending = false; // Start the next command, if there is one. WriteCommandData(); } } else { ERR("Response with no command"); } } if (bytesRemaining > 0) { // There is data in the receive buffer beyond the current line. // Shift it down to the beginning. memmove(&mRcvBuf[0], &mRcvBuf[mRcvIdx + 1], bytesRemaining); } mRcvIdx = 0; } else { mRcvIdx++; } } } }