forked from miftahulmahfuzh/slidingwindowprotocol
-
Notifications
You must be signed in to change notification settings - Fork 0
/
receiver.c
186 lines (150 loc) · 5 KB
/
receiver.c
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
/* File : T1_rx.cpp */
#include "receiver.h"
Byte rxbuf[RXQSIZE];
QTYPE rcvq = { 0, 0, 0, RXQSIZE, rxbuf };
QTYPE *rxq = &rcvq;
Byte sent_xonxoff = XON;
unsigned send_xon = 0,
send_xoff = 0;
int endFileReceived;
/* Socket */
int sockfd; // listen on sock_fd
struct sockaddr_in adhost;
struct sockaddr_in srcAddr;
unsigned int srcLen = sizeof(srcAddr);
int main(int argc, char *argv[])
{
pthread_t thread[1];
if (argc<2) {
// case if arguments are less than specified
printf("Please use the program with arguments: %s <port>\n", argv[0]);
return 0;
}
printf("Creating socket to self in Port %s...\n", argv[1]);
if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
printf("ERROR: Create socket failed.\n");
bzero((char*) &adhost, sizeof(adhost));
adhost.sin_family = AF_INET;
adhost.sin_port = htons(atoi(argv[1]));
adhost.sin_addr.s_addr = INADDR_ANY;
if(bind(sockfd, (struct sockaddr*) &adhost, sizeof(adhost)) < 0)
error("ERROR: Binding failed.\n");
endFileReceived = 0;
memset(rxbuf, 0, sizeof(rxbuf));
/* Create child process */
if(pthread_create(&thread[0], NULL, childRProcess, 0))
error("ERROR: Failed to create thread for child.\n");
/* parent process: unlimited looping */
Byte c;
while (1) {
c = *(rcvchar(sockfd, rxq));
if (c == Endfile)
endFileReceived = 1;
}
printf("Receiving End of File... Receiver Complete!\n");
printf("Waiting for the next transmission...\n");
return 0;
}
void error(const char *message) {
perror(message);
exit(1);
}
static Byte *rcvchar(int sockfd, QTYPE *queue)
{
/* Insert code here. Read a character from socket and put it to the receive buffer.
If the number of characters in the receive buffer is above certain level, then send
XOFF and set a flag (why?). Return a pointer to the buffer where data is put. */
Byte* current;
char tempBuf[1];
char b[1];
static int counter = 1;
if (recvfrom(sockfd, tempBuf, 1, 0, (struct sockaddr *) &srcAddr, &srcLen) < 0)
error("ERROR: Failed to receive character from socket\n");
current = (Byte *) malloc(sizeof(Byte));
*current = tempBuf[0];
if (*current != Endfile) {
printf("Receiving byte no. %d: ", counter++);
switch (*current) {
case CR: printf("\'Carriage Return\'\n");
break;
case LF: printf("\'Line Feed\'\n");
break;
case Endfile:
printf("\'End of File\'\n");
break;
case 255: break;
default: printf("\'%c\'\n", *current);
break;
}
}
// adding char to buffer and resync the buffer queue
if (queue->count < 8) {
queue->rear = (queue->count > 0) ? (queue->rear+1) % 8 : queue->rear;
queue->data[queue->rear] = *current;
queue->count++;
}
// if the buffer reaches Minimum Upperlimit, send XOFF to Transmitter
if(queue->count >= (MIN_UPPERLIMIT) && sent_xonxoff == XON) {
printf("[XOFF] Buffer reached Minimum Upperlimit. Sending XOFF to transmitter...\n");
send_xoff = 1; send_xon = 0;
b[0] = sent_xonxoff = XOFF;
if(sendto(sockfd, b, 1, 0,(struct sockaddr *) &srcAddr, srcLen) < 0)
error("ERROR: Failed to send XOFF.\n");
}
return current;
}
void *childRProcess(void *threadid) {
Byte *data,
*current = NULL;
while (1) {
current = q_get(rxq, data);
// if end file, quit the process
/*if (current != NULL && endFileReceived)
break;*/
// introduce some delay here
sleep(2);
}
pthread_exit(NULL);
}
static Byte *q_get(QTYPE *queue, Byte *data)
/* q_get returns a pointer to the buffer where data is read or NULL if buffer is empty. */
{
Byte *current = NULL;
char b[1];
static int counter = 1;
/* Only consume if the buffer is not empty */
if (queue->count > 0) {
current = (Byte *) malloc(sizeof(Byte));
*current = queue->data[queue->front];
//if (*current == Endfile) exit(0);
// incrementing front (circular) and reducing number of elements
queue->front++;
if (queue->front == 8) queue->front = 0;
queue->count--;
printf("CONSUME! Consuming byte no. %d: ", counter++);
switch (*current) {
case CR: printf("\'Carriage Return\'\n");
break;
case LF: printf("\'Line Feed\'\n");
break;
case Endfile:
printf("\'End of File\'\n");
break;
case 255: break;
default: printf("\'%c\'\n", *current);
break;
}
}
/* Insert code here. Retrieve data from buffer, save it to "current" and "data"
If the number of characters in the receive buffer is below certain level, then send
XON. Increment front index and check for wraparound. */
if (queue->count <= MAX_LOWERLIMIT && sent_xonxoff == XOFF) {
printf("[XON] Buffer reaches Maximum Lowerlimit. Sending XON to transmitter...\n");
send_xon = 1; send_xoff = 0;
b[0] = sent_xonxoff = XON;
if(sendto(sockfd, b, 1, 0, (struct sockaddr *) &srcAddr, srcLen) < 0)
error("ERROR: Failed to send XON.\n");
}
// return the Byte consumed
return current;
}