]> git.mxchange.org Git - flightgear.git/blob - scripts/example/fgfsclient.cxx
Merge commit 'refs/merge-requests/13' of git://gitorious.org/fg/flightgear into next
[flightgear.git] / scripts / example / fgfsclient.cxx
1 // $Id$
2 // g++ -O2 -g -pedantic -Wall fgfsclient.cxx -o fgfsclient -lstdc++
3 // USAGE: ./fgfsclient [hostname [port]]
4 // Public Domain
5
6 #include <errno.h>
7 #include <iostream>
8 #include <netdb.h>
9 #include <netinet/in.h>
10 #include <stdarg.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <sys/socket.h>
14 #include <sys/time.h>
15 #include <sys/types.h>
16 #include <unistd.h>
17 #include <string.h>
18
19
20 const char *HOST = "localhost";
21 const unsigned PORT = 5501;
22 const int BUFLEN = 256;
23
24
25 class FGFSSocket {
26 public:
27         FGFSSocket(const char *name, unsigned port);
28         ~FGFSSocket();
29
30         int             write(const char *msg, ...);
31         const char      *read(void);
32         inline void     flush(void);
33         void            settimeout(unsigned t) { _timeout = t; }
34
35 private:
36         int             close(void);
37
38         int             _sock;
39         bool            _connected;
40         unsigned        _timeout;
41         char            _buffer[BUFLEN];
42 };
43
44
45 FGFSSocket::FGFSSocket(const char *hostname = HOST, unsigned port = PORT) :
46         _sock(-1),
47         _connected(false),
48         _timeout(1)
49 {
50         _sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
51         if (_sock < 0)
52                 throw("FGFSSocket/socket");
53
54         struct hostent *hostinfo;
55         hostinfo = gethostbyname(hostname);
56         if (!hostinfo) {
57                 close();
58                 throw("FGFSSocket/gethostbyname: unknown host");
59         }
60
61         struct sockaddr_in serv_addr;
62         serv_addr.sin_family = AF_INET;
63         serv_addr.sin_port = htons(port);
64         serv_addr.sin_addr = *(struct in_addr *)hostinfo->h_addr;
65
66         if (connect(_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
67                 close();
68                 throw("FGFSSocket/connect");
69         }
70         _connected = true;
71         try {
72                 write("data");
73         } catch (...) {
74                 close();
75                 throw;
76         }
77 }
78
79
80 FGFSSocket::~FGFSSocket()
81 {
82         close();
83 }
84
85
86 int FGFSSocket::close(void)
87 {
88         if (_connected)
89                 write("quit");
90         if (_sock < 0)
91                 return 0;
92         int ret = ::close(_sock);
93         _sock = -1;
94         return ret;
95 }
96
97
98 int FGFSSocket::write(const char *msg, ...)
99 {
100         va_list va;
101         ssize_t len;
102         char buf[BUFLEN];
103         fd_set fd;
104         struct timeval tv;
105
106         FD_ZERO(&fd);
107         FD_SET(_sock, &fd);
108         tv.tv_sec = _timeout;
109         tv.tv_usec = 0;
110         if (!select(FD_SETSIZE, 0, &fd, 0, &tv))
111                 throw("FGFSSocket::write/select: timeout exceeded");
112
113         va_start(va, msg);
114         vsnprintf(buf, BUFLEN - 2, msg, va);
115         va_end(va);
116         std::cout << "SEND: " << buf << std::endl;
117         strcat(buf, "\015\012");
118
119         len = ::write(_sock, buf, strlen(buf));
120         if (len < 0)
121                 throw("FGFSSocket::write");
122         return len;
123 }
124
125
126 const char *FGFSSocket::read(void)
127 {
128         char *p;
129         fd_set fd;
130         struct timeval tv;
131         ssize_t len;
132
133         FD_ZERO(&fd);
134         FD_SET(_sock, &fd);
135         tv.tv_sec = _timeout;
136         tv.tv_usec = 0;
137         if (!select(FD_SETSIZE, &fd, 0, 0, &tv)) {
138                 if (_timeout == 0)
139                         return 0;
140                 else
141                         throw("FGFSSocket::read/select: timeout exceeded");
142         }
143
144         len = ::read(_sock, _buffer, BUFLEN - 1);
145         if (len < 0)
146                 throw("FGFSSocket::read/read");
147         if (len == 0)
148                 return 0;
149
150         for (p = &_buffer[len - 1]; p >= _buffer; p--)
151                 if (*p != '\015' && *p != '\012')
152                         break;
153         *++p = '\0';
154         return strlen(_buffer) ? _buffer : 0;
155 }
156
157
158 inline void FGFSSocket::flush(void)
159 {
160         int i = _timeout;
161         _timeout = 0;
162         while (read())
163                 ;
164         _timeout = i;
165 }
166
167
168 int main(const int argc, const char *argv[])
169 try {
170         const char *hostname = argc > 1 ? argv[1] : "localhost";
171         int port = argc > 2 ? atoi(argv[2]) : 5501;
172
173         FGFSSocket f(hostname, port);
174         f.flush();
175         f.write("set /controls/engines/engine[%d]/throttle %lg", 0, 1.0);
176         f.write("set /controls/engines/engine[%d]/throttle %lg", 1, 1.0);
177         f.write("get /sim/aircraft");
178         const char *p = f.read();
179         if (p)
180                 std::cout << "RECV: " << p << std::endl;
181         return EXIT_SUCCESS;
182
183 } catch (const char s[]) {
184         std::cerr << "Error: " << s << ": " << strerror(errno) << std::endl;
185         return EXIT_FAILURE;
186
187 } catch (...) {
188         std::cerr << "Error: unknown exception" << std::endl;
189         return EXIT_FAILURE;
190 }
191
192
193 // vim:cindent