| 117 | } |
| 118 | |
| 119 | IPCSocketClient::ReadStatus |
| 120 | IPCSocketClient::read_all(std::string &content, std::chrono::milliseconds timeout_ms, int attempts) |
| 121 | { |
| 122 | if (this->is_closed()) { |
| 123 | // we had a failure. |
| 124 | return ReadStatus::UNKNOWN; |
| 125 | } |
| 126 | |
| 127 | MessageStorage<356000> bs; |
| 128 | int attempts_left{attempts}; |
| 129 | ReadStatus readStatus{ReadStatus::NO_ERROR}; |
| 130 | // Try to read all the data from the socket. If a timeout happens we retry |
| 131 | // 'attemps' times. On error we just stop. |
| 132 | while (attempts_left > 0 || readStatus == ReadStatus::NO_ERROR) { |
| 133 | auto buf = bs.writable_data(); |
| 134 | const auto to_read = bs.available(); // Available in the current memory chunk. |
| 135 | ssize_t nread{-1}; |
| 136 | |
| 137 | // Try again if timed out. |
| 138 | if (auto const r = read_ready(_sock, timeout_ms.count()); r == 0) { |
| 139 | readStatus = ReadStatus::TIMEOUT; |
| 140 | --attempts_left; |
| 141 | continue; |
| 142 | } else if (r < 0) { |
| 143 | // No more tries. |
| 144 | readStatus = ReadStatus::READ_ERROR; |
| 145 | break; |
| 146 | } |
| 147 | |
| 148 | nread = ::read(_sock, buf, to_read); |
| 149 | if (nread > 0) { |
| 150 | bs.save(nread); |
| 151 | continue; |
| 152 | } else if (nread == -1) { |
| 153 | if (errno == EAGAIN || errno == EINTR) { |
| 154 | continue; |
| 155 | } |
| 156 | readStatus = ReadStatus::READ_ERROR; |
| 157 | break; |
| 158 | } |
| 159 | // EOF |
| 160 | if (bs.stored() > 0) { |
| 161 | readStatus = ReadStatus::NO_ERROR; |
| 162 | break; |
| 163 | } |
| 164 | readStatus = ReadStatus::READ_ERROR; |
| 165 | break; |
| 166 | } |
| 167 | content = bs.str(); |
| 168 | return readStatus; |
| 169 | } |
| 170 | } // namespace shared::rpc |
no test coverage detected