source: trunk/src/kernel/qnetworkprotocol.cpp@ 7

Last change on this file since 7 was 2, checked in by dmik, 20 years ago

Imported xplatform parts of the official release 3.3.1 from Trolltech

  • Property svn:keywords set to Id
File size: 40.5 KB
Line 
1/****************************************************************************
2** $Id: qnetworkprotocol.cpp 2 2005-11-16 15:49:26Z dmik $
3**
4** Implementation of QNetworkProtocol class
5**
6** Created : 950429
7**
8** Copyright (C) 1992-2003 Trolltech AS. All rights reserved.
9**
10** This file is part of the kernel module of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22** licenses may use this file in accordance with the Qt Commercial License
23** Agreement provided with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37
38#include "qnetworkprotocol.h"
39
40#ifndef QT_NO_NETWORKPROTOCOL
41
42#include "qlocalfs.h"
43#include "qurloperator.h"
44#include "qtimer.h"
45#include "qmap.h"
46#include "qptrqueue.h"
47
48//#define QNETWORKPROTOCOL_DEBUG
49#define NETWORK_OP_DELAY 1000
50
51extern Q_EXPORT QNetworkProtocolDict *qNetworkProtocolRegister;
52
53QNetworkProtocolDict *qNetworkProtocolRegister = 0;
54
55class QNetworkProtocolPrivate
56{
57public:
58 QNetworkProtocolPrivate( QNetworkProtocol *p )
59 {
60 url = 0;
61 opInProgress = 0;
62 opStartTimer = new QTimer( p );
63 removeTimer = new QTimer( p );
64 operationQueue.setAutoDelete( FALSE );
65 autoDelete = FALSE;
66 removeInterval = 10000;
67 oldOps.setAutoDelete( FALSE );
68 }
69
70 ~QNetworkProtocolPrivate()
71 {
72 removeTimer->stop();
73 if ( opInProgress ) {
74 if ( opInProgress == operationQueue.head() )
75 operationQueue.dequeue();
76 opInProgress->free();
77 }
78 while ( operationQueue.head() ) {
79 operationQueue.head()->free();
80 operationQueue.dequeue();
81 }
82 while ( oldOps.first() ) {
83 oldOps.first()->free();
84 oldOps.removeFirst();
85 }
86 delete opStartTimer;
87 }
88
89 QUrlOperator *url;
90 QPtrQueue< QNetworkOperation > operationQueue;
91 QNetworkOperation *opInProgress;
92 QTimer *opStartTimer, *removeTimer;
93 int removeInterval;
94 bool autoDelete;
95 QPtrList< QNetworkOperation > oldOps;
96};
97
98/*!
99 \class QNetworkProtocol qnetworkprotocol.h
100 \brief The QNetworkProtocol class provides a common API for network protocols.
101\if defined(commercial)
102 It is part of the <a href="commercialeditions.html">Qt Enterprise Edition</a>.
103\endif
104
105 \module network
106 \ingroup io
107 \module network
108 \mainclass
109
110 This is a base class which should be used for network protocols
111 implementations that can then be used in Qt (e.g. in the file
112 dialog) together with the QUrlOperator.
113
114 The easiest way to implement a new network protocol is to
115 reimplement the operation*() methods, e.g. operationGet(), etc.
116 Only the supported operations should be reimplemented. To specify
117 which operations are supported, also reimplement
118 supportedOperations() and return an int that is OR'd together
119 using the supported operations from the \l
120 QNetworkProtocol::Operation enum.
121
122 When you implement a network protocol this way, it is important to
123 emit the correct signals. Also, always emit the finished() signal
124 when an operation is done (on success \e and on failure). Qt
125 relies on correctly emitted finished() signals.
126
127 For a detailed description of the Qt Network Architecture and how
128 to implement and use network protocols in Qt, see the \link
129 network.html Qt Network Documentation\endlink.
130*/
131
132/*!
133 \fn void QNetworkProtocol::newChildren( const QValueList<QUrlInfo> &i, QNetworkOperation *op )
134
135 This signal is emitted after listChildren() was called and new
136 children (files) have been read from the list of files. \a i holds
137 the information about the new children. \a op is the pointer to
138 the operation object which contains all the information about the
139 operation, including the state, etc.
140
141 When a protocol emits this signal, QNetworkProtocol is smart
142 enough to let the QUrlOperator, which is used by the network
143 protocol, emit its corresponding signal.
144
145 When implementing your own network protocol and reading children,
146 you usually don't read one child at once, but rather a list of
147 them. That's why this signal takes a list of QUrlInfo objects. If
148 you prefer to read just one child at a time you can use the
149 convenience signal newChild(), which takes a single QUrlInfo
150 object.
151*/
152
153/*!
154 \fn void QNetworkProtocol::newChild( const QUrlInfo &i, QNetworkOperation *op )
155
156 This signal is emitted if a new child (file) has been read.
157 QNetworkProtocol automatically connects it to a slot which creates
158 a list of QUrlInfo objects (with just one QUrlInfo \a i) and emits
159 the newChildren() signal with this list. \a op is the pointer to
160 the operation object which contains all the information about the
161 operation that has finished, including the state, etc.
162
163 This is just a convenience signal useful for implementing your own
164 network protocol. In all other cases connect to the newChildren()
165 signal with its list of QUrlInfo objects.
166*/
167
168/*!
169 \fn void QNetworkProtocol::finished( QNetworkOperation *op )
170
171 This signal is emitted when an operation finishes. This signal is
172 always emitted, for both success and failure. \a op is the pointer
173 to the operation object which contains all the information about
174 the operation, including the state, etc. Check the state and error
175 code of the operation object to determine whether or not the
176 operation was successful.
177
178 When a protocol emits this signal, QNetworkProtocol is smart
179 enough to let the QUrlOperator, which is used by the network
180 protocol, emit its corresponding signal.
181*/
182
183/*!
184 \fn void QNetworkProtocol::start( QNetworkOperation *op )
185
186 Some operations (such as listChildren()) emit this signal when
187 they start processing the operation. \a op is the pointer to the
188 operation object which contains all the information about the
189 operation, including the state, etc.
190
191 When a protocol emits this signal, QNetworkProtocol is smart
192 enough to let the QUrlOperator, which is used by the network
193 protocol, emit its corresponding signal.
194*/
195
196/*!
197 \fn void QNetworkProtocol::createdDirectory( const QUrlInfo &i, QNetworkOperation *op )
198
199 This signal is emitted when mkdir() has been succesful and the
200 directory has been created. \a i holds the information about the
201 new directory. \a op is the pointer to the operation object which
202 contains all the information about the operation, including the
203 state, etc. Using op->arg( 0 ), you can get the file name of the
204 new directory.
205
206 When a protocol emits this signal, QNetworkProtocol is smart
207 enough to let the QUrlOperator, which is used by the network
208 protocol, emit its corresponding signal.
209*/
210
211/*!
212 \fn void QNetworkProtocol::removed( QNetworkOperation *op )
213
214 This signal is emitted when remove() has been succesful and the
215 file has been removed. \a op holds the file name of the removed
216 file in the first argument, accessible with op->arg( 0 ). \a op is
217 the pointer to the operation object which contains all the
218 information about the operation, including the state, etc.
219
220 When a protocol emits this signal, QNetworkProtocol is smart
221 enough to let the QUrlOperator, which is used by the network
222 protocol, emit its corresponding signal.
223*/
224
225/*!
226 \fn void QNetworkProtocol::itemChanged( QNetworkOperation *op )
227
228 This signal is emitted whenever a file which is a child of this
229 URL has been changed, e.g. by successfully calling rename(). \a op
230 holds the original and the new file names in the first and second
231 arguments, accessible with op->arg( 0 ) and op->arg( 1 )
232 respectively. \a op is the pointer to the operation object which
233 contains all the information about the operation, including the
234 state, etc.
235
236 When a protocol emits this signal, QNetworkProtocol is smart
237 enough to let the QUrlOperator, which is used by the network
238 protocol, emit its corresponding signal.
239*/
240
241/*!
242 \fn void QNetworkProtocol::data( const QByteArray &data,
243 QNetworkOperation *op )
244
245 This signal is emitted when new \a data has been received after
246 calling get() or put(). \a op holds the name of the file from
247 which data is retrieved or uploaded in its first argument, and the
248 (raw) data in its second argument. You can get them with
249 op->arg( 0 ) and op->rawArg( 1 ). \a op is the pointer to the
250 operation object, which contains all the information about the
251 operation, including the state, etc.
252
253 When a protocol emits this signal, QNetworkProtocol is smart
254 enough to let the QUrlOperator (which is used by the network
255 protocol) emit its corresponding signal.
256*/
257
258/*!
259 \fn void QNetworkProtocol::dataTransferProgress( int bytesDone, int bytesTotal, QNetworkOperation *op )
260
261 This signal is emitted during the transfer of data (using put() or
262 get()). \a bytesDone is how many bytes of \a bytesTotal have been
263 transferred. \a bytesTotal may be -1, which means that the total
264 number of bytes is not known. \a op is the pointer to the
265 operation object which contains all the information about the
266 operation, including the state, etc.
267
268 When a protocol emits this signal, QNetworkProtocol is smart
269 enough to let the QUrlOperator, which is used by the network
270 protocol, emit its corresponding signal.
271*/
272
273/*!
274 \fn void QNetworkProtocol::connectionStateChanged( int state, const QString &data )
275
276 This signal is emitted whenever the state of the connection of the
277 network protocol is changed. \a state describes the new state,
278 which is one of, \c ConHostFound, \c ConConnected or \c ConClosed.
279 \a data is a message text.
280*/
281
282/*!
283 \enum QNetworkProtocol::State
284
285 This enum contains the state that a QNetworkOperation can have.
286
287 \value StWaiting The operation is in the QNetworkProtocol's queue
288 waiting to be prcessed.
289
290 \value StInProgress The operation is being processed.
291
292 \value StDone The operation has been processed succesfully.
293
294 \value StFailed The operation has been processed but an error occurred.
295
296 \value StStopped The operation has been processed but has been
297 stopped before it finished, and is waiting to be processed.
298
299*/
300
301/*!
302 \enum QNetworkProtocol::Operation
303
304 This enum lists the possible operations that a network protocol
305 can support. supportedOperations() returns an int of these that is
306 OR'd together. Also, the type() of a QNetworkOperation is always
307 one of these values.
308
309 \value OpListChildren List the children of a URL, e.g. of a directory.
310 \value OpMkDir Create a directory.
311 \value OpRemove Remove a child (e.g. a file).
312 \value OpRename Rename a child (e.g. a file).
313 \value OpGet Get data from a location.
314 \value OpPut Put data to a location.
315*/
316
317/*!
318 \enum QNetworkProtocol::ConnectionState
319
320 When the connection state of a network protocol changes it emits
321 the signal connectionStateChanged(). The first argument is one of
322 the following values:
323
324 \value ConHostFound Host has been found.
325 \value ConConnected Connection to the host has been established.
326 \value ConClosed Connection has been closed.
327*/
328
329/*!
330 \enum QNetworkProtocol::Error
331
332 When an operation fails (finishes unsuccessfully), the
333 QNetworkOperation of the operation returns an error code which has
334 one of the following values:
335
336 \value NoError No error occurred.
337
338 \value ErrValid The URL you are operating on is not valid.
339
340 \value ErrUnknownProtocol There is no protocol implementation
341 available for the protocol of the URL you are operating on (e.g.
342 if the protocol is http and no http implementation has been
343 registered).
344
345 \value ErrUnsupported The operation is not supported by the
346 protocol.
347
348 \value ErrParse The URL could not be parsed correctly.
349
350 \value ErrLoginIncorrect You needed to login but the username
351 or password is wrong.
352
353 \value ErrHostNotFound The specified host (in the URL) couldn't
354 be found.
355
356 \value ErrListChildren An error occurred while listing the
357 children (files).
358
359 \value ErrMkDir An error occurred when creating a directory.
360
361 \value ErrRemove An error occurred when removing a child (file).
362
363 \value ErrRename An error occurred when renaming a child (file).
364
365 \value ErrGet An error occurred while getting (retrieving) data.
366
367 \value ErrPut An error occurred while putting (uploading) data.
368
369 \value ErrFileNotExisting A file which is needed by the operation
370 doesn't exist.
371
372 \value ErrPermissionDenied Permission for doing the operation has
373 been denied.
374
375 You should also use these error codes when implementing custom
376 network protocols. If this is not possible, you can define your own
377 error codes by using integer values that don't conflict with any
378 of these values.
379*/
380
381/*!
382 Constructor of the network protocol base class. Does some
383 initialization and connecting of signals and slots.
384*/
385
386QNetworkProtocol::QNetworkProtocol()
387 : QObject()
388{
389 d = new QNetworkProtocolPrivate( this );
390
391 connect( d->opStartTimer, SIGNAL( timeout() ),
392 this, SLOT( startOps() ) );
393 connect( d->removeTimer, SIGNAL( timeout() ),
394 this, SLOT( removeMe() ) );
395
396 if ( url() ) {
397 connect( this, SIGNAL( data(const QByteArray&,QNetworkOperation*) ),
398 url(), SIGNAL( data(const QByteArray&,QNetworkOperation*) ) );
399 connect( this, SIGNAL( finished(QNetworkOperation*) ),
400 url(), SIGNAL( finished(QNetworkOperation*) ) );
401 connect( this, SIGNAL( start(QNetworkOperation*) ),
402 url(), SIGNAL( start(QNetworkOperation*) ) );
403 connect( this, SIGNAL( newChildren(const QValueList<QUrlInfo>&,QNetworkOperation*) ),
404 url(), SIGNAL( newChildren(const QValueList<QUrlInfo>&,QNetworkOperation*) ) );
405 connect( this, SIGNAL( newChildren(const QValueList<QUrlInfo>&,QNetworkOperation*) ),
406 url(), SLOT( addEntry(const QValueList<QUrlInfo>&) ) );
407 connect( this, SIGNAL( createdDirectory(const QUrlInfo&,QNetworkOperation*) ),
408 url(), SIGNAL( createdDirectory(const QUrlInfo&,QNetworkOperation*) ) );
409 connect( this, SIGNAL( removed(QNetworkOperation*) ),
410 url(), SIGNAL( removed(QNetworkOperation*) ) );
411 connect( this, SIGNAL( itemChanged(QNetworkOperation*) ),
412 url(), SIGNAL( itemChanged(QNetworkOperation*) ) );
413 connect( this, SIGNAL( dataTransferProgress(int,int,QNetworkOperation*) ),
414 url(), SIGNAL( dataTransferProgress(int,int,QNetworkOperation*) ) );
415 connect( this, SIGNAL( connectionStateChanged(int,const QString&) ),
416 url(), SIGNAL( connectionStateChanged(int,const QString&) ) );
417 }
418
419 connect( this, SIGNAL( finished(QNetworkOperation*) ),
420 this, SLOT( processNextOperation(QNetworkOperation*) ) );
421 connect( this, SIGNAL( newChild(const QUrlInfo&,QNetworkOperation*) ),
422 this, SLOT( emitNewChildren(const QUrlInfo&,QNetworkOperation*) ) );
423
424}
425
426/*!
427 Destructor.
428*/
429
430QNetworkProtocol::~QNetworkProtocol()
431{
432 delete d;
433}
434
435/*!
436 Sets the QUrlOperator, on which the protocol works, to \a u.
437
438 \sa QUrlOperator
439*/
440
441void QNetworkProtocol::setUrl( QUrlOperator *u )
442{
443 if ( url() ) {
444 disconnect( this, SIGNAL( data(const QByteArray&,QNetworkOperation*) ),
445 url(), SIGNAL( data(const QByteArray&,QNetworkOperation*) ) );
446 disconnect( this, SIGNAL( finished(QNetworkOperation*) ),
447 url(), SIGNAL( finished(QNetworkOperation*) ) );
448 disconnect( this, SIGNAL( start(QNetworkOperation*) ),
449 url(), SIGNAL( start(QNetworkOperation*) ) );
450 disconnect( this, SIGNAL( newChildren(const QValueList<QUrlInfo>&,QNetworkOperation*) ),
451 url(), SIGNAL( newChildren(const QValueList<QUrlInfo>&,QNetworkOperation*) ) );
452 disconnect( this, SIGNAL( newChildren(const QValueList<QUrlInfo>&,QNetworkOperation*) ),
453 url(), SLOT( addEntry(const QValueList<QUrlInfo>&) ) );
454 disconnect( this, SIGNAL( createdDirectory(const QUrlInfo&,QNetworkOperation*) ),
455 url(), SIGNAL( createdDirectory(const QUrlInfo&,QNetworkOperation*) ) );
456 disconnect( this, SIGNAL( removed(QNetworkOperation*) ),
457 url(), SIGNAL( removed(QNetworkOperation*) ) );
458 disconnect( this, SIGNAL( itemChanged(QNetworkOperation*) ),
459 url(), SIGNAL( itemChanged(QNetworkOperation*) ) );
460 disconnect( this, SIGNAL( dataTransferProgress(int,int,QNetworkOperation*) ),
461 url(), SIGNAL( dataTransferProgress(int,int,QNetworkOperation*) ) );
462 disconnect( this, SIGNAL( connectionStateChanged(int,const QString&) ),
463 url(), SIGNAL( connectionStateChanged(int,const QString&) ) );
464 }
465
466
467 // ### if autoDelete is TRUE, we should delete the QUrlOperator (something
468 // like below; but that is not possible since it would delete this, too).
469 //if ( d->autoDelete && (d->url!=u) ) {
470 // delete d->url; // destructor deletes the network protocol
471 //}
472 d->url = u;
473
474 if ( url() ) {
475 connect( this, SIGNAL( data(const QByteArray&,QNetworkOperation*) ),
476 url(), SIGNAL( data(const QByteArray&,QNetworkOperation*) ) );
477 connect( this, SIGNAL( finished(QNetworkOperation*) ),
478 url(), SIGNAL( finished(QNetworkOperation*) ) );
479 connect( this, SIGNAL( start(QNetworkOperation*) ),
480 url(), SIGNAL( start(QNetworkOperation*) ) );
481 connect( this, SIGNAL( newChildren(const QValueList<QUrlInfo>&,QNetworkOperation*) ),
482 url(), SIGNAL( newChildren(const QValueList<QUrlInfo>&,QNetworkOperation*) ) );
483 connect( this, SIGNAL( newChildren(const QValueList<QUrlInfo>&,QNetworkOperation*) ),
484 url(), SLOT( addEntry(const QValueList<QUrlInfo>&) ) );
485 connect( this, SIGNAL( createdDirectory(const QUrlInfo&,QNetworkOperation*) ),
486 url(), SIGNAL( createdDirectory(const QUrlInfo&,QNetworkOperation*) ) );
487 connect( this, SIGNAL( removed(QNetworkOperation*) ),
488 url(), SIGNAL( removed(QNetworkOperation*) ) );
489 connect( this, SIGNAL( itemChanged(QNetworkOperation*) ),
490 url(), SIGNAL( itemChanged(QNetworkOperation*) ) );
491 connect( this, SIGNAL( dataTransferProgress(int,int,QNetworkOperation*) ),
492 url(), SIGNAL( dataTransferProgress(int,int,QNetworkOperation*) ) );
493 connect( this, SIGNAL( connectionStateChanged(int,const QString&) ),
494 url(), SIGNAL( connectionStateChanged(int,const QString&) ) );
495 }
496
497 if ( !d->opInProgress && !d->operationQueue.isEmpty() )
498 d->opStartTimer->start( 0, TRUE );
499}
500
501/*!
502 For processing operations the network protocol base class calls
503 this method quite often. This should be reimplemented by new
504 network protocols. It should return TRUE if the connection is OK
505 (open); otherwise it should return FALSE. If the connection is not
506 open the protocol should open it.
507
508 If the connection can't be opened (e.g. because you already tried
509 but the host couldn't be found), set the state of \a op to
510 QNetworkProtocol::StFailed and emit the finished() signal with
511 this QNetworkOperation as argument.
512
513 \a op is the operation that needs an open connection.
514*/
515
516bool QNetworkProtocol::checkConnection( QNetworkOperation * )
517{
518 return TRUE;
519}
520
521/*!
522 Returns an int that is OR'd together using the enum values of
523 \l{QNetworkProtocol::Operation}, which describes which operations
524 are supported by the network protocol. Should be reimplemented by
525 new network protocols.
526*/
527
528int QNetworkProtocol::supportedOperations() const
529{
530 return 0;
531}
532
533/*!
534 Adds the operation \a op to the operation queue. The operation
535 will be processed as soon as possible. This method returns
536 immediately.
537*/
538
539void QNetworkProtocol::addOperation( QNetworkOperation *op )
540{
541#ifdef QNETWORKPROTOCOL_DEBUG
542 qDebug( "QNetworkOperation: addOperation: %p %d", op, op->operation() );
543#endif
544 d->operationQueue.enqueue( op );
545 if ( !d->opInProgress )
546 d->opStartTimer->start( 0, TRUE );
547}
548
549/*!
550 Static method to register a network protocol for Qt. For example,
551 if you have an implementation of NNTP (called Nntp) which is
552 derived from QNetworkProtocol, call:
553 \code
554 QNetworkProtocol::registerNetworkProtocol( "nntp", new QNetworkProtocolFactory<Nntp> );
555 \endcode
556 after which your implementation is registered for future nntp
557 operations.
558
559 The name of the protocol is given in \a protocol and a pointer to
560 the protocol factory is given in \a protocolFactory.
561*/
562
563void QNetworkProtocol::registerNetworkProtocol( const QString &protocol,
564 QNetworkProtocolFactoryBase *protocolFactory )
565{
566 if ( !qNetworkProtocolRegister ) {
567 qNetworkProtocolRegister = new QNetworkProtocolDict;
568 QNetworkProtocol::registerNetworkProtocol( "file", new QNetworkProtocolFactory< QLocalFs > );
569 }
570
571 qNetworkProtocolRegister->insert( protocol, protocolFactory );
572}
573
574/*!
575 Static method to get a new instance of the network protocol \a
576 protocol. For example, if you need to do some FTP operations, do
577 the following:
578 \code
579 QFtp *ftp = QNetworkProtocol::getNetworkProtocol( "ftp" );
580 \endcode
581 This returns a pointer to a new instance of an ftp implementation
582 or null if no protocol for ftp was registered. The ownership of
583 the pointer is transferred to you, so you must delete it if you
584 don't need it anymore.
585
586 Normally you should not work directly with network protocols, so
587 you will not need to call this method yourself. Instead, use
588 QUrlOperator, which makes working with network protocols much more
589 convenient.
590
591 \sa QUrlOperator
592*/
593
594QNetworkProtocol *QNetworkProtocol::getNetworkProtocol( const QString &protocol )
595{
596 if ( !qNetworkProtocolRegister ) {
597 qNetworkProtocolRegister = new QNetworkProtocolDict;
598 QNetworkProtocol::registerNetworkProtocol( "file", new QNetworkProtocolFactory< QLocalFs > );
599 }
600
601 if ( protocol.isNull() )
602 return 0;
603
604 QNetworkProtocolFactoryBase *factory = qNetworkProtocolRegister->find( protocol );
605 if ( factory )
606 return factory->createObject();
607
608 return 0;
609}
610
611/*!
612 Returns TRUE if the only protocol registered is for working on the
613 local filesystem; returns FALSE if other network protocols are
614 also registered.
615*/
616
617bool QNetworkProtocol::hasOnlyLocalFileSystem()
618{
619 if ( !qNetworkProtocolRegister )
620 return FALSE;
621
622 QDictIterator< QNetworkProtocolFactoryBase > it( *qNetworkProtocolRegister );
623 for ( ; it.current(); ++it )
624 if ( it.currentKey() != "file" )
625 return FALSE;
626 return TRUE;
627}
628
629/*!
630 \internal
631 Starts processing network operations.
632*/
633
634void QNetworkProtocol::startOps()
635{
636#ifdef QNETWORKPROTOCOL_DEBUG
637 qDebug( "QNetworkOperation: start processing operations" );
638#endif
639 processNextOperation( 0 );
640}
641
642/*!
643 \internal
644 Processes the operation \a op. It calls the
645 corresponding operation[something]( QNetworkOperation * )
646 methods.
647*/
648
649void QNetworkProtocol::processOperation( QNetworkOperation *op )
650{
651 if ( !op )
652 return;
653
654 switch ( op->operation() ) {
655 case OpListChildren:
656 operationListChildren( op );
657 break;
658 case OpMkDir:
659 operationMkDir( op );
660 break;
661 case OpRemove:
662 operationRemove( op );
663 break;
664 case OpRename:
665 operationRename( op );
666 break;
667 case OpGet:
668 operationGet( op );
669 break;
670 case OpPut:
671 operationPut( op );
672 break;
673 }
674}
675
676/*!
677 When implementing a new network protocol, this method should be
678 reimplemented if the protocol supports listing children (files);
679 this method should then process this QNetworkOperation.
680
681 When you reimplement this method it's very important that you emit
682 the correct signals at the correct time (especially the finished()
683 signal after processing an operation). Take a look at the \link
684 network.html Qt Network Documentation\endlink which describes in
685 detail how to reimplement this method. You may also want to look
686 at the example implementation in
687 examples/network/networkprotocol/nntp.cpp.
688
689 \a op is the pointer to the operation object which contains all
690 the information on the operation that has finished, including the
691 state, etc.
692*/
693
694void QNetworkProtocol::operationListChildren( QNetworkOperation * )
695{
696}
697
698/*!
699 When implementing a new network protocol, this method should be
700 reimplemented if the protocol supports making directories; this
701 method should then process this QNetworkOperation.
702
703 When you reimplement this method it's very important that you emit
704 the correct signals at the correct time (especially the finished()
705 signal after processing an operation). Take a look at the \link
706 network.html Qt Network Documentation\endlink which describes in
707 detail how to reimplement this method. You may also want to look
708 at the example implementation in
709 examples/network/networkprotocol/nntp.cpp.
710
711 \a op is the pointer to the operation object which contains all
712 the information on the operation that has finished, including the
713 state, etc.
714*/
715
716void QNetworkProtocol::operationMkDir( QNetworkOperation * )
717{
718}
719
720/*!
721 When implementing a new network protocol, this method should be
722 reimplemented if the protocol supports removing children (files);
723 this method should then process this QNetworkOperation.
724
725 When you reimplement this method it's very important that you emit
726 the correct signals at the correct time (especially the finished()
727 signal after processing an operation). Take a look at the \link
728 network.html Qt Network Documentation\endlink which is describes
729 in detail how to reimplement this method. You may also want to
730 look at the example implementation in
731 examples/network/networkprotocol/nntp.cpp.
732
733 \a op is the pointer to the operation object which contains all
734 the information on the operation that has finished, including the
735 state, etc.
736*/
737
738void QNetworkProtocol::operationRemove( QNetworkOperation * )
739{
740}
741
742/*!
743 When implementing a new newtork protocol, this method should be
744 reimplemented if the protocol supports renaming children (files);
745 this method should then process this QNetworkOperation.
746
747 When you reimplement this method it's very important that you emit
748 the correct signals at the correct time (especially the finished()
749 signal after processing an operation). Take a look at the \link
750 network.html Qt Network Documentation\endlink which describes in
751 detail how to reimplement this method. You may also want to look
752 at the example implementation in
753 examples/network/networkprotocol/nntp.cpp.
754
755 \a op is the pointer to the operation object which contains all
756 the information on the operation that has finished, including the
757 state, etc.
758*/
759
760void QNetworkProtocol::operationRename( QNetworkOperation * )
761{
762}
763
764/*!
765 When implementing a new network protocol, this method should be
766 reimplemented if the protocol supports getting data; this method
767 should then process the QNetworkOperation.
768
769 When you reimplement this method it's very important that you emit
770 the correct signals at the correct time (especially the finished()
771 signal after processing an operation). Take a look at the \link
772 network.html Qt Network Documentation\endlink which describes in
773 detail how to reimplement this method. You may also want to look
774 at the example implementation in
775 examples/network/networkprotocol/nntp.cpp.
776
777 \a op is the pointer to the operation object which contains all
778 the information on the operation that has finished, including the
779 state, etc.
780*/
781
782void QNetworkProtocol::operationGet( QNetworkOperation * )
783{
784}
785
786/*!
787 When implementing a new network protocol, this method should be
788 reimplemented if the protocol supports putting (uploading) data;
789 this method should then process the QNetworkOperation.
790
791 When you reimplement this method it's very important that you emit
792 the correct signals at the correct time (especially the finished()
793 signal after processing an operation). Take a look at the \link
794 network.html Qt Network Documentation\endlink which describes in
795 detail how to reimplement this method. You may also want to look
796 at the example implementation in
797 examples/network/networkprotocol/nntp.cpp.
798
799 \a op is the pointer to the operation object which contains all
800 the information on the operation that has finished, including the
801 state, etc.
802*/
803
804void QNetworkProtocol::operationPut( QNetworkOperation * )
805{
806}
807
808/*! \internal
809*/
810
811void QNetworkProtocol::operationPutChunk( QNetworkOperation * )
812{
813}
814
815/*!
816 \internal
817 Handles operations. Deletes the previous operation object and
818 tries to process the next operation. It also checks the connection state
819 and only processes the next operation, if the connection of the protocol
820 is open. Otherwise it waits until the protocol opens the connection.
821*/
822
823void QNetworkProtocol::processNextOperation( QNetworkOperation *old )
824{
825#ifdef QNETWORKPROTOCOL_DEBUG
826 qDebug( "QNetworkOperation: process next operation, old: %p", old );
827#endif
828 d->removeTimer->stop();
829
830 if ( old )
831 d->oldOps.append( old );
832 if ( d->opInProgress && d->opInProgress!=old )
833 d->oldOps.append( d->opInProgress );
834
835 if ( d->operationQueue.isEmpty() ) {
836 d->opInProgress = 0;
837 if ( d->autoDelete )
838 d->removeTimer->start( d->removeInterval, TRUE );
839 return;
840 }
841
842 QNetworkOperation *op = d->operationQueue.head();
843
844 d->opInProgress = op;
845
846 if ( !checkConnection( op ) ) {
847 if ( op->state() != QNetworkProtocol::StFailed ) {
848 d->opStartTimer->start( 0, TRUE );
849 } else {
850 d->operationQueue.dequeue();
851 clearOperationQueue();
852 emit finished( op );
853 }
854
855 return;
856 }
857
858 d->opInProgress = op;
859 d->operationQueue.dequeue();
860 processOperation( op );
861}
862
863/*!
864 Returns the QUrlOperator on which the protocol works.
865*/
866
867QUrlOperator *QNetworkProtocol::url() const
868{
869 return d->url;
870}
871
872/*!
873 Returns the operation, which is being processed, or 0 of no
874 operation is being processed at the moment.
875*/
876
877QNetworkOperation *QNetworkProtocol::operationInProgress() const
878{
879 return d->opInProgress;
880}
881
882/*!
883 Clears the operation queue.
884*/
885
886void QNetworkProtocol::clearOperationQueue()
887{
888 d->operationQueue.dequeue();
889 d->operationQueue.setAutoDelete( TRUE );
890 d->operationQueue.clear();
891}
892
893/*!
894 Stops the current operation that is being processed and clears all
895 waiting operations.
896*/
897
898void QNetworkProtocol::stop()
899{
900 QNetworkOperation *op = d->opInProgress;
901 clearOperationQueue();
902 if ( op ) {
903 op->setState( StStopped );
904 op->setProtocolDetail( tr( "Operation stopped by the user" ) );
905 emit finished( op );
906 setUrl( 0 );
907 op->free();
908 }
909}
910
911/*!
912 Because it's sometimes hard to take care of removing network
913 protocol instances, QNetworkProtocol provides an auto-delete
914 mechanism. If you set \a b to TRUE, the network protocol instance
915 is removed after it has been inactive for \a i milliseconds (i.e.
916 \a i milliseconds after the last operation has been processed).
917 If you set \a b to FALSE the auto-delete mechanism is switched
918 off.
919
920 If you switch on auto-delete, the QNetworkProtocol also deletes
921 its QUrlOperator.
922*/
923
924void QNetworkProtocol::setAutoDelete( bool b, int i )
925{
926 d->autoDelete = b;
927 d->removeInterval = i;
928}
929
930/*!
931 Returns TRUE if auto-deleting is enabled; otherwise returns FALSE.
932
933 \sa QNetworkProtocol::setAutoDelete()
934*/
935
936bool QNetworkProtocol::autoDelete() const
937{
938 return d->autoDelete;
939}
940
941/*!
942 \internal
943*/
944
945void QNetworkProtocol::removeMe()
946{
947 if ( d->autoDelete ) {
948#ifdef QNETWORKPROTOCOL_DEBUG
949 qDebug( "QNetworkOperation: autodelete of QNetworkProtocol %p", this );
950#endif
951 delete d->url; // destructor deletes the network protocol
952 }
953}
954
955void QNetworkProtocol::emitNewChildren( const QUrlInfo &i, QNetworkOperation *op )
956{
957 QValueList<QUrlInfo> lst;
958 lst << i;
959 emit newChildren( lst, op );
960}
961
962class QNetworkOperationPrivate
963{
964public:
965 QNetworkProtocol::Operation operation;
966 QNetworkProtocol::State state;
967 QMap<int, QString> args;
968 QMap<int, QByteArray> rawArgs;
969 QString protocolDetail;
970 int errorCode;
971 QTimer *deleteTimer;
972};
973
974/*!
975 \class QNetworkOperation
976
977 \brief The QNetworkOperation class provides common operations for network protocols.
978\if defined(commercial)
979 It is part of the <a href="commercialeditions.html">Qt Enterprise Edition</a>.
980\endif
981
982 \module network
983 \ingroup io
984
985 An object is created to describe the operation and the current
986 state for each operation that a network protocol should process.
987
988 For a detailed description of the Qt Network Architecture and how
989 to implement and use network protocols in Qt, see the \link
990 network.html Qt Network Documentation\endlink.
991
992 \sa QNetworkProtocol
993*/
994
995/*!
996 Constructs a network operation object. \a operation is the type of
997 the operation, and \a arg0, \a arg1 and \a arg2 are the first
998 three arguments of the operation. The state is initialized to
999 QNetworkProtocol::StWaiting.
1000
1001 \sa QNetworkProtocol::Operation QNetworkProtocol::State
1002*/
1003
1004QNetworkOperation::QNetworkOperation( QNetworkProtocol::Operation operation,
1005 const QString &arg0, const QString &arg1,
1006 const QString &arg2 )
1007{
1008 d = new QNetworkOperationPrivate;
1009 d->deleteTimer = new QTimer( this );
1010 connect( d->deleteTimer, SIGNAL( timeout() ),
1011 this, SLOT( deleteMe() ) );
1012 d->operation = operation;
1013 d->state = QNetworkProtocol::StWaiting;
1014 d->args[ 0 ] = arg0;
1015 d->args[ 1 ] = arg1;
1016 d->args[ 2 ] = arg2;
1017 d->rawArgs[ 0 ] = QByteArray( 0 );
1018 d->rawArgs[ 1 ] = QByteArray( 0 );
1019 d->rawArgs[ 2 ] = QByteArray( 0 );
1020 d->protocolDetail = QString::null;
1021 d->errorCode = (int)QNetworkProtocol::NoError;
1022}
1023
1024/*!
1025 Constructs a network operation object. \a operation is the type of
1026 the operation, and \a arg0, \a arg1 and \a arg2 are the first
1027 three raw data arguments of the operation. The state is
1028 initialized to QNetworkProtocol::StWaiting.
1029
1030 \sa QNetworkProtocol::Operation QNetworkProtocol::State
1031*/
1032
1033QNetworkOperation::QNetworkOperation( QNetworkProtocol::Operation operation,
1034 const QByteArray &arg0, const QByteArray &arg1,
1035 const QByteArray &arg2 )
1036{
1037 d = new QNetworkOperationPrivate;
1038 d->deleteTimer = new QTimer( this );
1039 connect( d->deleteTimer, SIGNAL( timeout() ),
1040 this, SLOT( deleteMe() ) );
1041 d->operation = operation;
1042 d->state = QNetworkProtocol::StWaiting;
1043 d->args[ 0 ] = QString::null;
1044 d->args[ 1 ] = QString::null;
1045 d->args[ 2 ] = QString::null;
1046 d->rawArgs[ 0 ] = arg0;
1047 d->rawArgs[ 1 ] = arg1;
1048 d->rawArgs[ 2 ] = arg2;
1049 d->protocolDetail = QString::null;
1050 d->errorCode = (int)QNetworkProtocol::NoError;
1051}
1052
1053/*!
1054 Destructor.
1055*/
1056
1057QNetworkOperation::~QNetworkOperation()
1058{
1059 delete d;
1060}
1061
1062/*!
1063 Sets the \a state of the operation object. This should be done by
1064 the network protocol during processing; at the end it should be
1065 set to QNetworkProtocol::StDone or QNetworkProtocol::StFailed,
1066 depending on success or failure.
1067
1068 \sa QNetworkProtocol::State
1069*/
1070
1071void QNetworkOperation::setState( QNetworkProtocol::State state )
1072{
1073 if ( d->deleteTimer->isActive() ) {
1074 d->deleteTimer->stop();
1075 d->deleteTimer->start( NETWORK_OP_DELAY );
1076 }
1077 d->state = state;
1078}
1079
1080/*!
1081 If the operation failed, the error message can be specified as \a
1082 detail.
1083*/
1084
1085void QNetworkOperation::setProtocolDetail( const QString &detail )
1086{
1087 if ( d->deleteTimer->isActive() ) {
1088 d->deleteTimer->stop();
1089 d->deleteTimer->start( NETWORK_OP_DELAY );
1090 }
1091 d->protocolDetail = detail;
1092}
1093
1094/*!
1095 Sets the error code to \a ec.
1096
1097 If the operation failed, the protocol should set an error code to
1098 describe the error in more detail. If possible, one of the error
1099 codes defined in QNetworkProtocol should be used.
1100
1101 \sa setProtocolDetail() QNetworkProtocol::Error
1102*/
1103
1104void QNetworkOperation::setErrorCode( int ec )
1105{
1106 if ( d->deleteTimer->isActive() ) {
1107 d->deleteTimer->stop();
1108 d->deleteTimer->start( NETWORK_OP_DELAY );
1109 }
1110 d->errorCode = ec;
1111}
1112
1113/*!
1114 Sets the network operation's \a{num}-th argument to \a arg.
1115*/
1116
1117void QNetworkOperation::setArg( int num, const QString &arg )
1118{
1119 if ( d->deleteTimer->isActive() ) {
1120 d->deleteTimer->stop();
1121 d->deleteTimer->start( NETWORK_OP_DELAY );
1122 }
1123 d->args[ num ] = arg;
1124}
1125
1126/*!
1127 Sets the network operation's \a{num}-th raw data argument to \a arg.
1128*/
1129
1130void QNetworkOperation::setRawArg( int num, const QByteArray &arg )
1131{
1132 if ( d->deleteTimer->isActive() ) {
1133 d->deleteTimer->stop();
1134 d->deleteTimer->start( NETWORK_OP_DELAY );
1135 }
1136 d->rawArgs[ num ] = arg;
1137}
1138
1139/*!
1140 Returns the type of the operation.
1141*/
1142
1143QNetworkProtocol::Operation QNetworkOperation::operation() const
1144{
1145 if ( d->deleteTimer->isActive() ) {
1146 d->deleteTimer->stop();
1147 d->deleteTimer->start( NETWORK_OP_DELAY );
1148 }
1149 return d->operation;
1150}
1151
1152/*!
1153 Returns the state of the operation. You can determine whether an
1154 operation is still waiting to be processed, is being processed,
1155 has been processed successfully, or failed.
1156*/
1157
1158QNetworkProtocol::State QNetworkOperation::state() const
1159{
1160 if ( d->deleteTimer->isActive() ) {
1161 d->deleteTimer->stop();
1162 d->deleteTimer->start( NETWORK_OP_DELAY );
1163 }
1164 return d->state;
1165}
1166
1167/*!
1168 Returns the operation's \a{num}-th argument. If this argument was
1169 not already set, an empty string is returned.
1170*/
1171
1172QString QNetworkOperation::arg( int num ) const
1173{
1174 if ( d->deleteTimer->isActive() ) {
1175 d->deleteTimer->stop();
1176 d->deleteTimer->start( NETWORK_OP_DELAY );
1177 }
1178 return d->args[ num ];
1179}
1180
1181/*!
1182 Returns the operation's \a{num}-th raw data argument. If this
1183 argument was not already set, an empty bytearray is returned.
1184*/
1185
1186QByteArray QNetworkOperation::rawArg( int num ) const
1187{
1188 if ( d->deleteTimer->isActive() ) {
1189 d->deleteTimer->stop();
1190 d->deleteTimer->start( NETWORK_OP_DELAY );
1191 }
1192 return d->rawArgs[ num ];
1193}
1194
1195/*!
1196 Returns a detailed error message for the last error. This must
1197 have been set using setProtocolDetail().
1198*/
1199
1200QString QNetworkOperation::protocolDetail() const
1201{
1202 if ( d->deleteTimer->isActive() ) {
1203 d->deleteTimer->stop();
1204 d->deleteTimer->start( NETWORK_OP_DELAY );
1205 }
1206 return d->protocolDetail;
1207}
1208
1209/*!
1210 Returns the error code for the last error that occurred.
1211*/
1212
1213int QNetworkOperation::errorCode() const
1214{
1215 if ( d->deleteTimer->isActive() ) {
1216 d->deleteTimer->stop();
1217 d->deleteTimer->start( NETWORK_OP_DELAY );
1218 }
1219 return d->errorCode;
1220}
1221
1222/*!
1223 \internal
1224*/
1225
1226QByteArray& QNetworkOperation::raw( int num ) const
1227{
1228 if ( d->deleteTimer->isActive() ) {
1229 d->deleteTimer->stop();
1230 d->deleteTimer->start( NETWORK_OP_DELAY );
1231 }
1232 return d->rawArgs[ num ];
1233}
1234
1235/*!
1236 Sets this object to delete itself when it hasn't been used for one
1237 second.
1238
1239 Because QNetworkOperation pointers are passed around a lot the
1240 QNetworkProtocol generally does not have enough knowledge to
1241 delete these at the correct time. If a QNetworkProtocol doesn't
1242 need an operation any more it will call this function instead.
1243
1244 Note: you should never need to call the method yourself.
1245*/
1246
1247void QNetworkOperation::free()
1248{
1249 d->deleteTimer->start( NETWORK_OP_DELAY );
1250}
1251
1252/*!
1253 \internal
1254 Internal slot for auto-deletion.
1255*/
1256
1257void QNetworkOperation::deleteMe()
1258{
1259 delete this;
1260}
1261
1262#endif
Note: See TracBrowser for help on using the repository browser.