* Receives a packet for the given client * @return The received packet (or nullptr when it didn't receive one) */
| 117 | * @return The received packet (or nullptr when it didn't receive one) |
| 118 | */ |
| 119 | std::unique_ptr<Packet> NetworkTCPSocketHandler::ReceivePacket() |
| 120 | { |
| 121 | ssize_t res; |
| 122 | |
| 123 | if (!this->IsConnected()) return nullptr; |
| 124 | |
| 125 | if (this->packet_recv == nullptr) { |
| 126 | this->packet_recv = std::make_unique<Packet>(this, TCP_MTU); |
| 127 | } |
| 128 | |
| 129 | Packet &p = *this->packet_recv.get(); |
| 130 | |
| 131 | /* Read packet size */ |
| 132 | if (!p.HasPacketSizeData()) { |
| 133 | while (p.RemainingBytesToTransfer() != 0) { |
| 134 | res = p.TransferIn(SocketReceiver{this->sock}); |
| 135 | if (res == -1) { |
| 136 | NetworkError err = NetworkError::GetLast(); |
| 137 | if (!err.WouldBlock()) { |
| 138 | /* Something went wrong... */ |
| 139 | if (!err.IsConnectionReset()) Debug(net, 0, "Recv failed: {}", err.AsString()); |
| 140 | this->CloseConnection(); |
| 141 | return nullptr; |
| 142 | } |
| 143 | /* Connection would block, so stop for now */ |
| 144 | return nullptr; |
| 145 | } |
| 146 | if (res == 0) { |
| 147 | /* Client/server has left */ |
| 148 | this->CloseConnection(); |
| 149 | return nullptr; |
| 150 | } |
| 151 | } |
| 152 | |
| 153 | /* Parse the size in the received packet and if not valid, close the connection. */ |
| 154 | if (!p.ParsePacketSize()) { |
| 155 | this->CloseConnection(); |
| 156 | return nullptr; |
| 157 | } |
| 158 | } |
| 159 | |
| 160 | /* Read rest of packet */ |
| 161 | while (p.RemainingBytesToTransfer() != 0) { |
| 162 | res = p.TransferIn(SocketReceiver{this->sock}); |
| 163 | if (res == -1) { |
| 164 | NetworkError err = NetworkError::GetLast(); |
| 165 | if (!err.WouldBlock()) { |
| 166 | /* Something went wrong... */ |
| 167 | if (!err.IsConnectionReset()) Debug(net, 0, "Recv failed: {}", err.AsString()); |
| 168 | this->CloseConnection(); |
| 169 | return nullptr; |
| 170 | } |
| 171 | /* Connection would block */ |
| 172 | return nullptr; |
| 173 | } |
| 174 | if (res == 0) { |
| 175 | /* Client/server has left */ |
| 176 | this->CloseConnection(); |
no test coverage detected