-
Notifications
You must be signed in to change notification settings - Fork 0
/
stop_n_wait.cpp
99 lines (79 loc) · 2.12 KB
/
stop_n_wait.cpp
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
#include "trans_protocols.h"
StopNWait::StopNWait (int timeout, float prob_error): SendRecv(timeout, 1, 1, prob_error) {
timeout_count = 0;
}
int StopNWait::sendMsgStream (MSG_TYPE *stream, int size) {
ackbuff ack;
ACK_TYPE slast = 0;
for (int i=0; i<size; i++) {
if (sendMsg(stream[i], &slast) && acknowledge(&ack)) {
// extract slast from the ack and check it
if (EXTRACT_RNEXT(ack.ack) == slast) {
cout << "Received wrong acknowledge - expected " << !slast << " but instead " << (EXTRACT_RNEXT(ack.ack)) << endl;
i--;
} else {
cout << "Received correct acknowledge" << endl;
// update slast
slast = !slast;
}
} else
i--;
}
return 0;
}
int StopNWait::recvMsgStream (MSG_TYPE *stream, int size) {
ACK_TYPE rnext = 0;
for (int i=0; i<size; i++) {
if (!recvMsg(&stream[i], &rnext))
i--;
}
return 0;
}
int StopNWait::acknowledge (ackbuff *ack) {
struct msqid_ds msg_info;
#ifdef MANUAL_ERROR
int waiter = 0;
#endif
signal(SIGALRM, alarm_dummy);
ack->mtype = 1;
// clean the ack buffer, if filled with old ack's
if (timeout_count > 0) {
msgctl(outputChannelId, IPC_STAT, &msg_info);
if (msg_info.msg_qnum > 0) {
cout << "ack flushed: " << ack->ack << " - number or msgs: " << msg_info.msg_qnum << endl;
if (msgrcv(outputChannelId, ack, sizeof(ackbuff), 0, 0) < 0) {
cout << "Message Queue error: " << strerror(errno) << endl;
exit(1);
}
}
timeout_count = 0;
}
#ifdef MANUAL_ERROR
cout << "Shaw we go? (Y,1/N,0)" << endl;
while (waiter == 0)
cin >> waiter;
#endif
// wait for the ack or the timeout
cout << "Waiting for the acknowledge" << endl;
alarm(timeout);
if (msgrcv(outputChannelId, ack, sizeof(ackbuff), 0, 0) < 0)
if (errno != EINTR){
cout << "Message Queue error: " << strerror(errno) << endl;
exit(1);
}
cout << "ack received: " << ack->ack << endl;
// treat the result of an ack
if (alarm(0) > 0) {
// crc on the ack
if (crc(ack->ack) != 0)
cout << "Acknowledge failed on CRC check" << endl;
else
return true;
}
// treat the result of a timeout
else {
cout << "Timeout!" << endl;
//timeout++;
}
return false;
}