CONFIG += link_pkgconfig
PKGCONFIG += libalarm
-DEFINES += QT_NO_DEBUG_OUTPUT
+//DEFINES += DEBUG_OUTPUT_TO_FILE
executable.files = qtmeetings
executable.path = /usr/bin/
<error code="104">Communication: Server closed the connection unexpectedly</error>
<error code="105">Communication: Server sent an invalid HTTP header</error>
<error code="106">Communication: Server sent an invalid content length</error>
- <error code="107">Communication: Invalid username or password</error>
+ <error code="107">Communication: The request was aborted</error>
<error code="108">Communication: SOAP error when fetching meetings</error>
<error code="109">Communication: SOAP error when fetching meeting details</error>
<error code="110">Communication error</error>
+ <error code="111">Communication: Invalid username or password</error>
<error code="200">Failed to change the operation mode. Error creating internal file storage.</error>
<error code="201">Failed to change the operation mode. Error removing old alarm events.</error>
<error code="202">Failed to change the operation mode. Error sending alarm events. %1</error>
iConnectionSettings = new ConnectionSettings( aConnection );
iHttp = new QHttp( iConnectionSettings->serverUrl().toString(), QHttp::ConnectionModeHttps );
- iResponse = new QByteArray();
connect( iHttp,
SIGNAL( readyRead( const QHttpResponseHeader& ) ),
{
delete iConnectionSettings;
delete iHttp;
- delete iResponse;
+ QList<QByteArray*> responses = iResponses.values();
+ while(!responses.isEmpty())
+ delete responses.takeFirst();
}
void Communication::processResponse( const QHttpResponseHeader& aHeader )
{
if ( aHeader.statusCode() == 200 )
{
- iResponse->append( iHttp->readAll() );
+ if( iResponses.contains( iCurrentRequest ) )
+ {
+ QByteArray* response = iResponses.value( iCurrentRequest, NULL );
+ response->append( iHttp->readAll() );
+ }
}
}
void Communication::handleRequestStarted( int aRequestId )
{
- if( aRequestId != 0 && iCurrentRequest != 0 &&
- aRequestId == iCurrentRequest )
+ if( iResponses.contains( aRequestId ) )
{
- emit requestStarted( iCurrentRequest );
+ iCurrentRequest = aRequestId;
+ emit requestStarted( aRequestId );
}
}
void Communication::handleResults( int aId, bool /*aError*/ )
{
- if( aId == iCurrentRequest )
+ if( iCurrentRequest != 0 && aId == iCurrentRequest )
{
+ iAuthFailCount = 0;
iCurrentRequest = 0;
- emit requestFinished( aId, iHttp->error() );
+ int err = (int)iHttp->error();
+ if( iHttp->error() == QHttp::Aborted && iAuthFailCount > 1 )
+ err = 11;
+ emit requestFinished( aId, err );
}
}
int Communication::request( const QString &aCommand, const QByteArray &aContent )
{
- //TODO: This is just temporarily here to implement multiple request support
- if( iCurrentRequest )
+ if( iAuthFailCount > 1 )
return 0;
+
QHttpRequestHeader header( QString( "POST" ), QString( "/ews/exchange.asmx" ) );
header.setValue( "Host", iConnectionSettings->serverUrl().toString() );
QString command = aCommand;
header.setContentType( command );
- iAuthFailCount = 0;
- iResponse->clear();
- iCurrentRequest = iHttp->request( header, aContent );
+ int id = iHttp->request( header, aContent );
+ if( iResponses.contains( id ) )
+ {
+ QByteArray* response = iResponses.value( id, NULL );
+ response->clear();
+ }
+ else
+ {
+ iResponses.insert( id, new QByteArray() );
+ }
- return iCurrentRequest;
+ return id;
}
-const QByteArray& Communication::response( int /*aRequestId*/ )
+QByteArray* Communication::response( int aRequestId )
{
- return *iResponse;
+ if( !iResponses.contains( aRequestId ) )
+ return NULL;
+ QByteArray* response = iResponses.take( aRequestId );
+ return response;
}
void Communication::handleReadProgress( int aDone, int aTotal )
#include <QObject>
#include <QHttp>
+#include <QHash>
class QByteArray;
class ConnectionSettings;
/*!
* This class uses the QHttp class to make HTTP requests. HTTP responses are
* returned as QByteArray.
- *
- * NOTE! Currently this class does NOT support multiple simultaneuos requests.
*/
class Communication : public QObject
{
virtual ~Communication();
//! Returns the response of a request identified by aRequestId.
/*!
- * NOTE! Currently the last request response is returned as the multiple
- * request support is not implemented.
* \param aRequestId Request id number.
*/
- const QByteArray& response( int aRequestId );
+ QByteArray* response( int aRequestId );
//! Makes a HTTP request to the server defined in the constructor.
/*!
* \param aRequestId Request id number.
* \param aError Error code of the request finished.
*/
- void requestFinished( int aRequestId, QHttp::Error aError );
+ void requestFinished( int aRequestId, int aError );
protected slots:
//! Connected to QHttp::readyRead to read the response buffer.
*/
QHttp* iHttp;
/*!
- * Response buffer
+ * QHash of requests and response buffers
*/
- QByteArray* iResponse;
+ QHash<int, QByteArray*> iResponses;
/*!
* ID number of a request currently ongoing
*/
SLOT( readProgress( int, int, int ) )
);
connect( iFetchingCommunication,
- SIGNAL( requestFinished( int, QHttp::Error ) ),
+ SIGNAL( requestFinished( int, int ) ),
this,
- SLOT( requestFinished( int, QHttp::Error ) )
+ SLOT( requestFinished( int, int ) )
);
}
}
void CommunicationManager::fetchMeetings( const QDateTime &aFrom, const QDateTime &aUntil, const Room &aIn )
{
+ //prevent making multiple simultaneous user availibility requests
+ const RequestData* rd = findRequest( GetUserAvailability );
+ if( rd )
+ return;
ReqMsgGetUserAvailability msg;
msg.setTimeZone();
msg.setTimeWindow( aFrom, aUntil );
}
}
-void CommunicationManager::requestFinished( int aRequestId, QHttp::Error aError )
+void CommunicationManager::requestFinished( int aRequestId, int aError )
{
RequestData* rd = takeRequest( aRequestId );
- qDebug() << "CommunicationManager::requestFinished: id: " << aRequestId << " error: " << (int)aError;
+ QByteArray* response = iFetchingCommunication->response( aRequestId );
+ qDebug() << "CommunicationManager::requestFinished: id: " << aRequestId << " error: " << aError;
- if( aError != QHttp::NoError || rd == NULL )
+ if( aError != (int)(QHttp::NoError) || rd == NULL || response == NULL )
{
- int err = (int)aError;
- if( rd == NULL )
+ int err = aError;
+ if( rd == NULL || response == NULL )
err = 10;
delete rd;
emit error( ERROR_BASE+(int)err, CommunicationManager::FetchingCommunication );
return;
}
- const QByteArray& response = iFetchingCommunication->response( aRequestId );
-
switch( rd->type )
{
case GetUserAvailability:
{
- ResMsgGetUserAvailability msg( response );
+ ResMsgGetUserAvailability msg( *response );
while ( !iMeetings.isEmpty() )
delete iMeetings.takeFirst();
}
case ConvertId:
{
- ResponseMessage msg( response );
+ ResponseMessage msg( *response );
QString id = msg.getNodeValue( QString( "Id" ),
QDomNode::AttributeNode,
QString( "AlternateId" ) );
}
case GetCalendarItem:
{
- ResMsgGetCalendarItem msg( response );
+ ResMsgGetCalendarItem msg( *response );
int err = msg.getMeetingDetailsFromResponse( *(rd->meeting) );
if( err )
emit error( ERROR_BASE+9, CommunicationManager::FetchingCommunication );
break;
}
}
+ delete response;
delete rd;
}
return NULL;
}
-
-
+const CommunicationManager::RequestData* CommunicationManager::findRequest( RequestType aRequestType ) const
+{
+ for( int i = iRequestInfos.count() - 1; i >= 0 ; i-- )
+ {
+ struct RequestData* rd = iRequestInfos[i];
+ if( rd->type == aRequestType )
+ {
+ return rd;
+ }
+ }
+ return NULL;
+}
protected slots:
//! Connected to Communication::requestFinished.
- void requestFinished( int aRequestId, QHttp::Error aError );
+ void requestFinished( int aRequestId, int aError );
//! Connected to Communication::readProgress.
void readProgress( int aRequestId, int aDone, int aTotal );
* \param aRequestId Request ID number returned by the Communication::request
*/
RequestData* takeRequest( int aRequestId );
+ //! Finds a RequestData from the iRequestInfos list.
+ /*!
+ * Returns a pointer to RequestData, NULL if not found.
+ * \param aRequestType Request type
+ */
+ const RequestData* findRequest( RequestType aRequestType ) const;
private:
//! Instance of Connection settings of the fetching communication
-#include <iostream>\r
-#include <fstream> \r
-#include <QApplication>\r
-#include <QTime>\r
-#include "WindowManager.h"\r
-\r
-using namespace std;\r
-\r
-ofstream logfile;\r
-\r
-void DebugOutputHandler( QtMsgType type, const char *msg ) {\r
- switch( type ) {\r
- case QtDebugMsg:\r
- logfile << QTime::currentTime().toString().toAscii().data() << " Debug: " << msg << "\n";\r
- logfile.flush();\r
- break;\r
- case QtCriticalMsg:\r
- logfile << QTime::currentTime().toString().toAscii().data() << " Critical: " << msg << "\n";\r
- logfile.flush();\r
- break;\r
- case QtWarningMsg:\r
- logfile << QTime::currentTime().toString().toAscii().data() << " Warning: " << msg << "\n";\r
- logfile.flush();\r
- break;\r
- case QtFatalMsg:\r
- logfile << QTime::currentTime().toString().toAscii().data() << " Fatal: " << msg << "\n";\r
- logfile.flush();\r
- }\r
-}\r
-\r
-int main( int argc, char *argv[] )\r
-{\r
- #ifndef QT_NO_DEBUG_OUTPUT\r
- logfile.open( "/tmp/qtmeetings.log", ios::app );\r
- qInstallMsgHandler( DebugOutputHandler );\r
- #endif\r
- \r
- QApplication app( argc, argv );\r
- WindowManager *windowManager = new WindowManager;\r
- return app.exec();\r
-}\r
+#include <iostream>
+#include <fstream>
+#include <QApplication>
+#include <QTime>
+#include "WindowManager.h"
+
+using namespace std;
+
+ofstream logfile;
+
+void DebugOutputHandler( QtMsgType type, const char *msg ) {
+ switch( type ) {
+ case QtDebugMsg:
+ logfile << QTime::currentTime().toString().toAscii().data() << " Debug: " << msg << "\n";
+ logfile.flush();
+ break;
+ case QtCriticalMsg:
+ logfile << QTime::currentTime().toString().toAscii().data() << " Critical: " << msg << "\n";
+ logfile.flush();
+ break;
+ case QtWarningMsg:
+ logfile << QTime::currentTime().toString().toAscii().data() << " Warning: " << msg << "\n";
+ logfile.flush();
+ break;
+ case QtFatalMsg:
+ logfile << QTime::currentTime().toString().toAscii().data() << " Fatal: " << msg << "\n";
+ logfile.flush();
+ }
+}
+
+int main( int argc, char *argv[] )
+{
+ #ifdef DEBUG_OUTPUT_TO_FILE
+ logfile.open( "/tmp/qtmeetings.log", ios::app );
+ qInstallMsgHandler( DebugOutputHandler );
+ #endif
+
+ QApplication app( argc, argv );
+ WindowManager *windowManager = new WindowManager;
+ return app.exec();
+}
delete conn;
conn = NULL;
connect( iComm,
- SIGNAL( requestFinished( int, QHttp::Error ) ),
+ SIGNAL( requestFinished( int, int ) ),
this,
- SLOT( requestFinished( int, QHttp::Error ) )
+ SLOT( requestFinished( int, int ) )
);
}
QCOMPARE( rp.isValid(), true );
QSignalSpy rs( iComm, SIGNAL(requestStarted( int )) );
QCOMPARE( rs.isValid(), true );
- qRegisterMetaType<QHttp::Error>("QHttp::Error");
- QSignalSpy rf( iComm, SIGNAL(requestFinished( int, QHttp::Error )) );
+ QSignalSpy rf( iComm, SIGNAL(requestFinished( int, int )) );
QCOMPARE( rf.isValid(), true );
iRequestId = iComm->request( "", QString("").toAscii() );
QCOMPARE( rf.count(), 1 );
args = rf.takeFirst();
QCOMPARE( args.at(0).type(), QVariant::Int );
- QCOMPARE( args.at(1).typeName(), "QHttp::Error" );
+ QCOMPARE( args.at(1).type(), QVariant::Int );
//verify readProgress
QCOMPARE( rp.count(), 1 );
}
QByteArray content = file.readAll();
- iRequestId = iComm->request( command, content );
+ iError = 0;
+ int id_ok = iComm->request( command, content );
+ iRequestId = id_ok;
int id_fail = iComm->request( "", QString("").toAscii() );
QVERIFY( iRequestId != 0 );
- QCOMPARE( id_fail, 0 );
+ QVERIFY( id_fail != 0 );
+ qDebug() << "id_ok:" << id_ok;
+ qDebug() << "id_fail: " << id_fail;
for(int i=0; iRequestId != 0 && i < 5000/250; i++ )
QTest::qWait( 250 );
- const QByteArray& response = iComm->response( 0 );
- QVERIFY( response.contains("GetUserAvailabilityResponse") );
- iRequestId = iComm->request( "", QString("").toAscii() );
- QVERIFY( iRequestId != 0 );
- QVERIFY( response.isEmpty() );
+ qDebug() << "iError:" << iError;
+ QVERIFY( iError == 0 );
+ QByteArray* response = iComm->response( id_ok );
+ QVERIFY( response != NULL );
+ QVERIFY( !response->isEmpty() );
+ if( response->contains("GetUserAvailabilityResponse") == FALSE )
+ {
+ QWARN( *response );
+ }
+ QVERIFY( response->contains("GetUserAvailabilityResponse") );
+ delete response;
+ response = iComm->response( 0 );
+ QVERIFY( response == NULL );
}
-void TestCommunication::requestFinished( int aRequestId, QHttp::Error /*aError*/ )
+void TestCommunication::requestFinished( int aRequestId, int aError )
{
- QCOMPARE( aRequestId, iRequestId );
+ qDebug() << "TestCommunication::requestFinished:" << aRequestId << aError;
+ if( aRequestId == iRequestId )
+ iError = aError;
iRequestId = 0;
}
void cleanupTestCase();
void testPublicSignals();
void testRequestAndResponse();
- void requestFinished( int aRequestId, QHttp::Error aError );
+ void requestFinished( int aRequestId, int aError );
private:
Communication* iComm;
- int iRequestId;
+ int iRequestId, iError;
};