--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/utilities/serviceipcclient/platform/qt/serviceipclocalsocket.cpp Fri Oct 15 17:30:59 2010 -0400
@@ -0,0 +1,289 @@
+/**
+ This file is part of CWRT package **
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). **
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU (Lesser) General Public License as
+ published by the Free Software Foundation, version 2.1 of the License.
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ (Lesser) General Public License for more details. You should have
+ received a copy of the GNU (Lesser) General Public License along
+ with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+
+#include <QByteArray>
+#include "serviceipclocalsocket_p.h"
+
+namespace WRT
+{
+// CONSTANTS
+const char* REQUEST_COMPLETE_TOKEN = ";ROK";
+const int REQUEST_COMPLETE_TOKEN_LENGTH = 4;
+const char REQUEST_DELIMITER_TOKEN = ';';
+/*!
+ \class ServiceLocalSocketIPC
+ QLocalSocket based IPC client-side backend
+ */
+
+/*!
+ Constructor
+ */
+ServiceLocalSocketIPC::ServiceLocalSocketIPC() : m_BufferType( ENoBuffer )
+{
+ m_Socket = new QLocalSocket();
+ QObject::connect(m_Socket, SIGNAL( error( QLocalSocket::LocalSocketError ) ),
+ this, SLOT( handleError( QLocalSocket::LocalSocketError ) ) );
+}
+
+/*!
+ Destructor
+ */
+
+ServiceLocalSocketIPC::~ServiceLocalSocketIPC()
+{
+ delete m_Socket;
+}
+
+/*!
+ Connect to the server
+ @param aServerName name of the server to connect to
+ @return true if connected, false otherwise
+ */
+bool ServiceLocalSocketIPC::connect(const QString& aServerName)
+{
+ bool rtn;
+ m_Socket->connectToServer(aServerName);
+ rtn = m_Socket->waitForConnected();
+ return rtn;
+}
+
+/*!
+ Disconnect from the server
+ */
+void ServiceLocalSocketIPC::disconnect()
+{
+ m_Socket->close();
+}
+
+/*!
+ Starts the service
+ @param aServerName name of the server to connect to
+ @param aExeName name of the server executable
+ @return true if server started, false otherwise
+ */
+bool ServiceLocalSocketIPC::startServer(const QString& aServerName,
+ const QString& aExeName)
+{
+ bool started(true);
+
+ //Semaphore with 1 initial count,
+ //Use system semaphore to ensure no contention exists across multiple processes
+ //According to QT documentation for System Semaphores on Windows,
+ //the semaphore is automatically cleaned up if a process crashes, thus preventing deadlock
+ //
+ QSystemSemaphore funcSem(aServerName + FUNCTIONSEM, 1);
+ funcSem.acquire();
+
+ // Shared chunk to check if the server has been started or not
+ QSharedMemory sharedMem(aServerName);
+ char* data(NULL);
+ bool attached = sharedMem.attach();
+ if (attached) {
+ data = (char*) sharedMem.data();
+ }
+
+ // Shared memory not created or the flag was not set properly
+ if (!attached || strcmp(data, SERVERNOTSTARTED) == 0) {
+ // Create the server wait semaphore. When the server has listened,
+ // it will signaled after listen has started
+ //
+ QSystemSemaphore sem(aServerName + SERVERSEM, 0);
+
+ // Start the server, since this function is mutex'ed by the global semaphore
+ // only 1 process/thread can reach here
+ //
+ started = QProcess::startDetached(aExeName);
+
+ // Wait until the server signals
+ if (started) {
+ sem.acquire();
+ }
+ }
+
+ // Test if server started successfully
+#if _DEBUG
+ attached = sharedMem.attach();
+ if( attached )
+ {
+ data = (char*)sharedMem.data();
+ if( strcmp( data, SERVERSTARTED ) == 0 )
+ {
+ qDebug() << "Server Started Successfully";
+ }
+ }
+#endif // _DEBUG
+ // Free shared memory
+ sharedMem.detach();
+
+ // Release the function semaphore
+ funcSem.release(1);
+ return started;
+}
+
+/*!
+ Send a request synchronously
+ @param aRequestType type of request, toAscii() will be called to serialize the data
+ @param aData aData data to send to the server
+ @return true if data is sent, false otherwise
+ */
+bool ServiceLocalSocketIPC::sendSync(const QString& aRequestType,
+ const QByteArray& aData)
+{
+ QByteArray data;
+ data.setNum(aData.length());
+ data.append(REQUEST_DELIMITER_TOKEN);
+ data.append(aRequestType.toAscii());
+ data.append(REQUEST_DELIMITER_TOKEN);
+ data.append(aData);
+ int count = m_Socket->write(data);
+ m_Socket->flush();
+ m_BufferType = ESyncBuffer;
+ return (count > 0);
+}
+
+/*!
+ Send a request asynchronously
+ @param aRequestType type of request, toAscii() will be called to serialize the data
+ @param aData data to send to the server
+ */
+void ServiceLocalSocketIPC::sendAsync(const QString& aRequestType,
+ const QByteArray& aData)
+{
+ QByteArray data;
+ data.setNum(aData.length());
+ data.append(REQUEST_DELIMITER_TOKEN);
+ data.append(aRequestType.toAscii());
+ data.append(REQUEST_DELIMITER_TOKEN);
+ data.append(aData);
+ m_Socket->write(data);
+
+ // Connect the signal and reset aync data buffer
+ m_AsyncData.clear();
+ QObject::connect(m_Socket, SIGNAL( readyRead() ),
+ this, SLOT( handleReadyRead() ) );
+ m_BufferType = EAsyncBuffer;
+}
+
+/*!
+ Reads all data pending in the buffer
+ @return QByteArray data that has been read
+ */
+QByteArray ServiceLocalSocketIPC::readAll()
+{
+ QByteArray result;
+
+ // If asynchronous read all data from the socket
+ //
+ if ( m_BufferType == ESyncBuffer ) {
+ // Wait for all data to be completed before returning
+ //
+ bool done = false;
+ do {
+ result.append(m_Socket->readAll());
+ if (result.right(REQUEST_COMPLETE_TOKEN_LENGTH)
+ == REQUEST_COMPLETE_TOKEN) {
+ // Chop the end token
+ result.chop(REQUEST_COMPLETE_TOKEN_LENGTH);
+ done = true;
+ }
+ } while (done == false);
+ }
+ // If async, return the internal databuffer
+ else if( m_BufferType == EAsyncBuffer ){
+ // Should be just a d-ptr copy
+ result = m_AsyncData;
+ QObject::disconnect(m_Socket, SIGNAL( readyRead() ),
+ this, SLOT( handleReadyRead() ) );
+ }
+ m_BufferType = ENoBuffer;
+
+ return result;
+}
+
+/*!
+ Waits until data is available for reading
+ @return bool true if data can be read
+ */
+bool ServiceLocalSocketIPC::waitForRead()
+{
+ return m_Socket->waitForReadyRead();
+}
+
+/*!
+ Handle any socket errors
+ @param socketError error
+ */
+void ServiceLocalSocketIPC::handleError(QLocalSocket::LocalSocketError aSocketError)
+{
+ // Use base class to send this
+ emitError(doMapErrors(aSocketError));
+}
+
+/*!
+ Handle when data is ready to be read
+ */
+void ServiceLocalSocketIPC::handleReadyRead()
+{
+ m_AsyncData.append(m_Socket->readAll());
+ if (m_AsyncData.right(REQUEST_COMPLETE_TOKEN_LENGTH)
+ == REQUEST_COMPLETE_TOKEN) {
+ // Chop the end token
+ m_AsyncData.chop(REQUEST_COMPLETE_TOKEN_LENGTH);
+
+ // Use base class to send signal when all the data has been assembled
+ emitReadyRead();
+ }
+}
+
+int ServiceLocalSocketIPC::doMapErrors( int aError )
+{
+ int error(0);
+
+ // Map QT Local Socket error codes to custom error codes
+ //
+ switch( aError ) {
+ case QLocalSocket::ConnectionError:
+ case QLocalSocket::ConnectionRefusedError: {
+ error = ServiceFwIPC::EConnectionError;
+ break;
+ }
+ case QLocalSocket::PeerClosedError: {
+ error = ServiceFwIPC::EConnectionClosed;
+ break;
+ }
+ case QLocalSocket::ServerNotFoundError: {
+ error = ServiceFwIPC::EServerNotFound;
+ break;
+ }
+ case QLocalSocket::SocketAccessError:
+ case QLocalSocket::SocketResourceError:
+ case QLocalSocket::SocketTimeoutError:
+ case QLocalSocket::DatagramTooLargeError:
+ case QLocalSocket::UnsupportedSocketOperationError: {
+ error = ServiceFwIPC::EIPCError;
+ break;
+ }
+ case QLocalSocket::UnknownSocketError: {
+ error = ServiceFwIPC::EUnknownError;
+ break;
+ }
+ }
+ return error;
+}
+
+}
+// END OF FILE