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