00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <config.h>
00024
00025 #include <kde_file.h>
00026 #include <ksock.h>
00027 #include <tqtimer.h>
00028
00029 #include <sys/types.h>
00030 #include <sys/signal.h>
00031 #include <sys/time.h>
00032
00033 #include <errno.h>
00034 #include <fcntl.h>
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <signal.h>
00038 #include <string.h>
00039 #include <unistd.h>
00040
00041 #include "tdeio/connection.h"
00042
00043 #include <kdebug.h>
00044 #include <tqsocketnotifier.h>
00045
00046 #if defined(__OpenBSD__) || defined(__FreeBSD__)
00047 #define __progname getprogname()
00048 #else
00049 extern char *__progname;
00050 #endif
00051
00052 using namespace TDEIO;
00053
00054 Connection::Connection()
00055 {
00056 f_out = 0;
00057 fd_in = -1;
00058 socket = 0;
00059 notifier = 0;
00060 receiver = 0;
00061 member = 0;
00062 m_suspended = false;
00063 tasks.setAutoDelete(true);
00064 }
00065
00066 Connection::~Connection()
00067 {
00068 close();
00069 }
00070
00071 void Connection::suspend()
00072 {
00073 m_suspended = true;
00074 if (notifier)
00075 notifier->setEnabled(false);
00076 }
00077
00078 void Connection::resume()
00079 {
00080 m_suspended = false;
00081 if (notifier)
00082 notifier->setEnabled(true);
00083 }
00084
00085 void Connection::close()
00086 {
00087 delete notifier;
00088 notifier = 0;
00089 delete socket;
00090 socket = 0;
00091
00092
00093
00094
00095
00096
00097 if (f_out)
00098 fclose(f_out);
00099 f_out = 0;
00100 fd_in = -1;
00101 tasks.clear();
00102 }
00103
00104 void Connection::send(int cmd, const TQByteArray& data)
00105 {
00106 if (!inited() || tasks.count() > 0) {
00107 Task *task = new Task();
00108 task->cmd = cmd;
00109 task->data = data;
00110 tasks.append(task);
00111 } else {
00112 sendnow( cmd, data );
00113 }
00114 }
00115
00116 void Connection::dequeue()
00117 {
00118 if (!inited())
00119 return;
00120
00121 while (tasks.count())
00122 {
00123 tasks.first();
00124 Task *task = tasks.take();
00125 sendnow( task->cmd, task->data );
00126 delete task;
00127 }
00128 }
00129
00130 void Connection::init(TDESocket *sock)
00131 {
00132 delete notifier;
00133 notifier = 0;
00134 #ifdef Q_OS_UNIX //TODO: not yet available on WIN32
00135 delete socket;
00136 socket = sock;
00137 fd_in = socket->socket();
00138 f_out = KDE_fdopen( socket->socket(), "wb" );
00139 #endif
00140 if (receiver && ( fd_in != -1 )) {
00141 notifier = new TQSocketNotifier(fd_in, TQSocketNotifier::Read);
00142 if ( m_suspended ) {
00143 suspend();
00144 }
00145 TQObject::connect(notifier, TQT_SIGNAL(activated(int)), receiver, member);
00146 }
00147 dequeue();
00148 }
00149
00150 void Connection::init(int _fd_in, int fd_out)
00151 {
00152 delete notifier;
00153 notifier = 0;
00154 fd_in = _fd_in;
00155 f_out = KDE_fdopen( fd_out, "wb" );
00156 if (receiver && ( fd_in != -1 )) {
00157 notifier = new TQSocketNotifier(fd_in, TQSocketNotifier::Read);
00158 if ( m_suspended ) {
00159 suspend();
00160 }
00161 TQObject::connect(notifier, TQT_SIGNAL(activated(int)), receiver, member);
00162 }
00163 dequeue();
00164 }
00165
00166
00167 void Connection::connect(TQObject *_receiver, const char *_member)
00168 {
00169 receiver = _receiver;
00170 member = _member;
00171 delete notifier;
00172 notifier = 0;
00173 if (receiver && (fd_in != -1 )) {
00174 notifier = new TQSocketNotifier(fd_in, TQSocketNotifier::Read);
00175 if ( m_suspended )
00176 suspend();
00177 TQObject::connect(notifier, TQT_SIGNAL(activated(int)), receiver, member);
00178 }
00179 }
00180
00181 bool Connection::sendnow( int _cmd, const TQByteArray &data )
00182 {
00183 if (f_out == 0) {
00184 return false;
00185 }
00186
00187 if (data.size() > 0xffffff)
00188 return false;
00189
00190 static char buffer[ 64 ];
00191 sprintf( buffer, "%6x_%2x_", data.size(), _cmd );
00192
00193 size_t n = fwrite( buffer, 1, 10, f_out );
00194
00195 if ( n != 10 ) {
00196 kdError(7017) << "Could not send header (pid " << getpid() << " process \"" << __progname << "\")" << endl;
00197 return false;
00198 }
00199
00200 n = fwrite( data.data(), 1, data.size(), f_out );
00201
00202 if ( n != data.size() ) {
00203 kdError(7017) << "Could not write data (pid " << getpid() << " process \"" << __progname << "\")" << endl;
00204 return false;
00205 }
00206
00207 if (fflush( f_out )) {
00208 kdError(7017) << "Could not write data (pid " << getpid() << " process \"" << __progname << "\")" << endl;
00209 return false;
00210 }
00211
00212 return true;
00213 }
00214
00215 int Connection::read( int* _cmd, TQByteArray &data )
00216 {
00217 if (fd_in == -1 ) {
00218 kdError(7017) << "read: not yet inited (pid " << getpid() << " process \"" << __progname << "\")" << endl;
00219 return -1;
00220 }
00221
00222 static char buffer[ 10 ];
00223
00224 again1:
00225 ssize_t n = ::read( fd_in, buffer, 10);
00226 if ( n == -1 && errno == EINTR )
00227 goto again1;
00228
00229 if ( n == -1) {
00230 kdError(7017) << "Header read failed, errno=" << errno << " (pid " << getpid() << " process \"" << __progname << "\")" << endl;
00231 }
00232
00233 if ( n != 10 ) {
00234 if ( n )
00235 kdError(7017) << "Header has invalid size (" << n << ") (pid " << getpid() << " process \"" << __progname << "\")" << endl;
00236 return -1;
00237 }
00238
00239 buffer[ 6 ] = 0;
00240 buffer[ 9 ] = 0;
00241
00242 char *p = buffer;
00243 while( *p == ' ' ) p++;
00244 long int len = strtol( p, 0L, 16 );
00245
00246 p = buffer + 7;
00247 while( *p == ' ' ) p++;
00248 long int cmd = strtol( p, 0L, 16 );
00249
00250 data.resize( len );
00251
00252 if ( len > 0L ) {
00253 size_t bytesToGo = len;
00254 size_t bytesRead = 0;
00255 do {
00256 n = ::read(fd_in, data.data()+bytesRead, bytesToGo);
00257 if (n == -1) {
00258 if (errno == EINTR)
00259 continue;
00260
00261 kdError(7017) << "Data read failed, errno=" << errno << " (pid " << getpid() << " process \"" << __progname << "\")" << endl;
00262 return -1;
00263 }
00264 if ( !n ) {
00265 kdError(7017) << "Connection ended unexpectedly (" << n << "/" << bytesToGo << ") (pid " << getpid() << " process \"" << __progname << "\")" << endl;
00266 return -1;
00267 }
00268
00269 bytesRead += n;
00270 bytesToGo -= n;
00271 }
00272 while(bytesToGo);
00273 }
00274
00275 *_cmd = cmd;
00276 return len;
00277 }
00278
00279 #include "connection.moc"