From 5702bd7ee80b33840b95c8194d7887f45aaa5977 Mon Sep 17 00:00:00 2001 From: curt Date: Wed, 4 Oct 2000 20:14:26 +0000 Subject: [PATCH] io changes and tweaks. Working on adding SOCK_STREAM (tcp) support. Still needs some work, but is basically there. --- simgear/io/Makefile.am | 8 +++ simgear/io/iochannel.cxx | 6 +-- simgear/io/iochannel.hxx | 16 ++++-- simgear/io/sg_file.cxx | 12 +++-- simgear/io/sg_file.hxx | 6 +-- simgear/io/sg_serial.cxx | 8 +-- simgear/io/sg_serial.hxx | 6 +-- simgear/io/sg_socket.cxx | 114 ++++++++++++++++++++++++++++++++------- simgear/io/sg_socket.hxx | 9 ++-- 9 files changed, 140 insertions(+), 45 deletions(-) diff --git a/simgear/io/Makefile.am b/simgear/io/Makefile.am index 9e17a424..8752d3d7 100644 --- a/simgear/io/Makefile.am +++ b/simgear/io/Makefile.am @@ -15,3 +15,11 @@ libsgio_a_SOURCES = \ sg_socket.cxx INCLUDES += -I$(top_srcdir) + +noinst_PROGRAMS = socktest + +socktest_SOURCES = socktest.cxx + +socktest_LDADD = \ + $(top_builddir)/simgear/io/libsgio.a \ + $(top_builddir)/simgear/debug/libsgdebug.a \ No newline at end of file diff --git a/simgear/io/iochannel.cxx b/simgear/io/iochannel.cxx index ab83fc09..ea8372cf 100644 --- a/simgear/io/iochannel.cxx +++ b/simgear/io/iochannel.cxx @@ -39,7 +39,7 @@ SGIOChannel::~SGIOChannel() // dummy configure routine -bool SGIOChannel::open( SGProtocolDir dir ) { +bool SGIOChannel::open( const SGProtocolDir d ) { return false; } @@ -57,13 +57,13 @@ int SGIOChannel::readline( char *buf, int length ) { // dummy process routine -int SGIOChannel::write( char *buf, int length ) { +int SGIOChannel::write( const char *buf, const int length ) { return false; } // dummy process routine -int SGIOChannel::writestring( char *str ) { +int SGIOChannel::writestring( const char *str ) { return false; } diff --git a/simgear/io/iochannel.hxx b/simgear/io/iochannel.hxx index 941cdc0d..1d324be2 100644 --- a/simgear/io/iochannel.hxx +++ b/simgear/io/iochannel.hxx @@ -55,21 +55,27 @@ enum SGChannelType { class SGIOChannel { SGChannelType type; + SGProtocolDir dir; + bool valid; public: SGIOChannel(); virtual ~SGIOChannel(); - virtual bool open( SGProtocolDir dir ); + virtual bool open( const SGProtocolDir d ); virtual int read( char *buf, int length ); virtual int readline( char *buf, int length ); - virtual int write( char *buf, int length ); - virtual int writestring( char *str ); + virtual int write( const char *buf, const int length ); + virtual int writestring( const char *str ); virtual bool close(); - virtual void set_type( SGChannelType t ) { type = t; } - virtual SGChannelType get_type() const { return type; } + inline void set_type( SGChannelType t ) { type = t; } + inline SGChannelType get_type() const { return type; } + + inline void set_dir( const SGProtocolDir d ) { dir = d; } + inline SGProtocolDir get_dir() const { return dir; } + inline bool isvalid() const { return valid; } }; diff --git a/simgear/io/sg_file.cxx b/simgear/io/sg_file.cxx index 055648c0..912bcb6c 100644 --- a/simgear/io/sg_file.cxx +++ b/simgear/io/sg_file.cxx @@ -47,15 +47,17 @@ SGFile::~SGFile() { // open the file based on specified direction -bool SGFile::open( SGProtocolDir dir ) { - if ( dir == SG_IO_OUT ) { +bool SGFile::open( const SGProtocolDir d ) { + set_dir( d ); + + if ( get_dir() == SG_IO_OUT ) { #ifdef _MSC_VER int mode = 00666; #else mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; #endif fp = ::open( file_name.c_str(), O_WRONLY | O_CREAT | O_TRUNC, mode ); - } else if ( dir == SG_IO_IN ) { + } else if ( get_dir() == SG_IO_IN ) { fp = ::open( file_name.c_str(), O_RDONLY ); } else { FG_LOG( FG_IO, FG_ALERT, @@ -105,7 +107,7 @@ int SGFile::readline( char *buf, int length ) { // write data to a file -int SGFile::write( char *buf, int length ) { +int SGFile::write( const char *buf, const int length ) { int result = ::write( fp, buf, length ); if ( result != length ) { FG_LOG( FG_IO, FG_ALERT, "Error writing data: " << file_name ); @@ -116,7 +118,7 @@ int SGFile::write( char *buf, int length ) { // write null terminated string to a file -int SGFile::writestring( char *str ) { +int SGFile::writestring( const char *str ) { int length = strlen( str ); return write( str, length ); } diff --git a/simgear/io/sg_file.hxx b/simgear/io/sg_file.hxx index b2618f28..00d47143 100644 --- a/simgear/io/sg_file.hxx +++ b/simgear/io/sg_file.hxx @@ -56,7 +56,7 @@ public: ~SGFile(); // open the file based on specified direction - bool open( SGProtocolDir dir ); + bool open( const SGProtocolDir dir ); // read a block of data of specified size int read( char *buf, int length ); @@ -65,10 +65,10 @@ public: int readline( char *buf, int length ); // write data to a file - int write( char *buf, int length ); + int write( const char *buf, const int length ); // write null terminated string to a file - int writestring( char *str ); + int writestring( const char *str ); // close file bool close(); diff --git a/simgear/io/sg_serial.cxx b/simgear/io/sg_serial.cxx index f59a9824..d174bcd2 100644 --- a/simgear/io/sg_serial.cxx +++ b/simgear/io/sg_serial.cxx @@ -47,7 +47,9 @@ SGSerial::~SGSerial() { // open the serial port based on specified direction -bool SGSerial::open( SGProtocolDir dir ) { +bool SGSerial::open( const SGProtocolDir d ) { + set_dir( d ); + if ( ! port.open_port( device ) ) { FG_LOG( FG_IO, FG_ALERT, "Error opening device: " << device ); return false; @@ -127,7 +129,7 @@ int SGSerial::readline( char *buf, int length ) { // write data to port -int SGSerial::write( char *buf, int length ) { +int SGSerial::write( const char *buf, const int length ) { int result = port.write_port( buf, length ); if ( result != length ) { @@ -139,7 +141,7 @@ int SGSerial::write( char *buf, int length ) { // write null terminated string to port -int SGSerial::writestring( char *str ) { +int SGSerial::writestring( const char *str ) { int length = strlen( str ); return write( str, length ); } diff --git a/simgear/io/sg_serial.hxx b/simgear/io/sg_serial.hxx index 43cb4433..f5f7ad4f 100644 --- a/simgear/io/sg_serial.hxx +++ b/simgear/io/sg_serial.hxx @@ -61,7 +61,7 @@ public: ~SGSerial(); // open the serial port based on specified direction - bool open( SGProtocolDir dir ); + bool open( const SGProtocolDir d ); // read a block of data of specified size int read( char *buf, int length ); @@ -70,10 +70,10 @@ public: int readline( char *buf, int length ); // write data to port - int write( char *buf, int length ); + int write( const char *buf, const int length ); // write null terminated string to port - int writestring( char *str ); + int writestring( const char *str ); // close port bool close(); diff --git a/simgear/io/sg_socket.cxx b/simgear/io/sg_socket.cxx index 288a4dd5..c7f70200 100644 --- a/simgear/io/sg_socket.cxx +++ b/simgear/io/sg_socket.cxx @@ -182,7 +182,9 @@ int SGSocket::closesocket( int fd ) { // If specified as a server (in direction for now) open the master // listening socket. If specified as a client (out direction), open a // connection to a server. -bool SGSocket::open( SGProtocolDir dir ) { +bool SGSocket::open( const SGProtocolDir d ) { + set_dir( d ); + if ( port_str == "" || port_str == "any" ) { port = 0; } else { @@ -191,14 +193,17 @@ bool SGSocket::open( SGProtocolDir dir ) { // client_connections.clear(); - if ( dir == SG_IO_IN ) { + if ( get_dir() == SG_IO_IN ) { // this means server for now // Setup socket to listen on. Set "port" before making this // call. A port of "0" indicates that we want to let the os // pick any available port. sock = make_server_socket(); - // TODO: check for error. + if ( sock == INVALID_SOCKET ) { + FG_LOG( FG_IO, FG_ALERT, "socket creation failed" ); + return false; + } FG_LOG( FG_IO, FG_INFO, "socket is connected to port = " << port ); @@ -211,7 +216,7 @@ bool SGSocket::open( SGProtocolDir dir ) { listen( sock, SG_MAX_SOCKET_QUEUE ); } - } else if ( dir == SG_IO_OUT ) { + } else if ( get_dir() == SG_IO_OUT ) { // this means client for now sock = make_client_socket(); @@ -221,7 +226,7 @@ bool SGSocket::open( SGProtocolDir dir ) { // Non-blocking UDP nonblock(); } - } else if ( dir == SG_IO_BI && sock_style == SOCK_STREAM ) { + } else if ( get_dir() == SG_IO_BI && sock_style == SOCK_STREAM ) { // this means server for TCP sockets // Setup socket to listen on. Set "port" before making this @@ -247,6 +252,10 @@ bool SGSocket::open( SGProtocolDir dir ) { return false; } + // extra SOCK_STREAM stuff + msgsock = INVALID_SOCKET; + first_read = false; + return true; } @@ -254,8 +263,11 @@ bool SGSocket::open( SGProtocolDir dir ) { // read data from socket (server) // read a block of data of specified size int SGSocket::read( char *buf, int length ) { - int result = 0; + if ( sock == INVALID_SOCKET ) { + return 0; + } + int result = 0; // check for potential input fd_set ready; FD_ZERO(&ready); @@ -269,7 +281,20 @@ int SGSocket::read( char *buf, int length ) { select(32, &ready, 0, 0, &tv); if ( FD_ISSET(sock, &ready) ) { - result = readsocket( sock, buf, length ); + // cout << "data ready" << endl; + + if ( sock_style == SOCK_STREAM ) { + if ( msgsock == INVALID_SOCKET ) { + msgsock = accept(sock, 0, 0); + closesocket(sock); + sock = msgsock; + } else { + result = readsocket( sock, buf, length ); + } + } else { + result = readsocket( sock, buf, length ); + } + if ( result != length ) { FG_LOG( FG_IO, FG_INFO, "Warning: read() not enough bytes." ); @@ -282,7 +307,11 @@ int SGSocket::read( char *buf, int length ) { // read a line of data, length is max size of input buffer int SGSocket::readline( char *buf, int length ) { - int result = 0; + if ( sock == INVALID_SOCKET ) { + return 0; + } + + // cout << "sock = " << sock << endl; // check for potential input fd_set ready; @@ -294,19 +323,55 @@ int SGSocket::readline( char *buf, int length ) { // test for any input read on sock (returning immediately, even if // nothing) - int rc = select(32, &ready, 0, 0, &tv); - // FG_LOG( FG_IO, FG_DEBUG, "select returned " << rc ); + int result = select(32, &ready, 0, 0, &tv); + // cout << "result = " << result << endl; if ( FD_ISSET(sock, &ready) ) { + // cout << "fd change state\n"; // read a chunk, keep in the save buffer until we have the // requested amount read - char *buf_ptr = save_buf + save_len; - result = readsocket( sock, buf_ptr, SG_IO_MAX_MSG_SIZE - save_len ); - save_len += result; + if ( sock_style == SOCK_STREAM ) { + // cout << "sock_stream\n"; + if ( msgsock == INVALID_SOCKET ) { + // cout << "msgsock == invalid\n"; + msgsock = accept(sock, 0, 0); + closesocket(sock); + sock = msgsock; + } else { + // cout << "ready to read\n"; + char *buf_ptr = save_buf + save_len; + result = readsocket( sock, buf_ptr, SG_IO_MAX_MSG_SIZE + - save_len ); + // cout << "read result = " << result << endl; + + if ( result > 0 ) { + first_read = true; + } + + save_len += result; + + // Try and detect that the remote end died. This + // could cause problems so if you see connections + // dropping for unexplained reasons, LOOK HERE! + if ( result == 0 && save_len == 0 && first_read == true ) { + FG_LOG( FG_IO, FG_ALERT, + "Connection closed by foreign host." ); + closesocket(sock); + open( get_dir() ); + } + } + } else { + char *buf_ptr = save_buf + save_len; + result = readsocket( sock, buf_ptr, SG_IO_MAX_MSG_SIZE - save_len ); + save_len += result; + } + // cout << "current read = " << buf_ptr << endl; // cout << "current save_buf = " << save_buf << endl; // cout << "save_len = " << save_len << endl; + } else { + // cout << "no data ready\n"; } // look for the end of line in save_buf @@ -339,7 +404,11 @@ int SGSocket::readline( char *buf, int length ) { // write data to socket (client) -int SGSocket::write( char *buf, int length ) { +int SGSocket::write( const char *buf, const int length ) { + if ( sock == INVALID_SOCKET ) { + return 0; + } + bool error_condition = false; if ( writesocket(sock, buf, length) < 0 ) { @@ -404,7 +473,11 @@ int SGSocket::write( char *buf, int length ) { // write null terminated string to socket (server) -int SGSocket::writestring( char *str ) { +int SGSocket::writestring( const char *str ) { + if ( sock == INVALID_SOCKET ) { + return 0; + } + int length = strlen( str ); return write( str, length ); } @@ -412,12 +485,9 @@ int SGSocket::writestring( char *str ) { // close the port bool SGSocket::close() { -#if 0 - for ( int i = 0; i < (int)client_connections.size(); ++i ) { - int msgsock = client_connections[i]; - closesocket( msgsock ); + if ( sock == INVALID_SOCKET ) { + return 0; } -#endif closesocket( sock ); return true; @@ -426,6 +496,10 @@ bool SGSocket::close() { // configure the socket as non-blocking bool SGSocket::nonblock() { + if ( sock == INVALID_SOCKET ) { + return 0; + } + #if defined(_MSC_VER) u_long arg = 1; if (ioctlsocket( sock, FIONBIO, &arg ) != 0) { diff --git a/simgear/io/sg_socket.hxx b/simgear/io/sg_socket.hxx index e775eb3b..22915a2a 100644 --- a/simgear/io/sg_socket.hxx +++ b/simgear/io/sg_socket.hxx @@ -63,9 +63,12 @@ private: int save_len; SocketType sock; + SocketType msgsock; short unsigned int port; int sock_style; // SOCK_STREAM or SOCK_DGRAM + bool first_read; + // make a server (master listening) socket SocketType make_server_socket(); @@ -93,7 +96,7 @@ public: // If specified as a server (in direction for now) open the master // listening socket. If specified as a client (out direction), // open a connection to a server. - bool open( SGProtocolDir dir ); + bool open( const SGProtocolDir d ); // read data from socket int read( char *buf, int length ); @@ -102,10 +105,10 @@ public: int readline( char *buf, int length ); // write data to a socket - int write( char *buf, int length ); + int write( const char *buf, const int length ); // write null terminated string to a socket - int writestring( char *str ); + int writestring( const char *str ); // close file bool close(); -- 2.39.5