-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfgfsconnectclient.cpp
161 lines (133 loc) · 3.71 KB
/
fgfsconnectclient.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
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
#include "fgfsconnectclient.h"
const char* HOST = "localhost";
const unsigned PORT = 5400;
const int BUFLEN = 256;
FGFSSocket::FGFSSocket(const char* hostname = HOST, unsigned port = PORT) : _sock(-1),
_connected(false),
_timeout(1)
{
_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (_sock < 0)
throw("FGFSSocket/socket");
struct hostent* hostinfo;
hostinfo = gethostbyname(hostname);
if (!hostinfo) {
close();
throw("FGFSSocket/gethostbyname: unknown host");
}
struct sockaddr_in serv_addr;
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
serv_addr.sin_addr = *(struct in_addr*)hostinfo->h_addr;
if (connect(_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
close();
throw("FGFSSocket/connect");
}
_connected = true;
try {
write("data");
} catch (...) {
close();
throw;
}
}
FGFSSocket::~FGFSSocket()
{
_isShutdown = true;
close();
}
int FGFSSocket::close(void)
{
if (_connected)
write("quit");
if (_sock < 0)
return 0;
int ret = ::close(_sock);
_sock = -1;
return ret;
}
int FGFSSocket::write(const char* msg, ...)
{
va_list va;
ssize_t len;
char buf[BUFLEN];
fd_set fd;
struct timeval tv;
FD_ZERO(&fd);
FD_SET(_sock, &fd);
tv.tv_sec = _timeout;
tv.tv_usec = 0;
if (!select(FD_SETSIZE, 0, &fd, 0, &tv))
if (_isShutdown) // don't throw during dtor
std::cout << "FGFSSocket::write/select: timeout exceeded" << std::endl;
else
throw("FGFSSocket::write/select: timeout exceeded");
va_start(va, msg);
vsnprintf(buf, BUFLEN - 2, msg, va);
va_end(va);
std::cout << "SEND: " << buf << std::endl;
strcat(buf, "\015\012");
len = ::write(_sock, buf, strlen(buf));
if (len < 0)
if (_isShutdown) // don't throw during dtor
std::cout << "FGFSSocket::write error" << std::endl;
else
throw("FGFSSocket::write");
return len;
}
const char* FGFSSocket::read(void)
{
char* p;
fd_set fd;
struct timeval tv;
ssize_t len;
FD_ZERO(&fd);
FD_SET(_sock, &fd);
tv.tv_sec = _timeout;
tv.tv_usec = 0;
if (!select(FD_SETSIZE, &fd, 0, 0, &tv)) {
if (_timeout == 0)
return 0;
else
throw("FGFSSocket::read/select: timeout exceeded");
}
len = ::read(_sock, _buffer, BUFLEN - 1);
if (len < 0)
throw("FGFSSocket::read/read");
if (len == 0)
return 0;
for (p = &_buffer[len - 1]; p >= _buffer; p--)
if (*p != '\015' && *p != '\012')
break;
*++p = '\0';
return strlen(_buffer) ? _buffer : 0;
}
inline void FGFSSocket::flush(void)
{
int i = _timeout;
_timeout = 0;
while (read())
;
_timeout = i;
}
int main(const int argc, const char* argv[])
try {
const char* hostname = argc > 1 ? argv[1] : "localhost";
int port = argc > 2 ? atoi(argv[2]) : 5400;
FGFSSocket f(hostname, port);
f.flush();
f.write("set /controls/engines/engine[%d]/throttle %lg", 0, 1.0);
f.write("set /controls/engines/engine[%d]/throttle %lg", 1, 1.0);
f.write("get /sim/aircraft");
const char* p = f.read();
if (p)
std::cout << "RECV: " << p << std::endl;
return EXIT_SUCCESS;
} catch (const char s[]) {
std::cerr << "Error: " << s << ": " << strerror(errno) << std::endl;
return EXIT_FAILURE;
} catch (...) {
std::cerr << "Error: unknown exception" << std::endl;
return EXIT_FAILURE;
}
// vim:cindent