-
Notifications
You must be signed in to change notification settings - Fork 0
/
reliable_file.h
206 lines (165 loc) · 4.6 KB
/
reliable_file.h
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#ifndef RELIABLE_H
#define RELIABLE_H
#define WINDOW_SIZE 60
#define TOT_WINDOWS 2*WINDOW_SIZE
#define PACKET_SIZE 1400
#define TIMEOUT_US 5000
enum PacketType {
FileSubdir,
Filename,
Data,
Terminal,
Ack
} __attribute__ ((__packed__));
typedef struct Header {
size_t length;
int32_t offset;
enum PacketType type;
int16_t ack_num;
} Header;
typedef struct Packet {
Header header;
void *data;
} Packet;
typedef struct PacketInfo {
Packet packet;
bool ack;
bool ready;
bool terminal;
} PacketInfo;
typedef struct SlidingWindow {
PacketInfo *packets;
struct timeval timeout;
bool timeout_set;
int min_accept;
int max_accept;
} SlidingWindow;
int modulo(int n, int mod) {
while (n > mod) {
n -= mod;
}
while (n < 0) {
n += mod;
}
if (n == mod) {
return 0;
}
return n;
}
int increment_mod(int n, int mod) {
n ++;
return modulo(n, mod);
}
int decrement_mod(int n, int mod) {
n --;
return modulo(n, mod);
}
void clear_packet(Packet *packet) {
free(packet->data);
memset(packet, 0, sizeof(*packet));
}
size_t get_data_len(Packet packet) {
return packet.header.length - sizeof(packet.header);
}
PacketInfo* get_packet_info(
SlidingWindow window, int index) {
// Bounds checking
if (index < 0 || index >= TOT_WINDOWS) {
return NULL;
}
return (PacketInfo *)(window.packets + index);
}
int fill_packet_info(PacketInfo *packet_info, bool terminal) {
packet_info->terminal = terminal;
packet_info->ready = true;
packet_info->ack = false;
return 0;
}
int clear_packet_info(PacketInfo *packet_info) {
clear_packet(&(packet_info->packet));
packet_info->ready = false;
packet_info->ack = false;
return 0;
}
void create_sliding_window(SlidingWindow *window) {
PacketInfo *packet_info_ptr;
packet_info_ptr = calloc(2*WINDOW_SIZE, sizeof(PacketInfo));
window->packets = packet_info_ptr;
int idx;
for (idx = 0; idx < TOT_WINDOWS; idx++) {
PacketInfo *curr_pack;
if ((curr_pack = get_packet_info(*window, idx)) != NULL) {
curr_pack->ready = false;
curr_pack->ack = false;
}
}
window->min_accept = 0;
window->max_accept = WINDOW_SIZE - 1;
window->timeout_set = false;
}
void shift_window(SlidingWindow *window) {
//clear_packet_info(get_packet_info(*window, window->min_accept));
window->min_accept = increment_mod(window->min_accept, TOT_WINDOWS);
window->max_accept = increment_mod(window->max_accept, TOT_WINDOWS);
fill_packet_info(get_packet_info(*window, window->max_accept), false);
}
int process_recv_data(void *data, size_t data_len, Packet *packet) {
size_t head_len = sizeof(packet->header);
if (data_len <= head_len) {
fprintf(stderr, "process_recv_data: Failed to process data.");
return -1;
}
// Perform checksum(s)
// Fill in Packet header and data
memcpy(&(packet->header), data, head_len);
data += head_len;
// Fill data
void *packet_data = calloc(1, data_len - head_len);
memcpy(packet_data, data, data_len - head_len);
packet->data = packet_data;
return 0;
}
int fill_send_buffer(void *buf, Packet packet) {
unsigned char *ptr = buf;
// Copy header
memcpy(ptr, &(packet.header), sizeof(packet.header));
ptr += sizeof(packet.header);
// Copy data
memcpy(ptr, packet.data, get_data_len(packet));
return 0;
}
void send_terminal(int sockfd, Packet *packet, int ack_num, struct sockaddr_in addr, socklen_t addr_len) {
int data_len = 1;
packet->header.length = sizeof(packet->header) + data_len;
void *buf = calloc(1, packet->header.length);
packet->header.offset = 0;
packet->header.type = Terminal;
packet->header.ack_num = ack_num;
void *packet_data = calloc(1, data_len);
packet->data = packet_data;
fill_send_buffer(buf, *packet);
// Send terminal packet.
int sent;
while ((sent = sendto(sockfd, buf, packet->header.length, 0,
(struct sockaddr*)&addr, addr_len)) == -1) {
continue;
}
free(buf);
}
bool in_bounds(SlidingWindow window, int16_t ack_num) {
if (ack_num >= TOT_WINDOWS) {
return false;
}
if (window.min_accept < window.max_accept) {
if (ack_num >= window.min_accept && ack_num <= window.max_accept) {
return true;
}
return false;
} else {
if (!(ack_num < window.min_accept && ack_num > window.max_accept)) {
return true;
}
return false;
}
}
#endif