· 9 years ago · Dec 08, 2016, 12:04 AM
1/*turboclient.c*/
2//gcc turboclient.c -o utc && utc 128.10.104.134 23456 abcdeabcdeab kl.au configfile.dat
3//utc 128.10.104.134 23456 abcdeabcdeab kl.au configfile.dat
4#include <signal.h>
5#include <sys/wait.h>
6#include <stdio.h>
7#include <fcntl.h>
8#include <sys/stat.h>
9#include <sys/types.h>
10#include <unistd.h>
11#include <string.h>
12#include <stdlib.h>
13#include <netdb.h>
14#include <errno.h>
15#include <sys/socket.h>
16#include <netinet/in.h>
17#include <arpa/inet.h>
18#include <sys/time.h>
19#include "dropsendto.h"
20#include "p_params.h"
21
22#define MAX_BUF 1600
23#define MAX_LOAD 1600
24
25#ifndef max
26 #define max(a,b) ((a) > (b) ? (a) : (b))
27#endif
28void signal_sigio_hndlr(int sig);
29
30int work_to_do = 0;
31void signal_sigio_hndlr(int sig){
32 work_to_do = 1;
33 //printf("HHHHHHHHHHHHHHHHHHHHHHHHHHHHAAAAAAAAAAAAAAAAANNNNNNNNNNNNNDDDDDDDDDDDLLLLLLLLLLLLEEEEEEEEEERRRRRRRRRRRR\n");
34}
35
36typedef struct
37{
38 int *seq_id;
39 int *paylen;
40 int *h_exist;
41 char *payload;
42}PKINFO;
43
44PKINFO *pckt_book = NULL;
45
46int check_fname(char *s);
47
48int check_fname(char *s){
49
50 //0 means good file name
51 //1 means bad file name
52 char *c = s;
53 int len = strlen(s);
54 const char *invalid_chars = " /";
55 if(len>16)
56 return 1;
57 while(*c){
58 if(strchr(invalid_chars, *c))
59 return 1;
60 c++;
61 }
62
63 return 0;
64}
65
66int main(int argc, char * argv[]) {
67
68 char *srv_name, *srv_port, *secretkey, *filename, *config_file;
69 struct sockaddr_in srv_addr, udp_cl;
70 struct sockaddr_storage from_addr;
71 socklen_t from_addr_len = sizeof(from_addr);
72 struct hostent *hp;
73 int len, block_size, val, fd, send_sock, sock_ack, j;
74 FILE *fp;
75 char request[MAX_BUF], f_name[MAX_BUF], r_filename[MAX_BUF], nack[25], p_ack[5] = "$P$", all_ack[5] = "$A$";
76
77
78 struct timeval tv1, tv2;
79 long time_elapsed = 0, bytes_read = 0;
80
81 if (argc == 6) {
82 srv_name= argv[1];
83 srv_port = argv[2];
84 secretkey = argv[3];
85 filename = argv[4];
86 config_file = argv[5];
87 } else {
88 printf(
89 "usage: $turboclient hostname portnumber secretkey filename configfile.dat\n");
90 exit(1);
91 }
92
93 if(check_fname(filename) == 1){
94 printf("Bad filename, cannot contain spaces, slashes or exceed a length of 16 ascii characters\n");
95 exit(1);
96 }
97
98 pckt_book = (PKINFO*)malloc(CACHE_SZ * sizeof(PKINFO));
99
100 for(j = 0; j< CACHE_SZ; j++) {
101 PKINFO tmp;
102 tmp.seq_id = (int *)malloc(sizeof(int));
103 tmp.paylen = (int *)malloc(sizeof(int));
104 tmp.h_exist = (int *)malloc(sizeof(int));
105 tmp.payload = (char *)malloc(MAX_LOAD);
106 memcpy((pckt_book + j), &tmp, sizeof(PKINFO));
107 }
108 for(j = 0; j< CACHE_SZ; j++) {
109 memset(pckt_book[j].seq_id, 0, sizeof(int));
110 memset(pckt_book[j].h_exist, 1, sizeof(int));
111 memset(pckt_book[j].paylen, 0, sizeof(int));
112 memset(pckt_book[j].payload, 0, MAX_LOAD);
113 }
114
115
116 //reading blocksize
117 fp = fopen(config_file, "r");
118 //fscanf stops scanning at whitespace
119 fscanf(fp, "%d", &block_size);
120 fclose(fp);
121
122 //Setting up io signal
123 struct sigaction sgio;
124 sgio.sa_handler = signal_sigio_hndlr;
125 sgio.sa_flags = 0;
126 //sgio.sa_flags = SA_RESTART;
127 sigemptyset(&sgio.sa_mask);
128
129 if (sigaction(SIGPOLL, &sgio, NULL) == -1) {
130 perror("sigaction sigio");
131 exit(1);
132 }
133
134 //char recvbuf[block_size];
135 char recvbuf[MAX_BUF];
136
137 hp = gethostbyname(srv_name);
138 if (!hp) {
139 printf("Error: unknown host: %s\n", srv_name);
140 exit(1);
141 }
142
143 memset((char *) &srv_addr, 0, sizeof(srv_addr));
144 srv_addr.sin_family = AF_INET;
145 bcopy(hp->h_addr_list[0], (char *) &srv_addr.sin_addr, hp->h_length);
146 srv_addr.sin_port = htons(atoi(srv_port));
147
148 send_sock = socket(AF_INET, SOCK_DGRAM, 0);
149
150 sprintf(request, "$%s$%s", secretkey, filename);
151
152 if ((val = sendto(send_sock, request, strlen(request), 0, (struct sockaddr *)&srv_addr, sizeof(srv_addr))) == -1) {
153 perror("Send to error: forwarding");
154 exit(1);
155 }
156
157 strcpy(f_name, "/tmp/");
158 strcpy(r_filename, "/tmp/");
159 strcat(r_filename, filename);
160
161 srand(time(NULL));
162 int f_ind = rand();
163 char r_append[MAX_BUF];
164 sprintf(r_append, "_w%d", f_ind);
165 strcat(strcat(f_name, filename), r_append);
166 //printf("f_name is %s\n", f_name);
167
168 //Read response and save it in ./filename
169 if (access(f_name, F_OK) != -1) {
170 // file exists
171 printf("Error: File already exists\n");
172 exit(1);
173
174 } else {
175 // file doesn't exist, hence create it
176 fd = open(f_name, O_RDWR| O_APPEND | O_CREAT, S_IRUSR | S_IWUSR |S_IXUSR);
177
178 //noting starting time
179 if (gettimeofday(&tv1, NULL) == -1) {
180 exit(1);
181 }
182 memset(recvbuf, 0, MAX_BUF);
183 int n_excpt = 0, seq_no = -1, p_len, buf_ind, eot_flag = 0, holes = CACHE_SZ, f_in, true_h = 0, c_rcv = 0;
184
185
186 memset((char *) &udp_cl, 0, sizeof(udp_cl));
187 udp_cl.sin_family = AF_INET;
188 bcopy(hp->h_addr_list[0], (char *) &udp_cl.sin_addr, hp->h_length);
189 udp_cl.sin_port = htons(0);
190 sock_ack = socket(AF_INET, SOCK_DGRAM, 0);
191 bind(sock_ack, (struct sockaddr *) &udp_cl, sizeof(udp_cl));
192
193 fcntl(send_sock, F_SETFL, O_NONBLOCK|O_ASYNC);
194 fcntl(send_sock, F_SETOWN, getpid());
195 int dum = 0, retran;
196 while (1) {
197 memset(recvbuf, 0, MAX_BUF);
198 if(work_to_do == 1){
199 if ((val = recvfrom(send_sock, recvbuf, MAX_BUF, 0, (struct sockaddr *) &from_addr, &from_addr_len)) > 0) {
200 work_to_do = 0;
201 //printf("Here000\n");
202 if (val == 1) {
203 eot_flag = 1;
204 break;
205 }
206 //Update holes upon any packet reception (except EOT)
207 c_rcv++;
208 printf("cum recv %d\t", c_rcv);
209 holes--;
210 char *temp_unravel;
211 char *s_et = strtok_r(recvbuf, "$", &temp_unravel);
212 seq_no = atoi(s_et);
213 printf("(n, s) (%d, %d)\n", n_excpt, seq_no);
214
215 if (n_excpt < seq_no) {
216 //It's a hole, retransmission requests to be sent from n_excpt to & including seq_no
217 retran = n_excpt;
218 true_h += (seq_no - n_excpt);
219 printf("Holes detected %d ##########\n", seq_no - retran);
220 n_excpt = seq_no + 1;
221 //fork child to retransmit -ve acks so that you may not lose packets being sent in that time
222 if(!fork()){
223
224 while (seq_no > retran) {
225 memset(nack, 0, 25);
226 printf("Sendin nack %d\n", retran);
227 sprintf(nack, "$N$%d$", retran++);
228
229 //send from different socket
230 if ((val = sendto(sock_ack, nack, strlen(nack), 0, (struct sockaddr *) &from_addr, from_addr_len))== -1) {
231 perror("Send to nack: forwarding");
232 exit(1);
233 }
234 }
235 printf("Exiting child ######\n");
236 exit(0);
237 }
238 }
239 else if (n_excpt > seq_no) {
240 //hole being filled
241 memset(pckt_book[(seq_no%CACHE_SZ)].h_exist, 0, sizeof(int));
242 true_h--;
243 }
244 else {
245 n_excpt++;
246 }
247 // printf("Here111\n");
248 buf_ind = seq_no % CACHE_SZ;
249 p_len = val - (strlen(s_et) + 2);
250
251 memcpy(pckt_book[buf_ind].seq_id, &(seq_no), sizeof(seq_no));
252 memcpy(pckt_book[buf_ind].paylen, &(p_len), sizeof(p_len));
253 memcpy(pckt_book[buf_ind].payload, temp_unravel, p_len);
254 memset(pckt_book[buf_ind].h_exist, 0, sizeof(int));
255
256 bytes_read += val;
257
258 if (holes == 0) {
259 printf("true_h must 0, is %d\t \n", true_h);
260 int v_wrt = 0;
261 for (f_in = 0; f_in < CACHE_SZ; f_in++) {
262 if ((val = write(fd, pckt_book[f_in].payload, *(pckt_book[f_in].paylen))) < 0) {
263 perror("write error\n");
264 exit(1);
265 }
266 v_wrt += val;
267
268 }
269 printf("$$$$$$$$$$$$$written all %d$$$$$$$$$$$$$$$$\n", v_wrt);
270 if (eot_flag == 1) {
271 //All work done
272 break;
273 }
274 else {
275 //reset buffer
276 for(j = 0; j< CACHE_SZ; j++) {
277 memset(pckt_book[j].seq_id, 0, sizeof(int));
278 memset(pckt_book[j].paylen, 0, sizeof(int));
279 memset(pckt_book[j].h_exist, 1, sizeof(int));
280 memset(pckt_book[j].payload, 0, MAX_LOAD);
281 }
282
283 holes = CACHE_SZ;
284 if ((val = sendto(send_sock, p_ack, strlen(p_ack), 0, (struct sockaddr *) &from_addr, from_addr_len)) == -1) {
285 perror("Send to nack: forwarding");
286 exit(1);
287 }
288 printf("sent p_ack %s\n", p_ack);
289 }
290 }
291 else if (eot_flag == 1 && (true_h == 0)) {
292 for (f_in = 0; f_in < (n_excpt%CACHE_SZ); f_in++) {
293 write(fd, pckt_book[f_in].payload, *(pckt_book[f_in].paylen));
294 }
295 }
296 //printf("in3\n");
297 //printf("Wfn %d; holes %d true_h %d \n", n_excpt, holes, true_h);
298 memset(recvbuf, 0, MAX_BUF);
299 // printf("Her3333\n");
300 }
301
302 }
303
304 if(true_h > 0){
305 //Send negative acks again for the first hole
306 if(!fork()){
307 for(j = 0; j< CACHE_SZ; j++) {
308 if(*(pckt_book[j].h_exist) == 1){
309 int quo = (int)n_excpt/CACHE_SZ;
310 memset(nack, 0, 25);
311 printf("Extra nack %d\n", quo + j);
312 sprintf(nack, "$N$%d$", (quo + j));
313
314 //send from different socket
315 if ((val = sendto(sock_ack, nack, strlen(nack), 0, (struct sockaddr *) &from_addr, from_addr_len))== -1) {
316 perror("Send to nack: forwarding");
317 exit(1);
318 }
319 break;
320 }
321 }
322 exit(0);
323 }
324 }
325
326
327 // if(eot_flag && !holes){
328 // for (f_in = 0; f_in < CACHE_SZ; f_in++) {
329 // if ((val = write(fd, pckt_book[f_in].payload, *(pckt_book[f_in].paylen))) < 0) {
330 // perror("write error\n");
331 // exit(1);
332 // }
333 // }
334 // break;
335 // }
336
337 if(eot_flag && (true_h == 0)){
338 for (f_in = 0; f_in < (n_excpt%CACHE_SZ); f_in++) {
339 write(fd, pckt_book[f_in].payload, *(pckt_book[f_in].paylen));
340 }
341 break;
342 }
343 }
344
345
346 close(fd);
347
348 if ((val = sendto(send_sock, all_ack, strlen(all_ack), 0, (struct sockaddr *) &from_addr, from_addr_len)) == -1) {
349 perror("Send to all_ack: forwarding");
350 exit(1);
351 }
352
353 //noting ending time
354 if (gettimeofday(&tv2, NULL) == -1) {
355 exit(1);
356 }
357
358 char cmd_to_exec[MAX_BUF];
359
360 //Checking content of files
361 sprintf(cmd_to_exec, "cmp %s %s && echo 'SUCCESS, FILES MATCH' || echo 'FILES DO NOT MATCH'", r_filename, f_name);
362 system(cmd_to_exec);
363
364 //seconds to milliseconds
365 time_elapsed = (tv2.tv_sec - tv1.tv_sec) * 1000.0;
366 //micro to milliseconds
367 time_elapsed += (tv2.tv_usec - tv1.tv_usec) / 1000.0;
368
369 printf("Last seq: %d\n", seq_no);
370 printf("Completion time: %ld msec\n", time_elapsed);
371 printf("Bytes downloaded: %ld\n", bytes_read);
372 printf("Throughput: %f KBps\n", (float)bytes_read/time_elapsed);
373
374 }
375
376
377
378
379
380
381 return 0;
382}