]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/input_output/FGfdmSocket.cpp
Clean up header file use of iostream and "using" declarations
[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 #include <iostream>
42
43 #include "FGfdmSocket.h"
44
45 namespace JSBSim {
46
47 static const char *IdSrc = "$Id$";
48 static const char *IdHdr = ID_FDMSOCKET;
49
50 using std::cerr;
51 using std::cout;
52 using std::endl;
53
54 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
55 CLASS IMPLEMENTATION
56 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
57
58 FGfdmSocket::FGfdmSocket(string address, int port)
59 {
60   sckt = sckt_in = size = 0;
61   connected = false;
62
63   #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
64     WSADATA wsaData;
65     int wsaReturnCode;
66     wsaReturnCode = WSAStartup(MAKEWORD(1,1), &wsaData);
67     if (wsaReturnCode == 0) cout << "Winsock DLL loaded ..." << endl;
68     else cout << "Winsock DLL not initialized ..." << endl;
69   #endif
70
71   if (address.find_first_not_of("0123456789.",0) != address.npos) {
72     if ((host = gethostbyname(address.c_str())) == NULL) {
73       cout << "Could not get host net address by name..." << endl;
74     }
75   } else {
76     if ((host = gethostbyaddr(address.c_str(), address.size(), PF_INET)) == NULL) {
77       cout << "Could not get host net address by number..." << endl;
78     }
79   }
80
81   if (host != NULL) {
82     cout << "Got host net address..." << endl;
83     sckt = socket(AF_INET, SOCK_STREAM, 0);
84
85     if (sckt >= 0) {  // successful
86       memset(&scktName, 0, sizeof(struct sockaddr_in));
87       scktName.sin_family = AF_INET;
88       scktName.sin_port = htons(port);
89       std::memcpy(&scktName.sin_addr, host->h_addr_list[0], host->h_length);
90       int len = sizeof(struct sockaddr_in);
91       if (connect(sckt, (struct sockaddr*)&scktName, len) == 0) {   // successful
92         cout << "Successfully connected to socket for output ..." << endl;
93         connected = true;
94       } else {                // unsuccessful
95         cout << "Could not connect to socket for output ..." << endl;
96       }
97     } else {          // unsuccessful
98       cout << "Could not create socket for FDM output, error = " << errno << endl;
99     }
100   }
101   Debug(0);
102 }
103
104 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
105
106 FGfdmSocket::FGfdmSocket(int port)
107 {
108   size = 0;
109   connected = false;
110   unsigned long NoBlock = true;
111
112   #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
113     WSADATA wsaData;
114     int wsaReturnCode;
115     wsaReturnCode = WSAStartup(MAKEWORD(1,1), &wsaData);
116     if (wsaReturnCode == 0) cout << "Winsock DLL loaded ..." << endl;
117     else cerr << "Winsock DLL not initialized ..." << endl;
118   #endif
119
120   sckt = socket(AF_INET, SOCK_STREAM, 0);
121
122   if (sckt >= 0) {  // successful
123     std::memset(&scktName, 0, sizeof(struct sockaddr_in));
124     scktName.sin_family = AF_INET;
125     scktName.sin_port = htons(port);
126     int len = sizeof(struct sockaddr_in);
127     if (bind(sckt, (struct sockaddr*)&scktName, len) == 0) {   // successful
128       cout << "Successfully bound to socket for input on port " << port << endl;
129       if (listen(sckt, 5) >= 0) { // successful listen()
130         #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
131           ioctlsocket(sckt, FIONBIO, &NoBlock);
132           sckt_in = accept(sckt, (struct sockaddr*)&scktName, &len);
133         #else
134           ioctl(sckt, FIONBIO, &NoBlock);
135           sckt_in = accept(sckt, (struct sockaddr*)&scktName, (socklen_t*)&len);
136         #endif
137       } else {
138         cerr << "Could not listen ..." << endl;
139       }
140       connected = true;
141     } else {                // unsuccessful
142       cerr << "Could not bind to socket for input ..." << endl;
143     }
144   } else {          // unsuccessful
145     cerr << "Could not create socket for FDM input, error = " << errno << endl;
146   }
147
148   Debug(0);
149 }
150
151 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
152
153 FGfdmSocket::~FGfdmSocket()
154 {
155   #ifndef macintosh
156   if (sckt) shutdown(sckt,2);
157   if (sckt_in) shutdown(sckt_in,2);
158   #endif
159
160   #ifdef __BORLANDC__
161     WSACleanup();
162   #endif
163   Debug(1);
164 }
165
166 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
167
168 string FGfdmSocket::Receive(void)
169 {
170   char buf[1024];
171   int len = sizeof(struct sockaddr_in);
172   int num_chars=0;
173   int total_chars = 0;
174   unsigned long NoBlock = true;
175   string data = ""; // todo: should allocate this with a standard size as a
176                     // class attribute and pass as a reference?
177
178   if (sckt_in <= 0) {
179     #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
180       sckt_in = accept(sckt, (struct sockaddr*)&scktName, &len);
181     #else
182       sckt_in = accept(sckt, (struct sockaddr*)&scktName, (socklen_t*)&len);
183     #endif
184     if (sckt_in > 0) {
185       #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
186          ioctlsocket(sckt_in, FIONBIO,&NoBlock);
187       #else
188          ioctl(sckt_in, FIONBIO, &NoBlock);
189       #endif
190       send(sckt_in, "Connected to JSBSim server\nJSBSim> ", 35, 0);
191     }
192   }
193
194   if (sckt_in > 0) {
195     while ((num_chars = recv(sckt_in, buf, 1024, 0)) > 0) {
196       data += string(buf).substr(0,num_chars);
197       total_chars += num_chars;
198     }
199
200 #if defined(_MSC_VER)
201     // when nothing received and the error isn't "would block"
202     // then assume that the client has closed the socket.
203     if (num_chars == 0) {
204         DWORD err = WSAGetLastError ();
205         if (err != WSAEWOULDBLOCK) {
206             printf ("Socket Closed. back to listening\n");
207             closesocket (sckt_in);
208             sckt_in = -1;
209         }
210     }
211 #endif
212   }
213
214   return data.substr(0, total_chars);
215 }
216
217 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
218
219 int FGfdmSocket::Reply(string text)
220 {
221   int num_chars_sent=0;
222
223   if (sckt_in >= 0) {
224     num_chars_sent = send(sckt_in, text.c_str(), text.size(), 0);
225     send(sckt_in, "JSBSim> ", 8, 0);
226   } else {
227     cerr << "Socket reply must be to a valid socket" << endl;
228     return -1;
229   }
230   return num_chars_sent;
231 }
232
233 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
234
235 void FGfdmSocket::Close(void)
236 {
237   close(sckt_in);
238 }
239
240 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
241
242 void FGfdmSocket::Clear(void)
243 {
244   buffer = "";
245   size = 0;
246 }
247
248 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
249
250 void FGfdmSocket::Clear(string s)
251 {
252   buffer = s + " ";
253   size = buffer.size();
254 }
255
256 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
257
258 void FGfdmSocket::Append(const char* item)
259 {
260   if (size == 0) buffer += string(item);
261   else buffer += string(",") + string(item);
262   size++;
263 }
264
265 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
266
267 void FGfdmSocket::Append(double item)
268 {
269   char s[25];
270
271   sprintf(s,"%12.7f",item);
272
273   if (size == 0) buffer += string(s);
274   else buffer += string(",") + string(s);
275   size++;
276 }
277
278 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
279
280 void FGfdmSocket::Append(long item)
281 {
282   char s[25];
283
284   sprintf(s,"%12ld",item);
285
286   if (size == 0) buffer += string(s);
287   else buffer += string(",") + string(s);
288   size++;
289 }
290
291 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
292
293 void FGfdmSocket::Send(void)
294 {
295   buffer += string("\n");
296   if ((send(sckt,buffer.c_str(),buffer.size(),0)) <= 0) {
297     perror("send");
298   } else {
299   }
300 }
301
302 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
303 //    The bitmasked value choices are as follows:
304 //    unset: In this case (the default) JSBSim would only print
305 //       out the normally expected messages, essentially echoing
306 //       the config files as they are read. If the environment
307 //       variable is not set, debug_lvl is set to 1 internally
308 //    0: This requests JSBSim not to output any messages
309 //       whatsoever.
310 //    1: This value explicity requests the normal JSBSim
311 //       startup messages
312 //    2: This value asks for a message to be printed out when
313 //       a class is instantiated
314 //    4: When this value is set, a message is displayed when a
315 //       FGModel object executes its Run() method
316 //    8: When this value is set, various runtime state variables
317 //       are printed out periodically
318 //    16: When set various parameters are sanity checked and
319 //       a message is printed out when they go out of bounds
320
321 void FGfdmSocket::Debug(int from)
322 {
323   if (debug_lvl <= 0) return;
324
325   if (debug_lvl & 1) { // Standard console startup message output
326     if (from == 0) { // Constructor
327     }
328   }
329   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
330     if (from == 0) cout << "Instantiated: FGfdmSocket" << endl;
331     if (from == 1) cout << "Destroyed:    FGfdmSocket" << endl;
332   }
333   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
334   }
335   if (debug_lvl & 8 ) { // Runtime state variables
336   }
337   if (debug_lvl & 16) { // Sanity checking
338   }
339   if (debug_lvl & 64) {
340     if (from == 0) { // Constructor
341       cout << IdSrc << endl;
342       cout << IdHdr << endl;
343     }
344   }
345 }
346 }