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