This repository has been archived by the owner on Dec 31, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
communication.cpp
88 lines (69 loc) · 2.58 KB
/
communication.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include "communication.hpp"
#include <algorithm>
#include <iostream>
#include <cassert>
#include <cstring>
#include "packets.hpp"
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
const size_t kMaxAckPacketSize = 4;
const size_t kMaxDataPacketSize = 516;
void AcknowledgePacket(int socket, sockaddr client_addr, uint16_t block_number) {
std::array<uint8_t, 4> buffer = { 0 };
buffer[1] = kACK;
uint8_t* block_number_array = ConvertIntegerTypes(block_number);
std::copy(block_number_array, block_number_array + 2, buffer.data() + 2);
assert(sendto(socket, buffer.data(), sizeof(buffer), 0, &client_addr, sizeof(client_addr)) != -1);
}
void SendData(int socket, sockaddr client_addr, uint16_t block_number, std::vector<uint8_t> data) {
std::vector<uint8_t> bytes;
bytes.reserve(4 + data.size());
bytes.resize(4, 0);
uint8_t* block_number_bytes = ConvertIntegerTypes(block_number);
bytes[1] = Opcode::kDATA;
bytes[2] = *(block_number_bytes);
bytes[3] = *(block_number_bytes + 1);
bytes.insert(bytes.end(), data.begin(), data.end());
assert(sendto(socket, bytes.data(), bytes.size(), 0, &client_addr, sizeof(client_addr)) != -1);
}
std::optional<std::vector<uint8_t>> SafelyReceivePacket(const int socket, const sockaddr expected_addr, size_t max_packet_size) {
sockaddr received_addr;
socklen_t received_addr_len = sizeof(received_addr);
std::vector<uint8_t> bytes(max_packet_size);
static ERROR error(ErrorCode::kUnknownTransferID, "You are not the allowed one.");
while (true) {
ssize_t n = recvfrom(socket, bytes.data(), max_packet_size, 0, &received_addr, &received_addr_len);
if (n == -1) {
if (errno == 11)
return std::nullopt;
else
assert(false);
}
else {
//Handle packets of another TID
if (memcmp(received_addr.sa_data, expected_addr.sa_data, 14) != 0) {
error.ReturnErrorToClient(socket, received_addr);
continue;
}
bytes.resize(n);
return bytes;
}
}
}
std::optional<std::vector<uint8_t>> WaitAndExtractData(const int socket, const sockaddr expected_addr, const uint16_t expected_block_number) {
std::optional<std::vector<uint8_t>> bytes;
do {
bytes = SafelyReceivePacket(socket, expected_addr, kMaxDataPacketSize);
if (!bytes) break;
uint16_t opcode = ConvertIntegerTypes(bytes.value().data());
if (opcode == Opcode::kDATA) {
if (ConvertIntegerTypes(bytes.value().data() + 2) == expected_block_number) {
return std::vector<uint8_t>(bytes.value().data() + 4, bytes.value().data() + bytes.value().size());
}
} else if (opcode == Opcode::kERROR) {
return bytes;
}
} while (bytes);
return bytes;
}