-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathreceiver.cpp
More file actions
214 lines (185 loc) · 5.85 KB
/
receiver.cpp
File metadata and controls
214 lines (185 loc) · 5.85 KB
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
207
208
209
210
211
212
213
214
#include "dcomm.h"
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <pthread.h>
#include <iostream>
// Delay to adjust speed of consumming buffer, in milliseconds
#define DELAY 500
//Maximum byte yang dapat diterima
#define MaxByte 1
//Define receive buffer size
#define RXQSIZE 8
//Jumlah buffer yang kosong untuk mengirim XON
#define minimum_upperlimit 6
//Untuk keperluan Socket
struct sockaddr_in localAddr;
struct sockaddr_in targetAddr;
unsigned int addrlen = sizeof(targetAddr);
int targetPort;
char ip[INET_ADDRSTRLEN];
int sockfd; //listen on sock_fd
//Pengaturan queue sebagai tiruan buffer
Byte rxbuf[RXQSIZE];
QTYPE rcvq = {0, 0, 0, RXQSIZE, rxbuf};
QTYPE * rxq = &rcvq;
Byte result[MAXLEN];
int recvLen;
//bool send_xon = false, send_xoff = false;
int idx = 0;
int recvCounter = 0;
int conCounter = 0;
//Deklarasi variabel pendukung
bool end = false;
bool isXOFF = false;
Byte XONXOFFACK[MaxByte];
//function declaration
static Byte *rcvchar(int sockfd, QTYPE *queue);
void q_get(QTYPE *, Byte *);
void* threadParent(void * arg);
void* threadChild(void * arg);
bool isQueueFull(QTYPE queue);
bool isQueueEmpty(QTYPE queue);
void push(QTYPE * queue, Byte c);
Byte pull(QTYPE * queue);
int main (int argc, char *argv[]) {
Byte c;
//creating socket
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0))< 0) {
perror("Cannot create socket");
return 0;
}
targetPort = atoi(argv[1]);
memset((void *)&localAddr, 0, sizeof(localAddr));
localAddr.sin_family = AF_INET;
inet_pton(AF_INET, "127.0.0.1", &(localAddr.sin_addr));
localAddr.sin_port = htons(targetPort);
localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
//Binding socket
if (bind(sockfd, (struct sockaddr *)&localAddr, sizeof(localAddr)) <0) {
perror("Bind error");
return 0;
}
memset((char *) &targetAddr, 0, sizeof(targetAddr));
targetAddr.sin_family = AF_INET;
targetAddr.sin_port = htons(targetPort);
Byte * buf = (Byte *)malloc(sizeof(Byte));
recvLen = recvfrom(sockfd, buf, MaxByte, 0, (struct sockaddr *)&targetAddr, &addrlen);
inet_ntop(AF_INET, &(targetAddr.sin_addr), ip, INET_ADDRSTRLEN);
printf("Binding pada : %s:%d...\n", ip, targetPort);
//Buat thread untuk 2 prosedur
pthread_t tid[2];
int error;
error = pthread_create(&(tid[0]), NULL, &threadParent, NULL);
if (error!=0) printf("can't create thread : %s\n", strerror(error));
error = pthread_create(&(tid[1]), NULL, &threadChild, NULL);
if (error!=0) printf("can't create thread : %s\n", strerror(error));
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
//cetak hasil yang diterima
printf("\n\n%s\n", result);
}
//Menerima karakter dari transmitter kemudian memasukkan ke queue
static Byte *rcvchar (int sockfd, QTYPE *queue) {
Byte * buf = (Byte *)malloc(sizeof(Byte));
recvLen = recvfrom(sockfd, buf, MaxByte, 0, (struct sockaddr *)&targetAddr, &addrlen);
if (!isQueueFull(*queue) && buf[0] != Endfile) { //Karakter yang diterima bukan Endfile
push(queue, buf[0]); //Memasukkan karakter ke dalam queue
}
if (buf[0] == Endfile) end = true; //Karakter yang diterima berupa Endfile
return buf;
}
//Memasukkan nilai dari queue (buffer tiruan) ke dalam array of char (I/O tiruan)
void q_get(QTYPE *queue, Byte *data) {
char current;
if (isQueueEmpty(*queue)){}
else {
usleep(DELAY*15000);
current = pull(&*queue);
printf("Mengkonsumsi byte ke-%d: '%c'\n", conCounter+1, current);
data[idx] = current;
idx++;
conCounter++;
}
}
//Thread parent sebagai thread utama untuk menghandle masuknya data dan mengirim XOFF jika buffer penuh
void* threadParent(void * arg) {
Byte * c = (Byte *)malloc(sizeof(Byte));
while (!end) { //Bukan Endfile
if (!isQueueFull(*rxq)) { //queue / buffer belum penuh
c = rcvchar(sockfd, rxq);
if (c != NULL) {
printf("Menerima byte ke-%d\n", recvCounter+1);
recvCounter++;
}
}
else { //queue penuh
if (!isXOFF) {
printf("Buffer > Minimum upperlimit\n");
if (isQueueFull(*rxq)) {
XONXOFFACK[0] = XOFF;
printf("Mengirim XOFF...\n");
if (sendto(sockfd, XONXOFFACK, MaxByte, 0, (struct sockaddr *)&targetAddr, addrlen) == -1) { //Kirim XOFF ke transmitter
perror("err");
}
isXOFF = true;
}
}
}
}
XONXOFFACK[0] = ACK;
sendto(sockfd, XONXOFFACK, MaxByte, 0, (struct sockaddr *)&targetAddr, addrlen);
}
//Thread child digunakan sebagai pengonsumsi karakter dari buffer ke I/O dan mengirimkan XON ke transmitter jika di buffer ada space > minimum upperlimit
void * threadChild(void * arg) {
while (!isQueueEmpty(*rxq) || !end) { //Buffer tidak kosong atau bukan akhir dari file
q_get(&*rxq, result); //masukkan karakter dari buffer ke I/O
if (rxq->count < minimum_upperlimit && isXOFF) { //Jika ada space kosong di buffer > minimum upperlimit, maka kirim XON
printf("Buffer < maximum lowerlimit\n");
XONXOFFACK[0] = XON;
printf("Mengirim XON...\n");
if (sendto(sockfd, XONXOFFACK, MaxByte, 0, (struct sockaddr *)&targetAddr, addrlen) == -1) { //kirim XON
}
isXOFF = false;
}
}
}
//Queue Penuh
bool isQueueFull(QTYPE queue) {
return queue.count == queue.maxsize;
}
//Queue Kosong
bool isQueueEmpty(QTYPE queue) {
return queue.count == 0;
}
//Masukkan data ke queue
void push(QTYPE * queue, Byte data) {
queue->data[queue->rear] = data;
queue->rear++;
queue->count++;
if (queue->rear == queue->maxsize) queue->rear = 0;
}
//Ambil data dari queue
Byte pull(QTYPE * queue) {
Byte c;
if (queue->front == queue->maxsize) queue->front = 0;
c = queue->data[queue->front];
queue->front++;
queue->count--;
return c;
}
bool checkchecksum(MESGB inp) {
unsigned int temp=inp.soh+inp.stx +inp.etx+(unsigned char)inp.magno;
for (int i = 0; i < inp.data.length; i++) {
temp+=(unsigned char)inp.data[i];
}
if (temp == (unsigned char)inp.checksum) return true;
return false;
}