File indexing completed on 2024-12-01 06:51:47
0001 // 0002 // C++ Implementation: cnotifymanager 0003 // 0004 // Description: Notification manager for the /notify macro 0005 // 0006 /* 0007 Copyright 2005-2011 Tomas Mecir <kmuddy@kmuddy.com> 0008 Copyright 2005 Alex Bache <alexbache@ntlworld.com> 0009 0010 This program is free software; you can redistribute it and/or 0011 modify it under the terms of the GNU General Public License as 0012 published by the Free Software Foundation; either version 2 of 0013 the License, or (at your option) any later version. 0014 0015 This program is distributed in the hope that it will be useful, 0016 but WITHOUT ANY WARRANTY; without even the implied warranty of 0017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0018 GNU General Public License for more details. 0019 0020 You should have received a copy of the GNU General Public License 0021 along with this program. If not, see <http://www.gnu.org/licenses/>. 0022 */ 0023 0024 #include "cnotifymanager.h" 0025 0026 #include "kdebug.h" 0027 #include <QTcpSocket> 0028 0029 cNotifyManager::cNotifyManager () 0030 { 0031 notifications.clear(); 0032 } 0033 0034 cNotifyManager::~cNotifyManager() 0035 { 0036 } 0037 0038 /** send information to external IP port */ 0039 void cNotifyManager::doNotify(const int port, 0040 QString &ip_data) 0041 { 0042 std::list <cEventNotification *>::iterator ptr = notifications.begin(); 0043 std::list <cEventNotification *>::iterator last = notifications.end(); 0044 0045 while ((ptr != last)&& 0046 ((*ptr)->port_num() != port) ) 0047 { 0048 ++ptr; 0049 } // endwhile more 'in progress' event notifications to search 0050 0051 if (ptr == last) 0052 { 0053 cEventNotification *notify_event = new cEventNotification(port,ip_data); 0054 0055 notifications.push_back(notify_event); 0056 0057 connect(notify_event, 0058 SIGNAL (finished(cEventNotification *)), 0059 this, 0060 SLOT (portNotified(cEventNotification *))); 0061 0062 notify_event->send(); 0063 0064 } // endif no other notifications in progress to this IP port at this time 0065 else 0066 { 0067 // Queue data for sending later 0068 (*ptr)->queue(ip_data); 0069 0070 } // endelse need to queue notification 0071 0072 } 0073 0074 0075 void cNotifyManager::portNotified(cEventNotification *event_notify) 0076 { 0077 std::list<cEventNotification *>::iterator ptr = notifications.begin(); 0078 std::list<cEventNotification *>::iterator last = notifications.end(); 0079 0080 while ((ptr != last) && 0081 (*ptr != event_notify) ) 0082 { 0083 ++ptr; 0084 } // endwhile event notification not found 0085 0086 if (ptr != last) 0087 { 0088 delete *ptr; 0089 0090 notifications.erase(ptr); 0091 } // endif found relevant event notification 0092 0093 } 0094 0095 0096 // cEventNotification implementation from here on 0097 0098 //*************************************************************** 0099 // Constructor - set up signals and initialise variables 0100 //*************************************************************** 0101 0102 cEventNotification::cEventNotification(const int ip_port, 0103 const QString &ip_data) 0104 { 0105 QString data; 0106 0107 port = ip_port; 0108 data = ip_data+"\n"; 0109 0110 data_list.push_back(data); 0111 0112 // Set up signal handling 0113 0114 sock = new QTcpSocket; 0115 0116 connect(sock, SIGNAL(connected()), this, SLOT(connected())); 0117 connect(sock, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error())); 0118 connect(sock, SIGNAL(bytesWritten(qint64)), this, SLOT(wroteAll())); 0119 connect(sock, SIGNAL(disconnected()), this, SLOT (connectionClosed())); 0120 } // cEventNotification::cEventNotification 0121 0122 0123 //*************************************************************** 0124 // Destructor 0125 //*************************************************************** 0126 0127 cEventNotification::~cEventNotification() 0128 { 0129 connectionClosed (); 0130 } // cEventNotification::~cEventNotification 0131 0132 0133 //*************************************************************** 0134 // Function to initiate information sending to the specified IP port 0135 //*************************************************************** 0136 0137 void cEventNotification::send() 0138 { 0139 sock->connectToHost ("127.0.0.1", port); 0140 } // cEventNotification::send 0141 0142 0143 //*************************************************************** 0144 // Queue data for sending at next opportunity 0145 //*************************************************************** 0146 0147 void cEventNotification::queue(const QString &ip_data) 0148 { 0149 QString data = ip_data+"\n"; 0150 0151 data_list.push_back(data); 0152 0153 if (data_list.size() == 1) 0154 writeNext (); 0155 } // cEventNotification::queue 0156 0157 0158 //*************************************************************** 0159 // Called when connected to IP port successfully 0160 //*************************************************************** 0161 0162 void cEventNotification::connected() 0163 { 0164 writeNext (); 0165 } // cEventNotification::connected 0166 0167 0168 0169 //*************************************************************** 0170 // Wrote some data to the IP port 0171 //*************************************************************** 0172 0173 void cEventNotification::wroteAll() 0174 { 0175 // At this point, we can try writing more data 0176 data_list.pop_front(); 0177 0178 writeNext(); 0179 } // cEventNotification::wroteAll 0180 0181 0182 0183 //*************************************************************** 0184 // Connection closed - all done 0185 //*************************************************************** 0186 0187 void cEventNotification::connectionClosed() 0188 { 0189 // Empty notification queue 0190 data_list.clear(); 0191 0192 if (!sock) return; 0193 0194 sock->blockSignals (true); 0195 0196 // delete socket 0197 sock->deleteLater(); 0198 sock = 0; 0199 0200 if (port != -1) 0201 { 0202 port = -1; 0203 emit finished(this); 0204 } // endif not already announced we're finished 0205 0206 } // cEventNotification::connectionClosed 0207 0208 0209 //*************************************************************** 0210 // An error occured 0211 //*************************************************************** 0212 0213 void cEventNotification::error() 0214 { 0215 // Usually called when we attempt to connect to a port that's no longer 0216 // got a server attached to it. 0217 0218 data_list.clear(); 0219 0220 if (port != -1) 0221 { 0222 port = -1; 0223 0224 emit finished(this); 0225 0226 } // endif not already announced we're finished 0227 0228 } // cEventNotification::error 0229 0230 void cEventNotification::writeNext () 0231 { 0232 if (data_list.empty()) return; 0233 std::list<QString>::iterator ptr = data_list.begin(); 0234 0235 // Note: this might not buffer the entire message contents. Not completely sure 0236 qint64 written = sock->write(ptr->toLatin1()); 0237 0238 if (written != ptr->length()) 0239 { 0240 // NOTE: Far as I can tell, this never happens. It's just here in case it ever does 0241 kWarning() << "/notify warning: write() was unable to buffer all data" << endl; 0242 } // endif unable to buffer all requested data 0243 0244 if (written == -1) 0245 { 0246 // NOTE: This shouldn't ever happen because we wait until the buffer is empty before 0247 // trying to send any more data, but just in case... 0248 kWarning() << "/notify warning: write() buffer is full" << endl; 0249 data_list.clear(); 0250 0251 connectionClosed(); 0252 } // endif unable to write data (write buffer is full) 0253 } 0254 0255 #include "moc_cnotifymanager.cpp"