1 /*=============================================================================
2 
3   Library: CTK
4 
5   Copyright (c) German Cancer Research Center,
6     Division of Medical and Biological Informatics
7 
8   Licensed under the Apache License, Version 2.0 (the "License");
9   you may not use this file except in compliance with the License.
10   You may obtain a copy of the License at
11 
12     http://www.apache.org/licenses/LICENSE-2.0
13 
14   Unless required by applicable law or agreed to in writing, software
15   distributed under the License is distributed on an "AS IS" BASIS,
16   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   See the License for the specific language governing permissions and
18   limitations under the License.
19 
20 =============================================================================*/
21 
22 // Qt includes
23 #include <QTcpSocket>
24 
25 // CTK includes
26 #include "ctkSoapConnectionRunnable_p.h"
27 #include "ctkSoapLog.h"
28 
29 //----------------------------------------------------------------------------
ctkSoapConnectionRunnable(int socketDescriptor)30 ctkSoapConnectionRunnable::ctkSoapConnectionRunnable(int socketDescriptor)
31   : socketDescriptor(socketDescriptor), isAboutToQuit(0)
32 {
33   connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(aboutToQuit()));
34 }
35 
36 //----------------------------------------------------------------------------
~ctkSoapConnectionRunnable()37 ctkSoapConnectionRunnable::~ctkSoapConnectionRunnable()
38 {
39 
40 }
41 
42 //----------------------------------------------------------------------------
run()43 void ctkSoapConnectionRunnable::run()
44 {
45   QTcpSocket tcpSocket;
46   if (!tcpSocket.setSocketDescriptor(socketDescriptor))
47     {
48     // error handling
49     return;
50     }
51 
52   const int timeout = 1 * 1000;
53   while (tcpSocket.state() == QTcpSocket::ConnectedState &&
54          isAboutToQuit.fetchAndAddOrdered(0) == 0)
55     {
56 
57     tcpSocket.waitForReadyRead(timeout);
58 
59     readClient(tcpSocket);
60     }
61 
62 }
63 
64 //----------------------------------------------------------------------------
readClient(QTcpSocket & socket)65 void ctkSoapConnectionRunnable::readClient(QTcpSocket& socket)
66 {
67   QString requestType;
68   int contentLength = -1;
69   //qDebug() << socket->readAll();
70   while (socket.canReadLine()) {
71     QString line = socket.readLine();
72     CTK_SOAP_LOG_LOWLEVEL( << line );
73     if(line.contains("?wsdl HTTP"))
74       {
75       requestType = "?wsdl";
76       }
77     if(line.contains("?xsd=1"))
78       {
79       requestType = "?xsd=1";
80       }
81     if(line.contains("SoapAction"))
82       {
83       requestType = line;
84       }
85     if(line.contains("Content-Length: "))
86       {
87       contentLength = line.section(':',1).trimmed().toInt();
88       }
89     if (line.trimmed().isEmpty())
90       {
91       QString content;
92       if(requestType.startsWith("?"))
93         {
94         QByteArray body = socket.readAll();
95         emit incomingWSDLMessage(requestType, &content);
96         }
97       else
98         {
99         // Read the http body, which contains the soap message
100         int bytesRead = 0;
101         QByteArray body;
102         while(body.size() < contentLength)
103           {
104           QByteArray bodyPart = socket.read(contentLength);
105           CTK_SOAP_LOG_LOWLEVEL( << bodyPart );
106           bytesRead += bodyPart.size();
107           body.append(bodyPart);
108           CTK_SOAP_LOG_LOWLEVEL( << " Expected content-length: " << contentLength << ". Bytes read so far: " << body.size() );
109           if (body.size()<contentLength)
110             {
111             qCritical() << " Message body too small. Trying to read more.";
112             socket.waitForReadyRead(-1);
113             }
114           }
115         if(body.trimmed().isEmpty()==false)
116           {
117           QtSoapMessage msg;
118           if (!msg.setContent(body))
119             {
120             qCritical() << "QtSoap import failed:" << msg.errorString();
121             return;
122             }
123 
124           QtSoapMessage reply;
125           CTK_SOAP_LOG(<< "###################" << msg.toXmlString());
126           emit incomingSoapMessage(msg, &reply);
127 
128           if (reply.isFault())
129             {
130             qCritical() << "QtSoap reply faulty";
131             return;
132             }
133 
134           CTK_SOAP_LOG_LOWLEVEL( << "SOAP reply:" );
135 
136           content = reply.toXmlString();
137           }
138         }
139 
140       QByteArray block;
141       block.append("HTTP/1.1 200 OK\n");
142       block.append("Content-Type: text/xml;charset=utf-8\n");
143       block.append("Content-Length: ").append(QString::number(content.size())).append("\n");
144       block.append("\n");
145 
146       block.append(content);
147 
148       CTK_SOAP_LOG_LOWLEVEL( << block );
149 
150       socket.write(block);
151 
152       requestType = "";
153       contentLength = -1;
154       }
155     }
156 }
157 
aboutToQuit()158 void ctkSoapConnectionRunnable::aboutToQuit()
159 {
160   isAboutToQuit.testAndSetOrdered(0, 1);
161 }
162