PageRenderTime 24ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/src/qt/paymentserver.cpp

https://gitlab.com/AirTank/primecoin
C++ | 161 lines | 108 code | 27 blank | 26 comment | 11 complexity | 4226abf21cd915d385a5335e0d5435d0 MD5 | raw file
  1. // Copyright (c) 2009-2012 The Bitcoin developers
  2. // Copyright (c) 2013 The Primecoin developers
  3. // Distributed under the MIT/X11 software license, see the accompanying
  4. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  5. #include <QApplication>
  6. #include "paymentserver.h"
  7. #include "guiconstants.h"
  8. #include "ui_interface.h"
  9. #include "util.h"
  10. #include <QByteArray>
  11. #include <QDataStream>
  12. #include <QDebug>
  13. #include <QFileOpenEvent>
  14. #include <QHash>
  15. #include <QLocalServer>
  16. #include <QLocalSocket>
  17. #include <QStringList>
  18. #include <QUrl>
  19. using namespace boost;
  20. const int BITCOIN_IPC_CONNECT_TIMEOUT = 1000; // milliseconds
  21. const QString BITCOIN_IPC_PREFIX("primecoin:");
  22. //
  23. // Create a name that is unique for:
  24. // testnet / non-testnet
  25. // data directory
  26. //
  27. static QString ipcServerName()
  28. {
  29. QString name("PrimecoinQt");
  30. // Append a simple hash of the datadir
  31. // Note that GetDataDir(true) returns a different path
  32. // for -testnet versus main net
  33. QString ddir(GetDataDir(true).string().c_str());
  34. name.append(QString::number(qHash(ddir)));
  35. return name;
  36. }
  37. //
  38. // This stores payment requests received before
  39. // the main GUI window is up and ready to ask the user
  40. // to send payment.
  41. //
  42. static QStringList savedPaymentRequests;
  43. //
  44. // Sending to the server is done synchronously, at startup.
  45. // If the server isn't already running, startup continues,
  46. // and the items in savedPaymentRequest will be handled
  47. // when uiReady() is called.
  48. //
  49. bool PaymentServer::ipcSendCommandLine()
  50. {
  51. bool fResult = false;
  52. const QStringList& args = qApp->arguments();
  53. for (int i = 1; i < args.size(); i++)
  54. {
  55. if (!args[i].startsWith(BITCOIN_IPC_PREFIX, Qt::CaseInsensitive))
  56. continue;
  57. savedPaymentRequests.append(args[i]);
  58. }
  59. foreach (const QString& arg, savedPaymentRequests)
  60. {
  61. QLocalSocket* socket = new QLocalSocket();
  62. socket->connectToServer(ipcServerName(), QIODevice::WriteOnly);
  63. if (!socket->waitForConnected(BITCOIN_IPC_CONNECT_TIMEOUT))
  64. return false;
  65. QByteArray block;
  66. QDataStream out(&block, QIODevice::WriteOnly);
  67. out.setVersion(QDataStream::Qt_4_0);
  68. out << arg;
  69. out.device()->seek(0);
  70. socket->write(block);
  71. socket->flush();
  72. socket->waitForBytesWritten(BITCOIN_IPC_CONNECT_TIMEOUT);
  73. socket->disconnectFromServer();
  74. delete socket;
  75. fResult = true;
  76. }
  77. return fResult;
  78. }
  79. PaymentServer::PaymentServer(QApplication* parent) : QObject(parent), saveURIs(true)
  80. {
  81. // Install global event filter to catch QFileOpenEvents on the mac (sent when you click bitcoin: links)
  82. parent->installEventFilter(this);
  83. QString name = ipcServerName();
  84. // Clean up old socket leftover from a crash:
  85. QLocalServer::removeServer(name);
  86. uriServer = new QLocalServer(this);
  87. if (!uriServer->listen(name))
  88. qDebug() << tr("Cannot start primecoin: click-to-pay handler");
  89. else
  90. connect(uriServer, SIGNAL(newConnection()), this, SLOT(handleURIConnection()));
  91. }
  92. bool PaymentServer::eventFilter(QObject *object, QEvent *event)
  93. {
  94. // clicking on bitcoin: URLs creates FileOpen events on the Mac:
  95. if (event->type() == QEvent::FileOpen)
  96. {
  97. QFileOpenEvent* fileEvent = static_cast<QFileOpenEvent*>(event);
  98. if (!fileEvent->url().isEmpty())
  99. {
  100. if (saveURIs) // Before main window is ready:
  101. savedPaymentRequests.append(fileEvent->url().toString());
  102. else
  103. emit receivedURI(fileEvent->url().toString());
  104. return true;
  105. }
  106. }
  107. return false;
  108. }
  109. void PaymentServer::uiReady()
  110. {
  111. saveURIs = false;
  112. foreach (const QString& s, savedPaymentRequests)
  113. emit receivedURI(s);
  114. savedPaymentRequests.clear();
  115. }
  116. void PaymentServer::handleURIConnection()
  117. {
  118. QLocalSocket *clientConnection = uriServer->nextPendingConnection();
  119. while (clientConnection->bytesAvailable() < (int)sizeof(quint32))
  120. clientConnection->waitForReadyRead();
  121. connect(clientConnection, SIGNAL(disconnected()),
  122. clientConnection, SLOT(deleteLater()));
  123. QDataStream in(clientConnection);
  124. in.setVersion(QDataStream::Qt_4_0);
  125. if (clientConnection->bytesAvailable() < (int)sizeof(quint16)) {
  126. return;
  127. }
  128. QString message;
  129. in >> message;
  130. if (saveURIs)
  131. savedPaymentRequests.append(message);
  132. else
  133. emit receivedURI(message);
  134. }