CJsonNode CReadJsonFromSocket::ReadMessage(CSocket& sock) { try { char read_buffer[READ_BUFFER_SIZE]; size_t bytes_read; do { s_ReadSocket(sock, read_buffer, READ_BUFFER_SIZE, &bytes_read); m_UTTPReader.SetNewBuffer(read_buffer, bytes_read); } while (!m_JSONReader.ReadMessage(m_UTTPReader)); } catch (...) { sock.Close(); throw; } if (m_UTTPReader.GetNextEvent() != CUTTPReader::eEndOfBuffer) { string server_address(sock.GetPeerAddress()); sock.Close(); NCBI_THROW_FMT(CNetStorageException, eIOError, "Extra bytes past message end while reading from " << server_address << " after receiving " << m_JSONReader.GetMessage().Repr() << '.'); } return m_JSONReader.GetMessage(); }
static void s_ReadSocket(CSocket& sock, void* buffer, size_t buffer_size, size_t* bytes_read) { EIO_Status status; while ((status = sock.Read(buffer, buffer_size, bytes_read)) == eIO_Interrupt) /* no-op */; if (status != eIO_Success) { // eIO_Timeout, eIO_Closed, eIO_InvalidArg, // eIO_NotSupported, eIO_Unknown NCBI_THROW_FMT(CNetStorageException, eIOError, "I/O error while reading from NetStorage server " << sock.GetPeerAddress() << ". " "Socket status: " << IO_StatusStr(status) << '.'); } }
static void s_WriteToSocket(CSocket& sock, const char* output_buffer, size_t output_buffer_size) { size_t bytes_written; while (output_buffer_size > 0) { EIO_Status status = sock.Write(output_buffer, output_buffer_size, &bytes_written); if (status != eIO_Success) { // Error writing to the socket. // Log what we can. string message_start; if (output_buffer_size > 32) { CTempString buffer_head(output_buffer, 32); message_start = NStr::PrintableString(buffer_head); message_start += " (TRUNCATED)"; } else { CTempString buffer_head(output_buffer, output_buffer_size); message_start = NStr::PrintableString(buffer_head); } NCBI_THROW_FMT(CNetStorageException, eIOError, "Error writing message to the NetStorage server " << sock.GetPeerAddress() << ". " "Socket write error status: " << IO_StatusStr(status) << ". " "Bytes written: " << NStr::NumericToString(bytes_written) << ". " "Message begins with: " << message_start); } output_buffer += bytes_written; output_buffer_size -= bytes_written; } }
static void s_TrapErrors(const CJsonNode& request, const CJsonNode& reply, CSocket& sock, SNetStorage::SConfig::EErrMode err_mode) { const string server_address(sock.GetPeerAddress()); CJsonNode issues(reply.GetByKeyOrNull("Warnings")); if (issues) { for (CJsonIterator it = issues.Iterate(); it; ++it) { const SIssue issue(*it); LOG_POST(Warning << "NetStorage server " << server_address << " issued warning " << issue); } } const string status = reply.GetString("Status"); const bool status_ok = status == "OK"; issues = reply.GetByKeyOrNull("Errors"); // Got errors if (!status_ok || issues) { if (status_ok && err_mode != SNetStorage::SConfig::eThrow) { if (err_mode == SNetStorage::SConfig::eLog) { for (CJsonIterator it = issues.Iterate(); it; ++it) { const SIssue issue(*it); LOG_POST(Error << "NetStorage server " << server_address << " issued error " << issue); } } } else { Int8 code = CNetStorageServerError::eUnknownError; Int8 sub_code = SIssue::kEmptySubCode; ostringstream errors; if (!issues) errors << status; else { const char* prefix = "error "; for (CJsonIterator it = issues.Iterate(); it; ++it) { const SIssue issue(*it); code = issue.code; sub_code = issue.sub_code; errors << prefix << issue; prefix = ", error "; } } string err_msg = FORMAT("Error while executing " << request.GetString("Type") << " " "on NetStorage server " << sock.GetPeerAddress() << ". " "Server returned " << errors.str()); s_ThrowError(code, sub_code, err_msg); } } if (reply.GetInteger("RE") != request.GetInteger("SN")) { NCBI_THROW_FMT(CNetStorageException, eServerError, "Message serial number mismatch " "(NetStorage server: " << sock.GetPeerAddress() << "; " "request: " << request.Repr() << "; " "reply: " << reply.Repr() << ")."); } }