00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00024
00025 #ifdef unix
00026 #include <sys/types.h>
00027 #include <sys/stat.h>
00028 #include <stdlib.h>
00029 #include <fcntl.h>
00030 #include <stdio.h>
00031 #elif WIN32
00032 #include <QThread>
00033 #include <windows.h>
00034 #include <tchar.h>
00035 #endif
00036
00037
00038 #include <QNamedPipe>
00039 #include <QDebug>
00040 #include <unistd.h>
00041
00043
00044 #ifdef WIN32
00045 TCHAR * char_to_tchar(const char* pSrc)
00046 {
00047 if(!pSrc) return NULL;
00048 unsigned int n = strlen (pSrc);
00049 TCHAR * wsOut = new TCHAR[n+1];
00050 for (unsigned int i=0; i<1+n; i++)
00051 wsOut[i] = pSrc[i];
00052
00053 return wsOut;
00054 };
00055
00056 #define BUFSIZE 256*1024
00057
00058 QNamedPipeThread::QNamedPipeThread(HANDLE pipe1, HANDLE pipe2, char *name)
00059 {
00060 qDebug() << "QNamedPipeThread::QNamedPipeThread(" << pipe1 << "," << pipe2 << "," << name << ")";
00061 this->hPipe1 = pipe1;
00062 this->hPipe2 = pipe2;
00063 this->finished = false;
00064 this->pipeName = strdup(name);
00065 qDebug() << "QNamedPipeThread::QNamedPipeThread() <- return";
00066 }
00067
00068 QNamedPipeThread::~QNamedPipeThread()
00069 {
00070 qDebug() << "QNamedPipeThread::~QNamedPipeThread()";
00071 delete this->pipeName;
00072 qDebug() << "QNamedPipeThread::~QNamedPipeThread() <- return";
00073 }
00074
00075
00076 void QNamedPipeThread::run()
00077 {
00078 qDebug() << "QNamedPipeThread::run()";
00079
00080
00081 BOOL fConnected1 = ConnectNamedPipe(hPipe1, NULL) ?
00082 TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
00083 qDebug() << "QNamedPipeThread::run(): input end for pipe" << pipeName << "connected";
00084
00085 BOOL fConnected2 = ConnectNamedPipe(hPipe2, NULL) ?
00086 TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
00087 qDebug() << "QNamedPipeThread::run(): output end for pipe" << pipeName << "connected";
00088
00089 if (!fConnected1 || !fConnected2)
00090 {
00091 qDebug() << "QNamedPipeThread::run(): connection for named pipe " << pipeName << "failed";
00092 return;
00093 }
00094
00095
00096 int c = 0;
00097
00098 while (not finished)
00099 {
00100 qDebug() << "QNamedPipeThread::run(): dispatching loop for named pipe " << pipeName << "started";
00101
00102 TCHAR buffer[BUFSIZE];
00103 DWORD cbBytesRead, cbWritten;
00104
00105
00106 BOOL fSuccess = ReadFile(
00107 hPipe1,
00108 buffer,
00109 BUFSIZE*sizeof(TCHAR),
00110 &cbBytesRead,
00111 NULL);
00112 qDebug() << "QNamedPipeThread::run(): read " << cbBytesRead << "bytes from input of pipe" << pipeName;
00113
00114 FlushFileBuffers(hPipe1);
00115 qDebug() << "QNamedPipeThread::run(): done flushing for input end of named pipe"<< pipeName;
00116 c += cbBytesRead;
00117
00118 if (! fSuccess)
00119 {
00120 qDebug() << "QNamedPipeThread::run(): ReadFile false, exiting main loop for pipe"<< pipeName;
00121 finished = true;
00122 break;
00123 }
00124 else if (cbBytesRead == 0)
00125 {
00126 qDebug() << "QNamedPipeThread::run(): 0 bytes read, exiting main loop for pipe"<< pipeName;
00127 finished = true;
00128 break;
00129 }
00130 else
00131 {
00132 fSuccess = WriteFile(
00133 hPipe2,
00134 buffer,
00135 cbBytesRead,
00136 &cbWritten,
00137 NULL);
00138 qDebug() << "QNamedPipeThread::run(): sent" << cbWritten << "bytes to output end of named pipe" << pipeName;
00139
00140 FlushFileBuffers(hPipe2);
00141 qDebug() << "QNamedPipeThread::run(): done flushing for output end of named pipe"<< pipeName;
00142
00143 c -= cbWritten;
00144
00145 if (c > BUFSIZE)
00146 qDebug() << "QNamedPipeThread::run(): Buffer OVERFLOW" << c << "of" << BUFSIZE << "bytes max\n";
00147
00148 if (! fSuccess || cbBytesRead != cbWritten) break;
00149 qDebug() << "QNamedPipeThread::run(): finished loop for pipe" << pipeName;
00150 }
00151 }
00152
00153 qDebug() << "QNamedPipeThread::run(): closing pipe" << pipeName;
00154
00155
00156 FlushFileBuffers(hPipe1);
00157 FlushFileBuffers(hPipe2);
00158 DisconnectNamedPipe(hPipe1);
00159 DisconnectNamedPipe(hPipe2);
00160 CloseHandle(hPipe1);
00161 CloseHandle(hPipe2);
00162 qDebug() << "QNamedPipeThread::run() <- return";
00163 }
00164 #endif
00165
00167
00168 QNamedPipe::QNamedPipe(QString identifier): QObject()
00169 {
00170 qDebug() << "QNamedPipeThread::QNamedPipe(" << identifier <<")";
00171
00172 name = identifier + QString(".")
00173 + QString().setNum(QNamedPipe::namedPipesNum++)
00174 + QString(".pid") + QString().setNum(getpid());
00175
00176 #ifdef unix
00177 pathIn = QString("/tmp/") + name + QString(".qnamedpipe");
00178 pathOut = QString("/tmp/") + name + QString(".qnamedpipe");
00179 qDebug() << "QNamedPipeThread::QNamedPipe(): (UNIX) going to create pipe" << name
00180 << "\n\t"<< pathIn << "\n\t" << pathOut;
00181
00182 mkfifo(pathIn.toAscii().data(),0644); pathOut = pathIn;
00183
00184 #elif WIN32
00185 pathIn = QString("\\\\.\\pipe\\") + name + QString(".in.qnamedpipe");
00186 pathOut = QString("\\\\.\\pipe\\") + name + QString(".out.qnamedpipe");
00187 qDebug() << "QNamedPipeThread::QNamedPipe(): (WIN32) going to create pipe" << name
00188 << "\n\t"<< pathIn << "\n\t" << pathOut;
00189
00190
00191 HANDLE hPipe1 = CreateNamedPipe(
00192 TEXT(char_to_tchar(pathIn.toAscii().data())),
00193 PIPE_ACCESS_DUPLEX,
00194 PIPE_TYPE_BYTE |
00195 PIPE_WAIT,
00196 1,
00197 BUFSIZE,
00198 BUFSIZE,
00199 NMPWAIT_USE_DEFAULT_WAIT,
00200 NULL);
00201
00202 HANDLE hPipe2 = CreateNamedPipe(
00203 TEXT(char_to_tchar(pathOut.toAscii().data())),
00204 PIPE_ACCESS_DUPLEX,
00205 PIPE_TYPE_BYTE |
00206 PIPE_WAIT,
00207 1,
00208 BUFSIZE,
00209 BUFSIZE,
00210 NMPWAIT_USE_DEFAULT_WAIT,
00211 NULL);
00212
00213
00214 if ((hPipe1 == INVALID_HANDLE_VALUE) || (hPipe2 == INVALID_HANDLE_VALUE))
00215 {
00216 qDebug() << "QNamedPipeThread::QNamedPipe(): failed create of pipe" << name;
00217 return;
00218 }
00219
00220 pipeThread = new QNamedPipeThread(hPipe1,hPipe2,name.toAscii().data());
00221 pipeThread->start(QThread::TimeCriticalPriority);
00222 #endif
00223 qDebug() << "QNamedPipeThread::QNamedPipe(): named pipe" << name
00224 << "created:\n\t"<< pathIn << "\n\t" << pathOut;
00225
00226 qDebug() << "QNamedPipeThread::QNamedPipe() <- return";
00227 }
00228
00229 QNamedPipe::~QNamedPipe()
00230 {
00231 qDebug() << "QNamedPipeThread::~QNamedPipe()";
00232 qDebug() << "QNamedPipeThread::~QNamedPipe(): deleting pipe" << name;
00233
00234 #ifdef unix
00235 remove(pathIn.toAscii().data());
00236 #elif WIN32
00237 pipeThread->finished = true;
00238 pipeThread->wait();
00239 qDebug() << "QNamedPipeThread::~QNamedPipe(): pipeThread finished";
00240 delete pipeThread;
00241 qDebug() << "QNamedPipeThread::~QNamedPipe(): pipeThread deleted";
00242 #endif
00243
00244 qDebug() << "QNamedPipeThread::~QNamedPipe() <- return";
00245 }
00246
00247
00248 QString QNamedPipe::getInputFilePath() const { return pathIn; }
00249 QString QNamedPipe::getOutputFilePath() const { return pathOut; }
00250 QString QNamedPipe::getPipeName() const { return name; }
00251 int QNamedPipe::namedPipesNum = 0;