]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/input_output/FGfdmSocket.cpp
Fixes for compiling with gcc 4.3
[flightgear.git] / src / FDM / JSBSim / input_output / FGfdmSocket.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3  Module:       FGfdmSocket.cpp
4  Author:       Jon S. Berndt
5  Date started: 11/08/99
6  Purpose:      Encapsulates a socket
7  Called by:    FGOutput, et. al.
8
9  ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------
10
11  This program is free software; you can redistribute it and/or modify it under
12  the terms of the GNU Lesser General Public License as published by the Free Software
13  Foundation; either version 2 of the License, or (at your option) any later
14  version.
15
16  This program is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18  FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
19  details.
20
21  You should have received a copy of the GNU Lesser General Public License along with
22  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
23  Place - Suite 330, Boston, MA  02111-1307, USA.
24
25  Further information about the GNU Lesser General Public License can also be found on
26  the world wide web at http://www.gnu.org.
27
28 FUNCTIONAL DESCRIPTION
29 --------------------------------------------------------------------------------
30 This class excapsulates a socket for simple data writing
31
32 HISTORY
33 --------------------------------------------------------------------------------
34 11/08/99   JSB   Created
35
36 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
37 INCLUDES
38 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
39
40 #include <cstring>
41
42 #include "FGfdmSocket.h"
43
44 namespace JSBSim {
45
46 static const char *IdSrc = "$Id$";
47 static const char *IdHdr = ID_FDMSOCKET;
48
49 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
50 CLASS IMPLEMENTATION
51 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
52
53 FGfdmSocket::FGfdmSocket(string address, int port)
54 {
55   sckt = sckt_in = size = 0;
56   connected = false;
57
58   #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
59     WSADATA wsaData;
60     int wsaReturnCode;
61     wsaReturnCode = WSAStartup(MAKEWORD(1,1), &wsaData);
62     if (wsaReturnCode == 0) cout << "Winsock DLL loaded ..." << endl;
63     else cout << "Winsock DLL not initialized ..." << endl;
64   #endif
65
66   if (address.find_first_not_of("0123456789.",0) != address.npos) {
67     if ((host = gethostbyname(address.c_str())) == NULL) {
68       cout << "Could not get host net address by name..." << endl;
69     }
70   } else {
71     if ((host = gethostbyaddr(address.c_str(), address.size(), PF_INET)) == NULL) {
72       cout << "Could not get host net address by number..." << endl;
73     }
74   }
75
76   if (host != NULL) {
77     cout << "Got host net address..." << endl;
78     sckt = socket(AF_INET, SOCK_STREAM, 0);
79
80     if (sckt >= 0) {  // successful
81       memset(&scktName, 0, sizeof(struct sockaddr_in));
82       scktName.sin_family = AF_INET;
83       scktName.sin_port = htons(port);
84       std::memcpy(&scktName.sin_addr, host->h_addr_list[0], host->h_length);
85       int len = sizeof(struct sockaddr_in);
86       if (connect(sckt, (struct sockaddr*)&scktName, len) == 0) {   // successful
87         cout << "Successfully connected to socket for output ..." << endl;
88         connected = true;
89       } else {                // unsuccessful
90         cout << "Could not connect to socket for output ..." << endl;
91       }
92     } else {          // unsuccessful
93       cout << "Could not create socket for FDM output, error = " << errno << endl;
94     }
95   }
96   Debug(0);
97 }
98
99 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
100
101 FGfdmSocket::FGfdmSocket(int port)
102 {
103   size = 0;
104   connected = false;
105   unsigned long NoBlock = true;
106
107   #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
108     WSADATA wsaData;
109     int wsaReturnCode;
110     wsaReturnCode = WSAStartup(MAKEWORD(1,1), &wsaData);
111     if (wsaReturnCode == 0) cout << "Winsock DLL loaded ..." << endl;
112     else cerr << "Winsock DLL not initialized ..." << endl;
113   #endif
114
115   sckt = socket(AF_INET, SOCK_STREAM, 0);
116
117   if (sckt >= 0) {  // successful
118     std::memset(&scktName, 0, sizeof(struct sockaddr_in));
119     scktName.sin_family = AF_INET;
120     scktName.sin_port = htons(port);
121     int len = sizeof(struct sockaddr_in);
122     if (bind(sckt, (struct sockaddr*)&scktName, len) == 0) {   // successful
123       cout << "Successfully bound to socket for input on port " << port << endl;
124       if (listen(sckt, 5) >= 0) { // successful listen()
125         #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
126           ioctlsocket(sckt, FIONBIO, &NoBlock);
127           sckt_in = accept(sckt, (struct sockaddr*)&scktName, &len);
128         #else
129           ioctl(sckt, FIONBIO, &NoBlock);
130           sckt_in = accept(sckt, (struct sockaddr*)&scktName, (socklen_t*)&len);
131         #endif
132       } else {
133         cerr << "Could not listen ..." << endl;
134       }
135       connected = true;
136     } else {                // unsuccessful
137       cerr << "Could not bind to socket for input ..." << endl;
138     }
139   } else {          // unsuccessful
140     cerr << "Could not create socket for FDM input, error = " << errno << endl;
141   }
142
143   Debug(0);
144 }
145
146 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
147
148 FGfdmSocket::~FGfdmSocket()
149 {
150   #ifndef macintosh
151   if (sckt) shutdown(sckt,2);
152   if (sckt_in) shutdown(sckt_in,2);
153   #endif
154
155   #ifdef __BORLANDC__
156     WSACleanup();
157   #endif
158   Debug(1);
159 }
160
161 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
162
163 string FGfdmSocket::Receive(void)
164 {
165   char buf[1024];
166   int len = sizeof(struct sockaddr_in);
167   int num_chars=0;
168   int total_chars = 0;
169   unsigned long NoBlock = true;
170   string data = ""; // todo: should allocate this with a standard size as a
171                     // class attribute and pass as a reference?
172
173   if (sckt_in <= 0) {
174     #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
175       sckt_in = accept(sckt, (struct sockaddr*)&scktName, &len);
176     #else
177       sckt_in = accept(sckt, (struct sockaddr*)&scktName, (socklen_t*)&len);
178     #endif
179     if (sckt_in > 0) {
180       #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
181          ioctlsocket(sckt_in, FIONBIO,&NoBlock);
182       #else
183          ioctl(sckt_in, FIONBIO, &NoBlock);
184       #endif
185       send(sckt_in, "Connected to JSBSim server\nJSBSim> ", 35, 0);
186     }
187   }
188
189   if (sckt_in > 0) {
190     while ((num_chars = recv(sckt_in, buf, 1024, 0)) > 0) {
191       data += string(buf).substr(0,num_chars);
192       total_chars += num_chars;
193     }
194
195 #if defined(_MSC_VER)
196     // when nothing received and the error isn't "would block"
197     // then assume that the client has closed the socket.
198     if (num_chars == 0) {
199         DWORD err = WSAGetLastError ();
200         if (err != WSAEWOULDBLOCK) {
201             printf ("Socket Closed. back to listening\n");
202             closesocket (sckt_in);
203             sckt_in = -1;
204         }
205     }
206 #endif
207   }
208
209   return data.substr(0, total_chars);
210 }
211
212 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
213
214 int FGfdmSocket::Reply(string text)
215 {
216   int num_chars_sent=0;
217
218   if (sckt_in >= 0) {
219     num_chars_sent = send(sckt_in, text.c_str(), text.size(), 0);
220     send(sckt_in, "JSBSim> ", 8, 0);
221   } else {
222     cerr << "Socket reply must be to a valid socket" << endl;
223     return -1;
224   }
225   return num_chars_sent;
226 }
227
228 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
229
230 void FGfdmSocket::Close(void)
231 {
232   close(sckt_in);
233 }
234
235 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
236
237 void FGfdmSocket::Clear(void)
238 {
239   buffer = "";
240   size = 0;
241 }
242
243 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
244
245 void FGfdmSocket::Clear(string s)
246 {
247   buffer = s + " ";
248   size = buffer.size();
249 }
250
251 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
252
253 void FGfdmSocket::Append(const char* item)
254 {
255   if (size == 0) buffer += string(item);
256   else buffer += string(",") + string(item);
257   size++;
258 }
259
260 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
261
262 void FGfdmSocket::Append(double item)
263 {
264   char s[25];
265
266   sprintf(s,"%12.7f",item);
267
268   if (size == 0) buffer += string(s);
269   else buffer += string(",") + string(s);
270   size++;
271 }
272
273 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
274
275 void FGfdmSocket::Append(long item)
276 {
277   char s[25];
278
279   sprintf(s,"%12ld",item);
280
281   if (size == 0) buffer += string(s);
282   else buffer += string(",") + string(s);
283   size++;
284 }
285
286 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
287
288 void FGfdmSocket::Send(void)
289 {
290   buffer += string("\n");
291   if ((send(sckt,buffer.c_str(),buffer.size(),0)) <= 0) {
292     perror("send");
293   } else {
294   }
295 }
296
297 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
298 //    The bitmasked value choices are as follows:
299 //    unset: In this case (the default) JSBSim would only print
300 //       out the normally expected messages, essentially echoing
301 //       the config files as they are read. If the environment
302 //       variable is not set, debug_lvl is set to 1 internally
303 //    0: This requests JSBSim not to output any messages
304 //       whatsoever.
305 //    1: This value explicity requests the normal JSBSim
306 //       startup messages
307 //    2: This value asks for a message to be printed out when
308 //       a class is instantiated
309 //    4: When this value is set, a message is displayed when a
310 //       FGModel object executes its Run() method
311 //    8: When this value is set, various runtime state variables
312 //       are printed out periodically
313 //    16: When set various parameters are sanity checked and
314 //       a message is printed out when they go out of bounds
315
316 void FGfdmSocket::Debug(int from)
317 {
318   if (debug_lvl <= 0) return;
319
320   if (debug_lvl & 1) { // Standard console startup message output
321     if (from == 0) { // Constructor
322     }
323   }
324   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
325     if (from == 0) cout << "Instantiated: FGfdmSocket" << endl;
326     if (from == 1) cout << "Destroyed:    FGfdmSocket" << endl;
327   }
328   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
329   }
330   if (debug_lvl & 8 ) { // Runtime state variables
331   }
332   if (debug_lvl & 16) { // Sanity checking
333   }
334   if (debug_lvl & 64) {
335     if (from == 0) { // Constructor
336       cout << IdSrc << endl;
337       cout << IdHdr << endl;
338     }
339   }
340 }
341 }