~ubuntu-branches/ubuntu/trusty/digikam/trusty

« back to all changes in this revision

Viewing changes to extra/kipi-plugins/dlnaexport/extra/hupnp/src/http/hhttp_asynchandler_p.cpp

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2012-09-27 21:41:30 UTC
  • mfrom: (1.2.43)
  • mto: This revision was merged to the branch mainline in revision 86.
  • Revision ID: package-import@ubuntu.com-20120927214130-i8v3ufr21nesp29i
Tags: 4:3.0.0~beta1a-1
* New upstream release

* Fix "wrongly conflicts phonon-backend-vlc" dropped (Closes: #688142)
* debian/watch include download.kde.org

* digikam 3.0.0 uses features from unreleased kdegraphics >=4.10 & ships 
a private version of the kdegraphics libs - this is not the Debian way :-(
* Unsatisfactory Conflicts: libkipi8, libkexiv2-10, libkdcraw20, libksane0
* Suspend digikam-dbg >130Mb

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Copyright (C) 2010, 2011 Tuomo Penttinen, all rights reserved.
 
3
 *
 
4
 *  Author: Tuomo Penttinen <tp@herqq.org>
 
5
 *
 
6
 *  This file is part of Herqq UPnP (HUPnP) library.
 
7
 *
 
8
 *  Herqq UPnP is free software: you can redistribute it and/or modify
 
9
 *  it under the terms of the GNU Lesser General Public License as published by
 
10
 *  the Free Software Foundation, either version 3 of the License, or
 
11
 *  (at your option) any later version.
 
12
 *
 
13
 *  Herqq UPnP is distributed in the hope that it will be useful,
 
14
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 
16
 *  GNU Lesser General Public License for more details.
 
17
 *
 
18
 *  You should have received a copy of the GNU Lesser General Public License
 
19
 *  along with Herqq UPnP. If not, see <http://www.gnu.org/licenses/>.
 
20
 */
 
21
 
 
22
#include "hhttp_asynchandler_p.h"
 
23
#include "hhttp_messagecreator_p.h"
 
24
#include "hhttp_utils_p.h"
 
25
 
 
26
#include "../general/hupnp_global_p.h"
 
27
#include "../devicehosting/messages/hevent_messages_p.h"
 
28
 
 
29
#include <QtNetwork/QTcpSocket>
 
30
 
 
31
#include <QtSoapMessage>
 
32
 
 
33
namespace Herqq
 
34
{
 
35
 
 
36
namespace Upnp
 
37
{
 
38
 
 
39
HHttpAsyncOperation::HHttpAsyncOperation(
 
40
    const QByteArray& loggingIdentifier, unsigned int id, HMessagingInfo* mi,
 
41
    bool waitingRequest, QObject* parent) :
 
42
        QObject(parent),
 
43
            m_mi(mi),
 
44
            m_dataToSend(),
 
45
            m_dataSend(0),
 
46
            m_dataSent(0),
 
47
            m_state(Internal_NotStarted),
 
48
            m_headerRead(0),
 
49
            m_dataRead(),
 
50
            m_dataToRead(0),
 
51
            m_id(id),
 
52
            m_loggingIdentifier(loggingIdentifier),
 
53
            m_opType(waitingRequest ? ReceiveRequest : ReceiveResponse)
 
54
{
 
55
    bool ok = connect(
 
56
        &m_mi->socket(), SIGNAL(readyRead()), this, SLOT(readyRead()));
 
57
 
 
58
    Q_ASSERT(ok); Q_UNUSED(ok)
 
59
 
 
60
    ok = connect(
 
61
        &m_mi->socket(), SIGNAL(error(QAbstractSocket::SocketError)),
 
62
        this, SLOT(error(QAbstractSocket::SocketError)));
 
63
 
 
64
    Q_ASSERT(ok);
 
65
}
 
66
 
 
67
HHttpAsyncOperation::HHttpAsyncOperation(
 
68
    const QByteArray& loggingIdentifier, unsigned int id, HMessagingInfo* mi,
 
69
    const QByteArray& data, bool sendOnly, QObject* parent) :
 
70
        QObject(parent),
 
71
            m_mi(mi),
 
72
            m_dataToSend(data),
 
73
            m_dataSend(0),
 
74
            m_dataSent(0),
 
75
            m_state(Internal_NotStarted),
 
76
            m_headerRead(0),
 
77
            m_dataRead(),
 
78
            m_dataToRead(0),
 
79
            m_id(id),
 
80
            m_loggingIdentifier(loggingIdentifier),
 
81
            m_opType(sendOnly ? SendOnly : MsgIO)
 
82
{
 
83
    bool ok = connect(
 
84
        &m_mi->socket(), SIGNAL(bytesWritten(qint64)),
 
85
        this, SLOT(bytesWritten(qint64)));
 
86
 
 
87
    Q_ASSERT(ok); Q_UNUSED(ok)
 
88
 
 
89
    ok = connect(
 
90
        &m_mi->socket(), SIGNAL(readyRead()), this, SLOT(readyRead()));
 
91
 
 
92
    Q_ASSERT(ok);
 
93
 
 
94
    ok = connect(
 
95
        &m_mi->socket(), SIGNAL(error(QAbstractSocket::SocketError)),
 
96
        this, SLOT(error(QAbstractSocket::SocketError)));
 
97
 
 
98
    Q_ASSERT(ok);
 
99
}
 
100
 
 
101
HHttpAsyncOperation::~HHttpAsyncOperation()
 
102
{
 
103
    delete m_mi;
 
104
    delete m_headerRead;
 
105
}
 
106
 
 
107
void HHttpAsyncOperation::sendChunked()
 
108
{
 
109
    static const char crlf[] = {"\r\n"};
 
110
 
 
111
    // then start sending the data in chunks
 
112
    qint64 bytesWritten = 0;
 
113
 
 
114
    if (m_dataSent < m_dataToSend.size())
 
115
    {
 
116
        qint32 dataToSendSize =
 
117
            m_dataSend > 0 ? m_dataSend :
 
118
                qMin(m_dataToSend.size() - m_dataSent,
 
119
                    static_cast<qint64>(m_mi->chunkedInfo().max()));
 
120
 
 
121
        if (m_state == Internal_WritingChunkedSizeLine)
 
122
        {
 
123
            // write the size line of the next chunk
 
124
            QByteArray sizeLine;
 
125
            sizeLine.setNum(dataToSendSize, 16);
 
126
            sizeLine.append(crlf, 2);
 
127
 
 
128
            bytesWritten = m_mi->socket().write(sizeLine);
 
129
            if (bytesWritten != sizeLine.size())
 
130
            {
 
131
                m_mi->setLastErrorDescription("failed to send chunked data");
 
132
                done_(Internal_Failed);
 
133
                return;
 
134
            }
 
135
 
 
136
            m_state = Internal_WritingChunk;
 
137
        }
 
138
 
 
139
        // write the chunk
 
140
        bytesWritten =
 
141
            m_mi->socket().write(m_dataToSend.data() + m_dataSent, dataToSendSize);
 
142
 
 
143
        if (bytesWritten < 0)
 
144
        {
 
145
            m_mi->setLastErrorDescription("failed to send chunked data");
 
146
            done_(Internal_Failed);
 
147
            return;
 
148
        }
 
149
 
 
150
        m_dataSent += bytesWritten;
 
151
 
 
152
        if (bytesWritten != dataToSendSize)
 
153
        {
 
154
            m_dataSend = dataToSendSize - bytesWritten;
 
155
 
 
156
            // wait for bytesWritten() and then attempt to send the data remaining
 
157
            // in the chunk
 
158
            return;
 
159
        }
 
160
        else
 
161
        {
 
162
            m_dataSend = 0;
 
163
        }
 
164
 
 
165
        // and after the chunk, write the trailing crlf and start again if there's
 
166
        // chunks left
 
167
        bytesWritten = m_mi->socket().write(crlf, 2);
 
168
        if (bytesWritten != 2)
 
169
        {
 
170
            m_mi->setLastErrorDescription("failed to send chunked data");
 
171
            done_(Internal_Failed);
 
172
            return;
 
173
        }
 
174
 
 
175
        m_state = Internal_WritingChunkedSizeLine;
 
176
    }
 
177
 
 
178
    if (m_dataSent >= m_dataToSend.size())
 
179
    {
 
180
        // write the "eof" == zero + crlf
 
181
        const char eof[] = "0\r\n";
 
182
        m_mi->socket().write(&eof[0], 3);
 
183
        m_mi->socket().flush();
 
184
 
 
185
        if (m_opType == SendOnly)
 
186
        {
 
187
            done_(Internal_FinishedSuccessfully);
 
188
            return;
 
189
        }
 
190
 
 
191
        m_state = Internal_ReadingHeader;
 
192
    }
 
193
}
 
194
 
 
195
void HHttpAsyncOperation::readBlob()
 
196
{
 
197
    QByteArray buf; buf.resize(m_dataToRead+1);
 
198
    do
 
199
    {
 
200
        qint64 retVal = m_mi->socket().read(
 
201
            buf.data(), qMin(static_cast<qint64>(buf.size()), m_dataToRead));
 
202
 
 
203
        if (retVal < 0)
 
204
        {
 
205
            m_mi->setLastErrorDescription(
 
206
                QString("failed to read data: %1").arg(
 
207
                    m_mi->socket().errorString()));
 
208
 
 
209
            done_(Internal_Failed);
 
210
            return;
 
211
        }
 
212
        else if (retVal > 0)
 
213
        {
 
214
            m_dataToRead -= retVal;
 
215
            m_dataRead.append(QByteArray(buf.data(), retVal));
 
216
        }
 
217
        else
 
218
        {
 
219
            break;
 
220
        }
 
221
    }
 
222
    while(m_dataToRead > 0);
 
223
 
 
224
    if (m_dataToRead <= 0)
 
225
    {
 
226
        done_(Internal_FinishedSuccessfully);
 
227
    }
 
228
}
 
229
 
 
230
bool HHttpAsyncOperation::readChunkedSizeLine()
 
231
{
 
232
    if (m_mi->socket().bytesAvailable() <= 0)
 
233
    {
 
234
        return false;
 
235
    }
 
236
 
 
237
    QByteArray buf;
 
238
    if (!HHttpUtils::readLines(m_mi->socket(), buf, 1))
 
239
    {
 
240
        // No size line. It should be available at this point.
 
241
        m_mi->setLastErrorDescription("missing chunk-size line");
 
242
        done_(Internal_Failed);
 
243
        return false;
 
244
    }
 
245
 
 
246
    qint32 endOfSize = buf.indexOf(';');
 
247
    if (endOfSize < 0)
 
248
    {
 
249
        // no extensions
 
250
        endOfSize = buf.size() - 2; // 2 == crlf
 
251
    }
 
252
    QByteArray sizeLine = buf.left(endOfSize);
 
253
 
 
254
    bool ok = false;
 
255
    qint32 chunkSize = sizeLine.toInt(&ok, 16);
 
256
    if (!ok || chunkSize < 0)
 
257
    {
 
258
        m_mi->setLastErrorDescription(
 
259
            QString("invalid chunk-size line: %1").arg(
 
260
                  QString::fromUtf8(sizeLine)));
 
261
 
 
262
        done_(Internal_Failed);
 
263
        return false;
 
264
    }
 
265
 
 
266
    if (chunkSize == 0)
 
267
    {
 
268
        // the last chunk, ignore possible trailers
 
269
        done_(Internal_FinishedSuccessfully);
 
270
        return false;
 
271
    }
 
272
 
 
273
    m_dataToRead = chunkSize;
 
274
    m_state = Internal_ReadingChunk;
 
275
 
 
276
    return true;
 
277
}
 
278
 
 
279
bool HHttpAsyncOperation::readChunk()
 
280
{
 
281
    QByteArray tmp;
 
282
    tmp.resize(m_dataToRead);
 
283
 
 
284
    qint32 read = m_mi->socket().read(tmp.data(), tmp.size());
 
285
 
 
286
    if (read < 0)
 
287
    {
 
288
        m_mi->setLastErrorDescription(QString(
 
289
            "failed to read chunk: %1").arg(m_mi->socket().errorString()));
 
290
 
 
291
        done_(Internal_Failed);
 
292
        return false;
 
293
    }
 
294
    else if (read == 0)
 
295
    {
 
296
        // couldn't read the entire chunk in one pass
 
297
        return false;
 
298
    }
 
299
 
 
300
    tmp.resize(read);
 
301
    m_dataRead.append(tmp);
 
302
 
 
303
    m_dataToRead -= read;
 
304
    if (m_dataToRead > 0)
 
305
    {
 
306
        // couldn't read the entire chunk in one pass
 
307
        return false;
 
308
    }
 
309
 
 
310
    // if here, the entire chunk data is read.
 
311
    // clear the remaining crlf and move to the next chunk
 
312
 
 
313
    char c;
 
314
    m_mi->socket().getChar(&c);
 
315
    m_mi->socket().getChar(&c);
 
316
 
 
317
    m_state = Internal_ReadingChunkSizeLine;
 
318
 
 
319
    return true;
 
320
}
 
321
 
 
322
bool HHttpAsyncOperation::readHeader()
 
323
{
 
324
    if (!HHttpUtils::readLines(m_mi->socket(), m_dataRead, 2))
 
325
    {
 
326
        m_mi->setLastErrorDescription(QString(
 
327
            "failed to read HTTP header: %1").arg(m_mi->socket().errorString()));
 
328
 
 
329
        done_(Internal_Failed);
 
330
        return false;
 
331
    }
 
332
 
 
333
    if (m_opType == ReceiveRequest)
 
334
    {
 
335
        m_headerRead = new HHttpRequestHeader(QString::fromUtf8(m_dataRead));
 
336
    }
 
337
    else
 
338
    {
 
339
        m_headerRead = new HHttpResponseHeader(QString::fromUtf8(m_dataRead));
 
340
    }
 
341
 
 
342
    m_dataRead.clear();
 
343
 
 
344
    if (!m_headerRead->isValid())
 
345
    {
 
346
        m_mi->setLastErrorDescription("read invalid HTTP header");
 
347
        done_(Internal_Failed);
 
348
        return false;
 
349
    }
 
350
 
 
351
    m_mi->setKeepAlive(HHttpUtils::keepAlive(*m_headerRead));
 
352
 
 
353
    if (m_headerRead->hasContentLength())
 
354
    {
 
355
        m_dataToRead = m_headerRead->contentLength();
 
356
        if (m_dataToRead == 0)
 
357
        {
 
358
            done_(Internal_FinishedSuccessfully);
 
359
            return false;
 
360
        }
 
361
    }
 
362
    else if (m_headerRead->value("TRANSFER-ENCODING") != "chunked")
 
363
    {
 
364
        done_(Internal_FinishedSuccessfully);
 
365
        return false;
 
366
    }
 
367
 
 
368
    m_state = Internal_ReadingData;
 
369
    return true;
 
370
}
 
371
 
 
372
bool HHttpAsyncOperation::readData()
 
373
{
 
374
    if (!m_mi->socket().bytesAvailable())
 
375
    {
 
376
        return false;
 
377
    }
 
378
 
 
379
    bool chunked = m_headerRead->value("TRANSFER-ENCODING") == "chunked";
 
380
    if (chunked)
 
381
    {
 
382
        if (m_headerRead->hasContentLength())
 
383
        {
 
384
            m_mi->setLastErrorDescription("read invalid HTTP header where both "
 
385
                "TRANSFER-ENCODING and CONTENT-LENGTH where defined");
 
386
 
 
387
            done_(Internal_Failed);
 
388
            return false;
 
389
        }
 
390
 
 
391
        m_state = Internal_ReadingChunkSizeLine;
 
392
    }
 
393
    else
 
394
    {
 
395
        if (m_headerRead->hasContentLength())
 
396
        {
 
397
            readBlob();
 
398
        }
 
399
        else
 
400
        {
 
401
            // not chunked and content length is not specified ==>
 
402
            // no way to know what to expect ==> read all that is available
 
403
            QByteArray body = m_mi->socket().readAll();
 
404
            m_dataRead.append(body);
 
405
 
 
406
            done_(Internal_FinishedSuccessfully);
 
407
            return false;
 
408
        }
 
409
    }
 
410
 
 
411
    return true;
 
412
}
 
413
 
 
414
bool HHttpAsyncOperation::run()
 
415
{
 
416
    if (m_dataToSend.isEmpty())
 
417
    {
 
418
        m_state = Internal_ReadingHeader;
 
419
        return true;
 
420
    }
 
421
 
 
422
    if (m_mi->socket().state() != QTcpSocket::ConnectedState)
 
423
    {
 
424
        m_mi->setLastErrorDescription("socket is not connected");
 
425
        return false;
 
426
    }
 
427
 
 
428
    qint32 indexOfData = m_dataToSend.indexOf("\r\n\r\n");
 
429
    Q_ASSERT(indexOfData > 0);
 
430
 
 
431
    if (m_mi->chunkedInfo().max() > 0 &&
 
432
        m_dataToSend.size() - indexOfData > m_mi->chunkedInfo().max())
 
433
    {
 
434
        // send the http header first (it is expected that the header has been
 
435
        // properly setup for chunked transfer, as it should be, since this is
 
436
        // private stuff not influenced by public input)
 
437
 
 
438
        qint32 endOfHdr = m_dataToSend.indexOf("\r\n\r\n") + 4;
 
439
        m_dataSent = m_mi->socket().write(m_dataToSend.data(), endOfHdr);
 
440
 
 
441
        if (m_dataSent != endOfHdr)
 
442
        {
 
443
            m_mi->setLastErrorDescription(QString(
 
444
                "failed to send HTTP header %1").arg(
 
445
                    m_mi->socket().errorString()));
 
446
 
 
447
            done_(Internal_Failed, false);
 
448
            return false;
 
449
        }
 
450
 
 
451
        m_state = Internal_WritingChunkedSizeLine;
 
452
        sendChunked();
 
453
    }
 
454
    else
 
455
    {
 
456
        m_dataSent = m_mi->socket().write(m_dataToSend);
 
457
 
 
458
        if (m_dataSent < 0)
 
459
        {
 
460
            m_mi->setLastErrorDescription(
 
461
                QString("failed to send data: %1").arg(
 
462
                    m_mi->socket().errorString()));
 
463
 
 
464
            done_(Internal_Failed, false);
 
465
            return false;
 
466
        }
 
467
 
 
468
        m_state = Internal_WritingBlob;
 
469
 
 
470
        if (m_mi->sendWait() > 0)
 
471
        {
 
472
            if (m_mi->socket().waitForBytesWritten(m_mi->sendWait()))
 
473
            {
 
474
                bytesWritten(-1);
 
475
            }
 
476
            else
 
477
            {
 
478
                m_mi->setLastErrorDescription(QString(
 
479
                    "failed to send data %1").arg(m_mi->socket().errorString()));
 
480
                done_(Internal_Failed, false);
 
481
                return false;
 
482
            }
 
483
        }
 
484
    }
 
485
 
 
486
    return true;
 
487
}
 
488
 
 
489
void HHttpAsyncOperation::done_(InternalState state, bool emitSignal)
 
490
{
 
491
    m_mi->socket().disconnect(this);
 
492
 
 
493
    Q_ASSERT((state == Internal_FinishedSuccessfully && (headerRead() || m_opType == SendOnly)) ||
 
494
              state != Internal_FinishedSuccessfully);
 
495
 
 
496
    m_state = state;
 
497
    if (emitSignal)
 
498
    {
 
499
        emit done(m_id);
 
500
    }
 
501
}
 
502
 
 
503
void HHttpAsyncOperation::bytesWritten(qint64)
 
504
{
 
505
    if (m_state == Internal_WritingBlob)
 
506
    {
 
507
        if (m_dataSent < m_dataToSend.size())
 
508
        {
 
509
            qint64 dataSent = m_mi->socket().write(
 
510
                m_dataToSend.data() + m_dataSent,
 
511
                m_dataToSend.size() - m_dataSent);
 
512
 
 
513
            if (dataSent < 0)
 
514
            {
 
515
                m_mi->setLastErrorDescription(
 
516
                    QString("failed to send data: %1").arg(
 
517
                        m_mi->socket().errorString()));
 
518
 
 
519
                done_(Internal_Failed);
 
520
                return;
 
521
            }
 
522
 
 
523
            m_dataSent += dataSent;
 
524
        }
 
525
 
 
526
        if (m_dataSent >= m_dataToSend.size())
 
527
        {
 
528
            if (m_opType == SendOnly)
 
529
            {
 
530
                done_(Internal_FinishedSuccessfully);
 
531
            }
 
532
            else
 
533
            {
 
534
                m_state = Internal_ReadingHeader;
 
535
            }
 
536
        }
 
537
    }
 
538
    else if (m_state == Internal_WritingChunk ||
 
539
             m_state == Internal_WritingChunkedSizeLine)
 
540
    {
 
541
        sendChunked();
 
542
    }
 
543
}
 
544
 
 
545
void HHttpAsyncOperation::readyRead()
 
546
{
 
547
    if (m_state == Internal_ReadingHeader)
 
548
    {
 
549
        if (!readHeader())
 
550
        {
 
551
            return;
 
552
        }
 
553
    }
 
554
 
 
555
    if (m_state == Internal_ReadingData)
 
556
    {
 
557
        if (!readData())
 
558
        {
 
559
            return;
 
560
        }
 
561
    }
 
562
 
 
563
    for(; m_state == Internal_ReadingChunkSizeLine ||
 
564
          m_state == Internal_ReadingChunk;)
 
565
    {
 
566
        // the request contained chunked data
 
567
 
 
568
        if (m_state == Internal_ReadingChunkSizeLine)
 
569
        {
 
570
            if (!readChunkedSizeLine())
 
571
            {
 
572
                // no more data available at the moment
 
573
                return;
 
574
            }
 
575
        }
 
576
 
 
577
        if (m_state == Internal_ReadingChunk)
 
578
        {
 
579
            if (!readChunk())
 
580
            {
 
581
                // no more data available at the moment
 
582
                return;
 
583
            }
 
584
        }
 
585
    }
 
586
}
 
587
 
 
588
void HHttpAsyncOperation::error(QAbstractSocket::SocketError err)
 
589
{
 
590
    if (err != QAbstractSocket::RemoteHostClosedError)
 
591
    {
 
592
        done_(Internal_Failed);
 
593
        return;
 
594
    }
 
595
    else if (m_state >= Internal_Failed && m_state < Internal_ReadingHeader)
 
596
    {
 
597
        done_(Internal_Failed);
 
598
        return;
 
599
    }
 
600
    else if (m_dataToRead > 0)
 
601
    {
 
602
        m_mi->setLastErrorDescription(
 
603
            "remote host closed connection before all data could be read");
 
604
 
 
605
        done_(Internal_Failed);
 
606
        return;
 
607
    }
 
608
    else if (m_state == Internal_ReadingHeader)
 
609
    {
 
610
        if (m_dataRead.size() <= 0)
 
611
        {
 
612
            m_mi->setLastErrorDescription(
 
613
                QString("failed to read HTTP header: %1").arg(m_mi->socket().errorString()));
 
614
            done_(Internal_Failed);
 
615
            return;
 
616
        }
 
617
 
 
618
        if (m_opType == ReceiveRequest)
 
619
        {
 
620
            m_headerRead = new HHttpRequestHeader(QString::fromUtf8(m_dataRead));
 
621
        }
 
622
        else
 
623
        {
 
624
            m_headerRead = new HHttpResponseHeader(QString::fromUtf8(m_dataRead));
 
625
        }
 
626
 
 
627
        if (!m_headerRead->isValid())
 
628
        {
 
629
            m_mi->setLastErrorDescription("read invalid HTTP header");
 
630
            done_(Internal_Failed);
 
631
            return;
 
632
        }
 
633
    }
 
634
 
 
635
    // at this point a header is successfully read and possibly some data ==>
 
636
    // it is up to the user to check the contents of the data to determine was the
 
637
    // operation "really" successful
 
638
    done_(Internal_FinishedSuccessfully);
 
639
}
 
640
 
 
641
HHttpAsyncOperation::State HHttpAsyncOperation::state() const
 
642
{
 
643
    switch(m_state)
 
644
    {
 
645
    case Internal_Failed:
 
646
        return Failed;
 
647
 
 
648
    case Internal_NotStarted:
 
649
        return NotStarted;
 
650
 
 
651
    case Internal_WritingBlob:
 
652
    case Internal_WritingChunkedSizeLine:
 
653
    case Internal_WritingChunk:
 
654
        return Writing;
 
655
 
 
656
    case Internal_ReadingHeader:
 
657
    case Internal_ReadingData:
 
658
    case Internal_ReadingChunkSizeLine:
 
659
    case Internal_ReadingChunk:
 
660
        return Reading;
 
661
 
 
662
    case Internal_FinishedSuccessfully:
 
663
        return Succeeded;
 
664
 
 
665
    default:
 
666
        Q_ASSERT(false);
 
667
        return Failed;
 
668
    }
 
669
}
 
670
 
 
671
/*******************************************************************************
 
672
 * HHttpAsyncHandler
 
673
 ******************************************************************************/
 
674
HHttpAsyncHandler::HHttpAsyncHandler(
 
675
    const QByteArray& loggingIdentifier, QObject* parent) :
 
676
        QObject(parent),
 
677
            m_loggingIdentifier(loggingIdentifier), m_operations(),
 
678
            m_lastIdUsed(0)
 
679
{
 
680
}
 
681
 
 
682
HHttpAsyncHandler::~HHttpAsyncHandler()
 
683
{
 
684
}
 
685
 
 
686
void HHttpAsyncHandler::done(unsigned int id)
 
687
{
 
688
    HHttpAsyncOperation* ao = m_operations.value(id);
 
689
 
 
690
    Q_ASSERT(ao);
 
691
    Q_ASSERT(ao->state() != HHttpAsyncOperation::NotStarted);
 
692
 
 
693
    bool ok = ao->disconnect(this);
 
694
    Q_ASSERT(ok); Q_UNUSED(ok)
 
695
 
 
696
    m_operations.remove(id);
 
697
 
 
698
    emit msgIoComplete(ao);
 
699
}
 
700
 
 
701
HHttpAsyncOperation* HHttpAsyncHandler::msgIo(
 
702
    HMessagingInfo* mi, const QByteArray& req)
 
703
{
 
704
    Q_ASSERT(mi);
 
705
    Q_ASSERT(!req.isEmpty());
 
706
 
 
707
    HHttpAsyncOperation* ao =
 
708
        new HHttpAsyncOperation(
 
709
            m_loggingIdentifier, ++m_lastIdUsed, mi, req, false, this);
 
710
 
 
711
    bool ok = connect(ao, SIGNAL(done(unsigned int)), this, SLOT(done(unsigned int)));
 
712
 
 
713
    Q_ASSERT(ok); Q_UNUSED(ok)
 
714
 
 
715
    m_operations.insert(ao->id(), ao);
 
716
 
 
717
    if (!ao->run())
 
718
    {
 
719
        m_operations.remove(ao->id());
 
720
        delete ao;
 
721
        return 0;
 
722
    }
 
723
 
 
724
    return ao;
 
725
}
 
726
 
 
727
HHttpAsyncOperation* HHttpAsyncHandler::msgIo(
 
728
    HMessagingInfo* mi, HHttpRequestHeader& reqHdr, const QtSoapMessage& soapMsg)
 
729
{
 
730
    QByteArray dataToSend =
 
731
        HHttpMessageCreator::setupData(
 
732
            reqHdr, soapMsg.toXmlString().toUtf8(), *mi, TextXml);
 
733
 
 
734
    return msgIo(mi, dataToSend);
 
735
}
 
736
 
 
737
HHttpAsyncOperation* HHttpAsyncHandler::send(
 
738
    HMessagingInfo* mi, const QByteArray& data)
 
739
{
 
740
    Q_ASSERT(mi);
 
741
    Q_ASSERT(!data.isEmpty());
 
742
 
 
743
    HHttpAsyncOperation* ao =
 
744
        new HHttpAsyncOperation(
 
745
            m_loggingIdentifier, ++m_lastIdUsed, mi, data, true, this);
 
746
 
 
747
    bool ok = connect(ao, SIGNAL(done(unsigned int)), this, SLOT(done(unsigned int)));
 
748
    Q_ASSERT(ok); Q_UNUSED(ok)
 
749
 
 
750
    m_operations.insert(ao->id(), ao);
 
751
 
 
752
    if (!ao->run())
 
753
    {
 
754
        m_operations.remove(ao->id());
 
755
        delete ao;
 
756
        return 0;
 
757
    }
 
758
 
 
759
    return ao;
 
760
}
 
761
 
 
762
HHttpAsyncOperation* HHttpAsyncHandler::receive(
 
763
    HMessagingInfo* mi, bool waitingRequest)
 
764
{
 
765
    Q_ASSERT(mi);
 
766
 
 
767
    HHttpAsyncOperation* ao =
 
768
        new HHttpAsyncOperation(
 
769
            m_loggingIdentifier, ++m_lastIdUsed, mi, waitingRequest, this);
 
770
 
 
771
    bool ok = connect(ao, SIGNAL(done(unsigned int)), this, SLOT(done(unsigned int)));
 
772
    Q_ASSERT(ok); Q_UNUSED(ok)
 
773
 
 
774
    m_operations.insert(ao->id(), ao);
 
775
 
 
776
    if (!ao->run())
 
777
    {
 
778
        m_operations.remove(ao->id());
 
779
        delete ao;
 
780
        return 0;
 
781
    }
 
782
 
 
783
    return ao;
 
784
}
 
785
 
 
786
}
 
787
}