X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fio%2Fsg_netChannel.cxx;h=1561e8de464bbbc83413915f1b53d82ec2367727;hb=70c5d605641b628039f75cb8761ce783a17a5bdf;hp=a189f6816af6de09e6b8a1af07315fc0b4a2f947;hpb=4566bece900ce4305ca4eeb56e6bf5b88c65640d;p=simgear.git diff --git a/simgear/io/sg_netChannel.cxx b/simgear/io/sg_netChannel.cxx index a189f681..1561e8de 100644 --- a/simgear/io/sg_netChannel.cxx +++ b/simgear/io/sg_netChannel.cxx @@ -16,7 +16,7 @@ You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA For further information visit http://plib.sourceforge.net @@ -41,8 +41,6 @@ namespace simgear { -static NetChannel* channels = 0 ; - NetChannel::NetChannel () { closed = true ; @@ -51,31 +49,14 @@ NetChannel::NetChannel () accepting = false ; write_blocked = false ; should_delete = false ; - - next_channel = channels ; - channels = this ; + poller = NULL; } NetChannel::~NetChannel () { close(); - - NetChannel* prev = NULL ; - - for ( NetChannel* ch = channels; ch != NULL; - ch = ch -> next_channel ) - { - if (ch == this) - { - ch = ch -> next_channel ; - if ( prev != NULL ) - prev -> next_channel = ch ; - else - channels = ch ; - next_channel = 0 ; - break; - } - prev = ch ; + if (poller) { + poller->removeChannel(this); } } @@ -211,7 +192,7 @@ NetChannel::handleResolve() if (!addr.isValid()) { SG_LOG(SG_IO, SG_WARN, "Network: host lookup failed:" << host); - handleError (0); + handleError (ENOENT); close(); return -1; } @@ -232,103 +213,140 @@ NetChannel::handleResolve() } } +void NetChannel::handleRead (void) { + SG_LOG(SG_IO, SG_WARN, "Network:" << getHandle() << ": unhandled read"); +} + +void NetChannel::handleWrite (void) { + SG_LOG(SG_IO, SG_WARN, "Network:" << getHandle() << ": unhandled write"); +} + +void NetChannel::handleAccept (void) { + SG_LOG(SG_IO, SG_WARN, "Network:" << getHandle() << ": unhandled accept"); +} + +void NetChannel::handleError (int error) +{ + // warn about address lookup failures seperately, don't warn again. + // (and we (ab-)use ENOENT to mean 'name not found'. + if (error != ENOENT) { + SG_LOG(SG_IO, SG_WARN,"Network:" << getHandle() << ": errno: " << strerror(errno) <<"(" << errno << ")"); + } +} + +void +NetChannelPoller::addChannel(NetChannel* channel) +{ + assert(channel); + assert(channel->poller == NULL); + + channel->poller = this; + channels.push_back(channel); +} + +void +NetChannelPoller::removeChannel(NetChannel* channel) +{ + assert(channel); + assert(channel->poller == this); + channel->poller = NULL; + + // portability: MSVC throws assertion failure when empty + if (channels.empty()) { + return; + } + + ChannelList::iterator it = channels.begin(); + for (; it != channels.end(); ++it) { + if (*it == channel) { + channels.erase(it); + return; + } + } +} + bool -NetChannel::poll (unsigned int timeout) +NetChannelPoller::poll(unsigned int timeout) { - if (!channels) - return false ; - - enum { MAX_SOCKETS = 256 } ; - Socket* reads [ MAX_SOCKETS+1 ] ; - Socket* writes [ MAX_SOCKETS+1 ] ; - Socket* deletes [ MAX_SOCKETS+1 ] ; - int nreads = 0 ; - int nwrites = 0 ; - int ndeletes = 0 ; - int nopen = 0 ; - NetChannel* ch; - for ( ch = channels; ch != NULL; ch = ch -> next_channel ) - { - if ( ch -> should_delete ) - { - assert(ndeletes closed ) + + enum { MAX_SOCKETS = 256 } ; + Socket* reads [ MAX_SOCKETS+1 ] ; + Socket* writes [ MAX_SOCKETS+1 ] ; + int nreads = 0 ; + int nwrites = 0 ; + int nopen = 0 ; + + ChannelList::iterator it = channels.begin(); + while( it != channels.end() ) { - if (ch -> resolving_host ) - { - ch -> handleResolve(); - continue; - } + NetChannel* ch = *it; + if ( ch -> should_delete ) + { + // avoid the channel trying to remove itself from us, or we get + // bug http://code.google.com/p/flightgear-bugs/issues/detail?id=1144 + ch->poller = NULL; + delete ch; + it = channels.erase(it); + continue; + } + + ++it; // we've copied the pointer into ch + if ( ch->closed ) { + continue; + } + + if (ch -> resolving_host ) + { + ch -> handleResolve(); + continue; + } - nopen++ ; - if (ch -> readable()) { - assert(nreads writable()) { - assert(nwrites readable()) { + assert(nreads writable()) { + assert(nwrites closed ) - ch -> handleReadEvent(); - } + for ( int i=0; reads[i]; i++ ) + { + NetChannel* ch = (NetChannel*)reads[i]; + if ( ! ch -> closed ) + ch -> handleReadEvent(); + } - for ( i=0; writes[i]; i++ ) - { - ch = (NetChannel*)writes[i]; - if ( ! ch -> closed ) - ch -> handleWriteEvent(); - } + for ( int i=0; writes[i]; i++ ) + { + NetChannel* ch = (NetChannel*)writes[i]; + if ( ! ch -> closed ) + ch -> handleWriteEvent(); + } - return true ; + return true ; } void -NetChannel::loop (unsigned int timeout) +NetChannelPoller::loop (unsigned int timeout) { while ( poll (timeout) ) ; } -void NetChannel::handleRead (void) { - SG_LOG(SG_IO, SG_WARN, "Network:" << getHandle() << ": unhandled read"); -} - -void NetChannel::handleWrite (void) { - SG_LOG(SG_IO, SG_WARN, "Network:" << getHandle() << ": unhandled write"); -} - -void NetChannel::handleAccept (void) { - SG_LOG(SG_IO, SG_WARN, "Network:" << getHandle() << ": unhandled accept"); -} - -void NetChannel::handleError (int error) { - SG_LOG(SG_IO, SG_WARN,"Network:" << getHandle() << ": errno: " << strerror(errno) <<"(" << errno << ")"); -} - } // of namespace simgear