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