1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * Vulkan CTS Framework
3e5c31af7Sopenharmony_ci * --------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright (c) 2021 The Khronos Group Inc.
6e5c31af7Sopenharmony_ci *
7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
10e5c31af7Sopenharmony_ci *
11e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
12e5c31af7Sopenharmony_ci *
13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
17e5c31af7Sopenharmony_ci * limitations under the License.
18e5c31af7Sopenharmony_ci *
19e5c31af7Sopenharmony_ci *-------------------------------------------------------------------------*/
20e5c31af7Sopenharmony_ci
21e5c31af7Sopenharmony_ci#include "vksNetwork.hpp"
22e5c31af7Sopenharmony_ci#include "vksSerializer.hpp"
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci#include <sstream>
25e5c31af7Sopenharmony_ci
26e5c31af7Sopenharmony_ci#include "deSocket.hpp"
27e5c31af7Sopenharmony_ci
28e5c31af7Sopenharmony_cinamespace vksc_server
29e5c31af7Sopenharmony_ci{
30e5c31af7Sopenharmony_ci
31e5c31af7Sopenharmony_civoid StringToAddress (const string& str, string& host, int& port)
32e5c31af7Sopenharmony_ci{
33e5c31af7Sopenharmony_ci	auto pos = str.find_last_of(':');
34e5c31af7Sopenharmony_ci	if (pos == string::npos)
35e5c31af7Sopenharmony_ci	{
36e5c31af7Sopenharmony_ci		host = str.c_str();
37e5c31af7Sopenharmony_ci		port = DefaultPort;
38e5c31af7Sopenharmony_ci	}
39e5c31af7Sopenharmony_ci	else
40e5c31af7Sopenharmony_ci	{
41e5c31af7Sopenharmony_ci		host = str.substr(0, pos);
42e5c31af7Sopenharmony_ci		std::stringstream{str.substr(pos+1)} >> port;
43e5c31af7Sopenharmony_ci	}
44e5c31af7Sopenharmony_ci}
45e5c31af7Sopenharmony_ci
46e5c31af7Sopenharmony_cibool ProccessNetworkData (vector<u8>& buffer, const std::function<void(u32, vector<u8>)>& packetInterpreter)
47e5c31af7Sopenharmony_ci{
48e5c31af7Sopenharmony_ci	constexpr msize headerSize = 8;
49e5c31af7Sopenharmony_ci
50e5c31af7Sopenharmony_ci	if (buffer.size() >= headerSize)
51e5c31af7Sopenharmony_ci	{
52e5c31af7Sopenharmony_ci		u32 classHash;
53e5c31af7Sopenharmony_ci		u32 packetSize;
54e5c31af7Sopenharmony_ci
55e5c31af7Sopenharmony_ci		Serializer<ToRead>{buffer}.Serialize(classHash, packetSize);
56e5c31af7Sopenharmony_ci
57e5c31af7Sopenharmony_ci		if (buffer.size() >= packetSize + headerSize)
58e5c31af7Sopenharmony_ci		{
59e5c31af7Sopenharmony_ci			auto itbeging	= buffer.begin() + headerSize;
60e5c31af7Sopenharmony_ci			auto itend		= itbeging + packetSize;
61e5c31af7Sopenharmony_ci			packetInterpreter(classHash, vector<u8>(itbeging, itend));
62e5c31af7Sopenharmony_ci			buffer.erase(buffer.begin(), itend);
63e5c31af7Sopenharmony_ci			return buffer.size() >= headerSize; // Try again?
64e5c31af7Sopenharmony_ci		}
65e5c31af7Sopenharmony_ci	}
66e5c31af7Sopenharmony_ci
67e5c31af7Sopenharmony_ci	return false;
68e5c31af7Sopenharmony_ci}
69e5c31af7Sopenharmony_ci
70e5c31af7Sopenharmony_civoid Send (de::Socket* socket, const vector<u8>& buffer)
71e5c31af7Sopenharmony_ci{
72e5c31af7Sopenharmony_ci	msize sent_total{};
73e5c31af7Sopenharmony_ci	do
74e5c31af7Sopenharmony_ci	{
75e5c31af7Sopenharmony_ci		msize sent{};
76e5c31af7Sopenharmony_ci		auto result = socket->send(buffer.data() + sent_total, buffer.size() - sent_total, &sent);
77e5c31af7Sopenharmony_ci		if (result != DE_SOCKETRESULT_SUCCESS)
78e5c31af7Sopenharmony_ci			throw std::runtime_error("Can't send data to socket");
79e5c31af7Sopenharmony_ci		sent_total += sent;
80e5c31af7Sopenharmony_ci	} while (sent_total < buffer.size());
81e5c31af7Sopenharmony_ci}
82e5c31af7Sopenharmony_ci
83e5c31af7Sopenharmony_civoid RecvSome (de::Socket* socket, vector<u8>& recvb)
84e5c31af7Sopenharmony_ci{
85e5c31af7Sopenharmony_ci	msize received;
86e5c31af7Sopenharmony_ci	u8 data[8 * 1024];
87e5c31af7Sopenharmony_ci	auto result = socket->receive(data, sizeof(data), &received);
88e5c31af7Sopenharmony_ci	if (result != DE_SOCKETRESULT_SUCCESS)
89e5c31af7Sopenharmony_ci		throw std::runtime_error("Can't receive data from socket");
90e5c31af7Sopenharmony_ci	recvb.insert(recvb.end(), data, data + received);
91e5c31af7Sopenharmony_ci}
92e5c31af7Sopenharmony_ci
93e5c31af7Sopenharmony_civoid SendPayloadWithHeader (de::Socket* socket, u32 type, const std::vector<u8>& payload)
94e5c31af7Sopenharmony_ci{
95e5c31af7Sopenharmony_ci	u32 size = static_cast<u32>(payload.size());
96e5c31af7Sopenharmony_ci
97e5c31af7Sopenharmony_ci	vector<u8> header;
98e5c31af7Sopenharmony_ci	Serializer<ToWrite> header_serializer(header);
99e5c31af7Sopenharmony_ci	header_serializer.Serialize(type, size);
100e5c31af7Sopenharmony_ci
101e5c31af7Sopenharmony_ci	Send(socket, header);
102e5c31af7Sopenharmony_ci	Send(socket, payload);
103e5c31af7Sopenharmony_ci}
104e5c31af7Sopenharmony_ci
105e5c31af7Sopenharmony_civector<u8> RecvPacket (de::Socket* socket, vector<u8>& recvb, u32 type)
106e5c31af7Sopenharmony_ci{
107e5c31af7Sopenharmony_ci	bool result = false;
108e5c31af7Sopenharmony_ci	vector<u8> packet;
109e5c31af7Sopenharmony_ci
110e5c31af7Sopenharmony_ci	while (socket->isConnected() && !result)
111e5c31af7Sopenharmony_ci	{
112e5c31af7Sopenharmony_ci		RecvSome(socket, recvb);
113e5c31af7Sopenharmony_ci
114e5c31af7Sopenharmony_ci		auto interpret = [&](u32 classHash, vector<u8> bufferData)
115e5c31af7Sopenharmony_ci		{
116e5c31af7Sopenharmony_ci			if (classHash != type) throw std::runtime_error("Unexpected packet type received");
117e5c31af7Sopenharmony_ci			packet = std::move(bufferData);
118e5c31af7Sopenharmony_ci			result = true;
119e5c31af7Sopenharmony_ci		};
120e5c31af7Sopenharmony_ci
121e5c31af7Sopenharmony_ci		ProccessNetworkData(recvb, interpret);
122e5c31af7Sopenharmony_ci	}
123e5c31af7Sopenharmony_ci
124e5c31af7Sopenharmony_ci	if (!result) throw std::runtime_error("connection lost before we could get data");
125e5c31af7Sopenharmony_ci
126e5c31af7Sopenharmony_ci	return packet;
127e5c31af7Sopenharmony_ci}
128e5c31af7Sopenharmony_ci
129e5c31af7Sopenharmony_ci};
130