From ab08ff9b01c1c492fc00c166ad2a1bce6dd1819e Mon Sep 17 00:00:00 2001 From: David Rose Date: Mon, 21 Apr 2003 17:31:19 +0000 Subject: [PATCH] more verbose shutdown messages --- panda/src/net/connection.cxx | 2 +- panda/src/net/connectionManager.cxx | 52 +++++++++++++++++++++++ panda/src/net/connectionManager.h | 22 +++++----- panda/src/net/connectionReader.cxx | 26 ++++++++---- panda/src/net/queuedConnectionManager.cxx | 9 ++-- panda/src/net/queuedConnectionManager.h | 7 +-- 6 files changed, 91 insertions(+), 27 deletions(-) diff --git a/panda/src/net/connection.cxx b/panda/src/net/connection.cxx index 6ff09230e5..e57eb3c0b2 100644 --- a/panda/src/net/connection.cxx +++ b/panda/src/net/connection.cxx @@ -520,7 +520,7 @@ check_send_error(PRInt32 result, PRErrorCode errcode, PRInt32 bytes_to_send) { // The connection has been reset; tell our manager about it // and ignore it. if (_manager != (ConnectionManager *)NULL) { - _manager->connection_reset(this); + _manager->connection_reset(this, errcode); } } else if (errcode != PR_PENDING_INTERRUPT_ERROR) { diff --git a/panda/src/net/connectionManager.cxx b/panda/src/net/connectionManager.cxx index 8033df960b..9008c2a2a1 100644 --- a/panda/src/net/connectionManager.cxx +++ b/panda/src/net/connectionManager.cxx @@ -257,6 +257,10 @@ close_connection(const PT(Connection) &connection) { // shut it down. It will be eventually closed when all the // pointers let go. + net_cat.info() + << "Shutting down connection " << (void *)connection + << " locally.\n"; + PRStatus result = PR_Shutdown(socket, PR_SHUTDOWN_BOTH); if (result != PR_SUCCESS) { PRErrorCode errcode = PR_GetError(); @@ -302,6 +306,54 @@ new_connection(const PT(Connection) &connection) { PR_Unlock(_set_mutex); } +//////////////////////////////////////////////////////////////////// +// Function: ConnectionManager::connection_reset +// Access: Protected, Virtual +// Description: An internal function called by the ConnectionReader, +// ConnectionWriter, or ConnectionListener when a +// connection has been externally reset. This adds the +// connection to the queue of those which have recently +// been reset. +//////////////////////////////////////////////////////////////////// +void ConnectionManager:: +connection_reset(const PT(Connection) &connection, PRErrorCode errcode) { + if (net_cat.is_info()) { + if (errcode == 0) { + net_cat.info() + << "Connection " << (void *)connection + << " was closed normally by the other end.\n"; + + } else { + net_cat.info() + << "Lost connection " << (void *)connection + << " unexpectedly: "; + + switch (errcode) { + case PR_CONNECT_RESET_ERROR: + net_cat.info(false) + << "connection reset\n"; + break; + +#ifdef PR_SOCKET_SHUTDOWN_ERROR + case PR_SOCKET_SHUTDOWN_ERROR: + net_cat.info(false) + << "socket shutdown\n"; + break; + + case PR_CONNECT_ABORTED_ERROR: + net_cat.info(false) + << "connection aborted\n"; + break; +#endif + + default: + net_cat.info(false) + << "NSPR error code " << errcode << "\n"; + } + } + } +} + //////////////////////////////////////////////////////////////////// // Function: ConnectionManager::add_reader // Access: Protected diff --git a/panda/src/net/connectionManager.h b/panda/src/net/connectionManager.h index db18628c80..076b902fde 100644 --- a/panda/src/net/connectionManager.h +++ b/panda/src/net/connectionManager.h @@ -19,15 +19,15 @@ #ifndef CONNECTIONMANAGER_H #define CONNECTIONMANAGER_H -#include +#include "pandabase.h" #include "netDatagram.h" #include "connection.h" - -#include +#include "pointerTo.h" +#include "pset.h" #include -#include "pset.h" +#include class NetAddress; class ConnectionReader; @@ -42,11 +42,12 @@ class ConnectionWriter; // is handled via ConnectionReader, ConnectionWriter, // and ConnectionListener. // -// This is actually an abstract class, since it does not -// define what to do when a connection is externally -// reset (i.e. closed on the other end, or dropped -// because of network errors). See -// QueuedConnectionManager. +// You may use this class directly if you don't care +// about tracking which connections have been +// unexpectedly closed; otherwise, you should use +// QueuedConnectionManager to get reports about these +// events (or derive your own class to handle these +// events properly). //////////////////////////////////////////////////////////////////// class EXPCL_PANDA ConnectionManager { PUBLISHED: @@ -67,7 +68,8 @@ PUBLISHED: protected: void new_connection(const PT(Connection) &connection); - virtual void connection_reset(const PT(Connection) &connection)=0; + virtual void connection_reset(const PT(Connection) &connection, + PRErrorCode errcode); void add_reader(ConnectionReader *reader); void remove_reader(ConnectionReader *reader); diff --git a/panda/src/net/connectionReader.cxx b/panda/src/net/connectionReader.cxx index 3820a9e5d5..f289feb6fc 100644 --- a/panda/src/net/connectionReader.cxx +++ b/panda/src/net/connectionReader.cxx @@ -481,7 +481,7 @@ process_incoming_udp_data(SocketInfo *sinfo) { // The socket was closed (!). This shouldn't happen with a UDP // connection. Oh well. Report that and return. if (_manager != (ConnectionManager *)NULL) { - _manager->connection_reset(sinfo->_connection); + _manager->connection_reset(sinfo->_connection, 0); } finish_socket(sinfo); return; @@ -558,7 +558,7 @@ process_incoming_tcp_data(SocketInfo *sinfo) { ) { // The socket was closed. if (_manager != (ConnectionManager *)NULL) { - _manager->connection_reset(sinfo->_connection); + _manager->connection_reset(sinfo->_connection, errcode); } } else if (errcode != PR_PENDING_INTERRUPT_ERROR) { @@ -570,7 +570,7 @@ process_incoming_tcp_data(SocketInfo *sinfo) { } else if (bytes_read == 0) { // The socket was closed. Report that and return. if (_manager != (ConnectionManager *)NULL) { - _manager->connection_reset(sinfo->_connection); + _manager->connection_reset(sinfo->_connection, 0); } finish_socket(sinfo); return; @@ -616,7 +616,7 @@ process_incoming_tcp_data(SocketInfo *sinfo) { ) { // The socket was closed. if (_manager != (ConnectionManager *)NULL) { - _manager->connection_reset(sinfo->_connection); + _manager->connection_reset(sinfo->_connection, errcode); } } else if (errcode != PR_PENDING_INTERRUPT_ERROR) { @@ -628,7 +628,7 @@ process_incoming_tcp_data(SocketInfo *sinfo) { } else if (bytes_read == 0) { // The socket was closed. Report that and return. if (_manager != (ConnectionManager *)NULL) { - _manager->connection_reset(sinfo->_connection); + _manager->connection_reset(sinfo->_connection, 0); } finish_socket(sinfo); return; @@ -695,7 +695,7 @@ process_raw_incoming_udp_data(SocketInfo *sinfo) { // The socket was closed (!). This shouldn't happen with a UDP // connection. Oh well. Report that and return. if (_manager != (ConnectionManager *)NULL) { - _manager->connection_reset(sinfo->_connection); + _manager->connection_reset(sinfo->_connection, 0); } finish_socket(sinfo); return; @@ -750,7 +750,7 @@ process_raw_incoming_tcp_data(SocketInfo *sinfo) { } else if (bytes_read == 0) { // The socket was closed. Report that and return. if (_manager != (ConnectionManager *)NULL) { - _manager->connection_reset(sinfo->_connection); + _manager->connection_reset(sinfo->_connection, 0); } finish_socket(sinfo); return; @@ -866,7 +866,17 @@ get_next_available_socket(PRIntervalTime timeout, // Something bad happened to this socket. Tell the // ConnectionManager to drop it. if (_manager != (ConnectionManager *)NULL) { - _manager->connection_reset(sinfo->_connection); + // Perform a recv to force an error code. + char buffer[1]; + PRInt32 got_bytes = + PR_Recv(sinfo->get_socket(), buffer, 1, 0, PR_INTERVAL_NO_WAIT); + if (got_bytes > 0) { + net_cat.error() + << "poll returned error flags " << hex << _poll[i].out_flags + << dec << " but read " << got_bytes << " from socket.\n"; + } + PRErrorCode errcode = PR_GetError(); + _manager->connection_reset(sinfo->_connection, errcode); } sinfo->_error = true; _reexamine_sockets = true; diff --git a/panda/src/net/queuedConnectionManager.cxx b/panda/src/net/queuedConnectionManager.cxx index f84ea4a908..a8a74e4fa8 100644 --- a/panda/src/net/queuedConnectionManager.cxx +++ b/panda/src/net/queuedConnectionManager.cxx @@ -98,12 +98,11 @@ get_reset_connection(PT(Connection) &connection) { // been reset. //////////////////////////////////////////////////////////////////// void QueuedConnectionManager:: -connection_reset(const PT(Connection) &connection) { +connection_reset(const PT(Connection) &connection, PRErrorCode errcode) { + ConnectionManager::connection_reset(connection, errcode); + // Largely, we don't care if this particular queue fills up. If it // does, it probably just means the user isn't bothering to track // this. - if (enqueue_unique_thing(connection)) { - net_cat.info() - << "Lost connection\n"; - } + enqueue_unique_thing(connection); } diff --git a/panda/src/net/queuedConnectionManager.h b/panda/src/net/queuedConnectionManager.h index 6a824d47de..7a75b623ad 100644 --- a/panda/src/net/queuedConnectionManager.h +++ b/panda/src/net/queuedConnectionManager.h @@ -19,13 +19,13 @@ #ifndef QUEUEDCONNECTIONMANAGER_H #define QUEUEDCONNECTIONMANAGER_H -#include +#include "pandabase.h" #include "connectionManager.h" #include "queuedReturn.h" +#include "pdeque.h" #include -#include "pdeque.h" EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, QueuedReturn< PT(Connection) >); @@ -52,7 +52,8 @@ PUBLISHED: bool get_reset_connection(PT(Connection) &connection); protected: - virtual void connection_reset(const PT(Connection) &connection); + virtual void connection_reset(const PT(Connection) &connection, + PRErrorCode errcode); }; #endif