14e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 24e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#include "XmlRpcDispatch.h" 34e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#include "XmlRpcSource.h" 44e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#include "XmlRpcUtil.h" 54e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 64e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#include <math.h> 74e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 84e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#if defined(_WINDOWS) 94e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius# include <winsock2.h> 104e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 114e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius# define USE_FTIME 124e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius# if defined(_MSC_VER) 134e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius# define timeb _timeb 144e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius# define ftime _ftime 154e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius# endif 164e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#else 174e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius# include <sys/time.h> 184e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#endif // _WINDOWS 194e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 204e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 214e2ea8184cc1f9609f1f1251394316629a108a78Roshan Piususing namespace XmlRpc; 224e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 234e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 244e2ea8184cc1f9609f1f1251394316629a108a78Roshan PiusXmlRpcDispatch::XmlRpcDispatch() 254e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius{ 264e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius _endTime = -1.0; 274e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius _doClear = false; 284e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius _inWork = false; 294e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius} 304e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 314e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 324e2ea8184cc1f9609f1f1251394316629a108a78Roshan PiusXmlRpcDispatch::~XmlRpcDispatch() 334e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius{ 344e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius} 354e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 364e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// Monitor this source for the specified events and call its event handler 374e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// when the event occurs 384e2ea8184cc1f9609f1f1251394316629a108a78Roshan Piusvoid 394e2ea8184cc1f9609f1f1251394316629a108a78Roshan PiusXmlRpcDispatch::addSource(XmlRpcSource* source, unsigned mask) 404e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius{ 414e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius _sources.push_back(MonitoredSource(source, mask)); 424e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius} 434e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 444e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// Stop monitoring this source. Does not close the source. 454e2ea8184cc1f9609f1f1251394316629a108a78Roshan Piusvoid 464e2ea8184cc1f9609f1f1251394316629a108a78Roshan PiusXmlRpcDispatch::removeSource(XmlRpcSource* source) 474e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius{ 484e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius for (SourceList::iterator it=_sources.begin(); it!=_sources.end(); ++it) 494e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius if (it->getSource() == source) 504e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius { 514e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius _sources.erase(it); 524e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius break; 534e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius } 544e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius} 554e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 564e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 574e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// Modify the types of events to watch for on this source 584e2ea8184cc1f9609f1f1251394316629a108a78Roshan Piusvoid 594e2ea8184cc1f9609f1f1251394316629a108a78Roshan PiusXmlRpcDispatch::setSourceEvents(XmlRpcSource* source, unsigned eventMask) 604e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius{ 614e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius for (SourceList::iterator it=_sources.begin(); it!=_sources.end(); ++it) 624e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius if (it->getSource() == source) 634e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius { 644e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius it->getMask() = eventMask; 654e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius break; 664e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius } 674e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius} 684e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 694e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 704e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 714e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// Watch current set of sources and process events 724e2ea8184cc1f9609f1f1251394316629a108a78Roshan Piusvoid 734e2ea8184cc1f9609f1f1251394316629a108a78Roshan PiusXmlRpcDispatch::work(double timeout) 744e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius{ 754e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius // Compute end time 764e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius _endTime = (timeout < 0.0) ? -1.0 : (getTime() + timeout); 774e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius _doClear = false; 784e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius _inWork = true; 794e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 804e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius // Only work while there is something to monitor 814e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius while (_sources.size() > 0) { 824e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 834e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius // Construct the sets of descriptors we are interested in 844e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius fd_set inFd, outFd, excFd; 854e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius FD_ZERO(&inFd); 864e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius FD_ZERO(&outFd); 874e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius FD_ZERO(&excFd); 884e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 894e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius int maxFd = -1; // Not used on windows 904e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius SourceList::iterator it; 914e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius for (it=_sources.begin(); it!=_sources.end(); ++it) { 924e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius int fd = it->getSource()->getfd(); 934e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius if (it->getMask() & ReadableEvent) FD_SET(fd, &inFd); 944e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius if (it->getMask() & WritableEvent) FD_SET(fd, &outFd); 954e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius if (it->getMask() & Exception) FD_SET(fd, &excFd); 964e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius if (it->getMask() && fd > maxFd) maxFd = fd; 974e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius } 984e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 994e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius // Check for events 1004e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius int nEvents; 1014e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius if (timeout < 0.0) 1024e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius nEvents = select(maxFd+1, &inFd, &outFd, &excFd, NULL); 1034e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius else 1044e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius { 1054e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius struct timeval tv; 1064e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius tv.tv_sec = (int)floor(timeout); 1074e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius tv.tv_usec = ((int)floor(1000000.0 * (timeout-floor(timeout)))) % 1000000; 1084e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius nEvents = select(maxFd+1, &inFd, &outFd, &excFd, &tv); 1094e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius } 1104e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 1114e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius if (nEvents < 0) 1124e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius { 1134e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius XmlRpcUtil::error("Error in XmlRpcDispatch::work: error in select (%d).", nEvents); 1144e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius _inWork = false; 1154e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius return; 1164e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius } 1174e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 1184e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius // Process events 1194e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius for (it=_sources.begin(); it != _sources.end(); ) 1204e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius { 1214e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius SourceList::iterator thisIt = it++; 1224e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius XmlRpcSource* src = thisIt->getSource(); 1234e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius int fd = src->getfd(); 1244e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius unsigned newMask = (unsigned) -1; 1254e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius if (fd <= maxFd) { 1264e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius // If you select on multiple event types this could be ambiguous 1274e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius if (FD_ISSET(fd, &inFd)) 1284e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius newMask &= src->handleEvent(ReadableEvent); 1294e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius if (FD_ISSET(fd, &outFd)) 1304e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius newMask &= src->handleEvent(WritableEvent); 1314e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius if (FD_ISSET(fd, &excFd)) 1324e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius newMask &= src->handleEvent(Exception); 1334e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 1344e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius if ( ! newMask) { 1354e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius _sources.erase(thisIt); // Stop monitoring this one 1364e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius if ( ! src->getKeepOpen()) 1374e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius src->close(); 1384e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius } else if (newMask != (unsigned) -1) { 1394e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius thisIt->getMask() = newMask; 1404e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius } 1414e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius } 1424e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius } 1434e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 1444e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius // Check whether to clear all sources 1454e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius if (_doClear) 1464e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius { 1474e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius SourceList closeList = _sources; 1484e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius _sources.clear(); 1494e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius for (SourceList::iterator it=closeList.begin(); it!=closeList.end(); ++it) { 1504e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius XmlRpcSource *src = it->getSource(); 1514e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius src->close(); 1524e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius } 1534e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 1544e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius _doClear = false; 1554e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius } 1564e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 1574e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius // Check whether end time has passed 1584e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius if (0 <= _endTime && getTime() > _endTime) 1594e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius break; 1604e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius } 1614e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 1624e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius _inWork = false; 1634e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius} 1644e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 1654e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 1664e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// Exit from work routine. Presumably this will be called from 1674e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// one of the source event handlers. 1684e2ea8184cc1f9609f1f1251394316629a108a78Roshan Piusvoid 1694e2ea8184cc1f9609f1f1251394316629a108a78Roshan PiusXmlRpcDispatch::exit() 1704e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius{ 1714e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius _endTime = 0.0; // Return from work asap 1724e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius} 1734e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 1744e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// Clear all sources from the monitored sources list 1754e2ea8184cc1f9609f1f1251394316629a108a78Roshan Piusvoid 1764e2ea8184cc1f9609f1f1251394316629a108a78Roshan PiusXmlRpcDispatch::clear() 1774e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius{ 1784e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius if (_inWork) 1794e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius _doClear = true; // Finish reporting current events before clearing 1804e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius else 1814e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius { 1824e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius SourceList closeList = _sources; 1834e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius _sources.clear(); 1844e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius for (SourceList::iterator it=closeList.begin(); it!=closeList.end(); ++it) 1854e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius it->getSource()->close(); 1864e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius } 1874e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius} 1884e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 1894e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 1904e2ea8184cc1f9609f1f1251394316629a108a78Roshan Piusdouble 1914e2ea8184cc1f9609f1f1251394316629a108a78Roshan PiusXmlRpcDispatch::getTime() 1924e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius{ 1934e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#ifdef USE_FTIME 1944e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius struct timeb tbuff; 1954e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 1964e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius ftime(&tbuff); 1974e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius return ((double) tbuff.time + ((double)tbuff.millitm / 1000.0) + 1984e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius ((double) tbuff.timezone * 60)); 1994e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#else 2004e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius struct timeval tv; 2014e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius struct timezone tz; 2024e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 2034e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius gettimeofday(&tv, &tz); 2044e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius return (tv.tv_sec + tv.tv_usec / 1000000.0); 2054e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#endif /* USE_FTIME */ 2064e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius} 2074e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 2084e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius 209