Home · All Classes · Grouped Classes · Annotated · Functions

QObexServerSession Class Reference

The QObexServerSession class provides an abstract base class for implementing an OBEX server. More...

    #include <QObexServerSession>

Inherits QObject.

Public Types

Public Functions

Signals

Protected Functions

Protected Slots

Additional Inherited Members


Detailed Description

The QObexServerSession class provides an abstract base class for implementing an OBEX server.

To implement an OBEX server, subclass QObexServerSession and override the protected slots that correspond to the requests to be handled by your server, as shown below.

QObexServerSession can accept OBEX client requests over any transport that is provided through a subclass of QIODevice. For example, QBluetoothRfcommSocket, QIrSocket and QTcpSocket are all subclasses of QIODevice, and objects of these subclasses can passed to the QObexServerSession constructor to run OBEX servers over RFCOMM, IrDA or TCP, respectively.

Receiving client requests

In order to receive requests from an OBEX client, your QObexServerSession subclass must override the protected slots for the requests that it wants to receive. For example, if you want to receive Connect requests, you must override the corresponding connect() slot, which will be called each time a Connect request is received:

    class SimpleObexServer : public QObexServerSession
    {
        Q_OBJECT
    public:
        SimpleObexServer(QIODevice *device, QObject *parent = 0)
            : QObexServerSession(device, parent)
        {
        }

    protected slots:
        QObex::ResponseCode connect(const QObexHeader &header)
        {
            qDebug() << "Received a CONNECT request";

            // Return QObex::Success to allow the request, or return
            // some other response code to deny the request.
            return QObex::Success;
        }
    };

Other slots are similarly named according to their request types. Here are the types of requests that can be received by a subclass of QObexServerSession, and the corresponding slots that must be overridden to receive them:

Request typeProtected slot
Connectconnect()
Disconnectdisconnect()
Putput()
Put-DeleteputDelete()
Getget()
SetPathsetPath()

If a client sends a request but the server subclass has not overridden the slot for that particular type of request, the request will automatically be denied by returning a QObex::NotImplemented response to the client.

There is no corresponding slot for Abort requests. When an Abort request is received, error() will be called with an error value of QObexServerSession::Aborted. Abort requests cannot be denied.

Handling Put and Get requests

When a Put request is received, the put() slot is called with the initial request headers. This allows you to refuse the request before any body data is received. Then, the virtual dataAvailable() function is called each time body data is received for the Put request. You can return a non-success response from dataAvaiable() to cancel the Put operaton. Here is an example subclass implementation:

    private:
        QFile *m_incomingFile;

    protected slots:
        QObex::ResponseCode put(const QObexHeader &header)
        {
            // Reject the PUT request if the requested file cannot be opened
            QString incomingFilename = header.filename();
            m_incomingFile = new QFile(incomingFilename);

            if (!m_incomingFile->open(QIODevice::WriteOnly)) {
                delete m_incomingFile;
                return QObex::InternalServerError;
            }

            return QObex::Success;
        }

    protected:
        QObex::ResponseCode dataAvailable(const char *data, qint64 size)
        {
            if (size > 0) {
                // Write the new data to file. If the data cannot be written, reject
                // the request.
                if (m_incomingFile->write(data, size) < 0) {
                    m_incomingFile->close();
                    return QObex::InternalServerError;
                }
            } else {
                qDebug() << "Received all PUT data";
                m_incomingFile->close();
            }

            return QObex::Success;
        }

For Get requests, override the get() slot and override the provideData() function. The get() slot is called when the Get request is received, and provideData() is called each time the service is required to send more body data to the client. You can return a non-success response from provideData() to cancel the Get request.

Note that when implementing provideData(), the subclass must ensure that the data remains valid until the next call to provideData(), or until the request is finished.

Here is an example implementation:

    private:
        QFile *m_requestedFile;
        QByteArray m_lastSentBytes;

    protected slots:
        QObex::ResponseCode get(const QObexHeader &header)
        {
            QString requestedFilename = header.name();
            if (!QFile::exists(requestedFilename))
                return QObex::NotFound;

            m_requestedFile = new QFile(requestedFilename);
            if (!m_requestedFile->open(QIODevice::ReadOnly)) {
                delete m_requestedFile;
                return QObex::InternalServerError;
            }

            qDebug() << "Prepared for GET request for" << requestedFile;
            return QObex::Success;
        }

    protected:
        QObex::ResponseCode provideData(const char **data, qint64 *size)
        {
            // Read another data chunk from the file.
            // The read data is stored in m_lastSentBytes so that it remains
            // valid until the next call to provideData(), or until the
            // request is finished.
            m_lastSentBytes = m_requestedFile.read(1024);

            if (m_lastSentBytes.size() > 0) {
                *data = m_lastSentBytes.constData();
                *size = m_lastSentBytes.size();
                qDebug() << "Sending another" << size << "bytes";
            } else {
                *size = 0;
                m_requestedFile->close();
                m_lastSentBytes.clear();
                qDebug() << "Finished reading file";
            }

            return QObex::Success;
        }

Handling errors and Abort requests

If an error occurs while running the server, error() will be called with the corresponding error. The server should override this function to perform any clean-up actions that might be necessary.

The error() function is also called when an OBEX client sends an Abort request to cancel a multi-packet request such as Put or Get. When an Abort request is received, the server will automatically respond with QObex::Success and call error() with the error argument set to QObexServerSession::Aborted. Therefore, if a server supports the Put or Get requests, it should override error() so that it can be notified of Abort requests and perform any clean-up actions that might be necessary.

Handling socket disconnections

You should ensure that the QIODevice provided in the constructor emits QIODevice::aboutToClose() or QObject::destroyed() when the associated transport connection is disconnected. If one of these signals are emitted, QObexServerSession will know the transport connection has been lost, and will call error() with the argument set to ConnectionError.

This is particularly an issue for socket classes such as QTcpSocket that do not emit QIODevice::aboutToClose() when a disconnected() signal is emitted. In these cases, QObexServerSession will not know that the transport has been disconnected. To avoid this, you can make the socket emit QIODevice::aboutToClose() when it is disconnected:

    // make the socket emit aboutToClose() when disconnected() is emitted
    QObject::connect(socket, SIGNAL(disconnected()), socket, SIGNAL(aboutToClose()));

Or, if the socket can be discarded as soon as it is disconnected:

    // delete the socket when the transport is disconnected
    QObject::connect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater()));

See also QObexClientSession.


Member Type Documentation

enum QObexServerSession::Error

These are the errors that may be passed to QObexServerSession::error().

ConstantValueDescription
QObexServerSession::ConnectionError1The client is unable to send data, or the client-server communication process is otherwise disrupted. In this case, the client and server is no longer synchronized with each other, so the server session should be closed and the underlying OBEX socket should not be used any longer.
QObexServerSession::InvalidRequest2A client request was malformed or otherwise invalid.
QObexServerSession::Aborted3The client sent an Abort request.
QObexServerSession::AuthenticationFailed4The current request failed because the client could not be authenticated, or the server ignored an authentication request from the client.
QObexServerSession::UnknownError100An error other than those above has occurred.


Member Function Documentation

QObexServerSession::QObexServerSession ( QIODevice * device, QObject * parent = 0 )

Constructs an OBEX server session that uses device for the transport connection. The parent is the QObject parent.

The device must be opened, or else the service will be unable to receive any client requests.

QObexServerSession::~QObexServerSession ()   [pure virtual]

Destroys the server session.

void QObexServerSession::authenticationRequired ( QObexAuthenticationChallenge * challenge )   [signal]

This signal is emitted when a client requires the server to authenticate itself before proceeding with the current request.

The challenge provides the details of the authentication challenge sent by the client. The challenge object can then be filled in with the username and password that should be sent back to the client in order to authenticate this server.

The server will not be notified if the client rejects the authentication details provided in challenge; in this case, it is likely that the client will simply disconnect from the server.

This signal is not emitted if the protected slot for the current request has denied the request by returning a response code other than QObex::Success.

Note: It is not possible to use a QueuedConnection to connect to this signal, as the server will not send back a username and password (and so authentication will fail) if the challenge has not been filled in with new information when the signal returns.

void QObexServerSession::authenticationResponse ( const QObexAuthenticationResponse & response, bool * accept )   [signal]

This signal is emitted if the server has previously issued an authentication challenge to indicate that the client must authenticate itself before proceeding with the current request, and the client has now responded with an authentication response containing a username and password for authentication.

Set accept to true if the authentication details in response are correct. If accept is set to true, the corresponding slot for the current request will be called after this signal is emitted. Otherwise, the request will automatically be denied with a QObex::Unauthorized response, and error() will be called with QObexServerSession::AuthenticationFailed.

You can issue an authentication challenge to a client by responding to a request with QObex::Unauthorized and a QObexHeader object that includes an authentication challenge (by calling QObexHeader::setAuthenticationChallenge()).

Note: It is not possible to use a QueuedConnection to connect to this signal, as accept will automatically be set to false if its value has not been set when the signal returns.

void QObexServerSession::close ()

Closes the service. The service will no longer receive client requests.

QObex::ResponseCode QObexServerSession::connect ( const QObexHeader & header )   [protected slot]

Called when a Connect request is received with header.

If your server supports Connect requests, override this slot and return QObex::Success to allow the request to continue. If you return any other response code, the request will be denied. The default implementation returns QObex::NotImplemented.

QObex::ResponseCode QObexServerSession::dataAvailable ( const char * data, qint64 size )   [virtual protected]

Called each time the server receives body data for a Put request. The data is the received data and size is the data length. If size is 0, then all body data has been received.

If your server supports Put requests, override this function to read and store the data. The data will not be buffered and made available elsewhere, so it must be read at this point. Return QObex::Success to allow the request to continue, or any other response code to stop the request.

The default implementation returns QObex::InternalServerError.

See also put().

QObex::ResponseCode QObexServerSession::disconnect ( const QObexHeader & header )   [protected slot]

Called when a Disconnect request is received with header.

If your server supports Disconnect requests, override this slot and return QObex::Success to allow the request to continue. If you return any other response code, the request will be denied. The default implementation returns QObex::NotImplemented.

Note: Clients may terminate the transport connection without sending a Disconnect request, so you should not necessarily expect to receive this request.

void QObexServerSession::error ( QObexServerSession::Error error, const QString & errorString )   [virtual protected]

Called when an error occurs while running the server. The error is the error that has occurred, and errorString is a human-readable description of the error.

Override this to provide custom error handling functionality. The default implementation prints the warning to the console, and also calls close() if the error is QObexServerSession::ConnectionError.

void QObexServerSession::finalResponseSent ( QObex::Request request )   [signal]

This signal is emitted when the server has sent the final response for the specified request.

Note this signal not emitted if the request was aborted, or if the server responded with QObex::NotImplemented because the corresponding request slot was not implemented by this server session.

QObex::ResponseCode QObexServerSession::get ( const QObexHeader & header )   [protected slot]

Called when a Get request is received with header.

If your server supports Get requests, override this slot and return QObex::Success to allow the request to continue. If you return any other response code, the request will be denied. The default implementation returns QObex::NotImplemented.

If you override this slot, you should also override provideData() to provide the body data that will be sent back to the client, and also override error() so you can be notified if the client aborts the request.

See also provideData() and error().

QObex::ResponseCode QObexServerSession::provideData ( const char ** data, qint64 * size )   [virtual protected]

Called each time the server is required to send body data back to the client for a Get request.

If your server supports Get requests, override this function and set data to the body data to be sent and size to the length of the data. If all body data has been sent, set size to zero. Return QObex::Success to allow the request to continue, or any other response code to stop the request.

The default implementation returns QObex::InternalServerError.

Note: The subclass is responsible for ensuring that data remains valid until the next call to provideData(), or until all data has been sent.

See also get().

QObex::ResponseCode QObexServerSession::put ( const QObexHeader & header )   [protected slot]

Called when a Put request is received with header.

If your server supports Put requests, override this slot and return QObex::Success to allow the request to continue. If you return any other response code, the request will be denied. The default implementation returns QObex::NotImplemented.

If you override this slot, you should also override dataAvailable() to read the body data that is received during the request, and also override error() so you can be notified if the client aborts the request.

See also dataAvailable() and error().

QObex::ResponseCode QObexServerSession::putDelete ( const QObexHeader & header )   [protected slot]

Called when a Put-Delete request is received with header.

If your server supports Put-Delete requests, override this slot and return QObex::Success to allow the request to continue. If you return any other response code, the request will be denied. The default implementation returns QObex::NotImplemented.

QIODevice * QObexServerSession::sessionDevice ()

Returns the device used by this server session, as provided in the constructor.

void QObexServerSession::setNextResponseHeader ( const QObexHeader & header )   [protected]

Sets the session to send header in the next server response for the current request.

This might be useful, for example, to give the client some information about the file that is about to be sent back in response to a Get request:

    protected slots:
        QObex::ResponseCode get(const QObexHeader &header)
        {
            QString requestedFilename = header.name();
            QFile file(requestedFilename);
            if (file.open(QIODevice::ReadOnly)) {
                QObexHeader header;
                header.setLength(file.size());
                setNextResponseHeader(header);
            }

            return QObex::Success;
        }

QObex::ResponseCode QObexServerSession::setPath ( const QObexHeader & header, QObex::SetPathFlags flags )   [protected slot]

Called when a SetPath request is received with header and flags.

If your server supports SetPath requests, override this slot and return QObex::Success to allow the request to continue. If you return any other response code, the request will be denied. The default implementation returns QObex::NotImplemented.


Copyright © 2008 Nokia Trademarks
Qtopia 4.3.3