Open-Transactions  0.93.0-ge03d287
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
OTServerConnection.cpp
Go to the documentation of this file.
1 /************************************************************
2 *
3 * OTServerConnection.cpp
4 *
5 */
6 
7 /************************************************************
8  -----BEGIN PGP SIGNED MESSAGE-----
9  Hash: SHA1
10 
11  * OPEN TRANSACTIONS
12  *
13  * Financial Cryptography and Digital Cash
14  * Library, Protocol, API, Server, CLI, GUI
15  *
16  * -- Anonymous Numbered Accounts.
17  * -- Untraceable Digital Cash.
18  * -- Triple-Signed Receipts.
19  * -- Cheques, Vouchers, Transfers, Inboxes.
20  * -- Basket Currencies, Markets, Payment Plans.
21  * -- Signed, XML, Ricardian-style Contracts.
22  * -- Scripted smart contracts.
23  *
24  * Copyright (C) 2010-2013 by "Fellow Traveler" (A pseudonym)
25  *
26  * EMAIL:
28  *
29  * BITCOIN: 1NtTPVVjDsUfDWybS4BwvHpG2pdS9RnYyQ
30  *
31  * KEY FINGERPRINT (PGP Key in license file):
32  * 9DD5 90EB 9292 4B48 0484 7910 0308 00ED F951 BB8E
33  *
34  * OFFICIAL PROJECT WIKI(s):
35  * https://github.com/FellowTraveler/Moneychanger
36  * https://github.com/FellowTraveler/Open-Transactions/wiki
37  *
38  * WEBSITE:
39  * http://www.OpenTransactions.org/
40  *
41  * Components and licensing:
42  * -- Moneychanger..A Java client GUI.....LICENSE:.....GPLv3
43  * -- otlib.........A class library.......LICENSE:...LAGPLv3
44  * -- otapi.........A client API..........LICENSE:...LAGPLv3
45  * -- opentxs/ot....Command-line client...LICENSE:...LAGPLv3
46  * -- otserver......Server Application....LICENSE:....AGPLv3
47  * Github.com/FellowTraveler/Open-Transactions/wiki/Components
48  *
49  * All of the above OT components were designed and written by
50  * Fellow Traveler, with the exception of Moneychanger, which
51  * was contracted out to Vicky C ([email protected]).
52  * The open-source community has since actively contributed.
53  *
54  * -----------------------------------------------------
55  *
56  * LICENSE:
57  * This program is free software: you can redistribute it
58  * and/or modify it under the terms of the GNU Affero
59  * General Public License as published by the Free Software
60  * Foundation, either version 3 of the License, or (at your
61  * option) any later version.
62  *
63  * ADDITIONAL PERMISSION under the GNU Affero GPL version 3
64  * section 7: (This paragraph applies only to the LAGPLv3
65  * components listed above.) If you modify this Program, or
66  * any covered work, by linking or combining it with other
67  * code, such other code is not for that reason alone subject
68  * to any of the requirements of the GNU Affero GPL version 3.
69  * (==> This means if you are only using the OT API, then you
70  * don't have to open-source your code--only your changes to
71  * Open-Transactions itself must be open source. Similar to
72  * LGPLv3, except it applies to software-as-a-service, not
73  * just to distributing binaries.)
74  *
75  * Extra WAIVER for OpenSSL, Lucre, and all other libraries
76  * used by Open Transactions: This program is released under
77  * the AGPL with the additional exemption that compiling,
78  * linking, and/or using OpenSSL is allowed. The same is true
79  * for any other open source libraries included in this
80  * project: complete waiver from the AGPL is hereby granted to
81  * compile, link, and/or use them with Open-Transactions,
82  * according to their own terms, as long as the rest of the
83  * Open-Transactions terms remain respected, with regard to
84  * the Open-Transactions code itself.
85  *
86  * Lucre License:
87  * This code is also "dual-license", meaning that Ben Lau-
88  * rie's license must also be included and respected, since
89  * the code for Lucre is also included with Open Transactions.
90  * See Open-Transactions/src/otlib/lucre/LUCRE_LICENSE.txt
91  * The Laurie requirements are light, but if there is any
92  * problem with his license, simply remove the Lucre code.
93  * Although there are no other blind token algorithms in Open
94  * Transactions (yet. credlib is coming), the other functions
95  * will continue to operate.
96  * See Lucre on Github: https://github.com/benlaurie/lucre
97  * -----------------------------------------------------
98  * You should have received a copy of the GNU Affero General
99  * Public License along with this program. If not, see:
100  * http://www.gnu.org/licenses/
101  *
102  * If you would like to use this software outside of the free
103  * software license, please contact FellowTraveler.
104  * (Unfortunately many will run anonymously and untraceably,
105  * so who could really stop them?)
106  *
107  * DISCLAIMER:
108  * This program is distributed in the hope that it will be
109  * useful, but WITHOUT ANY WARRANTY; without even the implied
110  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
111  * PURPOSE. See the GNU Affero General Public License for
112  * more details.
113 
114  -----BEGIN PGP SIGNATURE-----
115  Version: GnuPG v1.4.9 (Darwin)
116 
117  iQIcBAEBAgAGBQJRSsfJAAoJEAMIAO35UbuOQT8P/RJbka8etf7wbxdHQNAY+2cC
118  vDf8J3X8VI+pwMqv6wgTVy17venMZJa4I4ikXD/MRyWV1XbTG0mBXk/7AZk7Rexk
119  KTvL/U1kWiez6+8XXLye+k2JNM6v7eej8xMrqEcO0ZArh/DsLoIn1y8p8qjBI7+m
120  aE7lhstDiD0z8mwRRLKFLN2IH5rAFaZZUvj5ERJaoYUKdn4c+RcQVei2YOl4T0FU
121  LWND3YLoH8naqJXkaOKEN4UfJINCwxhe5Ke9wyfLWLUO7NamRkWD2T7CJ0xocnD1
122  sjAzlVGNgaFDRflfIF4QhBx1Ddl6wwhJfw+d08bjqblSq8aXDkmFA7HeunSFKkdn
123  oIEOEgyj+veuOMRJC5pnBJ9vV+7qRdDKQWaCKotynt4sWJDGQ9kWGWm74SsNaduN
124  TPMyr9kNmGsfR69Q2Zq/FLcLX/j8ESxU+HYUB4vaARw2xEOu2xwDDv6jt0j3Vqsg
125  x7rWv4S/Eh18FDNDkVRChiNoOIilLYLL6c38uMf1pnItBuxP3uhgY6COm59kVaRh
126  nyGTYCDYD2TK+fI9o89F1297uDCwEJ62U0Q7iTDp5QuXCoxkPfv8/kX6lS6T3y9G
127  M9mqIoLbIQ1EDntFv7/t6fUTS2+46uCrdZWbQ5RjYXdrzjij02nDmJAm2BngnZvd
128  kamH0Y/n11lCvo1oQxM+
129  =uSzz
130  -----END PGP SIGNATURE-----
131  **************************************************************/
132 
133 #include "../core/stdafx.hpp"
134 
135 #include "OTServerConnection.hpp"
136 #include "OpenTransactions.hpp"
137 #include "OTClient.hpp"
138 #include "OTWallet.hpp"
139 #include "TransportCallback.hpp"
140 
141 #include "../core/OTAssetContract.hpp"
142 #include "../core/util/OTDataCheck.hpp"
143 #include "../core/crypto/OTEnvelope.hpp"
144 #include "../core/OTLog.hpp"
145 #include "../core/OTMessage.hpp"
146 #include "../core/OTPayload.hpp"
147 #include "../core/OTPseudonym.hpp"
148 #include "../core/OTServerContract.hpp"
149 
150 extern "C" {
151 #ifdef _WIN32
152 #include <winsock2.h>
153 #pragma comment(lib, "ws2_32.lib")
154 #else
155 #include <netinet/in.h>
156 #endif
157 }
158 
159 namespace opentxs
160 {
161 
162 int32_t allow_debug = 1;
163 
164 void SetupHeader(u_header& theCMD, int32_t nTypeID, int32_t nCmdID,
165  OTPayload& thePayload)
166 {
167  uint32_t lSize = thePayload.GetSize(); // outputting in normal byte order,
168  // but sent to network in network
169  // byte order.
170 
171  theCMD.fields.type_id = (nTypeID > 0) ? static_cast<BYTE>(nTypeID) : '\0';
172  theCMD.fields.command_id = (nCmdID > 0) ? static_cast<BYTE>(nCmdID) : '\0';
173  ;
174  theCMD.fields.size =
175  htonl(lSize); // think this is causing problems.. maybe not...
176  theCMD.fields.checksum = CalcChecksum(theCMD.buf, OT_CMD_HEADER_SIZE - 1);
177 
178  BYTE byChecksum = (BYTE)theCMD.fields.checksum;
179  int32_t nChecksum = byChecksum;
180 
181  otLog4 << "OT_CMD_HEADER_SIZE: " << OT_CMD_HEADER_SIZE
182  << " -- CMD TYPE: " << nTypeID << " -- CMD NUM: " << nCmdID
183  << " -- (followed by 2 bytes of filler)\n"
184  "PAYLOAD SIZE: " << lSize << " -- CHECKSUM: " << nChecksum
185  << "\n";
186 
187  otLog5 << "First 9 bytes are:";
188  for (int i = 0; i < 9; i++) {
189  otLog5 << " " << int(theCMD.buf[i]);
190  }
191  otLog5 << "\n";
192 }
193 
194 bool OTServerConnection::s_bInitialized = false;
195 
196 void OTServerConnection::Initialize()
197 {
198  // We've already been initialized. We can just return
199  if (s_bInitialized) {
200  return;
201  }
202 
203  // This is the first time this function has run.
204  s_bInitialized = true; // set this to true so the function can't run again.
205  // It only runs the first time.
206 
207  // Initialize SSL -- MUST happen before any Private keys are loaded, if you
208  // want it to work.
209  // Update: this no longer initializes OpenSSL, which I do in
210  // OTLog::OT_Init() now.
211  // Just make sure you call that early on.
212  //
213  // SFSocketGlobalInit();
214 }
215 
216 // Connect is used for SSL mode, but SetFocus is used for XmlRpc mode.
217 // Everytime you send a message, it is a new connection -- and could be to
218 // a different server! So it's important to switch focus each time so we
219 // have the right server contract, etc.
220 //
222  OTServerContract& theServerContract,
223  TransportCallback* pCallback)
224 {
225  if (nullptr == pCallback) {
226  otErr << __FUNCTION__ << ": pCallback is nullptr";
227  OT_FAIL;
228  };
229 
230  // We're already connected! You can't use SetFocus if you're in connection
231  // mode (TCP instead of HTTP.)
232  // if (IsConnected())
233  // return false;
234  //
235  // This call initializes OpenSSL (only the first time it's called.)
236  Initialize();
237 
238  // The Client keeps an internal ServerConnection at all times.
239  // In SSL/TCP mode, you connect, and stay connected. But in RPC
240  // mode, you must call SetFocus before each time you prepare or
241  // process any server-related messages. Why? Since the Client normally
242  // expects the connection to already be made, and therefore expects
243  // to have access to the Nym and Server Contract (and server ID, etc)
244  // available since those pointers are normally set during Connect().
245  // Since we no longer connect in RPC mode, we must still make sure those
246  // pointers are ready by calling SetFocus before they might end up being
247  // used.
248  // Each time you send a new message, it might be to a different server or
249  // from a different nym. That's fine -- just call SetFocus() before you do
250  // it.
251  m_pNym = &theNym;
252  m_pServerContract = &theServerContract;
253  m_pCallback = pCallback; // This is what we get instead of a socket, when
254  // we're in RPC mode.
255  m_bFocused = true;
256 
257  return true;
258 }
259 
260 // When the server sends a reply back with our new request number, we
261 // need to update our records accordingly.
262 //
263 // This function is meant to be called when that happens, so that we
264 // can do just that.
265 //
267  int64_t lNewRequestNumber) const
268 {
269  if (m_pNym && m_pServerContract) {
270  otOut << "Received new request number from the server: "
271  << lNewRequestNumber << ". Updating Nym records...\n";
272 
273  OTString strServerID;
274  m_pServerContract->GetIdentifier(strServerID);
275  m_pNym->OnUpdateRequestNum(*m_pNym, strServerID, lNewRequestNumber);
276  }
277  else {
278  otErr << "Expected m_pNym or m_pServerContract to be not null in "
279  "OTServerConnection::OnServerResponseToGetRequestNumber.\n";
280  }
281 }
282 
284 {
285  if (m_pServerContract) {
286  m_pServerContract->GetIdentifier(theID);
287  return true;
288  }
289  return false;
290 }
291 
292 // When a certain Nym opens a certain account on a certain server,
293 // that account is put onto a list of accounts inside the wallet.
294 // Therefore, a certain Nym's connection to a certain server will
295 // occasionally require access to those accounts. Therefore the
296 // server connection object needs to have a pointer to the wallet.
297 // There might be MORE THAN ONE connection per wallet, or only one,
298 // but either way the connections need a pointer to the wallet
299 // they are associated with, so they can access those accounts.
301 {
302  m_pCallback = nullptr;
303  m_bFocused = false;
304  m_pNym = nullptr;
305  m_pServerContract = nullptr;
306  m_pWallet = &theWallet;
307  m_pClient = &theClient;
308 }
309 
310 // ProcessInBuffer calls this function, once it has verified the header,
311 // this function gets the payload. If successful, returns true and
312 // theServerReply
313 // will contain the OTMessage that was received.
314 // It also flushes the pipe in the event of any errors. (TCP / SSL mode)
316  OTMessage& theServerReply)
317 {
318  bool bSuccess = false;
319 
320  otLog4
321  << "\n****************************************************************"
322  "\n"
323  "===> Processing header from server response.\nFirst 9 bytes are: "
324  << theCMD.buf[0] << " " << theCMD.buf[1] << " " << theCMD.buf[2] << " "
325  << theCMD.buf[3] << " " << theCMD.buf[4] << " " << theCMD.buf[5] << " "
326  << theCMD.buf[6] << " " << theCMD.buf[7] << " " << theCMD.buf[8]
327  << "...\n";
328 
329  if (theCMD.fields.type_id == CMD_TYPE_1) {
330  otWarn << "Received a Type 1 Command...\n";
331 
332  if (IsChecksumValid(theCMD.buf, OT_CMD_HEADER_SIZE)) {
333  otWarn << "Checksum is valid! Processing payload.\n";
334 
335  if (true == ProcessType1Cmd(theCMD, theServerReply))
336  bSuccess = true;
337  }
338  else {
339  otErr << "Invalid checksum - Type 1 Command\n";
340  }
341  }
342  else {
343  int32_t nCMDType = theCMD.fields.type_id;
344  otErr << "Unknown command type: " << nCMDType << "\n";
345  }
346 
347  // I added this for error correction. In the event that there are errors,
348  // just clean out whatever is in the pipe and throw it away.
349  // Should probably send an Error message back, as well.
350  if (bSuccess == false) {
351  int32_t err = 0, nread = 0;
352 
353  for (;;) {
354  if (err > 0) // _WIN32
355  nread += err;
356 
357 #ifdef _WIN32
358  if (0 == err || SOCKET_ERROR == err) // 0 means disconnect. error
359  // means error. >0 means bytes
360  // read.
361 #else
362  if (err <= 0)
363 #endif
364  break;
365  }
366 
367  otErr << "Transmission error--therefore have flushed the pipe, "
368  "discarding " << nread << " bytes.\n";
369  }
370 
371  return bSuccess;
372 }
373 
374 // If this function returns a true, that means theServerReply now contains a
375 // valid message
376 // from the server. (So something should be done with it.)
378  OTMessage& theServerReply) const
379 {
380  // At this point, the checksum has already validated.
381  // Might as well get the PAYLOAD next.
382  int32_t err = 0;
383  uint32_t nread;
384 
385  // Make sure our byte-order is correct here.
386  theCMD.fields.size = ntohl(
387  theCMD.fields.size); // think this is causing problems... maybe not...
388 
389  OTPayload thePayload;
390  thePayload.SetPayloadSize(static_cast<uint32_t>(theCMD.fields.size));
391 
392  for (nread = 0; nread < theCMD.fields.size; nread += err) {
393 
394 #ifdef _WIN32
395  if (0 == err || SOCKET_ERROR == 0) // 0 means disconnect. error means
396  // error. otherwise, err contains
397  // bytes read.
398 #else
399  if (err <= 0)
400 #endif
401  break;
402  }
403 
404  switch (theCMD.fields.command_id) {
405  case TYPE_1_CMD_1:
406  otWarn << "Received TYPE 1 CMD 1, an OTMessage.\n";
407  break;
408  case TYPE_1_CMD_2:
409  otLog3 << "Received TYPE 1 CMD 2, an OTEnvelope containing an "
410  "OTMessage.\n";
411  break;
412  default:
413  break;
414  }
415 
416  if (theCMD.fields.size == 0) {
417  otErr << "(The payload was a 0 size.)\n";
418  return true;
419  }
420  else if (nread < theCMD.fields.size) {
421  otErr << "Number of bytes read (" << nread
422  << ") did NOT match size in header (" << theCMD.fields.size
423  << ").\n";
424  return false;
425  }
426  else {
427  otLog4 << "Loaded a payload, size: " << theCMD.fields.size << "\n";
428  }
429 
430  // a signed OTMessage
431  if (TYPE_1_CMD_1 == theCMD.fields.command_id) {
432  if (thePayload.GetMessagePayload(theServerReply)) {
433  otLog4 << "Successfully retrieved payload message...\n";
434 
435  if (theServerReply.ParseRawFile()) {
436  otLog4 << "Successfully parsed payload message.\n";
437 
438  const OTPseudonym* pServerNym =
439  (nullptr != m_pServerContract)
440  ? m_pServerContract->GetContractPublicNym()
441  : nullptr;
442 
443  if (m_pServerContract && pServerNym) // todo casting.
444  {
445  if (theServerReply.VerifySignature(*pServerNym)) // todo
446  // casting.
447  {
448  otOut << "VERIFIED -- this message was signed "
449  "by the Server.\n";
450  }
451  else {
452  otOut << "Signature verification failed on "
453  "this message, proportedly from the "
454  "Server.\n";
455  return false;
456  }
457  }
458  else {
459  otOut << "No server contract loaded, or could not "
460  "load public key from server contract.\n";
461  return false;
462  }
463 
464  return true;
465  }
466  else {
467  otErr << "Error parsing message.\n";
468  return false;
469  }
470 
471  }
472  else {
473  otErr << "Error retrieving message from payload.\n";
474  return false;
475  }
476 
477  }
478 
479  // A base64-encoded envelope, encrypted, and containing a signed message.
480  else if (TYPE_1_CMD_2 == theCMD.fields.command_id) {
481  OTEnvelope theEnvelope;
482  if (thePayload.GetEnvelope(theEnvelope)) {
483  otWarn << "===> Received encrypted envelope. (Server "
484  "reply.) Decrypting...\n";
485 
486  OTString strEnvelopeContents;
487 
488  // Decrypt the Envelope.
489  if (m_pNym && theEnvelope.Open(*m_pNym, strEnvelopeContents)) {
490  // All decrypted, now let's load the results into an OTMessage.
491  // No need to call theMessage.ParseRawFile() after, since
492  // LoadContractFromString handles it.
493  //
494  if (theServerReply.LoadContractFromString(
495  strEnvelopeContents)) {
496  otLog4 << "Success decrypting the message out of "
497  "the envelope and parsing it.\n";
498 
499  const OTPseudonym* pServerNym =
500  (nullptr != m_pServerContract)
501  ? m_pServerContract->GetContractPublicNym()
502  : nullptr;
503 
504  if (m_pServerContract && pServerNym) // todo casting.
505  {
506  if (theServerReply.VerifySignature(
507  *pServerNym)) // todo casting.
508  {
509  otOut << "VERIFIED -- this message was "
510  "signed by the Server.\n";
511  }
512  else {
513  otOut << "Signature verification failed on "
514  "this message, purportedly from "
515  "the Server.\n";
516  return false;
517  }
518  }
519  else {
520  otErr << "No server contract loaded, or could not "
521  "load public key from server contract.\n";
522  return false;
523  }
524 
525  return true;
526  }
527  else {
528  otErr << "Error loading message from envelope contents.\n";
529  return false;
530  }
531  }
532  else {
533  otErr << "Unable to open envelope.\n";
534  return false;
535  }
536  }
537  else {
538  otErr << "Error retrieving message from payload.\n";
539  return false;
540  }
541  }
542  else {
543  otErr << "Error retrieving message from payload. Unknown type.\n";
544  return false;
545  }
546 }
547 
549 {
550  if (m_pNym && m_pWallet && theMessage.SignContract(*m_pNym) &&
551  theMessage.SaveContract()) {
552  ProcessMessageOut(theMessage);
553  return true;
554  }
555 
556  return false;
557 }
558 
560 {
561  u_header theCMD;
562  OTPayload thePayload;
563 
564  // clear the header
565  memset((void*)theCMD.buf, 0, OT_CMD_HEADER_SIZE);
566 
567  // Here is where we set up the Payload (so we have the size ready before the
568  // header goes out)
569  // This is also where we have turned on the encrypted envelopes }:-)
570  OTEnvelope theEnvelope; // All comms should be encrypted in one of these
571  // envelopes.
572 
573  // Testing encrypted envelopes...
574  const OTPseudonym* pServerNym = nullptr;
575 
576  if (m_pServerContract &&
577  (nullptr != (pServerNym = m_pServerContract->GetContractPublicNym()))) {
578  OTString strEnvelopeContents;
579  // Save the ready-to-go message into a string.
580  theMessage.SaveContractRaw(strEnvelopeContents);
581 
582  // Seal the string up into an encrypted Envelope
583  theEnvelope.Seal(*pServerNym, strEnvelopeContents);
584 
585  // From here on out, theMessage is disposable. OTPayload takes over.
586  // OTMessage doesn't care about checksums and headers.
587  thePayload.SetEnvelope(theEnvelope);
588 
589  // Now that the payload is ready, we'll set up the header.
590  SetupHeader(theCMD, CMD_TYPE_1, TYPE_1_CMD_2, thePayload);
591  }
592  // else, for whatever reason, we just send an UNencrypted message... (This
593  // shouldn't happen anymore...) TODO remove.
594  else {
595  thePayload.SetMessagePayload(theMessage);
596 
597  // Now that the payload is ready, we'll set up the header.
598  SetupHeader(theCMD, CMD_TYPE_1, TYPE_1_CMD_1, thePayload);
599  }
600 
602  OT_ASSERT(nullptr != m_pCallback);
603  OT_ASSERT(nullptr != m_pServerContract);
604 
605  // Call the callback here.
606  otOut << "\n=====>BEGIN Sending " << theMessage.m_strCommand
607  << " message via ZMQ... Request number: "
608  << theMessage.m_strRequestNum << "\n";
609 
610  (*m_pCallback)(*m_pServerContract, theEnvelope);
611 
612  otWarn << "<=====END Finished sending " << theMessage.m_strCommand
613  << " message (and hopefully receiving "
614  "a reply.)\nRequest number: " << theMessage.m_strRequestNum
615  << "\n\n";
616 
617  // At this point, we have sent the envelope to the server.
618 }
619 
620 // This function interprets test input (so should have been in test client?)
621 // then it uses that to send a message to server.
622 // The buf passed in is simply data collected by fgets from stdin.
623 void OTServerConnection::ProcessMessageOut(const char* buf, const int32_t*)
624 {
625 
626  OT_ASSERT(nullptr != buf);
627 
628  bool bSendCommand = false;
629  bool bSendPayload = false;
630 
631  OTMessage theMessage;
632 
633  bool bHandledIt = false;
634 
635  u_header theCMD;
636 
637  // clear the header
638  memset((void*)theCMD.buf, 0, OT_CMD_HEADER_SIZE);
639 
640  // Simple rule here: In each of the below if statements,
641  // YOU MUST set up the header bytes HERE!
642  // OR you must set the boolean bSendCommand TO TRUE!!
643  // It must be one or the other in each block.
644  // If you set to true, code at the bottom will calculate header
645  // for you. If you fail to do this, the header is now uncalculated either
646  // way.
647  // Don't send uncalculated headers to the server unless doing it on purpose
648  // for TESTING.
649 
650  if (buf[0] == '1') {
651  bHandledIt = true;
652 
653  theCMD.fields.type_id = CMD_TYPE_1;
654  theCMD.fields.command_id = TYPE_1_CMD_1;
655  theCMD.fields.size = 0;
656  theCMD.fields.checksum =
657  CalcChecksum(theCMD.buf, OT_CMD_HEADER_SIZE - 1);
658 
659  int32_t nChecksum = theCMD.fields.checksum;
660 
661  otOut << "(User has instructed to send a size " << OT_CMD_HEADER_SIZE
662  << ", TYPE 1 "
663  "COMMAND to the server...)\n CHECKSUM: " << nChecksum << "\n";
664  bSendCommand = true;
665  }
666  else if (buf[0] == '2') {
667  bHandledIt = true;
668 
669  theCMD.fields.type_id = 12;
670  theCMD.fields.command_id = 3;
671  theCMD.fields.size = 98;
672  theCMD.fields.checksum =
673  CalcChecksum(theCMD.buf, OT_CMD_HEADER_SIZE - 1);
674 
675  otOut << "(User has instructed to send a size "
676  << (OT_CMD_HEADER_SIZE + 3) << ", **malformed "
677  "command** to the server...)\n";
678  bSendCommand = true;
679  }
680  // Empty OTMessage including signed XML, but no other commands
681  else if (buf[0] == '3') {
682  otOut << "(User has instructed to create a signed XML message "
683  "and send it to the server...)\n";
684  bHandledIt = true;
685 
686  // Normally you'd update the member variables here, before signing it.
687  // But this is just an empty OTMessage.
688 
689  // When a message is signed, it updates its m_xmlUnsigned contents to
690  // the values in the members variables
691  m_pWallet->SignContractWithFirstNymOnList(theMessage);
692 
693  // SaveContract takes m_xmlUnsigned and wraps it with the signatures and
694  // ------- BEGIN bookends
695  // If you don't pass a string in, then SaveContract saves the new
696  // version to its member, m_strRawFile
697  theMessage.SaveContract();
698 
699  bSendCommand = true;
700  bSendPayload = true;
701  }
702 
703  // Above are various test messages.
704 
705  // This section for commands that involve building full XML messages,
706  // that is, most of the real implementation of the transaction protocol.
707 
708  // If we can match the user's request to a client command,
709  // AND theClient object is able to process that request into
710  // a payload, THEN we create the header and send it all down the pipe.
711 
712  if (!bHandledIt && m_pNym && m_pServerContract) {
713  // check server ID command
714  if (buf[0] == 'c') {
715  otOut << "(User has instructed to send a checkServerID "
716  "command to the server...)\n";
717 
718  // if successful setting up the command payload...
719 
721  theMessage, *m_pNym,
722  *m_pServerContract, nullptr) >
723  0) // nullptr pAccount on this command.
724  {
725  bSendCommand = true;
726  bSendPayload = true;
727  }
728  else
729  otErr << "Error processing checkServerID command in "
730  "ProcessMessage: " << buf[0] << "\n";
731  }
732 
733  // register new user account
734  else if (buf[0] == 'r') {
735  otOut << "(User has instructed to send a createUserAccount "
736  "command to the server...)\n";
737 
738  // if successful setting up the command payload...
739 
741  theMessage, *m_pNym,
742  *m_pServerContract, nullptr) >
743  0) // nullptr pAccount on this command.
744  {
745  bSendCommand = true;
746  bSendPayload = true;
747  }
748  else
749  otErr << "Error processing createUserAccount command in "
750  "ProcessMessage: " << buf[0] << "\n";
751  }
752 
753  // ALL MESSAGES BELOW THIS POINT SHOULD ATTACH A REQUEST NUMBER IF THEY
754  // EXPECT THE SERVER TO PROCESS THEM.
755  // (Handled inside ProcessUserCommand)
756 
757  // checkUser
758  else if (buf[0] == 'u') {
759  otOut << "(User has instructed to send a checkUser command "
760  "to the server...)\n";
761 
762  // if successful setting up the command payload...
763 
764  if (m_pClient->ProcessUserCommand(OTClient::checkUser, theMessage,
765  *m_pNym, *m_pServerContract,
766  nullptr)) // nullptr pAccount on
767  // this command.
768  {
769  bSendCommand = true;
770  bSendPayload = true;
771  }
772  else
773  otErr << "Error processing checkUser command in "
774  "ProcessMessage: " << buf[0] << "\n";
775  }
776 
777  // register new asset account
778  else if (buf[0] == 'a') {
779  otOut << "(User has instructed to send a createAccount "
780  "command to the server...)\n";
781 
782  // if successful setting up the command payload...
783 
784  if (m_pClient->ProcessUserCommand(
785  OTClient::createAccount, theMessage, *m_pNym,
786  *m_pServerContract,
787  nullptr)) // nullptr pAccount on this command.
788  {
789  bSendCommand = true;
790  bSendPayload = true;
791  }
792  else
793  otErr << "Error processing createAccount command in "
794  "ProcessMessage: " << buf[0] << "\n";
795  }
796 
797  // issue a new asset type
798  else if (!strcmp(buf, "issue\n")) {
799  otOut << "(User has instructed to send an issueAssetType "
800  "command to the server...)\n";
801 
802  // if successful setting up the command payload...
803 
805  theMessage, *m_pNym,
806  *m_pServerContract, nullptr) >
807  0) // nullptr pAccount on this command.
808  {
809  bSendCommand = true;
810  bSendPayload = true;
811  }
812  else
813  otErr << "Error processing issueAssetType command in "
814  "ProcessMessage: " << buf[0] << "\n";
815  }
816 
817  // issue a new basket asset type
818  else if (!strcmp(buf, "basket\n")) {
819  otOut << "(User has instructed to send an issueBasket "
820  "command to the server...)\n";
821 
822  // if successful setting up the command payload...
823 
824  if (m_pClient->ProcessUserCommand(OTClient::issueBasket, theMessage,
825  *m_pNym, *m_pServerContract,
826  nullptr) >
827  0) // nullptr pAccount on this command.
828  {
829  bSendCommand = true;
830  bSendPayload = true;
831  }
832  else
833  otErr << "Error processing issueBasket command in "
834  "ProcessMessage: " << buf[0] << "\n";
835  }
836 
837  // exchange in/out of a basket currency
838  else if (!strcmp(buf, "exchange\n")) {
839  otOut << "(User has instructed to send an exchangeBasket "
840  "command to the server...)\n";
841 
842  // if successful setting up the command payload...
843 
845  theMessage, *m_pNym,
846  *m_pServerContract, nullptr) >
847  0) // nullptr pAccount on this command.
848  {
849  bSendCommand = true;
850  bSendPayload = true;
851  }
852  else
853  otErr << "Error processing exchangeBasket command in "
854  "ProcessMessage: " << buf[0] << "\n";
855  }
856 
857  // make an offer and put it onto a market.
858  else if (!strcmp(buf, "offer\n")) {
859  otOut << "(User has instructed to send a marketOffer "
860  "command to the server...)\n";
861 
862  // if successful setting up the command payload...
863 
864  if (m_pClient->ProcessUserCommand(OTClient::marketOffer, theMessage,
865  *m_pNym, *m_pServerContract,
866  nullptr) >
867  0) // nullptr pAccount on this command.
868  {
869  bSendCommand = true;
870  bSendPayload = true;
871  }
872  else
873  otErr << "Error processing marketOffer command in "
874  "ProcessMessage: " << buf[0] << "\n";
875  }
876 
877  // set asset contract's name
878  else if (!strcmp(buf, "setassetname\n")) {
879  otOut << "(User has instructed to set an Asset Contract's "
880  "client-side name...)\n";
881 
882  // if successful setting up the command payload...
883 
884  if (m_pClient->ProcessUserCommand(
885  OTClient::setAssetName, theMessage, *m_pNym,
886  *m_pServerContract,
887  nullptr)) // nullptr pAccount on this command.
888  {
889  // bSendCommand = true; // No message sent.
890  // bSendPayload = true;
891  }
892  }
893 
894  // set server contract's name
895  else if (!strcmp(buf, "setservername\n")) {
896  otOut << "(User has instructed to set a Server Contract's "
897  "client-side name...)\n";
898 
899  // if successful setting up the command payload...
900 
902  theMessage, *m_pNym,
903  *m_pServerContract, nullptr) >
904  0) // nullptr pAccount on this command.
905  {
906  // bSendCommand = true; // No message sent.
907  // bSendPayload = true;
908  }
909  }
910 
911  // set nym name
912  else if (!strcmp(buf, "setnymname\n")) {
913  otOut
914  << "(User has instructed to set a Nym's client-side name...)\n";
915 
916  // if successful setting up the command payload...
917 
918  if (m_pClient->ProcessUserCommand(OTClient::setNymName, theMessage,
919  *m_pNym, *m_pServerContract,
920  nullptr) >
921  0) // nullptr pAccount on this command.
922  {
923  // bSendCommand = true; // No message sent.
924  // bSendPayload = true;
925  }
926  }
927 
928  // set account name
929  else if (!strcmp(buf, "setaccountname\n")) {
930  otOut << "(User wants to set an Asset Account's client-side "
931  "name...)\n";
932 
933  // if successful setting up the command payload...
934 
936  theMessage, *m_pNym,
937  *m_pServerContract, nullptr) >
938  0) // nullptr pAccount on this command.
939  {
940  // bSendCommand = true; // No message sent.
941  // bSendPayload = true;
942  }
943  }
944 
945  // sendUserMessage
946  else if (buf[0] == 's') {
947  otOut << "(User has instructed to send a sendUserMessage "
948  "command to the server...)\n";
949 
950  // if successful setting up the command payload...
951 
953  theMessage, *m_pNym,
954  *m_pServerContract, nullptr) >
955  0) // nullptr pAccount on this command.
956  {
957  bSendCommand = true;
958  bSendPayload = true;
959  }
960  else
961  otErr << "Error processing sendUserMessage command in "
962  "ProcessMessage: " << buf[0] << "\n";
963  }
964 
965  // get nymbox
966  else if (buf[0] == 'y') {
967  otOut << "(User has instructed to send a getNymbox command "
968  "to the server...)\n";
969 
970  // if successful setting up the command payload...
971 
972  if (m_pClient->ProcessUserCommand(OTClient::getNymbox, theMessage,
973  *m_pNym, *m_pServerContract,
974  nullptr) >
975  0) // nullptr pAccount on this command.
976  {
977  bSendCommand = true;
978  bSendPayload = true;
979  }
980  else
981  otErr << "Error processing getNymbox command in "
982  "ProcessMessage: " << buf[0] << "\n";
983  }
984 
985  // get inbox
986  else if (buf[0] == 'i') {
987  otOut << "(User has instructed to send a getInbox command "
988  "to the server...)\n";
989 
990  // if successful setting up the command payload...
991 
992  if (m_pClient->ProcessUserCommand(
993  OTClient::getInbox, theMessage, *m_pNym, *m_pServerContract,
994  nullptr) > 0) // nullptr pAccount on this command.
995  {
996  bSendCommand = true;
997  bSendPayload = true;
998  }
999  else
1000  otErr << "Error processing getInbox command in ProcessMessage: "
1001  << buf[0] << "\n";
1002  }
1003 
1004  // get outbox
1005  else if (buf[0] == 'o') {
1006  otOut << "(User has instructed to send a getOutbox command "
1007  "to the server...)\n";
1008 
1009  // if successful setting up the command payload...
1010 
1011  if (m_pClient->ProcessUserCommand(OTClient::getOutbox, theMessage,
1012  *m_pNym, *m_pServerContract,
1013  nullptr) >
1014  0) // nullptr pAccount on this command.
1015  {
1016  bSendCommand = true;
1017  bSendPayload = true;
1018  }
1019  else
1020  otErr << "Error processing getOutbox command in "
1021  "ProcessMessage: " << buf[0] << "\n";
1022  }
1023 
1024  // deposit cheque
1025  else if (buf[0] == 'q') {
1026  otOut << "User has instructed to deposit a cheque...\n";
1027 
1028  // if successful setting up the command payload...
1029 
1031  theMessage, *m_pNym,
1032  *m_pServerContract, nullptr) >
1033  0) // nullptr pAccount on this command.
1034  {
1035  bSendCommand = true;
1036  bSendPayload = true;
1037  }
1038  else
1039  otErr << "Error processing deposit cheque command in "
1040  "ProcessMessage: " << buf[0] << "\n";
1041  }
1042 
1043  // withdraw voucher
1044  else if (buf[0] == 'v') {
1045  otOut << "User has instructed to withdraw a voucher (like "
1046  "a cashier's cheque)...\n";
1047 
1048  // if successful setting up the command payload...
1049 
1051  theMessage, *m_pNym,
1052  *m_pServerContract, nullptr) >
1053  0) // nullptr pAccount on this command.
1054  {
1055  bSendCommand = true;
1056  bSendPayload = true;
1057  }
1058  else
1059  otErr << "Error processing withdraw voucher command in "
1060  "ProcessMessage: " << buf[0] << "\n";
1061  }
1062 
1063  // withdraw cash
1064  else if (buf[0] == 'w') {
1065  otOut << "(User has instructed to withdraw cash...)\n";
1066 
1067  // if successful setting up the command payload...
1068 
1070  theMessage, *m_pNym,
1071  *m_pServerContract, nullptr) >
1072  0) // nullptr pAccount on this command.
1073  {
1074  bSendCommand = true;
1075  bSendPayload = true;
1076  }
1077  else
1078  otErr << "Error processing withdraw command in ProcessMessage: "
1079  << buf[0] << "\n";
1080  }
1081 
1082  // deposit tokens
1083  else if (buf[0] == 'd') {
1084  otOut << "(User has instructed to deposit cash tokens...)\n";
1085 
1086  // if successful setting up the command payload...
1087 
1089  theMessage, *m_pNym,
1090  *m_pServerContract, nullptr) >
1091  0) // nullptr pAccount on this command.
1092  {
1093  bSendCommand = true;
1094  bSendPayload = true;
1095  }
1096  else
1097  otErr << "Error processing deposit command in ProcessMessage: "
1098  << buf[0] << "\n";
1099  }
1100 
1101  // activate payment plan
1102  else if (!strcmp(buf, "plan\n")) {
1103  otOut << "User has instructed to activate a payment plan...\n";
1104 
1105  // if successful setting up the command payload...
1106 
1107  if (m_pClient->ProcessUserCommand(OTClient::paymentPlan, theMessage,
1108  *m_pNym, *m_pServerContract,
1109  nullptr) >
1110  0) // nullptr pAccount on this command.
1111  {
1112  bSendCommand = true;
1113  bSendPayload = true;
1114  }
1115  else
1116  otErr << "Error processing payment plan command in "
1117  "ProcessMessage: " << buf[0] << "\n";
1118  }
1119 
1120  // deposit purse
1121  else if (buf[0] == 'p') {
1122  otOut << "(User has instructed to deposit a purse "
1123  "containing cash...)\n";
1124 
1125  // if successful setting up the command payload...
1126 
1128  theMessage, *m_pNym,
1129  *m_pServerContract, nullptr) >
1130  0) // nullptr pAccount on this command.
1131  {
1132  bSendCommand = true;
1133  bSendPayload = true;
1134  }
1135  else
1136  otErr << "Error processing deposit command in ProcessMessage: "
1137  << buf[0] << "\n";
1138  }
1139 
1140  // get account
1141  else if (!strcmp(buf, "test\n")) {
1142  otOut << "(User has instructed to perform a test...)\n";
1143 
1144  // if successful setting up the command payload...
1145 
1146  if (m_pNym) {
1147  OTString strMessage(
1148  "Well well well, this is just a little bit of "
1149  "plaintext.\nNotice there are NO NEWLINES at the start.\n"
1150  "I'm just trying to make it as long as i can, so that\nI "
1151  "can test the envelope and armor functionality.\n");
1152 
1153  otOut << "MESSAGE:\n------>" << strMessage << "<--------\n";
1154 
1155  OTASCIIArmor ascMessage(strMessage);
1156 
1157  otOut << "ASCII ARMOR:\n------>" << ascMessage << "<--------\n";
1158 
1159  OTEnvelope theEnvelope;
1160  theEnvelope.Seal(*m_pNym, strMessage);
1161 
1162  ascMessage.Release();
1163 
1164  theEnvelope.GetAsciiArmoredData(ascMessage);
1165 
1166  otOut << "ENCRYPTED PLAIN TEXT AND THEN ASCII "
1167  "ARMOR:\n------>" << ascMessage << "<--------\n";
1168 
1169  strMessage.Release();
1170 
1171  OTEnvelope the2Envelope(ascMessage);
1172  the2Envelope.Open(*m_pNym, strMessage);
1173 
1174  otOut << "DECRYPTED PLAIN TEXT:\n------>" << strMessage
1175  << "<--------\n";
1176 
1177  OTEnvelope the3Envelope;
1178  the3Envelope.Seal(*m_pNym, strMessage.Get());
1179 
1180  ascMessage.Release();
1181 
1182  the3Envelope.GetAsciiArmoredData(ascMessage);
1183 
1184  otOut << "RE-ENCRYPTED PLAIN TEXT AND THEN ASCII "
1185  "ARMOR:\n------>" << ascMessage << "<--------\n";
1186 
1187  strMessage.Release();
1188 
1189  OTEnvelope the4Envelope(ascMessage);
1190  the4Envelope.Open(*m_pNym, strMessage);
1191 
1192  otOut << "RE-DECRYPTED PLAIN TEXT:\n------>" << strMessage
1193  << "<--------\n";
1194 
1195  OTEnvelope the5Envelope;
1196  the5Envelope.Seal(*m_pNym, strMessage.Get());
1197 
1198  ascMessage.Release();
1199 
1200  the3Envelope.GetAsciiArmoredData(ascMessage);
1201 
1202  otOut << "RE-RE-ENCRYPTED PLAIN TEXT AND THEN ASCII "
1203  "ARMOR:\n------>" << ascMessage << "<--------\n";
1204 
1205  strMessage.Release();
1206 
1207  OTEnvelope the6Envelope(ascMessage);
1208  the6Envelope.Open(*m_pNym, strMessage);
1209 
1210  otOut << "RE-RE-DECRYPTED PLAIN TEXT:\n------>" << strMessage
1211  << "<--------\n";
1212  }
1213 
1214  }
1215 
1216  // get account
1217  else if (!strcmp(buf, "get\n")) {
1218  otOut << "(User has instructed to send a getAccount "
1219  "command to the server...)\n";
1220 
1221  // if successful setting up the command payload...
1222 
1223  if (m_pClient->ProcessUserCommand(OTClient::getAccount, theMessage,
1224  *m_pNym, *m_pServerContract,
1225  nullptr) >
1226  0) // nullptr pAccount on this command.
1227  {
1228  bSendCommand = true;
1229  bSendPayload = true;
1230  }
1231  else
1232  otErr << "Error processing getAccount command in "
1233  "ProcessMessage: " << buf[0] << "\n";
1234  }
1235 
1236  // get contract
1237  else if (!strcmp(buf, "getcontract\n")) {
1238  otOut << "(User has instructed to send a getContract "
1239  "command to the server...)\n";
1240 
1241  // if successful setting up the command payload...
1242 
1243  if (m_pClient->ProcessUserCommand(OTClient::getContract, theMessage,
1244  *m_pNym, *m_pServerContract,
1245  nullptr) >
1246  0) // nullptr pAccount on this command.
1247  {
1248  bSendCommand = true;
1249  bSendPayload = true;
1250  }
1251  else
1252  otErr << "Error processing getContract command in "
1253  "ProcessMessage: " << buf[0] << "\n";
1254  }
1255 
1256  // sign contract
1257  else if (!strcmp(buf, "signcontract\n")) {
1258  otOut << "Is the contract a server contract, or an asset "
1259  "contract [s/a]: ";
1260  OTString strContractType;
1261  strContractType.OTfgets(std::cin);
1262 
1263  char cContractType = 's';
1264  bool bIsAssetContract = strContractType.At(0, cContractType);
1265 
1266  if (bIsAssetContract) {
1267  if ('S' == cContractType || 's' == cContractType)
1268  bIsAssetContract = false;
1269  }
1270  otOut << "Is the contract properly escaped already? (If "
1271  "escaped, all lines beginning with ----- will "
1272  "instead appear as - ----- ) [y\n]: ";
1273  // User input.
1274  // I need a from account, Yes even in a deposit, it's still the
1275  // "From" account.
1276  // The "To" account is only used for a transfer. (And perhaps for a
1277  // 2-way trade.)
1278  OTString strEscape;
1279  strEscape.OTfgets(std::cin);
1280 
1281  char cEscape = 'n';
1282  bool bEscaped = strEscape.At(0, cEscape);
1283 
1284  if (bEscaped) {
1285  if ('N' == cEscape || 'n' == cEscape) bEscaped = false;
1286  }
1287 
1288  otOut << "Please enter an unsigned asset contract; "
1289  "terminate with ~ on a new line:\n> ";
1290  OTString strContract;
1291  char decode_buffer[200]; // Safe since we only read
1292  // sizeof(decode_buffer)-1
1293 
1294  do {
1295  decode_buffer[0] = 0; // Make it fresh.
1296 
1297  if ((nullptr !=
1298  fgets(decode_buffer, sizeof(decode_buffer) - 1, stdin)) &&
1299  (decode_buffer[0] != '~')) {
1300  if (!bEscaped && decode_buffer[0] == '-') {
1301  strContract.Concatenate("- ");
1302  }
1303  strContract.Concatenate("%s", decode_buffer);
1304  otOut << "> ";
1305  }
1306  else {
1307  break;
1308  }
1309 
1310  } while (decode_buffer[0] != '~');
1311 
1312  OTServerContract theServerContract;
1313  OTAssetContract theAssetContract;
1314 
1315  OTContract* pContract =
1316  bIsAssetContract
1317  ? dynamic_cast<OTContract*>(&theAssetContract)
1318  : dynamic_cast<OTContract*>(&theServerContract);
1319 
1320  pContract->CreateContract(strContract, *m_pNym);
1321 
1322  // re-using strContract here for output this time.
1323  strContract.Release();
1324  pContract->SaveContractRaw(strContract);
1325 
1326  otOut << ".\n..\n...\n....\n.....\n......\n.......\n........\n....."
1327  "....\n\nNEW CONTRACT:\n\n" << strContract << "\n";
1328  }
1329 
1330  // get mint
1331  else if (!strcmp(buf, "getmint\n")) {
1332  otOut << "(User has instructed to send a getMint command "
1333  "to the server...)\n";
1334 
1335  // if successful setting up the command payload...
1336 
1337  if (m_pClient->ProcessUserCommand(
1338  OTClient::getMint, theMessage, *m_pNym, *m_pServerContract,
1339  nullptr) > 0) // nullptr pAccount on this command.
1340  {
1341  bSendCommand = true;
1342  bSendPayload = true;
1343  }
1344  else
1345  otErr << "Error processing getMint command in ProcessMessage: "
1346  << buf[0] << "\n";
1347  }
1348 
1349  // notarize transfer
1350  else if (buf[0] == 't') {
1351  otOut << "(User has instructed to send a Transfer command "
1352  "(Notarize Transactions) to the server...)\n";
1353 
1354  // if successful setting up the command payload...
1355 
1357  theMessage, *m_pNym,
1358  *m_pServerContract, nullptr) >
1359  0) // nullptr pAccount on this command.
1360  {
1361  bSendCommand = true;
1362  bSendPayload = true;
1363  }
1364  else
1365  otErr << "Error processing notarizeTransactions command "
1366  "in ProcessMessage: " << buf[0] << "\n";
1367  }
1368 
1369  // getRequest
1370  else if (buf[0] == 'g') {
1371  otOut << "(User has instructed to send a getRequest "
1372  "command to the server...)\n";
1373 
1374  // if successful setting up the command payload...
1375 
1376  if (m_pClient->ProcessUserCommand(OTClient::getRequest, theMessage,
1377  *m_pNym, *m_pServerContract,
1378  nullptr) >
1379  0) // nullptr pAccount on this command.
1380  {
1381  bSendCommand = true;
1382  bSendPayload = true;
1383  }
1384  else
1385  otErr << "Error processing getRequest command in "
1386  "ProcessMessage: " << buf[0] << "\n";
1387  }
1388 
1389  // getTransactionNum
1390  else if (buf[0] == 'n') {
1391  // I just coded (here) for myself a secret option (for testing)...
1392  // Optionally instead of JUST 'n', I can put n <number>, (without
1393  // brackets) and
1394  // this code will add that number to my list of issued and
1395  // transaction numbers.
1396  // I already have the ability to clear the list, so now I can add
1397  // numbers to it as well.
1398  // (Which adds to both lists.)
1399  // I can also remove a number from the transaction list but LEAVE it
1400  // on the issued list,
1401  // for example by writing a cheque and throwing it away.
1402  //
1403  // This code is for testing and allows me to find and patch any
1404  // problems without
1405  // having to re-create my data each time -- speeds up debugging.
1406  //
1407  int64_t lTransactionNumber =
1408  ((strlen(buf) > 2) ? atol(&(buf[2])) : 0);
1409 
1410  if (lTransactionNumber > 0) {
1411  OTString strServerID;
1412  m_pServerContract->GetIdentifier(strServerID);
1413 
1414  m_pNym->AddTransactionNum(*m_pNym, strServerID,
1415  lTransactionNumber,
1416  true); // bool bSave=true
1417 
1418  otOut << "Transaction number " << lTransactionNumber
1419  << " added to both lists "
1420  "(on client side.)\n";
1421  }
1422  else {
1423  otOut << "(User has instructed to send a "
1424  "getTransactionNum command to the "
1425  "server...)\n";
1426 
1427  // if successful setting up the command payload...
1428 
1430  theMessage, *m_pNym,
1431  *m_pServerContract, nullptr) >
1432  0) // nullptr pAccount on this command.
1433  {
1434  bSendCommand = true;
1435  bSendPayload = true;
1436  }
1437  else
1438  otErr << "Error processing getTransactionNum command "
1439  "in ProcessMessage: " << buf[0] << "\n";
1440  }
1441 
1442  }
1443  else {
1444  if (allow_debug) {
1445  otOut << "\n";
1446  }
1447  return;
1448  }
1449  }
1450  else if (!bHandledIt) {
1451  otOut << "\n";
1452  }
1453 
1454  if (bSendCommand && bSendPayload) {
1455  // Voila -- it's sent. (If there was a payload involved.)
1456  ProcessMessageOut(theMessage);
1457  } // Otherwise... if it's a "header only" ...
1458 }
1459 
1460 } // namespace opentxs
OTLOG_IMPORT OTLogStream otLog4
bool SetFocus(OTPseudonym &theNym, OTServerContract &theServerContract, TransportCallback *pCallback)
BYTE buf[OT_CMD_HEADER_SIZE]
Definition: stdafx.hpp:26
virtual EXPORT bool SignContract(const OTPseudonym &theNym, const OTPasswordData *pPWData=nullptr)
Definition: OTMessage.cpp:3873
virtual EXPORT bool VerifySignature(const OTPseudonym &theNym, const OTPasswordData *pPWData=nullptr) const
Definition: OTMessage.cpp:3898
uint32_t size
Definition: stdafx.hpp:32
EXPORT bool GetEnvelope(OTEnvelope &theEnvelope) const
Definition: OTPayload.cpp:232
EXPORT bool SaveContract()
EXPORT bool ParseRawFile()
EXPORT OT_BYTE CalcChecksum(OT_BYTE *buffer, uint32_t size)
EXPORT bool SetMessagePayload(const OTMessage &theMessage)
Definition: OTPayload.cpp:215
struct u_header::@0 fields
virtual EXPORT bool CreateContract(const OTString &strContract, const OTPseudonym &theSigner)
EXPORT void OTfgets(std::istream &ofs)
Definition: OTString.cpp:1159
#define OT_CMD_HEADER_SIZE
Definition: stdafx.hpp:19
OTLOG_IMPORT OTLogStream otOut
OTLOG_IMPORT OTLogStream otLog3
EXPORT bool SaveContractRaw(OTString &strOutput) const
EXPORT int32_t ProcessUserCommand(OT_CLIENT_CMD_TYPE requestedCommand, OTMessage &theMessage, OTPseudonym &theNym, const OTServerContract &theServer, const OTAccount *pAccount=nullptr, int64_t lTransactionAmount=0, OTAssetContract *pMyAssetContract=nullptr, const OTIdentifier *pHisNymID=nullptr, const OTIdentifier *pHisAcctID=nullptr)
Definition: OTClient.cpp:8905
int32_t allow_debug
EXPORT bool Open(const OTPseudonym &theRecipient, OTString &theOutput, const OTPasswordData *pPWData=nullptr)
Definition: OTEnvelope.cpp:581
bool SignAndSend(OTMessage &theMessage) const
uint8_t BYTE
Definition: stdafx.hpp:21
EXPORT void Concatenate(const char *arg,...)
Definition: OTString.cpp:1334
EXPORT bool Seal(const OTPseudonym &theRecipient, const OTString &theInput)
Definition: OTEnvelope.cpp:521
bool ProcessType1Cmd(u_header &theCMD, OTMessage &theServerReply) const
EXPORT bool SignContractWithFirstNymOnList(OTContract &theContract)
Definition: OTWallet.cpp:252
BYTE command_id
Definition: stdafx.hpp:30
void SetupHeader(u_header &theCMD, int32_t nTypeID, int32_t nCmdID, OTPayload &thePayload)
EXPORT const OTPseudonym * GetContractPublicNym() const
Definition: OTContract.cpp:413
EXPORT bool AddTransactionNum(OTPseudonym &SIGNER_NYM, const OTString &strServerID, int64_t lTransNum, bool bSave)
#define TYPE_1_CMD_2
Definition: stdafx.hpp:13
BYTE type_id
Definition: stdafx.hpp:29
EXPORT bool GetAsciiArmoredData(OTASCIIArmor &theArmoredText, bool bLineBreaks=true) const
Definition: OTEnvelope.cpp:162
#define CMD_TYPE_1
Definition: stdafx.hpp:17
void ProcessMessageOut(const char *buf, const int32_t *pnExpectReply)
EXPORT OT_BOOL IsChecksumValid(OT_BYTE *buffer, uint32_t size)
#define OT_ASSERT(x)
Definition: Assert.hpp:150
EXPORT void SetPayloadSize(uint32_t lNewSize)
Definition: OTPayload.cpp:313
EXPORT bool GetMessagePayload(OTMessage &theMessage) const
Definition: OTPayload.cpp:280
virtual EXPORT void GetIdentifier(OTIdentifier &theIdentifier) const
Definition: OTContract.cpp:317
#define OT_FAIL
Definition: Assert.hpp:139
EXPORT bool At(uint32_t index, char &c) const
Definition: OTString.cpp:1025
bool GetServerID(OTIdentifier &theID) const
OTLOG_IMPORT OTLogStream otWarn
#define TYPE_1_CMD_1
Definition: stdafx.hpp:12
OTLOG_IMPORT OTLogStream otErr
void OnServerResponseToGetRequestNumber(int64_t lNewRequestNumber) const
EXPORT void OnUpdateRequestNum(OTPseudonym &SIGNER_NYM, const OTString &strServerID, int64_t lNewRequestNumber)
OTString m_strRequestNum
Definition: OTMessage.hpp:207
OTString m_strCommand
Definition: OTMessage.hpp:189
EXPORT bool LoadContractFromString(const OTString &theStr)
EXPORT bool SetEnvelope(const OTEnvelope &theEnvelope)
Definition: OTPayload.cpp:194
OTServerConnection(OTWallet &theWallet, OTClient &theClient)
virtual EXPORT void Release()
Definition: OTString.cpp:765
uint32_t GetSize() const
Definition: OTData.hpp:174
bool ProcessReply(u_header &theCMD, OTMessage &theServerReply)
OTLOG_IMPORT OTLogStream otLog5
BYTE checksum
Definition: stdafx.hpp:33