io changes and tweaks. Working on adding SOCK_STREAM (tcp) support. Still

needs some work, but is basically there.
This commit is contained in:
curt
2000-10-04 20:14:26 +00:00
parent 8eef3eb582
commit 5702bd7ee8
9 changed files with 140 additions and 45 deletions
+8
View File
@@ -15,3 +15,11 @@ libsgio_a_SOURCES = \
sg_socket.cxx sg_socket.cxx
INCLUDES += -I$(top_srcdir) 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
+3 -3
View File
@@ -39,7 +39,7 @@ SGIOChannel::~SGIOChannel()
// dummy configure routine // dummy configure routine
bool SGIOChannel::open( SGProtocolDir dir ) { bool SGIOChannel::open( const SGProtocolDir d ) {
return false; return false;
} }
@@ -57,13 +57,13 @@ int SGIOChannel::readline( char *buf, int length ) {
// dummy process routine // dummy process routine
int SGIOChannel::write( char *buf, int length ) { int SGIOChannel::write( const char *buf, const int length ) {
return false; return false;
} }
// dummy process routine // dummy process routine
int SGIOChannel::writestring( char *str ) { int SGIOChannel::writestring( const char *str ) {
return false; return false;
} }
+11 -5
View File
@@ -55,21 +55,27 @@ enum SGChannelType {
class SGIOChannel { class SGIOChannel {
SGChannelType type; SGChannelType type;
SGProtocolDir dir;
bool valid;
public: public:
SGIOChannel(); SGIOChannel();
virtual ~SGIOChannel(); virtual ~SGIOChannel();
virtual bool open( SGProtocolDir dir ); virtual bool open( const SGProtocolDir d );
virtual int read( char *buf, int length ); virtual int read( char *buf, int length );
virtual int readline( char *buf, int length ); virtual int readline( char *buf, int length );
virtual int write( char *buf, int length ); virtual int write( const char *buf, const int length );
virtual int writestring( char *str ); virtual int writestring( const char *str );
virtual bool close(); virtual bool close();
virtual void set_type( SGChannelType t ) { type = t; } inline void set_type( SGChannelType t ) { type = t; }
virtual SGChannelType get_type() const { return type; } 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; }
}; };
+7 -5
View File
@@ -47,15 +47,17 @@ SGFile::~SGFile() {
// open the file based on specified direction // open the file based on specified direction
bool SGFile::open( SGProtocolDir dir ) { bool SGFile::open( const SGProtocolDir d ) {
if ( dir == SG_IO_OUT ) { set_dir( d );
if ( get_dir() == SG_IO_OUT ) {
#ifdef _MSC_VER #ifdef _MSC_VER
int mode = 00666; int mode = 00666;
#else #else
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
#endif #endif
fp = ::open( file_name.c_str(), O_WRONLY | O_CREAT | O_TRUNC, mode ); 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 ); fp = ::open( file_name.c_str(), O_RDONLY );
} else { } else {
FG_LOG( FG_IO, FG_ALERT, FG_LOG( FG_IO, FG_ALERT,
@@ -105,7 +107,7 @@ int SGFile::readline( char *buf, int length ) {
// write data to a file // 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 ); int result = ::write( fp, buf, length );
if ( result != length ) { if ( result != length ) {
FG_LOG( FG_IO, FG_ALERT, "Error writing data: " << file_name ); 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 // write null terminated string to a file
int SGFile::writestring( char *str ) { int SGFile::writestring( const char *str ) {
int length = strlen( str ); int length = strlen( str );
return write( str, length ); return write( str, length );
} }
+3 -3
View File
@@ -56,7 +56,7 @@ public:
~SGFile(); ~SGFile();
// open the file based on specified direction // open the file based on specified direction
bool open( SGProtocolDir dir ); bool open( const SGProtocolDir dir );
// read a block of data of specified size // read a block of data of specified size
int read( char *buf, int length ); int read( char *buf, int length );
@@ -65,10 +65,10 @@ public:
int readline( char *buf, int length ); int readline( char *buf, int length );
// write data to a file // 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 // write null terminated string to a file
int writestring( char *str ); int writestring( const char *str );
// close file // close file
bool close(); bool close();
+5 -3
View File
@@ -47,7 +47,9 @@ SGSerial::~SGSerial() {
// open the serial port based on specified direction // 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 ) ) { if ( ! port.open_port( device ) ) {
FG_LOG( FG_IO, FG_ALERT, "Error opening device: " << device ); FG_LOG( FG_IO, FG_ALERT, "Error opening device: " << device );
return false; return false;
@@ -127,7 +129,7 @@ int SGSerial::readline( char *buf, int length ) {
// write data to port // 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 ); int result = port.write_port( buf, length );
if ( result != length ) { if ( result != length ) {
@@ -139,7 +141,7 @@ int SGSerial::write( char *buf, int length ) {
// write null terminated string to port // write null terminated string to port
int SGSerial::writestring( char *str ) { int SGSerial::writestring( const char *str ) {
int length = strlen( str ); int length = strlen( str );
return write( str, length ); return write( str, length );
} }
+3 -3
View File
@@ -61,7 +61,7 @@ public:
~SGSerial(); ~SGSerial();
// open the serial port based on specified direction // 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 // read a block of data of specified size
int read( char *buf, int length ); int read( char *buf, int length );
@@ -70,10 +70,10 @@ public:
int readline( char *buf, int length ); int readline( char *buf, int length );
// write data to port // write data to port
int write( char *buf, int length ); int write( const char *buf, const int length );
// write null terminated string to port // write null terminated string to port
int writestring( char *str ); int writestring( const char *str );
// close port // close port
bool close(); bool close();
+94 -20
View File
@@ -182,7 +182,9 @@ int SGSocket::closesocket( int fd ) {
// If specified as a server (in direction for now) open the master // If specified as a server (in direction for now) open the master
// listening socket. If specified as a client (out direction), open a // listening socket. If specified as a client (out direction), open a
// connection to a server. // connection to a server.
bool SGSocket::open( SGProtocolDir dir ) { bool SGSocket::open( const SGProtocolDir d ) {
set_dir( d );
if ( port_str == "" || port_str == "any" ) { if ( port_str == "" || port_str == "any" ) {
port = 0; port = 0;
} else { } else {
@@ -191,14 +193,17 @@ bool SGSocket::open( SGProtocolDir dir ) {
// client_connections.clear(); // client_connections.clear();
if ( dir == SG_IO_IN ) { if ( get_dir() == SG_IO_IN ) {
// this means server for now // this means server for now
// Setup socket to listen on. Set "port" before making this // Setup socket to listen on. Set "port" before making this
// call. A port of "0" indicates that we want to let the os // call. A port of "0" indicates that we want to let the os
// pick any available port. // pick any available port.
sock = make_server_socket(); 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 ); 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 ); listen( sock, SG_MAX_SOCKET_QUEUE );
} }
} else if ( dir == SG_IO_OUT ) { } else if ( get_dir() == SG_IO_OUT ) {
// this means client for now // this means client for now
sock = make_client_socket(); sock = make_client_socket();
@@ -221,7 +226,7 @@ bool SGSocket::open( SGProtocolDir dir ) {
// Non-blocking UDP // Non-blocking UDP
nonblock(); 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 // this means server for TCP sockets
// Setup socket to listen on. Set "port" before making this // Setup socket to listen on. Set "port" before making this
@@ -247,6 +252,10 @@ bool SGSocket::open( SGProtocolDir dir ) {
return false; return false;
} }
// extra SOCK_STREAM stuff
msgsock = INVALID_SOCKET;
first_read = false;
return true; return true;
} }
@@ -254,8 +263,11 @@ bool SGSocket::open( SGProtocolDir dir ) {
// read data from socket (server) // read data from socket (server)
// read a block of data of specified size // read a block of data of specified size
int SGSocket::read( char *buf, int length ) { int SGSocket::read( char *buf, int length ) {
int result = 0; if ( sock == INVALID_SOCKET ) {
return 0;
}
int result = 0;
// check for potential input // check for potential input
fd_set ready; fd_set ready;
FD_ZERO(&ready); FD_ZERO(&ready);
@@ -269,7 +281,20 @@ int SGSocket::read( char *buf, int length ) {
select(32, &ready, 0, 0, &tv); select(32, &ready, 0, 0, &tv);
if ( FD_ISSET(sock, &ready) ) { 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 ) { if ( result != length ) {
FG_LOG( FG_IO, FG_INFO, FG_LOG( FG_IO, FG_INFO,
"Warning: read() not enough bytes." ); "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 // read a line of data, length is max size of input buffer
int SGSocket::readline( char *buf, int length ) { int SGSocket::readline( char *buf, int length ) {
int result = 0; if ( sock == INVALID_SOCKET ) {
return 0;
}
// cout << "sock = " << sock << endl;
// check for potential input // check for potential input
fd_set ready; 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 // test for any input read on sock (returning immediately, even if
// nothing) // nothing)
int rc = select(32, &ready, 0, 0, &tv); int result = select(32, &ready, 0, 0, &tv);
// FG_LOG( FG_IO, FG_DEBUG, "select returned " << rc ); // cout << "result = " << result << endl;
if ( FD_ISSET(sock, &ready) ) { if ( FD_ISSET(sock, &ready) ) {
// cout << "fd change state\n";
// read a chunk, keep in the save buffer until we have the // read a chunk, keep in the save buffer until we have the
// requested amount read // requested amount read
char *buf_ptr = save_buf + save_len; if ( sock_style == SOCK_STREAM ) {
result = readsocket( sock, buf_ptr, SG_IO_MAX_MSG_SIZE - save_len ); // cout << "sock_stream\n";
save_len += result; 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 read = " << buf_ptr << endl;
// cout << "current save_buf = " << save_buf << endl; // cout << "current save_buf = " << save_buf << endl;
// cout << "save_len = " << save_len << endl; // cout << "save_len = " << save_len << endl;
} else {
// cout << "no data ready\n";
} }
// look for the end of line in save_buf // 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) // 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; bool error_condition = false;
if ( writesocket(sock, buf, length) < 0 ) { if ( writesocket(sock, buf, length) < 0 ) {
@@ -404,7 +473,11 @@ int SGSocket::write( char *buf, int length ) {
// write null terminated string to socket (server) // 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 ); int length = strlen( str );
return write( str, length ); return write( str, length );
} }
@@ -412,12 +485,9 @@ int SGSocket::writestring( char *str ) {
// close the port // close the port
bool SGSocket::close() { bool SGSocket::close() {
#if 0 if ( sock == INVALID_SOCKET ) {
for ( int i = 0; i < (int)client_connections.size(); ++i ) { return 0;
int msgsock = client_connections[i];
closesocket( msgsock );
} }
#endif
closesocket( sock ); closesocket( sock );
return true; return true;
@@ -426,6 +496,10 @@ bool SGSocket::close() {
// configure the socket as non-blocking // configure the socket as non-blocking
bool SGSocket::nonblock() { bool SGSocket::nonblock() {
if ( sock == INVALID_SOCKET ) {
return 0;
}
#if defined(_MSC_VER) #if defined(_MSC_VER)
u_long arg = 1; u_long arg = 1;
if (ioctlsocket( sock, FIONBIO, &arg ) != 0) { if (ioctlsocket( sock, FIONBIO, &arg ) != 0) {
+6 -3
View File
@@ -63,9 +63,12 @@ private:
int save_len; int save_len;
SocketType sock; SocketType sock;
SocketType msgsock;
short unsigned int port; short unsigned int port;
int sock_style; // SOCK_STREAM or SOCK_DGRAM int sock_style; // SOCK_STREAM or SOCK_DGRAM
bool first_read;
// make a server (master listening) socket // make a server (master listening) socket
SocketType make_server_socket(); SocketType make_server_socket();
@@ -93,7 +96,7 @@ public:
// If specified as a server (in direction for now) open the master // If specified as a server (in direction for now) open the master
// listening socket. If specified as a client (out direction), // listening socket. If specified as a client (out direction),
// open a connection to a server. // open a connection to a server.
bool open( SGProtocolDir dir ); bool open( const SGProtocolDir d );
// read data from socket // read data from socket
int read( char *buf, int length ); int read( char *buf, int length );
@@ -102,10 +105,10 @@ public:
int readline( char *buf, int length ); int readline( char *buf, int length );
// write data to a socket // 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 // write null terminated string to a socket
int writestring( char *str ); int writestring( const char *str );
// close file // close file
bool close(); bool close();