Code:
/* code for CoE 151 MP2 by RhayneX
THIS IS THE WORKING CODE~!!
compile using:
gcc sender7.c -o sender7 -lm -Wall -lpthread
run using:
./sender7 -f slowstart.png -c 2000 -i 100 -d 100 -t 100 -vv -r 192.168.1.102:15151
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <time.h>
#include <sys/time.h>
#include <signal.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <netdb.h>
#include <pthread.h>
#include <math.h>
#define MYPORT "15151"
struct flist{ //linked list for file chunk
char *chunk; //file segment
int chunksize; //size of chunk of this node
int isn; //segment number of packet
int res;
int last;
int acked;
struct flist *next; //pointer to the next node
};
typedef struct flist Flist;
Flist *fileparse = NULL; //define pointer of struct flist
char filename[32];
int chunksize;
int isn;
int timeout;
int delay;
int v_flag = 0;
int vv_flag = 0;
char rcv_ipadd[17]; //ip address of receiver
int rcv_port; //int value of receive port
char rcv_port_str[6]; //port number used by the receiver in string format
int cwindow = 1;
int rcv_ack;
int rcv_ack;
int ack_max;
int syn_ack_received = 0;
int sent_last = 0;
//declare sender variables
int broadcast = 1;
int sockfd;
struct addrinfo hints, *servinfo; //structs for getaddrinfo
struct sockaddr_in their_addr; // connector's address information
struct hostent *he;
int numbytes;
int retval;
int lost = 0;
time_t now;
void make_seqnum(int seqnum, char seqbuf[]);
void make_packet(int flag, char seqbuf[], void *chunkbuf, char *packet, int chunksize);
int parsechunk(char *buf, char *buf2,int datasent,int seq_val, char flag[]);
void update_ackflag(int rcv_ack_local, Flist *sPtr, int lost);
void listener(int lost);
void inserttolist(Flist *sPtr, int chunksize, int isn, char *buffer, int last, int res, int modulo){
while(sPtr->next != NULL){
sPtr = sPtr->next; //find end of list
}
sPtr->next = (struct flist *)malloc(sizeof(struct flist)); //allocate memory for node
sPtr->next-> res = res;
sPtr->next->chunksize = chunksize; //size of the chunk pointed by sptr->chunk
sPtr->next->isn = isn; //segment number of this chunk
sPtr->next->next = NULL;
sPtr->next->acked = 0;
if(last == 0){
sPtr->next->last = 0;
sPtr->next->chunk = (char *)malloc(sizeof(char)*chunksize); //set sptr->chunk to point to the actual chunk
memcpy(sPtr->next->chunk,buffer,chunksize);
}
else{
sPtr->next->last = 1;
sPtr->next->chunk = (char *)malloc(sizeof(char)*modulo); //set sptr->chunk to point to the actual chunk
memcpy(sPtr->next->chunk,buffer,modulo);
}
}
void parse_file(Flist* sPtr, int chunksize, int isn, char filename[]){
FILE *ptr; //file pointer
char *buffer1, *buffer2; //pointer to memory holding each chunk
int filesize; //size of file to be sent
int quotient; //counter for f
int modulo;
size_t res; //for fread
int counter = 0; //just a counter
/*open file*/
if ((ptr = fopen(filename, "r+b")) == NULL) //if file cannot be opened..
{
printf("File open error\n");
goto end;
}
else{
/*obtain file size*/
fseek (ptr , 0 , SEEK_END);
filesize = ftell (ptr);
rewind (ptr);
}
/*obtain number of chunks to be made*/
if(filesize<chunksize){
printf("File size is too small for chunk\n");
quotient = 0;
modulo = filesize;
goto start;
}
quotient = filesize/chunksize;
modulo = filesize%chunksize;
printf("Modulo is %i\n",modulo);
start:
buffer1 = (char *)malloc(sizeof(char)*chunksize); //allocate memory for chunk
buffer2 = (char *)malloc(sizeof(char)*modulo); //allocate memory for chunk
/*start getting the chunks*/
while(1){
if(counter!=quotient){
memset(buffer1,0,chunksize);
if(buffer1 == NULL){
printf("Allocation failed\n");
goto end;
}
res = fread(buffer1,sizeof(char),chunksize,ptr); //get the chunk from file pointer
if (res != chunksize){
goto end;
}
inserttolist(sPtr,res,isn,buffer1,0,res,modulo);
counter++; //increment counter
isn = isn + res; //increment segment number
}
else if((counter == quotient) && (modulo != 0)){
memset(buffer2,0,modulo);
if(buffer2 == NULL){
printf("Allocation failed\n");
goto end;
}
res = fread (buffer2,sizeof(char),modulo,ptr); //get the chunk from file pointer
inserttolist(sPtr,res,isn,buffer2,1, res,modulo);
break;
}
}
end:
fclose(ptr);
}
void parse_cmdline(int argc, char *argv[]){
int i = 1; //counter for command line; counter for ip:port
int y = 0; //counter for ip:port
char c;
char ip_portbuff[23];
memset(ip_portbuff,0,23);
if((argc == 1)||(argc == 2)){
printf("Wrong parameter(s)\n");
}
while(argc>1){ //This loop gets the parameters needed in the program
if(!strcmp(argv[i],"-f"))
strcpy(filename,argv[i+1]);
else if(!strcmp(argv[i],"-c"))
chunksize = atoi(argv[i+1]);
else if(!strcmp(argv[i],"-i"))
isn = atoi(argv[i+1]);
else if(!strcmp(argv[i],"-t")){
timeout = atoi(argv[i+1]);
}
else if(!strcmp(argv[i],"-d")){
delay = atoi(argv[i+1]);
}
else if(!strcmp(argv[i],"-r"))
strcpy(ip_portbuff,argv[i+1]);
else if(!strcmp(argv[i],"-v"))
v_flag = 1;
else if(!strcmp(argv[i],"-vv"))
vv_flag = 1;
argc-=1;
i++;
}
int x = 0;
c = ip_portbuff[x]; //get ip address
while(c != ':'){
rcv_ipadd[x] = c;
x++;
c = ip_portbuff[x];
}
rcv_ipadd[x] = '\0';
x++;
c = ip_portbuff[x];
while(c!='\0'){ //get port
rcv_port_str[y] = c;
x++;
y++;
c = ip_portbuff[x];
}
rcv_port = atoi(rcv_port_str);
//printf("Done getting program parameters.\n\n\n");
//printf("filename is: %s\n chunksize is %i\n isn is %i\n timeout is %i\n delay is %i\n vflag is %i\n vvflag is %i\n ip_add is %s\n port is %i\n", filename, chunksize, isn, timeout, delay, v_flag, vv_flag, rcv_ipadd, rcv_port);
}
void send_syn(){
char *buffer = NULL;
char seqbuff[33];
memset(seqbuff,0,33);
buffer = (char *)malloc(sizeof(char)*chunksize);
//sending syn
while(syn_ack_received != 1){
puts("Sending syn packet..");
make_seqnum(isn,seqbuff);
make_packet(1, seqbuff, buffer, buffer, chunksize);
numbytes = sendto(sockfd, buffer, 32+35, 0, (struct sockaddr *)&their_addr, sizeof their_addr); //send datagram
// printf("sent:%s\n",buffer);
// numbytes = sendto(sockfd, buffer, sPtr->chunksize, 0, (struct sockaddr *)&their_addr, sizeof their_addr);
usleep(delay*1000);
memset(seqbuff,0,33);
memset(buffer,0,chunksize);
}
free(buffer);
}
void send_data(Flist *sPtr){
int x = 0;
int cwintemp = 0;
char *buffer = NULL;
char seqbuff[33];
memset(seqbuff,0,33);
buffer = (char *)malloc(sizeof(char)*chunksize);
puts("Sending data packets..");
//puts("wo");
//start:
while(sPtr->next != NULL){ //find first node to send
if(sPtr->acked == 1 || x == 0){ //node already acked, go to next node
// printf("acked isn:%i\n",sPtr->isn);
sPtr = sPtr->next;
x++;
}
else {
// printf("not acked isn:%i\n",sPtr->isn); //first unacked node found
break;
}
}
while(sPtr->last != 1){
while(cwintemp != cwindow && lost != 1 && sPtr->last != 1) {
if(x != 0){
//sending first data packet
make_seqnum(sPtr->isn,seqbuff);
make_packet(2, seqbuff, sPtr->chunk, buffer, sPtr->chunksize);
if(vv_flag == 1){
time(&now);
printf("%s", ctime(&now));
printf("Data with seq num %i sent\n\n",sPtr->isn);
}
numbytes = sendto(sockfd, buffer, sPtr->chunksize+35, 0, (struct sockaddr *)&their_addr, sizeof their_addr); //send datagram
// printf("sent:%s\n",buffer);
usleep((delay*1000)/cwindow);
memset(seqbuff,0,33);
memset(buffer,0,chunksize);
cwintemp++;
// printf("cwintemp is %i\ncwindow is %i\n", cwintemp, cwindow);
}
sPtr = sPtr->next;
x++;
if(vv_flag == 1){
// printf("Cwin is %i temp is%i lost is%i\n",cwindow,cwintemp,lost);
printf("Congestion window is %i\n",cwindow);
}
}
break;
}
if(sPtr->last == 1 && cwintemp != cwindow && lost != 1){
//send last data packet
puts("Sending last data packet and fin");
make_seqnum(sPtr->isn,seqbuff);
make_packet(3, seqbuff, sPtr->chunk, buffer, sPtr->chunksize);
if(vv_flag == 1){
time(&now);
printf("%s", ctime(&now));
printf("Data with seq num %i sent\n\n",sPtr->isn);
}
numbytes = sendto(sockfd, buffer, sPtr->chunksize+35, 0, (struct sockaddr *)&their_addr, sizeof their_addr); //send datagram
// printf("sent:%s\n",buffer);
usleep(delay*1000);
memset(seqbuff,0,33);
memset(buffer,0,chunksize);
goto end;
}
usleep(timeout*1000/cwindow);
// printf("a:%i",sPtr->isn);
ack_max = sPtr->isn;
// printf("ack_max:%i, rcv_ack:%i",ack_max,rcv_ack);
if(ack_max != rcv_ack){
lost = 1;
}
if(lost == 1){
cwindow = 1;
lost = 0;
}
else if(sPtr->last != 1){ //assume no loss..
cwindow = cwindow*2;
}
end:
puts(" ");
}
void make_seqnum(int seqnum, char seqbuf[]){
int x,y;
char temp_inv[32];
memset(temp_inv,0,32);
x = 0;
while(seqnum>1){ //convert to binary, inverted
if(seqnum%2 == 1){
temp_inv[x] = '1';
}
else{
temp_inv[x] = '0';
}
seqnum = seqnum/2;
x++;
}
if(seqnum == 1){
temp_inv[x] = '1';
}
else{
temp_inv[x] = '0';
}
x++;
while(x != 31){
temp_inv[x] = '0';
x++;
}
temp_inv[x] = '0';
x = 31;
y = 0;
while(x != 0){
seqbuf[y] = temp_inv[x];
y++;
x--;
}
seqbuf[y] = temp_inv[x];
y++;
seqbuf[y] = '\0';
}
void make_packet(int flag, char seqbuf[], void *chunkbuf, char *packet, int chunksize){
int x, y;
x = 0;
y = 0;
char chunksize_str[32];
memset(chunksize_str,0,32);
sprintf(chunksize_str,"%i",chunksize);
if(flag == 1){ //make syn packet
packet[0] = '1';
packet[1] = '0';
packet[2] = '0';
y = 3;
x = 0;
while(x != 32){
packet[y] = seqbuf[x];
y++;
x++;
}
memcpy(packet+35,chunksize_str,32);
}
if(flag == 2){ //make data packet
packet[0] = '0';
packet[1] = '0';
packet[2] = '0';
y = 3;
x = 0;
while(x != 32){
packet[y] = seqbuf[x];
y++;
x++;
}
memcpy(packet+35,chunkbuf,chunksize);
}
if(flag == 3){ //make data packet
packet[0] = '0';
packet[1] = '0';
packet[2] = '1';
y = 3;
x = 0;
while(x != 32){
packet[y] = seqbuf[x];
y++;
x++;
}
memcpy(packet+35,chunkbuf,chunksize);
}
}
void listener(int lost){
//VARIABLES:
int sockfd; //used for sockets
struct addrinfo hints, *servinfo, *p; //structs for getaddrinfo
int retval; //used for getaddrinfo
int datasent; //return value of data sent
struct sockaddr_storage addr;
socklen_t addr_len; //for sockets
int yes = 1; //for sockopt
char flags[4];
//set these values first
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // set to AF_INET to force IPv4
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE; // use my IP
retval = getaddrinfo(NULL, MYPORT, &hints, &servinfo); //check if getaddr is successful
for(p = servinfo; p != NULL; p = p->ai_next) { // loop through all the results and bind to the first we can
if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
// perror("listener: socket");
continue;
}
if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) { //fix for address in use
// perror("setsockopt");
}
if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
continue;
}
break;
} //end for loop
if (p == NULL) { //socket unable to bind
printf("listener: failed to bind socket\n");
}
freeaddrinfo(servinfo); //serveinfo already done; clean it
addr_len = sizeof(addr);
//start listening to port
char *buf, *buf2; //max length of message buffer
int fin = 0;
char temp[32+35],temp2[32];
memset(temp,0,32+35);
memset(temp2,0,32);
printf("syn_ack:%i\n",syn_ack_received);
while(syn_ack_received != 1){ //wait for syn packet
datasent = recvfrom(sockfd, temp, 32+35, 0, (struct sockaddr *)&addr, &addr_len);
printf("%s\n",temp);
rcv_ack = parsechunk(temp,temp2,datasent,rcv_ack,flags);
if(!strcmp(flags,"110")){
syn_ack_received = 1;
puts("syn ack packet received");
}
}
//wait for data
flags[0] = '0';
flags[1] = '0';
flags[2] = '0';
flags[3] = '\0';
//printf("%s\n",flags);
buf = (char *)malloc(sizeof(char)*chunksize+35);
buf2 = (char *)malloc(sizeof(char)*chunksize);
printf("Receiving data ack..\n");
while (fin != 1){
datasent = recvfrom(sockfd, buf, chunksize+35, 0, (struct sockaddr *)&addr, &addr_len);
// printf("%s\n",buf);
rcv_ack = parsechunk(buf,buf2,datasent,rcv_ack, flags);
if(!strcmp(flags,"010")){
if(vv_flag == 1){
printf("Ack for Seq: %i received\n", rcv_ack - chunksize);
}
update_ackflag(rcv_ack-chunksize,fileparse,lost);
memset(buf,0,chunksize+35);
memset(buf2,0,chunksize);
}
else if(!strcmp(flags,"011")){
if(vv_flag == 1){
printf("Ack for Seq: %i received\n", rcv_ack - chunksize);
}
update_ackflag(rcv_ack-chunksize,fileparse,lost);
memset(buf,0,chunksize+35);
memset(buf2,0,chunksize);
sent_last = 1;
fin = 1;
}
else if(!strcmp(flags,"110")){
memset(buf,0,chunksize+35);
memset(buf2,0,chunksize);
puts("duplicate syn received");
}
}
puts("FIN ack received");
close(sockfd); //close the socket
}
int parsechunk(char *buf, char *buf2,int datasent,int seq_val, char flag[]){
int x, y, seqnum_int;
char seqnum[1];
flag[0] = buf[0];
flag[1] = buf[1];
flag[2] = buf[2];
flag[3] = '\0';
x = 31;
y = 3;
seqnum_int = 0;
while(x!=0){
seqnum[0] = buf[y];
if(seqnum[0] == '1'){
seqnum_int = seqnum_int + pow(2,x);
}
x--;
y++;
}
seqnum[0] = buf[y];
if(seqnum[0] == '1'){
seqnum_int = seqnum_int + pow(2,x);
}
seq_val = seqnum_int;
memcpy(buf2,buf+35,datasent-35);
return seq_val;
}
//FOR TEST
void make_file(Flist *sPtr, char filename[]){
FILE *ptr; //file pointer
int filesize = 0; //size of file received
int x = 0; //just a counter
if ((ptr = fopen(filename, "w+b")) == NULL) //if file cannot be opened..
{
printf("File not found\n");
goto end;
}
else{
while(sPtr->next != NULL) { //loop to write to list until the 2nd to the last element
if(x != 0){
fwrite(sPtr->chunk, sPtr->chunksize, sizeof(char),ptr);
filesize = filesize + sPtr->chunksize;
}
sPtr = sPtr->next;
x++;
}
}
fwrite(sPtr->chunk, sPtr->chunksize, sizeof(char),ptr);
filesize = filesize + sPtr->chunksize;
printf("Filesize is: %i bytes\n", filesize);
end:
fclose(ptr); //close file pointer
}
//END OF FOR TEST
void update_ackflag(int rcv_ack_local, Flist *sPtr, int lost){
sPtr = sPtr->next;
printf("rcv_ack:%i,sPtr->isn:%i\n",rcv_ack_local, sPtr->isn);
while(sPtr->last != 1){
if(sPtr->acked == 1){
sPtr = sPtr->next;
}
else if(sPtr->acked == 0){
break;
}
}
//printf("UPDATEING ACK FLAG:rcv_ack:%i,sPtr->isn:%i\n",rcv_ack_local, sPtr->isn);
if(sPtr->isn == rcv_ack_local && sPtr->last != 1){
printf("isn:%i\n",sPtr->isn);
sPtr->acked = 1;
puts("Updated!");
}
else if(sPtr->isn == rcv_ack_local && sPtr->last == 1){
printf("isn:%i\n",sPtr->isn);
puts("Last packet Updated");
sPtr->acked = 1;
}
else{
if(vv_flag == 1){
printf("Ack for Seq: %i lost\n", sPtr->isn);
}
lost = 1;
}
}
int main(int argc, char *argv[]){
pthread_t ackthread;
int ack_ret = 0;
fileparse = (struct flist *)malloc(sizeof(struct flist));
ack_ret = pthread_create(&ackthread, NULL, (void *)listener,(void *)lost);
parse_cmdline(argc,argv);
//set sender variables
//set sender variables
retval = getaddrinfo(NULL, rcv_ipadd, &hints, &servinfo);
he=gethostbyname(rcv_ipadd);
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast));
their_addr.sin_family = AF_INET; // host byte order
their_addr.sin_port = htons(rcv_port); // short, network byte order
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
memset(their_addr.sin_zero, '\0', sizeof(their_addr.sin_zero));
parse_file(fileparse, chunksize, isn,filename);
send_syn();
while(sent_last != 1){
send_data(fileparse);
}
printf("Done\n");
pthread_kill(ackthread, ack_ret);
close(sockfd);
return 0;
}
and for the server(receiver):
Code:
/*MP02 for CoE 151 created by RhayneX
This will contain the networking codes and threading codes
Compile using:
gcc -lpthread -lm -Wall rcv4.c -o rcv
run using:
./rcv -f hello.png -v -r 15151 -l 0
*/
//declaration of libraries
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <pthread.h>
#include <math.h>
#define MYPORT "15151"
struct flist{ //linked list for file chunk
char *chunk; //file segment
int chunksize; //size of chunk of this node
int isn; //segment number of packet
struct flist *next; //pointer to the next node
};
typedef struct flist Flist;
Flist *filechunks = NULL;
int listnotempty = 0;
int isn_rcv;
int modulo;
int fin_rcv;
int probability;
int v;
int vv;
int port;
char *myport;
char filename[32];
//Initialize network variables
//For listener
int sockfd; //used for sockets
struct addrinfo hints, *servinfo, *p; //structs for getaddrinfo
int retval; //used for getaddrinfo
int datasent; //return value of data sent
struct sockaddr_storage addr;
socklen_t addr_len; //for sockets
int yes = 1; //for sockopt
//For sender
int broadcast = 1;
struct addrinfo hints, *servinfo; //structs for getaddrinfo
struct sockaddr_in their_addr; // connector's address information
struct hostent *he;
int numbytes;
int retval2;
int sockfd2;
char s[INET6_ADDRSTRLEN];
int parsechunk(char *buf, char *buf2, int datasent, int seq_val, char flag[]);
int cointoss(int a);
void set_send();
void make_seqnum(int seqnum, char seqbuf[]);
void make_packet(int flag, char seqbuf[], void *chunkbuf, char *packet, int chunksize);
void inserttolist_rcv(Flist *sPtr, int chunksize, int isn, Flist *buffer){
while (sPtr->next != NULL) {
sPtr = sPtr->next;
}
if(isn_rcv == buffer->isn && listnotempty == 0){
puts("First node inserted");
sPtr->next = buffer;
listnotempty = 1;
}
else if(fin_rcv == 1 && listnotempty == 1){
puts("last packet");
sPtr->next = buffer;
fin_rcv = 0;
}
else if(sPtr->isn + chunksize == buffer->isn && listnotempty == 1){
sPtr->next = buffer;
}
}
void make_file(Flist *sPtr, char filename[]){
FILE *ptr; //file pointer
int filesize = 0; //size of file received
int x = 0; //just a counter
if ((ptr = fopen(filename, "w+b")) == NULL) //if file cannot be opened..
{
printf("File not found\n");
goto end;
}
else{
while(sPtr->next != NULL) { //loop to write to list until the 2nd to the last element
if(x != 0){
fwrite(sPtr->chunk, sPtr->chunksize, sizeof(char),ptr);
filesize = filesize + sPtr->chunksize;
}
sPtr = sPtr->next;
x++;
}
}
fwrite(sPtr->chunk, sPtr->chunksize, sizeof(char),ptr);
filesize = filesize + sPtr->chunksize;
end:
fclose(ptr); //close file pointer
}
void make_chunk(Flist *sPtr, int isn, int chunksize, char *buff_chunk){
char *buffer; //pointer to memory holding each chunk
Flist *node; //file checking
node = (struct flist *)malloc(sizeof(struct flist)); //allocate memory for node
if(node == NULL){
printf("Allocation of node failed\n");
}
buffer = (char *)malloc(sizeof(char)*chunksize); //allocate memory for chunk
memcpy(buffer,buff_chunk,chunksize); //buff chunk is the buffer for file chunk
if(buffer == NULL){
printf("Allocation of buffer failed\n");
}
node->chunk = buffer; //assign values for node
node->isn = isn;
node->next = NULL;
if(modulo == 0){
inserttolist_rcv(sPtr, chunksize, node->isn, node);
node->chunksize = chunksize;
modulo = 0;
}
else{
inserttolist_rcv(sPtr, modulo, node->isn, node);
node->chunksize = modulo;
modulo = 0;
}
}
void listener(){
//VARIABLES:
int syn_received = 0;
int chunksize;
int isn;
int prob;
char flags[4];
//set these values first
//start listening to port
char *buf, *buf2; //max length of message buffer
int seq_val = 0;
int fin = 0;
char temp[32+35],temp2[32];
char seq_num[33];
memset(seq_num,0,33);
memset(temp,0,32+35);
memset(temp2,0,32);
while(syn_received != 1){ //wait for syn packet
datasent = recvfrom(sockfd, temp, 32+35, 0, (struct sockaddr *)&addr, &addr_len);
// printf("rcv:%s\n",temp);
set_send();
//JUST TEST
isn = parsechunk(temp,temp2,datasent,isn,flags);
chunksize = atoi(temp2);
if(!strcmp(flags,"100")){
syn_received = 1;
isn_rcv = isn;
puts("Syn packet received\n");
memset(temp,0,32+35);
make_seqnum(isn,seq_num);
make_packet(1,seq_num,temp,temp,chunksize);
numbytes = sendto(sockfd2, temp, 32+35, 0, (struct sockaddr *)&their_addr, sizeof their_addr); //send syn ack
printf("%s\n",temp);
}
}
//wait for data
flags[0] = '0';
flags[1] = '0';
flags[2] = '0';
flags[3] = '\0';
//printf("%s\n",flags);
buf = (char *)malloc(sizeof(char)*chunksize+35);
buf2 = (char *)malloc(sizeof(char)*chunksize);
printf("Receiving data..\n");
while (fin != 1){
datasent = recvfrom(sockfd, buf, chunksize+35, 0, (struct sockaddr *)&addr, &addr_len);
//printf("rcv:%s\n",temp);
seq_val = parsechunk(buf,buf2,datasent,seq_val, flags);
prob=cointoss(probability);
if (prob == 1){
if(!strcmp(flags,"000")){
if(v == 1 || vv == 1){
printf("Data with Seq: %i received\n", seq_val);
}
make_chunk(filechunks, seq_val, datasent-35, buf2);
memset(buf,0,chunksize+35);
memset(temp,0,32+35);
memset(buf2,0,chunksize);
memset(seq_num,0,33);
make_seqnum(seq_val+datasent-35,seq_num);
make_packet(2,seq_num,temp,temp,chunksize);
numbytes = sendto(sockfd2, temp, 32+35, 0, (struct sockaddr *)&their_addr, sizeof their_addr); //send data ack
// printf("sent:%s\n",temp);
}
else if(!strcmp(flags,"001")){
if(v == 1 || vv == 1){
printf("Data with Seq: %i received\n", seq_val);
}
modulo = datasent - 35;
fin_rcv = 1;
make_chunk(filechunks, seq_val, datasent, buf2);
memset(buf,0,chunksize+35);
memset(temp,0,32+35);
memset(buf2,0,chunksize);
fin = 1;
memset(seq_num,0,33);
make_seqnum(seq_val+chunksize,seq_num);
make_packet(3,seq_num,temp,temp,chunksize);
numbytes = sendto(sockfd2, temp, 32+35, 0, (struct sockaddr *)&their_addr, sizeof their_addr); //send fin ack
// printf("sent:%s\n",temp);
}
else if(!strcmp(flags,"100")){
memset(buf,0,chunksize+35);
memset(buf2,0,chunksize);
memset(temp,0,32+35);
make_seqnum(isn,seq_num);
make_packet(1,seq_num,temp,temp,chunksize);
numbytes = sendto(sockfd2, temp, 32+35, 0, (struct sockaddr *)&their_addr, sizeof their_addr);
// printf("sent:%s\n",temp);
puts("duplicate syn received");
}
}
else{
seq_val = parsechunk(buf,buf2,datasent,seq_val, flags);
printf("Dropped packet with seq num %d\n",seq_val);
}
}
puts("FIN received");
close(sockfd); //close the socket
}
void make_seqnum(int seqnum, char seqbuf[]){
int x,y;
char temp_inv[32];
memset(temp_inv,0,32);
x = 0;
while(seqnum>1){ //convert to binary, inverted
if(seqnum%2 == 1){
temp_inv[x] = '1';
}
else{
temp_inv[x] = '0';
}
seqnum = seqnum/2;
x++;
}
if(seqnum == 1){
temp_inv[x] = '1';
}
else{
temp_inv[x] = '0';
}
x++;
while(x != 31){
temp_inv[x] = '0';
x++;
}
temp_inv[x] = '0';
x = 31;
y = 0;
while(x != 0){
seqbuf[y] = temp_inv[x];
y++;
x--;
}
seqbuf[y] = temp_inv[x];
y++;
seqbuf[y] = '\0';
}
int parsechunk(char *buf, char *buf2,int datasent,int seq_val, char flag[]){
int x, y, seqnum_int;
char seqnum[1];
flag[0] = buf[0];
flag[1] = buf[1];
flag[2] = buf[2];
flag[3] = '\0';
x = 31;
y = 3;
seqnum_int = 0;
while(x!=0){
seqnum[0] = buf[y];
if(seqnum[0] == '1'){
seqnum_int = seqnum_int + pow(2,x);
}
x--;
y++;
}
seqnum[0] = buf[y];
if(seqnum[0] == '1'){
seqnum_int = seqnum_int + pow(2,x);
}
seq_val = seqnum_int;
memcpy(buf2,buf+35,datasent-35);
return seq_val;
}
int cointoss(int a)
{
int c;
int d,e;
if (a==0){
c=1;
}
srand ( time(NULL) ); //generate random number
d = rand();
e= d%100; //modulo number to 100
// printf("%d\n", e);
if (e>a){ //dont drop if greater than a which is the probability to drop
c=1;
}
else{
c=0; //drop if lesser than a
}
return c;
}
void parse_cmdline(int argc, char *argv[]){
int i = 1; //counter for command line; counter for ip:port
if((argc == 1)||(argc == 2)){
printf("Wrong parameter(s)\n");
goto end;
}
while(argc>1){ //This loop gets the parameters needed in the program
if(!strcmp(argv[i],"-f"))
strcpy(filename,argv[i+1]);
else if(!strcmp(argv[i],"-l"))
probability = atoi(argv[i+1]);
else if(!strcmp(argv[i],"-p")){
myport = argv[i+1];
port = atoi(argv[i+1]);
}
else if(!strcmp(argv[i],"-v"))
v = 1;
else if(!strcmp(argv[i],"-vv")){
v=1;
vv=1;
}
argc-=1;
i++;
}
filename[strlen(filename)] = '\0';
end:
// printf("fname:%s\n prob:%d\n myport:%s %d\n v:%d\n vv:%d\n",filename,probability,myport,port,v,vv);
puts(" ");
}
void *get_in_addr(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
void set_send(){
retval2 = getaddrinfo(NULL, myport, &hints, &servinfo);
inet_ntop(addr.ss_family,get_in_addr((struct sockaddr *)&addr), s, sizeof(s));
he=gethostbyname(s);
sockfd2 = socket(AF_INET, SOCK_DGRAM, 0);
setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast));
their_addr.sin_family = AF_INET; // host byte order
their_addr.sin_port = htons(port); // short, network byte order
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
memset(their_addr.sin_zero, '\0', sizeof(their_addr.sin_zero));
}
void make_packet(int flag, char seqbuf[], void *chunkbuf, char *packet, int chunksize){
int x, y;
x = 0;
y = 0;
char chunksize_str[32];
memset(chunksize_str,0,32);
sprintf(chunksize_str,"%i",chunksize);
if(flag == 1){ //make syn packet
packet[0] = '1';
packet[1] = '1';
packet[2] = '0';
y = 3;
x = 0;
while(x != 32){
packet[y] = seqbuf[x];
y++;
x++;
}
memcpy(packet+35,chunksize_str,32);
}
if(flag == 2){ //make data packet
packet[0] = '0';
packet[1] = '1';
packet[2] = '0';
y = 3;
x = 0;
while(x != 32){
packet[y] = seqbuf[x];
y++;
x++;
}
memcpy(packet+35,chunkbuf,0);
}
if(flag == 3){ //make data packet
packet[0] = '0';
packet[1] = '1';
packet[2] = '1';
y = 3;
x = 0;
while(x != 32){
packet[y] = seqbuf[x];
y++;
x++;
}
memcpy(packet+35,chunkbuf,0);
}
}
int main(int argc, char *argv[]){
//SET network variables
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // set to AF_INET to force IPv4
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE; // use my IP
retval = getaddrinfo(NULL, MYPORT, &hints, &servinfo); //check if getaddr is successful
for(p = servinfo; p != NULL; p = p->ai_next) { // loop through all the results and bind to the first we can
if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
// perror("listener: socket");
continue;
}
if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) { //fix for address in use
// perror("setsockopt");
}
if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
continue;
}
break;
} //end for loop
if (p == NULL) { //socket unable to bind
printf("listener: failed to bind socket\n");
}
freeaddrinfo(servinfo); //serveinfo already done; clean it
addr_len = sizeof(addr);
// for send
filechunks = (struct flist *)malloc(sizeof(struct flist));
parse_cmdline(argc,argv);
listener();
make_file(filechunks, filename);
return 0;
}