Poll.cxx
上传用户:sy_wanhua
上传日期:2013-07-25
资源大小:3048k
文件大小:19k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

C/C++

  1. /* ====================================================================
  2.  * The Vovida Software License, Version 1.0 
  3.  * 
  4.  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
  5.  * 
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 
  10.  * 1. Redistributions of source code must retain the above copyright
  11.  *    notice, this list of conditions and the following disclaimer.
  12.  * 
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in
  15.  *    the documentation and/or other materials provided with the
  16.  *    distribution.
  17.  * 
  18.  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
  19.  *    and "Vovida Open Communication Application Library (VOCAL)" must
  20.  *    not be used to endorse or promote products derived from this
  21.  *    software without prior written permission. For written
  22.  *    permission, please contact vocal@vovida.org.
  23.  *
  24.  * 4. Products derived from this software may not be called "VOCAL", nor
  25.  *    may "VOCAL" appear in their name, without prior written
  26.  *    permission of Vovida Networks, Inc.
  27.  * 
  28.  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
  29.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
  31.  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
  32.  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
  33.  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
  34.  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  35.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  36.  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  37.  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  38.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  39.  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  40.  * DAMAGE.
  41.  * 
  42.  * ====================================================================
  43.  * 
  44.  * This software consists of voluntary contributions made by Vovida
  45.  * Networks, Inc. and many individuals on behalf of Vovida Networks,
  46.  * Inc.  For more information on Vovida Networks, Inc., please see
  47.  * <http://www.vovida.org/>.
  48.  *
  49.  */
  50. static const char* const Poll_cxx_Version = 
  51.     "$Id: Poll.cxx,v 1.20 2001/04/17 16:49:00 icahoon Exp $";
  52. #include "Poll.hxx"
  53. #include "Protocol.hxx"
  54. #include "FileDescriptor.hxx"
  55. #include "TransportCommon.hxx"
  56. #include "SystemException.hxx"
  57. #include "SystemStatus.hxx"
  58. #include "ConnectionBrokenException.hxx"
  59. #include "ProtocolException.hxx"
  60. #include "IPAddress.hxx"
  61. #include "Lock.hxx"
  62. #include "VLog.hxx"
  63. #include <cerrno>
  64. #include <iomanip>
  65. using Vocal::Transport::Poll;
  66. using Vocal::Transport::Protocol;
  67. using Vocal::Transport::pollfdLess;
  68. using Vocal::IO::FileDescriptor;
  69. using Vocal::IO::file_descriptor_t;
  70. using Vocal::IO::Pipe;
  71. using Vocal::Process::Lock;
  72. using Vocal::Logging::VLog;
  73. using Vocal::ReturnCode;
  74. using Vocal::SUCCESS;
  75. Poll::EventType    Poll::Incoming = 0x01;
  76. Poll::EventType    Poll::Outgoing = 0x02;
  77. Poll::EventType    Poll::Priority = 0x04;
  78. Poll::Poll()
  79.     : myProtocolsChanged(false),
  80. myInterruptCount(0)
  81. {
  82.     myInterruptor.writeFD().setBlocking();
  83.     myInterruptor.readFD().setNonblocking();
  84.     
  85.     // Add interruptor to poll file descriptor list. We are marking the
  86.     // protocols and unchanged, so that they won't get reloaded.
  87.     //
  88.     addInterruptorToFds();
  89. }
  90. Poll::~Poll()
  91. {
  92. }
  93. void          
  94. Poll::registerFD(
  95.     const FileDescriptor &      fd, 
  96.     EventType                   flag,
  97.     Protocol                *   protocol
  98. )
  99. {
  100.     const string    fn("Poll::registerFD");
  101.     VLog         log(fn);
  102.     pollfd       newPollFd;
  103.     
  104.     newPollFd.fd = fd.getFD();
  105.     newPollFd.events = newPollFd.revents = 0;
  106.     
  107.     string   eventNames;
  108.     bool     awaitingSomething = false;
  109.     
  110.     if ( flag & Incoming )
  111.     {
  112.      newPollFd.events |= POLLIN;
  113. eventNames += " POLLIN";
  114. awaitingSomething = true;
  115.     }
  116.     if ( flag & Outgoing )
  117.     {
  118.      newPollFd.events |= POLLOUT;
  119. eventNames += " POLLOUT";
  120. awaitingSomething = true;
  121.     }
  122.     if ( flag & Priority )
  123.     {
  124.      newPollFd.events |= POLLPRI;
  125. eventNames += " POLLPRI";
  126. awaitingSomething = true;
  127.     }
  128.     
  129.     if ( !awaitingSomething )
  130.     {
  131.      VDEBUG(log) << fn << ": not awaiting any notifications, unregistering."
  132.          << VDEBUG_END(log);
  133.     
  134.      unregisterFD(fd);
  135. return;
  136.     }
  137.         
  138.     ProtocolMap::iterator   it = myProtocols.find(newPollFd);
  139.     
  140.     if ( it != myProtocols.end() )
  141.     {
  142.      // This may be an update. If necessary, replace the pollfd, 
  143. // effectively reseting the events.
  144. //
  145. if ( it->first.events != newPollFd.events )
  146. {
  147.     // The whole pollfd is being used as a key in the pair, but 
  148.     // looking more closely, only the file descriptor is being 
  149.     // keyed off of. If we are here, the file descriptors 
  150.     // (i.e. the true keys) are the same, but the events may 
  151.     // be different. So casting the key portion of the pair to 
  152.     // a non const pollfd is ok.
  153.     //
  154.     // This is the penalty I am paying for storing data in
  155.     // the key.
  156.     //
  157.     pollfd & pollFd = const_cast<pollfd &>(it->first);
  158.             pollFd = newPollFd;
  159.     myProtocolsChanged = true;
  160. }
  161.     }
  162.     else 
  163.     {
  164.      // The is a first time registration. Add the poll file
  165. // descriptor / protocol pair. 
  166. //
  167.      myProtocols[newPollFd] = protocol;
  168. myProtocolsChanged = true;
  169.     }
  170.     VDEBUG(log) << fn << "nt" << fd
  171.           << "ntprotocols changed = " << ( myProtocolsChanged ? "true" : "false" )
  172.           << "ntevents: " << eventNames
  173.           << VDEBUG_END(log);
  174.     VVERBOSE(log) << fn << ": " << *this << VVERBOSE_END(log);
  175. }
  176. void          
  177. Poll::updateFD(
  178.     const FileDescriptor    &   fd, 
  179.     EventType                   flag,
  180.     Protocol                *   protocol
  181. )
  182. {
  183.     registerFD(fd, flag, protocol);
  184. }
  185. void          
  186. Poll::unregisterFD(const FileDescriptor & fd)
  187. {
  188.     const string    fn("Poll::unregisterFD");
  189.     VLog         log(fn);
  190.     pollfd   pollFd;
  191.     pollFd.fd = fd.getFD();
  192.     bool    removed = false;
  193.         
  194.     ProtocolMap::iterator   it = myProtocols.find(pollFd);
  195.     if ( it != myProtocols.end() )
  196.     {
  197.      // Found it, so let's remove it.
  198. //
  199.      myProtocols.erase(it);
  200. myProtocolsChanged = true;
  201. removed = true;
  202.     }
  203.     VDEBUG(log) << fn << "nt" << fd
  204.           << "ntprotocols changed = " << ( myProtocolsChanged ? "true" : "false" )
  205. << "ntremoved = " << ( removed ? "true" : "false" )
  206.           << VDEBUG_END(log);
  207.     VVERBOSE(log) << fn << ": " << *this << VVERBOSE_END(log);
  208. }
  209. void          
  210. Poll::registerProtocol(Protocol & protocol)
  211. {
  212.     EventType   flag = 0;
  213.     if ( protocol.awaitIncoming() )
  214.     {
  215.      flag |= Incoming;
  216.     }
  217.     if ( protocol.awaitOutgoing() )
  218.     {
  219.      flag |= Outgoing;
  220.     }
  221.     if ( protocol.awaitPriority() )
  222.     {
  223.      flag |= Priority;
  224.     }
  225.     registerFD(protocol.getFileDescriptor(), flag, &protocol);
  226. }
  227. void          
  228. Poll::updateProtocol(Protocol & protocol)
  229. {
  230.     registerProtocol(protocol);
  231. }
  232. void          
  233. Poll::unregisterProtocol(Protocol & protocol)
  234. {
  235.     unregisterFD(protocol.getFileDescriptor());
  236. }
  237. int           
  238. Poll::poll(int timeout)
  239. throw ( Vocal::SystemException )
  240. {
  241.     const string    fn("Poll::poll");
  242.     VLog         log(fn);
  243.     
  244.     // Recreate the poll file descriptor if needed.
  245.     //
  246.     if ( myProtocolsChanged )
  247.     {
  248.      VDEBUG(log) << fn << ": protocols changed, updating." << VDEBUG_END(log);
  249.      myFds.clear();
  250. addInterruptorToFds();
  251. addProtocolsToFds();
  252. myProtocolsChanged = false;
  253.     }
  254.     VVERBOSE(log) << fn << ": " << *this << VVERBOSE_END(log);
  255.     VDEBUG(log) << fn << ": polling for activity. timeout = " << timeout
  256.           << VDEBUG_END(log);
  257.     
  258.     int numberFdsActive = ::poll(&myFds[0], myFds.size(), timeout);
  259.     if ( numberFdsActive < SUCCESS )
  260.     {
  261.      int error = errno;
  262.      // If we were interrupted, treat it like a timeout.
  263. //
  264.      if ( error == EINTR )
  265. {
  266.     VDEBUG(log) << fn << ": interrupted." << VDEBUG_END(log);
  267.          return ( 0 );
  268. }
  269.      throw Vocal::SystemException(fn + " on poll(): " + strerror(error), 
  270.                 __FILE__, __LINE__, error);
  271.     }    
  272.     // Clear interruptor so that numberFdsActive corresponds to
  273.     // registered file descriptors only.
  274.     //
  275.     for (   vector<pollfd>::iterator  it = myFds.begin();
  276.          it != myFds.end() && numberFdsActive > 0;
  277.     it++
  278. )
  279.     {
  280.      pollfd     &   pollFdEntry = (*it);
  281.      if ( processInterruptor(pollFdEntry) )
  282. {
  283.          VVERBOSE(log) << fn << ": " << *this << VVERBOSE_END(log);
  284.     numberFdsActive--;
  285.     pollFdEntry.revents = 0;
  286.     break;
  287. }
  288.     }
  289.         
  290.     return ( numberFdsActive );
  291. }
  292. Poll::EventType
  293. Poll::fdActive(const FileDescriptor & filedesc) const
  294. {
  295.     EventType returnEvent = 0;
  296.     
  297.     file_descriptor_t   fd = filedesc.getFD();
  298.     
  299.     for (   vector<pollfd>::const_iterator i = myFds.begin();
  300.             i != myFds.end();
  301.             ++i
  302.         )
  303.     {
  304.         if ( fd == i->fd )
  305.         {
  306.             returnEvent = i->revents;
  307.             break;
  308.         }
  309.     }
  310.     return ( returnEvent );
  311. }
  312. void           
  313. Poll::processProtocols(int numberFdsActive)
  314. throw ( Vocal::Transport::ProtocolException )
  315. {
  316.     const string    fn("Poll::processProtocols");
  317.     VLog         log(fn);
  318.     VDEBUG(log) << fn << ": Start: number file descriptors active = " 
  319.           << numberFdsActive 
  320.      << ", protocols changed = " 
  321. << ( myProtocolsChanged ? "true" : "false" )
  322. << VDEBUG_END(log);
  323.     VVERBOSE(log) << fn << ": " << *this << VVERBOSE_END(log);
  324.     for (   vector<pollfd>::iterator  it = myFds.begin();
  325.          it != myFds.end() && numberFdsActive > 0;
  326.     it++
  327. )
  328.     {
  329.      pollfd     &   pollFdEntry = (*it);
  330.      if ( pollFdEntry.fd == myInterruptor.readFD().getFD() )
  331. {
  332.     pollFdEntry.revents = 0;
  333.     continue;
  334. }
  335.      ProtocolMap::iterator   protocolIt = myProtocols.find(pollFdEntry);
  336. if ( protocolIt == myProtocols.end() )
  337. {
  338.     // If a two protocols are active, but then second protocol
  339.     // is unregistered as a result of activity on the first 
  340.     // protocol, we will end up here.
  341.     //
  342.     myProtocolsChanged = true;
  343.     VDEBUG(log) << fn << ": no protocol found for: fd = "
  344.           << it->fd << VDEBUG_END(log);
  345.          VVERBOSE(log) << fn << ": " << *this << VVERBOSE_END(log);
  346.     pollFdEntry.revents = 0;
  347.     continue;
  348. }
  349.      Protocol    * protocol = (*protocolIt).second;
  350.     
  351.         if ( protocol == 0 )
  352.         {
  353.             VWARN(log) << fn << ": no protocol associated with fd = " 
  354.                        << it->fd << VWARN_END(log);
  355.             continue;
  356.         }
  357.      if ( processPriority(pollFdEntry, protocol) )
  358. {
  359.          VVERBOSE(log) << fn << ": " << *this << VVERBOSE_END(log);
  360.     numberFdsActive--;
  361.     pollFdEntry.revents = 0;
  362.     continue;
  363. }
  364.      if ( processIncoming(pollFdEntry, protocol) )
  365. {
  366.          VVERBOSE(log) << fn << ": " << *this << VVERBOSE_END(log);
  367.     numberFdsActive--;
  368.     pollFdEntry.revents = 0;
  369.     continue;
  370. }
  371.      if ( processOutgoing(pollFdEntry, protocol) )
  372. {
  373.          VVERBOSE(log) << fn << ": " << *this << VVERBOSE_END(log);
  374.     numberFdsActive--;
  375.     pollFdEntry.revents = 0;
  376.     continue;
  377. }
  378.      if ( processHangup(pollFdEntry, protocol) )
  379. {
  380.          VVERBOSE(log) << fn << ": " << *this << VVERBOSE_END(log);
  381.     numberFdsActive--;
  382.          pollFdEntry.revents = 0;
  383.     continue;
  384. }
  385.      if ( processError(pollFdEntry, protocol) )
  386. {
  387.          VVERBOSE(log) << fn << ": " << *this << VVERBOSE_END(log);
  388.     numberFdsActive--;
  389. }
  390.      pollFdEntry.revents = 0;
  391.     }
  392.     VDEBUG(log) << fn << ": End: number file descriptors active = " 
  393.           << numberFdsActive 
  394.      << ", protocols changed = " 
  395. << ( myProtocolsChanged ? "true" : "false" )
  396. << VDEBUG_END(log);
  397. }
  398. void          
  399. Poll::interrupt()
  400. throw ( Vocal::SystemException )
  401. {
  402.     const string    fn("Poll::interrupt");
  403.     VLog         log(fn);
  404.     
  405.     Lock    lock(myInterruptorMutex); (void)lock;
  406.     myInterruptCount++;
  407.     
  408.     myInterruptor.writeFD().write(&myInterruptCount, 1);
  409.     VDEBUG(log) << fn << ": Interrupting: "   << (unsigned)myInterruptCount 
  410.           << " outstanding interrupts." << VDEBUG_END(log);
  411. }
  412. u_int8_t         
  413. Poll::interruptCount() const
  414. {
  415.     return ( myInterruptCount );
  416. }
  417. ostream &           
  418. Poll::writeTo(ostream & out) const
  419. {
  420.     out << "protocols (size: " << myProtocols.size() << ") = n{n";
  421.     for ( ProtocolMap::const_iterator it = myProtocols.begin(); it != myProtocols.end(); it++ )
  422.     {
  423.      if ( it->first.fd == myInterruptor.readFD().getFD() )
  424. {
  425.     continue;
  426. }
  427.      out << "  ";
  428. if ( it->second )
  429. {
  430.     out << *it->second << "n";
  431. }
  432. else
  433. {
  434.     out << "no protocol.n";
  435. }
  436.     }
  437.     out << "}ninterruptor = " << myInterruptor 
  438.      << "nnumber outstanding interruptions = " << (unsigned)myInterruptCount
  439. << "nprotocolsChanged = " << ( myProtocolsChanged ? "true" : "false" );
  440.     size_t  size = myFds.size();
  441.     
  442.     out << "nfds (size: " << size << ") = n{n";
  443.     for ( size_t i = 0; i < size; i++ )
  444.     {
  445.      out << " ( " << myFds[i].fd 
  446.     << ", 0x" << hex << setw(2) << setfill('0') << (unsigned)(myFds[i].events)
  447.     << ", 0x" << hex << setw(2) << setfill('0') << (unsigned)(myFds[i].revents)
  448.     << dec << " )n";
  449.     }
  450.     out << "}";
  451.     
  452.     return ( out );
  453. }
  454. void          
  455. Poll::addInterruptorToFds()
  456. {
  457.     pollfd   interruptorPollFd;
  458.     interruptorPollFd.fd     = myInterruptor.readFD().getFD();
  459.     interruptorPollFd.events = POLLIN;
  460.     interruptorPollFd.revents = 0;
  461.     myFds.insert(myFds.end(), interruptorPollFd);
  462. }
  463. void          
  464. Poll::addProtocolsToFds()
  465. {
  466.     for (   ProtocolMap::iterator  it = myProtocols.begin();
  467.          it != myProtocols.end();
  468.     it++
  469. )
  470.     {
  471.      myFds.insert(myFds.end(), it->first);
  472.     }
  473. }
  474. bool
  475. Poll::processInterruptor(pollfd &   pollFdEntry)
  476. {
  477.     const string    fn("Poll::processInterruptor");
  478.     VLog         log(fn);
  479.     VVERBOSE(log) << fn << ": fd = " << pollFdEntry.fd << VVERBOSE_END(log);
  480.         
  481.     if  ( pollFdEntry.fd == myInterruptor.readFD().getFD() )
  482.     {
  483.      if ( pollFdEntry.revents & POLLIN  )
  484. {
  485.     u_int8_t    interruptNumber = 0;
  486.     IPAddress   remoteAddr;
  487.     Lock    lock(myInterruptorMutex); (void)lock;
  488.     VDEBUG(log) << fn << ": Interrupted: " << (unsigned)myInterruptCount 
  489.           << " outstanding interrupts." << VDEBUG_END(log);
  490.     do
  491.     {
  492. // Let the user catch the exception, if thrown.
  493. //
  494.          myInterruptor.readFD().read(&interruptNumber, 1);
  495.     } while ( interruptNumber < myInterruptCount );
  496.     myInterruptCount = 0;
  497.     
  498.     return ( true );
  499. }
  500. else
  501. {
  502.     return ( false );
  503. }
  504.     }
  505.     return ( false );
  506. }
  507. bool
  508. Poll::processPriority(pollfd & pollFdEntry, Protocol * protocol)
  509. {
  510.     const string    fn("Poll::processPriority");
  511.     VLog         log(fn);
  512.     VDEBUG(log) << fn << ": fd = " << pollFdEntry.fd << VDEBUG_END(log);
  513.     if ( pollFdEntry.revents & POLLPRI )
  514.     {
  515. VDEBUG(log) << fn << ": Priority for protocol = " << *protocol
  516.          << VDEBUG_END(log);
  517.      // Notify the user of a priority message on the file descriptor.
  518. //
  519. try
  520. {
  521.     protocol->onPriority();
  522. }
  523. catch ( Vocal::SystemStatus & )
  524. {
  525.     // The status indicates that we need to poll again.
  526.     // This is the desfault behavior, so do nothing.
  527. }
  528. catch ( Vocal::Transport::ConnectionBrokenException & e)
  529. {
  530.     return ( processHangup(pollFdEntry, protocol, &e) );
  531. }
  532. catch ( Vocal::SystemException & e )
  533. {
  534.     return ( processError(pollFdEntry, protocol, &e) );
  535. }
  536. catch ( ... )
  537. {
  538.     protocol->handleUnknownException();
  539. }
  540. return ( true );
  541.     }
  542.     
  543.     return ( false );
  544. }
  545. bool
  546. Poll::processIncoming(pollfd & pollFdEntry, Protocol * protocol)
  547. {
  548.     const string    fn("Poll::processIncoming");
  549.     VLog         log(fn);
  550.     VVERBOSE(log) << fn << ": fd = " << pollFdEntry.fd << VVERBOSE_END(log);
  551.     if ( pollFdEntry.revents & POLLIN )
  552.     {
  553. VDEBUG(log) << fn << ": IncomingAvailable for protocol = " 
  554.     << *protocol << VDEBUG_END(log);
  555.      // Notify the user of an incoming message on the file 
  556. // descriptor.
  557. //
  558. try
  559. {
  560.     protocol->onIncomingAvailable();
  561. }
  562. catch ( Vocal::SystemStatus & )
  563. {
  564.     // The status indicates that we need to poll again.
  565.     // Do nothing.
  566. }
  567. catch ( Vocal::Transport::ConnectionBrokenException & e )
  568. {
  569.     return ( processHangup(pollFdEntry, protocol, &e) );
  570. }
  571. catch ( Vocal::SystemException & e )
  572. {
  573.     return ( processError(pollFdEntry, protocol, &e) );
  574. }
  575. catch ( ... )
  576. {
  577.     protocol->handleUnknownException();
  578. }
  579. return ( true );
  580.     }
  581.     return ( false );
  582. }
  583. bool
  584. Poll::processOutgoing(pollfd & pollFdEntry, Protocol * protocol)
  585. {
  586.     const string    fn("Poll::processOutgoing");
  587.     VLog         log(fn);
  588.     VVERBOSE(log) << fn << ": fd = " << pollFdEntry.fd << VVERBOSE_END(log);
  589.     if ( pollFdEntry.revents & POLLOUT )
  590.     {
  591. VDEBUG(log) << fn << ": OutgoingAvailable for protocol = " 
  592.     << *protocol << VDEBUG_END(log);
  593.      // Notify the user of that the file descriptor is
  594. // available to send outgoing messages.
  595. //
  596. try
  597. {
  598.     protocol->onOutgoingAvailable();
  599. }
  600. catch ( Vocal::SystemStatus )
  601. {
  602.     // The status indicates that we need to poll again.
  603.     // Do nothing.
  604. }
  605. catch ( Vocal::Transport::ConnectionBrokenException & e )
  606. {
  607.     return ( processHangup(pollFdEntry, protocol, &e) );
  608. }
  609. catch ( Vocal::SystemException & e )
  610. {
  611.     return ( processError(pollFdEntry, protocol, &e) );
  612. }
  613. catch ( ... )
  614. {
  615.     protocol->handleUnknownException();
  616. }
  617. return ( true );
  618.     }
  619.     return ( false );
  620. }
  621. bool
  622. Poll::processHangup(
  623.     pollfd             &   pollFdEntry, 
  624.     Protocol            *   protocol,
  625.     ConnectionBrokenException  *   connectionBrokenException
  626. )
  627. {
  628.     const string    fn("Poll::processHangup");
  629.     VLog         log(fn);
  630.     VVERBOSE(log) << fn << ": fd = " << pollFdEntry.fd << VVERBOSE_END(log);
  631.     
  632.     if  (   connectionBrokenException != 0
  633.      ||  pollFdEntry.revents & POLLHUP 
  634. )
  635.     {
  636. VDEBUG(log) << fn << ": Disconnect for protocol = " 
  637.     << *protocol << VDEBUG_END(log);
  638.      // Notify the user of that the file descriptor has hung up.
  639. //
  640. try
  641. {
  642.     protocol->onDisconnect(connectionBrokenException);
  643. }
  644. catch ( Vocal::SystemStatus & )
  645. {
  646.     // The status indicates that we need to poll again.
  647.     // Do nothing.
  648. }
  649. catch ( Vocal::SystemException & e )
  650. {
  651.     return ( processError(pollFdEntry, protocol, &e) );
  652. }
  653. catch ( ... )
  654. {
  655.     protocol->handleUnknownException();
  656. }
  657. return ( true );
  658.     }
  659.     return ( false );
  660. }
  661. bool
  662. Poll::processError(
  663.     pollfd        &   pollFdEntry, 
  664.     Protocol       *   protocol,
  665.     SystemException *   systemException
  666. )
  667. {
  668.     const string    fn("Poll::processError");
  669.     VLog         log(fn);
  670.     VVERBOSE(log) << fn << ": fd = " << pollFdEntry.fd << VVERBOSE_END(log);
  671.     if  (   systemException != 0 
  672.      ||  pollFdEntry.revents & POLLERR
  673. ||  pollFdEntry.revents & POLLNVAL
  674. )
  675.     {
  676. VWARN(log)  << fn << ": Error for protocol = " << *protocol
  677.          << VWARN_END(log);
  678.      // Notify the user of the error.
  679. //
  680. try
  681. {
  682.             protocol->onError(systemException);
  683. }
  684. catch ( ... )
  685. {
  686.     protocol->handleUnknownException();
  687. }
  688. return ( true );
  689.     }
  690.     return ( false );
  691. }
  692. bool 
  693. pollfdLess::operator()(const pollfd & left, const pollfd & right) const
  694. {
  695.     return ( left.fd < right.fd );
  696. }