00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "blobiohandler.h"
00025
00026 #include <QBuffer>
00027 #include <QDebug>
00028
00029 #include "SignOn/signonplugincommon.h"
00030
00031 #define SIGNON_IPC_BUFFER_PAGE_SIZE 16384
00032
00033 using namespace SignOn;
00034
00035 BlobIOHandler::BlobIOHandler(QIODevice *readChannel,
00036 QIODevice *writeChannel,
00037 QObject *parent)
00038 : QObject(parent),
00039 m_readChannel(readChannel),
00040 m_writeChannel(writeChannel),
00041 m_readNotifier(0),
00042 m_blobSize(-1)
00043 {
00044 }
00045
00046 void BlobIOHandler::setReadChannelSocketNotifier(QSocketNotifier *notifier)
00047 {
00048 if (notifier == 0)
00049 return;
00050
00051 m_readNotifier = notifier;
00052 }
00053
00054 bool BlobIOHandler::sendData(const QVariantMap &map)
00055 {
00056 if (m_writeChannel == 0) {
00057 TRACE() << "NULL write channel.";
00058 return false;
00059 }
00060
00061 QDataStream stream(m_writeChannel);
00062 QByteArray ba = variantMapToByteArray(map);
00063 stream << ba.size();
00064
00065 QVector<QByteArray> pages = pageByteArray(ba);
00066 for (int i = 0; i < pages.count(); ++i)
00067 stream << pages[i];
00068
00069 return true;
00070 }
00071
00072 void BlobIOHandler::setReadNotificationEnabled(bool enabled)
00073 {
00074 if (enabled) {
00075 if (m_readNotifier != 0) {
00076 m_readNotifier->setEnabled(true);
00077 connect(m_readNotifier, SIGNAL(activated(int)), this, SLOT(readBlob()));
00078 } else {
00079 connect(m_readChannel, SIGNAL(readyRead()), this, SLOT(readBlob()));
00080 }
00081 } else {
00082 if (m_readNotifier != 0) {
00083 disconnect(m_readNotifier, SIGNAL(activated(int)), this, SLOT(readBlob()));
00084 m_readNotifier->setEnabled(false);
00085 } else {
00086 disconnect(m_readChannel, SIGNAL(readyRead()), this, SLOT(readBlob()));
00087 }
00088 }
00089 }
00090
00091 void BlobIOHandler::receiveData(int expectedDataSize)
00092 {
00093 m_blobBuffer.clear();
00094 m_blobSize = expectedDataSize;
00095
00096
00097
00098 if (m_blobSize > SIGNON_IPC_BUFFER_PAGE_SIZE)
00099 setReadNotificationEnabled(true);
00100
00101 readBlob();
00102 }
00103
00104 void BlobIOHandler::readBlob()
00105 {
00106 QDataStream in(m_readChannel);
00107
00108 QByteArray fractionBa;
00109 in >> fractionBa;
00110 m_blobBuffer.append(fractionBa);
00111
00112
00113 if ((fractionBa.size() == 0) && (m_blobBuffer.size() < m_blobSize)) {
00114 setReadNotificationEnabled(false);
00115 emit error();
00116 return;
00117 }
00118
00119 if (m_blobBuffer.size() == m_blobSize) {
00120 QVariantMap sessionDataMap;
00121 sessionDataMap = byteArrayToVariantMap(m_blobBuffer);
00122
00123 if (m_blobSize > SIGNON_IPC_BUFFER_PAGE_SIZE)
00124 setReadNotificationEnabled(false);
00125
00126 emit dataReceived(sessionDataMap);
00127 }
00128 }
00129
00130 QByteArray BlobIOHandler::variantMapToByteArray(const QVariantMap &map)
00131 {
00132 QBuffer buffer;
00133 if (!buffer.open(QIODevice::WriteOnly))
00134 BLAME() << "Buffer opening failed.";
00135
00136 QDataStream stream(&buffer);
00137 stream << map;
00138 buffer.close();
00139
00140 return buffer.data();
00141 }
00142
00143 QVariantMap BlobIOHandler::byteArrayToVariantMap(const QByteArray &array)
00144 {
00145 QByteArray nonConst = array;
00146 QBuffer buffer(&nonConst);
00147 if (!buffer.open(QIODevice::ReadOnly))
00148 BLAME() << "Buffer opening failed.";
00149
00150 buffer.reset();
00151 QDataStream stream(&buffer);
00152 QVariantMap map;
00153 stream >> map;
00154 buffer.close();
00155
00156 return map;
00157 }
00158
00159 QVector<QByteArray> BlobIOHandler::pageByteArray(const QByteArray &array)
00160 {
00161 QVector<QByteArray> dataPages;
00162 QByteArray ba = array;
00163 QBuffer pagingBuffer(&ba);
00164
00165 if (!pagingBuffer.open(QIODevice::ReadOnly))
00166 BLAME() << "Error while paging BLOB. Buffer opening failed.";
00167
00168 while (!pagingBuffer.atEnd()) {
00169 QByteArray page = pagingBuffer.read(SIGNON_IPC_BUFFER_PAGE_SIZE);
00170 dataPages.append(page);
00171 }
00172 pagingBuffer.close();
00173
00174 return dataPages;
00175 }