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