sg_socket_udp.cxx

00001 // sg_socket.cxx -- Socket I/O routines
00002 //
00003 // Written by Curtis Olson, started November 1999.
00004 //
00005 // Copyright (C) 1999  Curtis L. Olson - http://www.flightgear.org/~curt
00006 //
00007 // This program is free software; you can redistribute it and/or
00008 // modify it under the terms of the GNU General Public License as
00009 // published by the Free Software Foundation; either version 2 of the
00010 // License, or (at your option) any later version.
00011 //
00012 // This program is distributed in the hope that it will be useful, but
00013 // WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015 // General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU General Public License
00018 // along with this program; if not, write to the Free Software
00019 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00020 //
00021 // $Id: sg__socket__udp_8cxx-source.html,v 1.15 2007-12-17 15:37:10 curt Exp $
00022 
00023 #ifdef HAVE_CONFIG_H
00024 #  include <simgear_config.h>
00025 #endif
00026 
00027 #include <simgear/compiler.h>
00028 
00029 #if defined( sgi )
00030 #include <strings.h>
00031 #endif
00032 
00033 #include <simgear/debug/logstream.hxx>
00034 
00035 #include "sg_socket_udp.hxx"
00036 
00037 
00038 SGSocketUDP::SGSocketUDP( const string& host, const string& port ) :
00039     hostname(host),
00040     port_str(port),
00041     save_len(0)
00042 {
00043     set_valid( false );
00044 }
00045 
00046 
00047 SGSocketUDP::~SGSocketUDP() {
00048 }
00049 
00050 
00051 // If specified as a server (in direction for now) open the master
00052 // listening socket.  If specified as a client (out direction), open a
00053 // connection to a server.
00054 bool SGSocketUDP::open( const SGProtocolDir d ) {
00055     set_dir( d );
00056 
00057     if ( ! sock.open( false ) ) {       // open a UDP socket
00058         SG_LOG( SG_IO, SG_ALERT, "error opening socket" );
00059         return false;
00060     }
00061 
00062     if ( port_str == "" || port_str == "any" ) {
00063         port = 0; 
00064     } else {
00065         port = atoi( port_str.c_str() );
00066     }
00067     
00068     // client_connections.clear();
00069 
00070     if ( get_dir() == SG_IO_IN ) {
00071         // this means server
00072 
00073         // bind ...
00074         if ( sock.bind( hostname.c_str(), port ) == -1 ) {
00075             SG_LOG( SG_IO, SG_ALERT, "error binding to port" << port_str );
00076             return false;
00077         }
00078     } else if ( get_dir() == SG_IO_OUT ) {
00079         // this means client
00080 
00081         // connect ...
00082         if ( sock.connect( hostname.c_str(), port ) == -1 ) {
00083             SG_LOG( SG_IO, SG_ALERT,
00084                     "error connecting to " << hostname << port_str );
00085             return false;
00086         }
00087     } else {
00088         SG_LOG( SG_IO, SG_ALERT, 
00089                 "Error:  bidirection mode not available for UDP sockets." );
00090         return false;
00091     }
00092 
00093     set_valid( true );
00094 
00095     return true;
00096 }
00097 
00098 
00099 // read data from socket (server)
00100 // read a block of data of specified size
00101 int SGSocketUDP::read( char *buf, int length ) {
00102     if ( ! isvalid() ) {
00103         return 0;
00104     }
00105 
00106     int result;
00107 
00108     if ( (result = sock.recv(buf, SG_IO_MAX_MSG_SIZE, 0)) >= 0 ) {
00109         buf[result] = '\0';
00110         // printf("msg received = %s\n", buf);
00111     }
00112 
00113     return result;
00114 }
00115 
00116 
00117 // read a line of data, length is max size of input buffer
00118 int SGSocketUDP::readline( char *buf, int length ) {
00119     if ( ! isvalid() ) {
00120         return 0;
00121     }
00122 
00123     // cout << "sock = " << sock << endl;
00124 
00125     char *buf_ptr = save_buf + save_len;
00126     int result = sock.recv(buf_ptr, SG_IO_MAX_MSG_SIZE, 0);
00127     // printf("msg received = %s\n", buf);
00128     save_len += result;
00129 
00130     // look for the end of line in save_buf
00131     int i;
00132     for ( i = 0; i < save_len && save_buf[i] != '\n'; ++i );
00133     if ( save_buf[i] == '\n' ) {
00134         result = i + 1;
00135     } else {
00136         // no end of line yet
00137         // cout << "no eol found" << endl;
00138         return 0;
00139     }
00140     // cout << "line length = " << result << endl;
00141 
00142     // we found an end of line
00143 
00144     // copy to external buffer
00145     strncpy( buf, save_buf, result );
00146     buf[result] = '\0';
00147     // cout << "sg_socket line = " << buf << endl;
00148     
00149     // shift save buffer
00150     for ( i = result; i < save_len; ++i ) {
00151         save_buf[ i - result ] = save_buf[i];
00152     }
00153     save_len -= result;
00154 
00155     return result;
00156 }
00157 
00158 
00159 // write data to socket (client)
00160 int SGSocketUDP::write( const char *buf, const int length ) {
00161     if ( ! isvalid() ) {
00162         return 0;
00163     }
00164 
00165     bool error_condition = false;
00166 
00167     if ( sock.send( buf, length, 0 ) < 0 ) {
00168         SG_LOG( SG_IO, SG_WARN, "Error writing to socket: " << port );
00169         error_condition = true;
00170         return 0;
00171     }
00172 
00173     return length;
00174 }
00175 
00176 
00177 // write null terminated string to socket (server)
00178 int SGSocketUDP::writestring( const char *str ) {
00179     if ( !isvalid() ) {
00180         return 0;
00181     }
00182 
00183     int length = strlen( str );
00184     return write( str, length );
00185 }
00186 
00187 
00188 // close the port
00189 bool SGSocketUDP::close() {
00190     if ( !isvalid() ) {
00191         return 0;
00192     }
00193 
00194     sock.close();
00195 
00196     return true;
00197 }
00198 
00199 
00200 // configure the socket as non-blocking
00201 bool SGSocketUDP::setBlocking( bool value ) {
00202     sock.setBlocking( value );
00203 
00204     return true;
00205 }

Generated on Mon Dec 17 09:30:55 2007 for SimGear by  doxygen 1.5.1