/src/qt/paymentserver.cpp
C++ | 161 lines | 108 code | 27 blank | 26 comment | 11 complexity | 4226abf21cd915d385a5335e0d5435d0 MD5 | raw file
- // Copyright (c) 2009-2012 The Bitcoin developers
- // Copyright (c) 2013 The Primecoin developers
- // Distributed under the MIT/X11 software license, see the accompanying
- // file COPYING or http://www.opensource.org/licenses/mit-license.php.
- #include <QApplication>
- #include "paymentserver.h"
- #include "guiconstants.h"
- #include "ui_interface.h"
- #include "util.h"
- #include <QByteArray>
- #include <QDataStream>
- #include <QDebug>
- #include <QFileOpenEvent>
- #include <QHash>
- #include <QLocalServer>
- #include <QLocalSocket>
- #include <QStringList>
- #include <QUrl>
- using namespace boost;
- const int BITCOIN_IPC_CONNECT_TIMEOUT = 1000; // milliseconds
- const QString BITCOIN_IPC_PREFIX("primecoin:");
- //
- // Create a name that is unique for:
- // testnet / non-testnet
- // data directory
- //
- static QString ipcServerName()
- {
- QString name("PrimecoinQt");
- // Append a simple hash of the datadir
- // Note that GetDataDir(true) returns a different path
- // for -testnet versus main net
- QString ddir(GetDataDir(true).string().c_str());
- name.append(QString::number(qHash(ddir)));
- return name;
- }
- //
- // This stores payment requests received before
- // the main GUI window is up and ready to ask the user
- // to send payment.
- //
- static QStringList savedPaymentRequests;
- //
- // Sending to the server is done synchronously, at startup.
- // If the server isn't already running, startup continues,
- // and the items in savedPaymentRequest will be handled
- // when uiReady() is called.
- //
- bool PaymentServer::ipcSendCommandLine()
- {
- bool fResult = false;
- const QStringList& args = qApp->arguments();
- for (int i = 1; i < args.size(); i++)
- {
- if (!args[i].startsWith(BITCOIN_IPC_PREFIX, Qt::CaseInsensitive))
- continue;
- savedPaymentRequests.append(args[i]);
- }
- foreach (const QString& arg, savedPaymentRequests)
- {
- QLocalSocket* socket = new QLocalSocket();
- socket->connectToServer(ipcServerName(), QIODevice::WriteOnly);
- if (!socket->waitForConnected(BITCOIN_IPC_CONNECT_TIMEOUT))
- return false;
- QByteArray block;
- QDataStream out(&block, QIODevice::WriteOnly);
- out.setVersion(QDataStream::Qt_4_0);
- out << arg;
- out.device()->seek(0);
- socket->write(block);
- socket->flush();
- socket->waitForBytesWritten(BITCOIN_IPC_CONNECT_TIMEOUT);
- socket->disconnectFromServer();
- delete socket;
- fResult = true;
- }
- return fResult;
- }
- PaymentServer::PaymentServer(QApplication* parent) : QObject(parent), saveURIs(true)
- {
- // Install global event filter to catch QFileOpenEvents on the mac (sent when you click bitcoin: links)
- parent->installEventFilter(this);
- QString name = ipcServerName();
- // Clean up old socket leftover from a crash:
- QLocalServer::removeServer(name);
- uriServer = new QLocalServer(this);
- if (!uriServer->listen(name))
- qDebug() << tr("Cannot start primecoin: click-to-pay handler");
- else
- connect(uriServer, SIGNAL(newConnection()), this, SLOT(handleURIConnection()));
- }
- bool PaymentServer::eventFilter(QObject *object, QEvent *event)
- {
- // clicking on bitcoin: URLs creates FileOpen events on the Mac:
- if (event->type() == QEvent::FileOpen)
- {
- QFileOpenEvent* fileEvent = static_cast<QFileOpenEvent*>(event);
- if (!fileEvent->url().isEmpty())
- {
- if (saveURIs) // Before main window is ready:
- savedPaymentRequests.append(fileEvent->url().toString());
- else
- emit receivedURI(fileEvent->url().toString());
- return true;
- }
- }
- return false;
- }
- void PaymentServer::uiReady()
- {
- saveURIs = false;
- foreach (const QString& s, savedPaymentRequests)
- emit receivedURI(s);
- savedPaymentRequests.clear();
- }
- void PaymentServer::handleURIConnection()
- {
- QLocalSocket *clientConnection = uriServer->nextPendingConnection();
- while (clientConnection->bytesAvailable() < (int)sizeof(quint32))
- clientConnection->waitForReadyRead();
- connect(clientConnection, SIGNAL(disconnected()),
- clientConnection, SLOT(deleteLater()));
- QDataStream in(clientConnection);
- in.setVersion(QDataStream::Qt_4_0);
- if (clientConnection->bytesAvailable() < (int)sizeof(quint16)) {
- return;
- }
- QString message;
- in >> message;
- if (saveURIs)
- savedPaymentRequests.append(message);
- else
- emit receivedURI(message);
- }