| /*------------------------------------------------------------------------- |
| * Vulkan CTS Framework |
| * -------------------- |
| * |
| * Copyright (c) 2021 The Khronos Group Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *-------------------------------------------------------------------------*/ |
| |
| #include "vksNetwork.hpp" |
| #include "vksSerializer.hpp" |
| |
| #include <sstream> |
| |
| #include "deSocket.hpp" |
| |
| namespace vksc_server |
| { |
| |
| void StringToAddress(const string &str, string &host, int &port) |
| { |
| auto pos = str.find_last_of(':'); |
| if (pos == string::npos) |
| { |
| host = str.c_str(); |
| port = DefaultPort; |
| } |
| else |
| { |
| host = str.substr(0, pos); |
| std::stringstream{str.substr(pos + 1)} >> port; |
| } |
| } |
| |
| bool ProccessNetworkData(vector<u8> &buffer, const std::function<void(u32, vector<u8>)> &packetInterpreter) |
| { |
| constexpr msize headerSize = 8; |
| |
| if (buffer.size() >= headerSize) |
| { |
| u32 classHash; |
| u32 packetSize; |
| |
| Serializer<ToRead>{buffer}.Serialize(classHash, packetSize); |
| |
| if (buffer.size() >= packetSize + headerSize) |
| { |
| auto itbeging = buffer.begin() + headerSize; |
| auto itend = itbeging + packetSize; |
| packetInterpreter(classHash, vector<u8>(itbeging, itend)); |
| buffer.erase(buffer.begin(), itend); |
| return buffer.size() >= headerSize; // Try again? |
| } |
| } |
| |
| return false; |
| } |
| |
| void Send(de::Socket *socket, const vector<u8> &buffer) |
| { |
| msize sent_total{}; |
| do |
| { |
| msize sent{}; |
| auto result = socket->send(buffer.data() + sent_total, buffer.size() - sent_total, &sent); |
| if (result != DE_SOCKETRESULT_SUCCESS) |
| throw std::runtime_error("Can't send data to socket"); |
| sent_total += sent; |
| } while (sent_total < buffer.size()); |
| } |
| |
| void RecvSome(de::Socket *socket, vector<u8> &recvb) |
| { |
| msize received; |
| u8 data[8 * 1024]; |
| auto result = socket->receive(data, sizeof(data), &received); |
| if (result != DE_SOCKETRESULT_SUCCESS) |
| throw std::runtime_error("Can't receive data from socket"); |
| recvb.insert(recvb.end(), data, data + received); |
| } |
| |
| void SendPayloadWithHeader(de::Socket *socket, u32 type, const std::vector<u8> &payload) |
| { |
| u32 size = static_cast<u32>(payload.size()); |
| |
| vector<u8> header; |
| Serializer<ToWrite> header_serializer(header); |
| header_serializer.Serialize(type, size); |
| |
| Send(socket, header); |
| Send(socket, payload); |
| } |
| |
| vector<u8> RecvPacket(de::Socket *socket, vector<u8> &recvb, u32 type) |
| { |
| bool result = false; |
| vector<u8> packet; |
| |
| while (socket->isConnected() && !result) |
| { |
| RecvSome(socket, recvb); |
| |
| auto interpret = [&](u32 classHash, vector<u8> bufferData) |
| { |
| if (classHash != type) |
| throw std::runtime_error("Unexpected packet type received"); |
| packet = std::move(bufferData); |
| result = true; |
| }; |
| |
| ProccessNetworkData(recvb, interpret); |
| } |
| |
| if (!result) |
| throw std::runtime_error("connection lost before we could get data"); |
| |
| return packet; |
| } |
| |
| }; // namespace vksc_server |