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