-
Notifications
You must be signed in to change notification settings - Fork 0
/
TcpMessage.cpp
124 lines (109 loc) · 3.09 KB
/
TcpMessage.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
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
#include "TcpMessage.h"
#include <iostream>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
using namespace std;
TcpMessage::TcpMessage(uint16_t seq, uint16_t ack, uint16_t recvWind, string tcpFlags) {
seqNum = seq;
ackNum = ack;
recvWindow = recvWind;
setFlag(tcpFlags);
}
TcpMessage::TcpMessage() {}
bool TcpMessage::setFlag(string flag) {
for (size_t i = 0; i < flag.size(); i++){
switch (flag[i]) {
case 'A':
case 'a':
flags |= ACK_FLAG;
break;
case 'F':
case 'f':
flags |= FIN_FLAG;
break;
case 'S':
case 's':
flags |= SYN_FLAG;
break;
default:
// cerr << "flag parameter must be A, F or S";
return false;
}
}
return true;
}
bool TcpMessage::getFlag(char flag) {
switch (flag) {
case 'A':
case 'a':
return !!(flags & ACK_FLAG);
case 'F':
case 'f':
return !!(flags & FIN_FLAG);
case 'S':
case 's':
return !!(flags & SYN_FLAG);
default:
// cerr << "flag parameter must be A, F or S";
return false;
}
}
//Converts a char buffer from recvfrom into a TcpMessage object
void TcpMessage::bufferToMessage(uint8_t* buf, size_t size) {
seqNum = ((buf[0] << 8) + buf[1]);
ackNum = ((buf[2] << 8) + buf[3]);
recvWindow = ((buf[4] << 8) + buf[5]);
flags = buf[7] & 0xff;
data.assign((char*)buf+8, size-8);
return;
}
//Solves the halting problem
size_t TcpMessage::messageToBuffer(uint8_t* b) {
//Probably a better way to do this...
b[0] = (seqNum >> 8) & 0xff;
b[1] = seqNum & 0xff;
b[2] = (ackNum >> 8) & 0xff;
b[3] = ackNum & 0xff;
b[4] = recvWindow >> 8;
b[5] = recvWindow & 0xff;
b[6] = 0x0;
b[7] = flags;
data.copy((char*)b + 8, data.size(), 0);
// 8 byte header + body
return HEADER_SIZE + data.size();
}
void TcpMessage::sendto(int sockfd, sockaddr_in *si_other, socklen_t len) {
uint8_t buf[BUFFER_SIZE];
size_t msgLen = messageToBuffer(buf);
if (::sendto(sockfd, buf, msgLen, 0, (sockaddr*)si_other, len) == -1) {
perror("sendto");
exit(1);
}
}
int TcpMessage::recvfrom(int sockfd, sockaddr_in *si_other, socklen_t len) {
uint8_t buf[BUFFER_SIZE];
int recv_len = ::recvfrom(sockfd, buf, BUFFER_SIZE, 0, (sockaddr*)si_other, &len);
if (recv_len == -1) {
if (errno == EWOULDBLOCK) {
// cerr << "timeout\n";
return RECV_TIMEOUT;
}
perror("recvfrom");
exit(1);
}
bufferToMessage(buf, recv_len);
return RECV_SUCCESS;
}
// Print out the TcpMessage's contents
void TcpMessage::dump() {
// cerr << "seqNum = " << seqNum << '\t';
// cerr << "ackNum = " << ackNum << '\t';
// cerr << "recvWindow = " << recvWindow << endl;
// cerr << "FIN_FLAG = " << getFlag('f') << '\t';
// cerr << "SYN_FLAG = " << getFlag('s') << '\t';
// cerr << "ACK_FLAG = " << getFlag('a') << endl;
// cerr << "data.size() = " << data.size() << endl;
// cerr << endl;
}