libt2n: (gerd) small improvements, resolve doxygen conflicts
authorGerd v. Egidy <gerd.von.egidy@intra2net.com>
Mon, 9 Oct 2006 11:06:11 +0000 (11:06 +0000)
committerGerd v. Egidy <gerd.von.egidy@intra2net.com>
Mon, 9 Oct 2006 11:06:11 +0000 (11:06 +0000)
src/server.cpp
src/server.hxx
src/socket_server.cpp
src/socket_server.hxx

index c8255ee..3424cd8 100644 (file)
@@ -17,6 +17,8 @@
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
 
+#include <sstream>
+
 #include "server.hxx"
 
 namespace libt2n
@@ -33,6 +35,13 @@ void connection::reset_timeout()
     last_action_time=time(NULL);
 }
 
+std::string connection::get_id_string()
+{
+    std::ostringstream os;
+    os << get_id();
+    return os.str();
+}
+
 bool connection::get_packet(std::string& data, unsigned int& conn_id)
 {
     // max packet size is unsigned int
@@ -62,8 +71,11 @@ server::~server()
 
 int server::add_connection(connection* newconn)
 {
-    connections[next_id]=newconn;
-    return next_id++;
+    unsigned int cid=next_id++;
+    newconn->set_id(cid);
+    newconn->set_server(this);
+    connections[cid]=newconn;
+    return cid;
 }
 
 /**
@@ -89,14 +101,6 @@ void server::check_timeout()
         i->second->check_timeout();
 }
 
-void server::fill_connection_buffers(void)
-{
-    std::map<unsigned int, connection*>::iterator ie=connections.end();
-    for(std::map<unsigned int, connection*>::iterator i=connections.begin(); i != ie; i++)
-        if (!i->second->is_closed())
-            i->second->fill_buffer();
-}
-
 bool server::get_packet(std::string& data, unsigned int& conn_id)
 {
     // todo: this is somehow unfair: the first connections in the map get checked more
index c93e43b..40113b8 100644 (file)
@@ -26,6 +26,8 @@
 namespace libt2n
 {
 
+class server;
+
 /**
     Basic connection class
 */
@@ -35,7 +37,7 @@ class connection
         int timeout;
         int last_action_time;
         bool closed;
-        std::string buffer;
+        unsigned int connection_id;
 
     protected:
         connection(int _timeout)
@@ -43,8 +45,15 @@ class connection
             set_timeout(_timeout);
             reset_timeout();
             closed=false;
+            connection_id=0;
+            my_server=0;
         }
 
+        server *my_server;
+        std::string buffer;
+
+        typedef unsigned int packet_size_indicator;
+
     public:
         ~connection()
             { this->close(); }
@@ -57,11 +66,18 @@ class connection
         bool is_closed()
             { return closed; }
 
+        void set_server(server* _my_server)
+            { my_server=_my_server; }
+
+        void set_id(unsigned int _connection_id)
+            { connection_id=_connection_id; }
+        unsigned int get_id()
+            { return connection_id; }
+        std::string get_id_string();
+
         virtual void close()
             { closed=true; }
 
-        virtual void fill_buffer(void)=0;
-
         bool get_packet(std::string& data, unsigned int& conn_id);
         virtual void write(const std::string& data)=0;
 };
@@ -80,14 +96,15 @@ class server
         std::ostream *logstream;
 
         unsigned int next_id;
-        std::map<unsigned int, connection*> connections;
 
     protected:
+        std::map<unsigned int, connection*> connections;
+
         server()
         {
             set_default_timeout(30);
             set_logging(NULL,none);
-            next_id=0;
+            next_id=1;
         }
 
         int add_connection(connection* newconn);
@@ -113,9 +130,8 @@ class server
 
         bool get_packet(std::string& data, unsigned int& conn_id);
 
-        void fill_connection_buffers(void);
+        virtual void fill_connection_buffers(void)=0;
 
-    protected:
         void log(log_level_values level, const std::string& message)
             { log(level,message.c_str()); }
         void log(log_level_values level, const char* message);
index e9bdde0..f0e573b 100644 (file)
@@ -33,6 +33,8 @@
 #include <pwd.h>
 #include <grp.h>
 
+#include <sstream>
+
 #include "socket_server.hxx"
 #include "t2n_exception.hxx"
 
@@ -330,6 +332,17 @@ void socket_server::fill_buffer(long long usec_timeout)
     return;
 }
 
+void socket_server::fill_connection_buffers()
+{
+    std::map<unsigned int, connection*>::iterator ie=connections.end();
+    for(std::map<unsigned int, connection*>::iterator i=connections.begin(); i != ie; i++)
+        if (!i->second->is_closed())
+        {
+            socket_connection* cp=dynamic_cast<socket_connection*>(i->second);
+            cp->fill_buffer(connection_set);
+        }
+}
+
 socket_connection::socket_connection(int _sock, int _timeout)
     : connection(_timeout)
 {
@@ -341,14 +354,124 @@ void socket_connection::close()
 
 }
 
-void socket_connection::fill_buffer(void)
+void socket_connection::fill_buffer(fd_set &cur_fdset)
 {
+    bool try_again=false;
+
+    if (is_closed() || !FD_ISSET (sock, &cur_fdset))
+        return;                                                // no data pending or connection closed
+
+    // data pending -> go and get it
+    char socket_buffer[recv_buffer_size];
+
+    int nbytes = read (sock, socket_buffer, recv_buffer_size);
+    if (nbytes < 0)
+    {
+        if (errno == EAGAIN)
+        {
+            if (my_server)
+                my_server->log(server::error,"read error: no data (EAGAIN) for connection "+get_id_string());
+            return;
+        }
+        else if (errno == EINTR)
+        {
+            // interrupted, try again
+            try_again=true;
+        }
+        else
+        {
+            if (my_server)
+                my_server->log(server::error,"error reading from socket of connection "+get_id_string()+": "+strerror(errno));
+            return;
+        }
+    }
+
+    // End-of-file
+    if (nbytes == 0 && !try_again)
+    {
+        close();
+        return;
+    }
+
+    // Data read -> store it
+    if (nbytes > 0)
+        buffer.assign(socket_buffer,nbytes);
 
+    // more data waiting?
+    fd_set active_fd_set;
+    struct timeval tval;
+
+    FD_ZERO (&active_fd_set);
+    FD_SET (sock, &active_fd_set);
+
+    /* no waiting */
+    tval.tv_sec=0;
+    tval.tv_usec=0;
+
+    if (select (FD_SETSIZE, &active_fd_set, NULL, NULL, &tval) >0)
+    {
+        /* more data waiting -> recurse */
+        fill_buffer(active_fd_set);
+    }
+
+    reset_timeout();
+
+    return;
 }
 
 void socket_connection::write(const std::string& data)
 {
+    static const unsigned int write_block_size=4096;
+
+    if (is_closed())
+        return;
+
+    // prepend packet size to data
+    packet_size_indicator psize=data.size();
+    string send_data(data);
+    send_data.insert(0,(char*)psize,sizeof(packet_size_indicator));
+
+    int offset = 0;
+    while (offset < send_data.size())
+    {
+        unsigned int write_size=write_block_size;
+
+        if (offset+write_size > send_data.size())
+            write_size = send_data.size()-offset;
 
+        int rtn;
+        while ((rtn=::write(sock, send_data.data()+offset, write_size)) &&
+               rtn == -1 && (errno == EAGAIN || errno == EINTR))
+        {
+            usleep (80000);
+            if (my_server)
+                my_server->log(server::debug,"resuming write() call after EAGAIN or EINTR for connection "+get_id_string());
+        }
+
+        if (rtn == -1)
+        {
+            if (my_server)
+                my_server->log(server::error,"write() error on connection "+get_id_string()+": "+strerror(errno));
+        }
+        else if (rtn != write_size)
+        {
+            if (my_server)
+            {
+                ostringstream msg;
+                msg << "write() error on connection " << get_id() 
+                    << ": wrote " << rtn << " bytes, should have been " 
+                    << write_size << " (complete: " << send_data.size() << ")";
+
+                my_server->log(server::error,msg.str());
+            }
+        }
+
+        offset += write_size;
+    }
+
+    reset_timeout();
+
+    return;
 }
 
 }
index 5dfea1f..6056136 100644 (file)
@@ -53,6 +53,7 @@ class socket_server : public server
             { return socket_type; }
 
         void fill_buffer(long long usec_timeout=-1);
+        void fill_connection_buffers();
 };
 
 /**
@@ -63,6 +64,8 @@ class socket_connection : public connection
     friend class socket_server;
 
     private:
+        static const int recv_buffer_size=2048;
+
         int sock;
 
         socket_connection(int _sock, int _timeout);
@@ -70,9 +73,7 @@ class socket_connection : public connection
     public:
 
         void close();
-
-        void fill_buffer(void);
-
+        void fill_buffer(fd_set &cur_fdset);
         void write(const std::string& data);
 };