00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef HAVE_CONFIG_H
00025 # include <simgear_config.h>
00026 #endif
00027
00028 #include <simgear/compiler.h>
00029
00030 #if defined( sgi )
00031 #include <strings.h>
00032 #endif
00033
00034 #include <iostream>
00035
00036 #include <simgear/debug/logstream.hxx>
00037
00038 #include "sg_socket.hxx"
00039
00040 bool SGSocket::init = false;
00041
00042 SGSocket::SGSocket( const string& host, const string& port_,
00043 const string& style ) :
00044 hostname(host),
00045 port_str(port_),
00046 save_len(0),
00047 client(0),
00048 is_tcp(false),
00049 is_server(false),
00050 first_read(false),
00051 timeout(0)
00052 {
00053 if (!init)
00054 {
00055 netInit(NULL, NULL);
00056 init = true;
00057 }
00058
00059 if ( style == "tcp" )
00060 {
00061 is_tcp = true;
00062 }
00063 else if ( style != "udp" )
00064 {
00065 SG_LOG( SG_IO, SG_ALERT,
00066 "Error: SGSocket() unknown style = " << style );
00067 }
00068
00069 set_type( sgSocketType );
00070 }
00071
00072
00073 SGSocket::~SGSocket()
00074 {
00075 this->close();
00076 }
00077
00078
00079 bool
00080 SGSocket::make_server_socket()
00081 {
00082 if (!sock.open( is_tcp ))
00083 {
00084 SG_LOG( SG_IO, SG_ALERT,
00085 "Error: socket() failed in make_server_socket()" );
00086 return false;
00087 }
00088
00089 if (sock.bind( "", port ) < 0)
00090 {
00091 SG_LOG( SG_IO, SG_ALERT,
00092 "Error: bind() failed in make_server_socket()" );
00093 sock.close();
00094 return false;
00095 }
00096
00097 return true;
00098 }
00099
00100
00101 bool
00102 SGSocket::make_client_socket()
00103 {
00104 if (!sock.open( is_tcp ))
00105 {
00106 SG_LOG( SG_IO, SG_ALERT,
00107 "Error: socket() failed in make_client_socket()" );
00108 return false;
00109 }
00110
00111 if (sock.connect( hostname.c_str(), port ) < 0)
00112 {
00113 SG_LOG( SG_IO, SG_ALERT,
00114 "Error: connect() failed in make_client_socket()" );
00115 sock.close();
00116 return false;
00117 }
00118
00119 return true;
00120 }
00121
00122
00123
00124
00125 bool
00126 SGSocket::open( SGProtocolDir direction )
00127 {
00128 set_dir( direction );
00129
00130 is_server = is_tcp &&
00131 (direction == SG_IO_IN || direction == SG_IO_BI);
00132
00133 if ( port_str == "" || port_str == "any" ) {
00134 port = 0;
00135 } else {
00136 port = atoi( port_str.c_str() );
00137 }
00138
00139 if (direction == SG_IO_IN)
00140 {
00141
00142
00143
00144
00145
00146 if (!make_server_socket())
00147 {
00148 SG_LOG( SG_IO, SG_ALERT, "SG_IO_IN socket creation failed" );
00149 return false;
00150 }
00151
00152 if ( !is_tcp )
00153 {
00154
00155 nonblock();
00156 }
00157 else
00158 {
00159
00160
00161 sock.listen( SG_MAX_SOCKET_QUEUE );
00162 }
00163
00164 }
00165 else if (direction == SG_IO_OUT)
00166 {
00167
00168
00169 if (!make_client_socket())
00170 {
00171 SG_LOG( SG_IO, SG_ALERT, "SG_IO_OUT socket creation failed" );
00172 return false;
00173 }
00174
00175 if ( !is_tcp )
00176 {
00177
00178 nonblock();
00179 }
00180 }
00181 else if (direction == SG_IO_BI && is_tcp)
00182 {
00183
00184
00185
00186
00187
00188 if (!make_server_socket())
00189 {
00190 SG_LOG( SG_IO, SG_ALERT, "SG_IO_BI socket creation failed" );
00191 return false;
00192 }
00193
00194
00195 sock.listen( SG_MAX_SOCKET_QUEUE );
00196 }
00197 else
00198 {
00199 SG_LOG( SG_IO, SG_ALERT,
00200 "Error: bidirection mode not available for UDP sockets." );
00201 return false;
00202 }
00203
00204 first_read = false;
00205
00206 return true;
00207 }
00208
00209
00210
00211
00212 int
00213 SGSocket::read( char *buf, int length )
00214 {
00215 if (sock.getHandle() == -1 &&
00216 (client == 0 || client->getHandle() == -1))
00217 {
00218 return 0;
00219 }
00220
00221
00222
00223 int result = poll();
00224
00225 if (result > 0)
00226 {
00227 if (is_tcp && is_server)
00228 {
00229 result = client->recv( buf, length );
00230 }
00231 else
00232 {
00233 result = sock.recv( buf, length );
00234 }
00235
00236 if ( result != length )
00237 {
00238 SG_LOG( SG_IO, SG_INFO,
00239 "Warning: read() not enough bytes." );
00240 }
00241 }
00242
00243 return result;
00244 }
00245
00246
00247
00248 int
00249 SGSocket::readline( char *buf, int length )
00250 {
00251 if (sock.getHandle() == -1 &&
00252 (client == 0 || client->getHandle() == -1))
00253 {
00254 return 0;
00255 }
00256
00257
00258
00259 int result = this->poll();
00260
00261 if (result > 0)
00262 {
00263
00264
00265
00266 if (is_tcp && is_server)
00267 {
00268 char *buf_ptr = save_buf + save_len;
00269 result = client->recv( buf_ptr, SG_IO_MAX_MSG_SIZE - save_len );
00270
00271 if ( result > 0 )
00272 {
00273 first_read = true;
00274 }
00275
00276 save_len += result;
00277
00278
00279
00280
00281 if (result == 0 && save_len == 0 && first_read == true)
00282 {
00283 SG_LOG( SG_IO, SG_ALERT,
00284 "Connection closed by foreign host." );
00285 delete client;
00286 client = 0;
00287 }
00288 }
00289 else
00290 {
00291 char *buf_ptr = save_buf + save_len;
00292 result = sock.recv( buf_ptr, SG_IO_MAX_MSG_SIZE - save_len );
00293 save_len += result;
00294 }
00295 }
00296
00297
00298 int i;
00299 for ( i = 0; i < save_len && save_buf[i] != '\n'; ++i )
00300 ;
00301 if ( save_buf[i] == '\n' ) {
00302 result = i + 1;
00303 } else {
00304
00305 return 0;
00306 }
00307
00308
00309
00310
00311 strncpy( buf, save_buf, result );
00312 buf[result] = '\0';
00313
00314
00315
00316 for ( i = result; i < save_len; ++i ) {
00317 save_buf[ i - result ] = save_buf[i];
00318 }
00319 save_len -= result;
00320
00321 return result;
00322 }
00323
00324
00325
00326 int
00327 SGSocket::write( const char *buf, const int length )
00328 {
00329 netSocket* s = client == 0 ? &sock : client;
00330 if (s->getHandle() == -1)
00331 {
00332 return 0;
00333 }
00334
00335 bool error_condition = false;
00336
00337 if ( s->send( buf, length ) < 0 )
00338 {
00339 SG_LOG( SG_IO, SG_WARN, "Error writing to socket: " << port );
00340 error_condition = true;
00341 }
00342
00343 if ( error_condition ) {
00344 return 0;
00345 }
00346
00347 return length;
00348 }
00349
00350
00351
00352 int
00353 SGSocket::writestring( const char *str )
00354 {
00355 int length = strlen( str );
00356 return this->write( str, length );
00357 }
00358
00359
00360
00361 bool
00362 SGSocket::close()
00363 {
00364 delete client;
00365 client = 0;
00366
00367 sock.close();
00368 return true;
00369 }
00370
00371
00372
00373 bool
00374 SGSocket::nonblock()
00375 {
00376 if (sock.getHandle() == -1) {
00377 return false;
00378 }
00379
00380 sock.setBlocking( false );
00381 return true;
00382 }
00383
00384 int
00385 SGSocket::poll()
00386 {
00387 netSocket* readers[2];
00388
00389 readers[0] = client != 0 ? client : &sock;
00390 readers[1] = 0;
00391
00392 netSocket* writers[1];
00393 writers[0] = 0;
00394
00395 int result = netSocket::select( readers, writers, timeout );
00396
00397 if (result > 0 && is_server && client == 0)
00398 {
00399
00400 netAddress addr;
00401 int new_fd = sock.accept( &addr );
00402 SG_LOG( SG_IO, SG_INFO, "Accepted connection from "
00403 << addr.getHost() << ":" << addr.getPort() );
00404 client = new netSocket();
00405 client->setHandle( new_fd );
00406 return 0;
00407 }
00408
00409 return result;
00410 }