41 #if defined(_MSC_VER) || defined(__MINGW32__)
43 #elif defined(__OpenBSD__)
44 #include <sys/types.h>
45 #include <sys/socket.h>
55 #include "FGfdmSocket.h"
68 #if defined(_MSC_VER) || defined(__MINGW32__)
69 static bool LoadWinSockDLL(
int debug_lvl)
72 if (WSAStartup(MAKEWORD(1, 1), &wsaData)) {
73 cerr <<
"Winsock DLL not initialized ..." << endl;
78 cout <<
"Winsock DLL loaded ..." << endl;
84 FGfdmSocket::FGfdmSocket(
const string& address,
int port,
int protocol,
int precision)
87 Protocol = (ProtocolType)protocol;
89 struct addrinfo *addr =
nullptr;
90 this->precision = precision;
92 #if defined(_MSC_VER) || defined(__MINGW32__)
93 if (!LoadWinSockDLL(debug_lvl))
return;
96 struct addrinfo hints;
97 memset(&hints, 0,
sizeof(
struct addrinfo));
98 hints.ai_family = AF_INET;
99 if (protocol == ptUDP)
100 hints.ai_socktype = SOCK_DGRAM;
102 hints.ai_socktype = SOCK_STREAM;
103 hints.ai_protocol = 0;
104 if (!is_number(address))
105 hints.ai_flags = AI_ADDRCONFIG;
107 hints.ai_flags = AI_NUMERICHOST;
109 int failure = getaddrinfo(address.c_str(), NULL, &hints, &addr);
110 if (failure || !addr) {
111 cerr <<
"Could not get host net address " << address;
113 if (hints.ai_flags == AI_NUMERICHOST)
114 cerr <<
" by number..." << endl;
116 cerr <<
" by name..." << endl;
118 cerr << gai_strerror(failure) << endl;
124 sckt = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
127 if (protocol == ptUDP)
128 cout <<
"Creating UDP socket on port " << port << endl;
130 cout <<
"Creating TCP socket on port " << port << endl;
134 int len =
sizeof(
struct sockaddr_in);
135 memcpy(&scktName, addr->ai_addr, len);
136 scktName.sin_port = htons(port);
138 if (connect(sckt, (
struct sockaddr*)&scktName, len) == 0) {
140 cout <<
"Successfully connected to socket for output ..." << endl;
143 cerr <<
"Could not connect to socket for output ..." << endl;
145 cerr <<
"Could not create socket for FDM output, error = " << errno << endl;
154 FGfdmSocket::FGfdmSocket(
int port,
int protocol,
int precision)
158 Protocol = (ProtocolType)protocol;
160 this->precision = precision;
162 #if defined(_MSC_VER) || defined(__MINGW32__)
163 if (!LoadWinSockDLL(debug_lvl))
return;
166 if (Protocol == ptUDP) {
167 ProtocolName =
"UDP";
168 sckt = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
169 #if defined(_MSC_VER) || defined(__MINGW32__)
171 ioctlsocket(sckt, FIONBIO, &NonBlock);
173 fcntl(sckt, F_SETFL, O_NONBLOCK);
177 ProtocolName =
"TCP";
178 sckt = socket(AF_INET, SOCK_STREAM, 0);
182 cout <<
"Creating input " << ProtocolName <<
" socket on port " << port
186 memset(&scktName, 0,
sizeof(
struct sockaddr_in));
187 scktName.sin_family = AF_INET;
188 scktName.sin_port = htons(port);
190 if (Protocol == ptUDP)
191 scktName.sin_addr.s_addr = htonl(INADDR_ANY);
193 int len =
sizeof(
struct sockaddr_in);
194 if (bind(sckt, (
struct sockaddr*)&scktName, len) != -1) {
196 cout <<
"Successfully bound to " << ProtocolName
197 <<
" input socket on port " << port << endl << endl;
199 if (Protocol == ptTCP) {
200 if (listen(sckt, 5) >= 0) {
201 #if defined(_MSC_VER) || defined(__MINGW32__)
203 ioctlsocket(sckt, FIONBIO, &NoBlock);
204 sckt_in = accept(sckt, (
struct sockaddr*)&scktName, &len);
206 int flags = fcntl(sckt, F_GETFL, 0);
207 fcntl(sckt, F_SETFL, flags | O_NONBLOCK);
208 sckt_in = accept(sckt, (
struct sockaddr*)&scktName, (socklen_t*)&len);
212 cerr <<
"Could not listen ..." << endl;
216 cerr <<
"Could not bind to " << ProtocolName <<
" input socket, error = "
219 cerr <<
"Could not create " << ProtocolName <<
" socket for input, error = "
227 FGfdmSocket::~FGfdmSocket()
229 if (sckt) shutdown(sckt,2);
230 if (sckt_in) shutdown(sckt_in,2);
236 string FGfdmSocket::Receive(
void)
239 int len =
sizeof(
struct sockaddr_in);
244 if (sckt_in <= 0 && Protocol == ptTCP) {
245 #if defined(_MSC_VER) || defined(__MINGW32__)
246 sckt_in = accept(sckt, (
struct sockaddr*)&scktName, &len);
248 sckt_in = accept(sckt, (
struct sockaddr*)&scktName, (socklen_t*)&len);
251 #if defined(_MSC_VER) || defined(__MINGW32__)
253 ioctlsocket(sckt_in, FIONBIO, &NoBlock);
255 int flags = fcntl(sckt_in, F_GETFL, 0);
256 fcntl(sckt_in, F_SETFL, flags | O_NONBLOCK);
258 send(sckt_in,
"Connected to JSBSim server\nJSBSim> ", 35, 0);
263 while ((num_chars = recv(sckt_in, buf,
sizeof buf, 0)) > 0) {
264 data.append(buf, num_chars);
267 #if defined(_MSC_VER)
270 if (num_chars == 0) {
271 DWORD err = WSAGetLastError ();
272 if (err != WSAEWOULDBLOCK) {
273 printf (
"Socket Closed. back to listening\n");
274 closesocket (sckt_in);
282 if (sckt >= 0 && Protocol == ptUDP) {
283 struct sockaddr addr;
284 socklen_t fromlen =
sizeof addr;
285 num_chars = recvfrom(sckt, buf,
sizeof buf, 0, (
struct sockaddr*)&addr, &fromlen);
286 if (num_chars != -1) data.append(buf, num_chars);
294 int FGfdmSocket::Reply(
const string& text)
296 int num_chars_sent=0;
299 num_chars_sent = send(sckt_in, text.c_str(), text.size(), 0);
300 send(sckt_in,
"JSBSim> ", 8, 0);
302 cerr <<
"Socket reply must be to a valid socket" << endl;
305 return num_chars_sent;
310 void FGfdmSocket::Close(
void)
317 void FGfdmSocket::Clear(
void)
319 buffer.str(
string());
324 void FGfdmSocket::Clear(
const string& s)
332 void FGfdmSocket::Append(
const char* item)
334 if (buffer.tellp() > 0) buffer <<
',';
340 void FGfdmSocket::Append(
double item)
342 if (buffer.tellp() > 0) buffer <<
',';
343 buffer << std::setw(12) << std::setprecision(precision) << item;
348 void FGfdmSocket::Append(
long item)
350 if (buffer.tellp() > 0) buffer <<
',';
351 buffer << std::setw(12) << item;
356 void FGfdmSocket::Send(
void)
359 string str = buffer.str();
360 if ((send(sckt,str.c_str(),str.size(),0)) <= 0) {
367 void FGfdmSocket::Send(
const char *data,
int length)
369 if ((send(sckt,data,length,0)) <= 0) {
376 void FGfdmSocket::WaitUntilReadable(
void)
383 FD_SET(sckt_in, &fds);
384 select(sckt_in+1, &fds, NULL, NULL, NULL);
416 void FGfdmSocket::Debug(
int from)
418 if (debug_lvl <= 0)
return;
424 if (debug_lvl & 2 ) {
425 if (from == 0) cout <<
"Instantiated: FGfdmSocket" << endl;
426 if (from == 1) cout <<
"Destroyed: FGfdmSocket" << endl;
428 if (debug_lvl & 4 ) {
430 if (debug_lvl & 8 ) {
432 if (debug_lvl & 16) {
434 if (debug_lvl & 64) {