]> git.mxchange.org Git - flightgear.git/commitdiff
Added first stab at a socket class.
authorcurt <curt>
Sat, 20 Nov 1999 15:41:48 +0000 (15:41 +0000)
committercurt <curt>
Sat, 20 Nov 1999 15:41:48 +0000 (15:41 +0000)
Fixed readline() bug in fg_serial.cxx and fg_socket.cxx.
Fixed process() bug in nmea.cxx and garmin.cxx.

src/Network/fg_serial.cxx
src/Network/fg_socket.cxx [new file with mode: 0644]
src/Network/fg_socket.hxx [new file with mode: 0644]
src/Network/garmin.cxx
src/Network/nmea.cxx

index 162c62fc6b576022806caef46a8cd1b70c56e483..5f70bea4b6c875d82e02e8d60cf751fa02b486ee 100644 (file)
@@ -116,7 +116,7 @@ int FGSerial::readline( char *buf, int length ) {
 
     // shift save buffer
     for ( i = result; i < save_len; ++i ) {
-       save_buf[ i - result ] = save_buf[result];
+       save_buf[ i - result ] = save_buf[i];
     }
     save_len -= result;
 
diff --git a/src/Network/fg_socket.cxx b/src/Network/fg_socket.cxx
new file mode 100644 (file)
index 0000000..64882c3
--- /dev/null
@@ -0,0 +1,304 @@
+// fg_socket.cxx -- Socket I/O routines
+//
+// Written by Curtis Olson, started November 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+
+
+#include <Include/compiler.h>
+
+#include <sys/time.h>          // select()
+#include <sys/types.h>         // socket(), bind(), select(), accept()
+#include <sys/socket.h>                // socket(), bind(), listen(), accept()
+#include <netinet/in.h>                // struct sockaddr_in
+#include <netdb.h>             // gethostbyname()
+#include <unistd.h>            // select()
+
+#include STL_STRING
+
+#include <Debug/logstream.hxx>
+
+#include "fg_socket.hxx"
+
+FG_USING_STD(string);
+
+
+FGSocket::FGSocket() :
+    save_len(0)
+{
+}
+
+
+FGSocket::~FGSocket() {
+}
+
+
+int FGSocket::make_server_socket () {
+    struct sockaddr_in name;
+    socklen_t length;
+     
+    // Create the socket.
+    sock = socket (PF_INET, SOCK_STREAM, 0);
+    if (sock < 0) {
+       FG_LOG( FG_IO, FG_ALERT, 
+               "Error: socket() failed in make_server_socket()" );
+       return -1;
+    }
+     
+    // Give the socket a name.
+    name.sin_family = AF_INET;
+    name.sin_addr.s_addr = INADDR_ANY;
+    name.sin_port = htons(port); // set port to zero to let system pick
+    name.sin_addr.s_addr = htonl (INADDR_ANY);
+    if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) {
+       FG_LOG( FG_IO, FG_ALERT,
+               "Error: bind() failed in make_server_socket()" );
+       return -1;
+    }
+     
+    // Find the assigned port number
+    length = sizeof(struct sockaddr_in);
+    if ( getsockname(sock, (struct sockaddr *) &name, &length) ) {
+       FG_LOG( FG_IO, FG_ALERT,
+               "Error: getsockname() failed in make_server_socket()" );
+       return -1;
+    }
+    port = ntohs(name.sin_port);
+
+    return sock;
+}
+
+
+int FGSocket::make_client_socket () {
+    struct sockaddr_in name;
+    struct hostent *hp;
+     
+    // Create the socket.
+    sock = socket (PF_INET, SOCK_STREAM, 0);
+    if (sock < 0) {
+       FG_LOG( FG_IO, FG_ALERT, 
+               "Error: socket() failed in make_client_socket()" );
+       return -1;
+    }
+     
+    // specify address family
+    name.sin_family = AF_INET;
+
+    // get the hosts official name/info
+    hp = gethostbyname( hostname.c_str() );
+
+    // Connect this socket to the host and the port specified on the
+    // command line
+    bcopy(hp->h_addr, &(name.sin_addr.s_addr), hp->h_length);
+    name.sin_port = htons(port);
+
+    if ( connect(sock, (struct sockaddr *) &name, 
+                sizeof(struct sockaddr_in)) < 0 )
+    {
+       std::close(sock);
+       FG_LOG( FG_IO, FG_ALERT, 
+               "Error: connect() failed in make_client_socket()" );
+       return -1;
+    }
+
+    return sock;
+}
+
+
+// If specified as a server (out direction for now) open the master
+// listening socket.  If specified as a client, open a connection to a
+// server.
+
+bool FGSocket::open( FGProtocol::fgProtocolDir dir ) {
+    if ( port_str == "" || port_str == "any" ) {
+       port = 0; 
+    } else {
+       port = atoi( port_str.c_str() );
+    }
+    
+    client_connections.clear();
+
+    if ( dir == FGProtocol::out ) {
+       // 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();
+       cout << "socket is connected to port = " << port << endl;
+
+       // Specify the maximum length of the connection queue
+       listen(sock, FG_MAX_SOCKET_QUEUE);
+
+    } else if ( dir == FGProtocol::in ) {
+       // this means client for now
+
+       sock = make_client_socket();
+    } else {
+       FG_LOG( FG_IO, FG_ALERT, 
+               "Error:  bidirection mode not available yet for sockets." );
+       return false;
+    }
+
+    if ( sock < 0 ) {
+       FG_LOG( FG_IO, FG_ALERT, "Error opening socket: " << hostname
+               << ":" << port );
+       return false;
+    }
+
+    return true;
+}
+
+
+// read data from socket (client)
+// read a block of data of specified size
+int FGSocket::read( char *buf, int length ) {
+    int result = 0;
+
+    // check for potential input
+    fd_set ready;
+    FD_ZERO(&ready);
+    FD_SET(sock, &ready);
+    struct timeval tv;
+    tv.tv_sec = 0;
+    tv.tv_usec = 0;
+
+    // test for any input read on sock (returning immediately, even if
+    // nothing)
+    select(32, &ready, 0, 0, &tv);
+
+    if ( FD_ISSET(sock, &ready) ) {
+       result = std::read( sock, buf, length );
+       if ( result != length ) {
+           FG_LOG( FG_IO, FG_INFO, 
+                   "Warning: read() not enough bytes." );
+       }
+    }
+
+    return result;
+}
+
+
+// read a line of data, length is max size of input buffer
+int FGSocket::readline( char *buf, int length ) {
+    int result = 0;
+
+    // check for potential input
+    fd_set ready;
+    FD_ZERO(&ready);
+    FD_SET(sock, &ready);
+    struct timeval tv;
+    tv.tv_sec = 0;
+    tv.tv_usec = 0;
+
+    // test for any input read on sock (returning immediately, even if
+    // nothing)
+    select(32, &ready, 0, 0, &tv);
+
+    if ( FD_ISSET(sock, &ready) ) {
+       // read a chunk, keep in the save buffer until we have the
+       // requested amount read
+
+       char *buf_ptr = save_buf + save_len;
+       result = std::read( sock, buf_ptr, FG_MAX_MSG_SIZE - save_len );
+       save_len += result;
+
+       // look for the end of line in save_buf
+       int i;
+       for ( i = 0; i < save_len && save_buf[i] != '\n'; ++i );
+       if ( save_buf[i] == '\n' ) {
+           result = i + 1;
+       } else {
+           // no end of line yet
+           return 0;
+       }
+
+       // we found an end of line
+
+       // copy to external buffer
+       strncpy( buf, save_buf, result );
+       buf[result] = '\0';
+       cout << "fg_serial line = " << buf << endl;
+
+       // shift save buffer
+       for ( i = result; i < save_len; ++i ) {
+           save_buf[ i - result ] = save_buf[i];
+       }
+       save_len -= result;
+    }
+
+    return result;
+}
+
+
+// write data to socket (server)
+int FGSocket::write( char *buf, int length ) {
+
+    // check for any new client connection requests
+    fd_set ready;
+    FD_ZERO(&ready);
+    FD_SET(sock, &ready);
+    struct timeval tv;
+    tv.tv_sec = 0;
+    tv.tv_usec = 0;
+
+    // test for any input on sock (returning immediately, even if
+    // nothing)
+    select(32, &ready, 0, 0, &tv);
+
+    // any new connections?
+    if ( FD_ISSET(sock, &ready) ) {
+       int msgsock = accept(sock, 0, 0);
+       if ( msgsock < 0 ) {
+           FG_LOG( FG_IO, FG_ALERT, 
+                   "Error: accept() failed in write()" );
+           return 0;
+       } else {
+           client_connections.push_back( msgsock );
+       }
+    }
+
+    bool error_condition = false;
+    for ( int i = 0; i < (int)client_connections.size(); ++i ) {
+       int msgsock = client_connections[i];
+       if ( std::write(msgsock, buf, length) < 0 ) {
+           FG_LOG( FG_IO, FG_ALERT, "Error writing to socket: " << port );
+           error_condition = true;
+       }
+    }
+
+    if ( error_condition ) {
+       return 0;
+    }
+
+    return length;
+}
+
+
+// close the port
+bool FGSocket::close() {
+    for ( int i = 0; i < (int)client_connections.size(); ++i ) {
+       int msgsock = client_connections[i];
+       std::close( msgsock );
+    }
+
+    std::close( sock );
+
+    return true;
+}
diff --git a/src/Network/fg_socket.hxx b/src/Network/fg_socket.hxx
new file mode 100644 (file)
index 0000000..7b96bd5
--- /dev/null
@@ -0,0 +1,95 @@
+// fg_socket.hxx -- Socket I/O routines
+//
+// Written by Curtis Olson, started November 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+
+
+#ifndef _FG_SOCKET_HXX
+#define _FG_SOCKET_HXX
+
+
+#ifndef __cplusplus
+# error This library requires C++
+#endif
+
+#include <Include/compiler.h>
+
+#include <string>
+
+#include <Include/fg_types.hxx>
+
+#include "iochannel.hxx"
+#include "protocol.hxx"
+
+FG_USING_STD(string);
+
+
+#define FG_MAX_SOCKET_QUEUE 32
+
+
+class FGSocket : public FGIOChannel {
+
+    string hostname;
+    string port_str;
+
+    char save_buf[ 2 * FG_MAX_MSG_SIZE ];
+    int save_len;
+
+    int sock;
+    short unsigned int port;
+
+    // make a server (master listening) socket
+    int make_server_socket();
+
+    // make a client socket
+    int make_client_socket();
+
+    int_list client_connections;
+
+public:
+
+    FGSocket();
+    ~FGSocket();
+
+    // open the file based on specified direction
+    bool open( FGProtocol::fgProtocolDir dir );
+
+    // read data from file
+    int read( char *buf, int length );
+
+    // read data from file
+    int readline( char *buf, int length );
+
+    // write data to a file
+    int write( char *buf, int length );
+
+    // close file
+    bool close();
+
+    inline string get_hostname() const { return hostname; }
+    inline void set_hostname( const string& hn ) { hostname = hn; }
+    inline string get_port_str() const { return port_str; }
+    inline void set_port_str( const string& p ) { port_str = p; }
+};
+
+
+#endif // _FG_SOCKET_HXX
+
+
index 81b279f04a70f4610d81cf4f1ab4f5e5f3ee4c25..6a0814b72c0124549e6bae27dc7199c3b899d911 100644 (file)
@@ -154,11 +154,11 @@ bool FGGarmin::gen_message() {
 
 // parse Garmin message
 bool FGGarmin::parse_message() {
-    FG_LOG( FG_IO, FG_DEBUG, "parse garmin message" );
+    FG_LOG( FG_IO, FG_INFO, "parse garmin message" );
 
     string msg = buf;
     msg = msg.substr( 0, length );
-    FG_LOG( FG_IO, FG_DEBUG, "entire message = " << msg );
+    FG_LOG( FG_IO, FG_INFO, "entire message = " << msg );
 
     string::size_type begin_line, end_line, begin, end;
     begin_line = begin = 0;
@@ -168,12 +168,12 @@ bool FGGarmin::parse_message() {
     while ( end_line != string::npos ) {
        string line = msg.substr(begin_line, end_line - begin_line);
        begin_line = end_line + 1;
-       FG_LOG( FG_IO, FG_DEBUG, "  input line = " << line );
+       FG_LOG( FG_IO, FG_INFO, "  input line = " << line );
 
        // leading character
        string start = msg.substr(begin, 1);
        ++begin;
-       FG_LOG( FG_IO, FG_DEBUG, "  start = " << start );
+       FG_LOG( FG_IO, FG_INFO, "  start = " << start );
 
        // sentence
        end = msg.find(",", begin);
@@ -183,7 +183,7 @@ bool FGGarmin::parse_message() {
     
        string sentence = msg.substr(begin, end - begin);
        begin = end + 1;
-       FG_LOG( FG_IO, FG_DEBUG, "  sentence = " << sentence );
+       FG_LOG( FG_IO, FG_INFO, "  sentence = " << sentence );
 
        double lon_deg, lon_min, lat_deg, lat_min;
        double lon, lat, speed, heading, altitude;
@@ -197,7 +197,7 @@ bool FGGarmin::parse_message() {
     
            string utc = msg.substr(begin, end - begin);
            begin = end + 1;
-           FG_LOG( FG_IO, FG_DEBUG, "  utc = " << utc );
+           FG_LOG( FG_IO, FG_INFO, "  utc = " << utc );
 
            // junk
            end = msg.find(",", begin);
@@ -207,7 +207,7 @@ bool FGGarmin::parse_message() {
     
            string junk = msg.substr(begin, end - begin);
            begin = end + 1;
-           FG_LOG( FG_IO, FG_DEBUG, "  junk = " << junk );
+           FG_LOG( FG_IO, FG_INFO, "  junk = " << junk );
 
            // lat val
            end = msg.find(",", begin);
@@ -236,7 +236,7 @@ bool FGGarmin::parse_message() {
            }
 
            cur_fdm_state->set_Latitude( lat * DEG_TO_RAD );
-           FG_LOG( FG_IO, FG_DEBUG, "  lat = " << lat );
+           FG_LOG( FG_IO, FG_INFO, "  lat = " << lat );
 
            // lon val
            end = msg.find(",", begin);
@@ -265,7 +265,7 @@ bool FGGarmin::parse_message() {
            }
 
            cur_fdm_state->set_Longitude( lon * DEG_TO_RAD );
-           FG_LOG( FG_IO, FG_DEBUG, "  lon = " << lon );
+           FG_LOG( FG_IO, FG_INFO, "  lon = " << lon );
 
            double sl_radius, lat_geoc;
            fgGeodToGeoc( cur_fdm_state->get_Latitude(), 
@@ -286,7 +286,7 @@ bool FGGarmin::parse_message() {
            speed = atof( speed_str.c_str() );
            cur_fdm_state->set_V_equiv_kts( speed );
            cur_fdm_state->set_V_ground_speed( speed );
-           FG_LOG( FG_IO, FG_DEBUG, "  speed = " << speed );
+           FG_LOG( FG_IO, FG_INFO, "  speed = " << speed );
 
            // heading
            end = msg.find(",", begin);
@@ -300,7 +300,7 @@ bool FGGarmin::parse_message() {
            cur_fdm_state->set_Euler_Angles( cur_fdm_state->get_Phi(), 
                                             cur_fdm_state->get_Theta(), 
                                             heading * DEG_TO_RAD );
-           FG_LOG( FG_IO, FG_DEBUG, "  heading = " << heading );
+           FG_LOG( FG_IO, FG_INFO, "  heading = " << heading );
        } else if ( sentence == "PGRMZ" ) {
            // altitude
            end = msg.find(",", begin);
@@ -327,7 +327,7 @@ bool FGGarmin::parse_message() {
 
            cur_fdm_state->set_Altitude( altitude );
     
-           FG_LOG( FG_IO, FG_DEBUG, " altitude  = " << altitude );
+           FG_LOG( FG_IO, FG_INFO, " altitude  = " << altitude );
 
        }
 
@@ -373,14 +373,24 @@ bool FGGarmin::process() {
            return false;
        }
     } else if ( get_direction() == in ) {
-       if ( io->readline( buf, FG_MAX_MSG_SIZE ) ) {
-           parse_message();
+       if ( length = io->readline( buf, FG_MAX_MSG_SIZE ) ) {
+           FG_LOG( FG_IO, FG_ALERT, "Success reading data." );
+           if ( parse_message() ) {
+               FG_LOG( FG_IO, FG_ALERT, "Success parsing data." );
+           } else {
+               FG_LOG( FG_IO, FG_ALERT, "Error parsing data." );
+           }
        } else {
            FG_LOG( FG_IO, FG_ALERT, "Error reading data." );
            return false;
        }
-       if ( io->readline( buf, FG_MAX_MSG_SIZE ) ) {
-           parse_message();
+       if ( length = io->readline( buf, FG_MAX_MSG_SIZE ) ) {
+           FG_LOG( FG_IO, FG_ALERT, "Success reading data." );
+           if ( parse_message() ) {
+               FG_LOG( FG_IO, FG_ALERT, "Success parsing data." );
+           } else {
+               FG_LOG( FG_IO, FG_ALERT, "Error parsing data." );
+           }
        } else {
            FG_LOG( FG_IO, FG_ALERT, "Error reading data." );
            return false;
index b1755f2e20fbe1809ca412fe5df35696e57ae7ff..7eeb98827281cd75430e6445059a095b5b0750cf 100644 (file)
@@ -476,13 +476,13 @@ bool FGNMEA::process() {
            return false;
        }
     } else if ( get_direction() == in ) {
-       if ( io->readline( buf, FG_MAX_MSG_SIZE ) ) {
+       if ( length = io->readline( buf, FG_MAX_MSG_SIZE ) ) {
            parse_message();
        } else {
            FG_LOG( FG_IO, FG_ALERT, "Error reading data." );
            return false;
        }
-       if ( io->readline( buf, FG_MAX_MSG_SIZE ) ) {
+       if ( length = io->readline( buf, FG_MAX_MSG_SIZE ) ) {
            parse_message();
        } else {
            FG_LOG( FG_IO, FG_ALERT, "Error reading data." );