EvEmu  0.8.4
11 September 2021
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
PyPacket.cpp
Go to the documentation of this file.
1 /*
2  ------------------------------------------------------------------------------------
3  LICENSE:
4  ------------------------------------------------------------------------------------
5  This file is part of EVEmu: EVE Online Server Emulator
6  Copyright 2006 - 2021 The EVEmu Team
7  For the latest information visit https://evemu.dev
8  ------------------------------------------------------------------------------------
9  This program is free software; you can redistribute it and/or modify it under
10  the terms of the GNU Lesser General Public License as published by the Free Software
11  Foundation; either version 2 of the License, or (at your option) any later
12  version.
13 
14  This program is distributed in the hope that it will be useful, but WITHOUT
15  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
17 
18  You should have received a copy of the GNU Lesser General Public License along with
19  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
20  Place - Suite 330, Boston, MA 02111-1307, USA, or go to
21  http://www.gnu.org/copyleft/lesser.txt.
22  ------------------------------------------------------------------------------------
23  Author: Zhur
24  Rewrite: Allan
25 */
26 
29 #include "eve-common.h"
30 
31 #include "python/PyPacket.h"
32 #include "python/PyVisitor.h"
33 #include "python/PyRep.h"
34 #include "python/PyDumpVisitor.h"
35 
37 {
38  "AUTHENTICATION_REQ",
39  "AUTHENTICATION_RSP",
40  "IDENTIFICATION_REQ",
41  "IDENTIFICATION_RSP",
42  "U4",
43  "U5",
44  "CALL_REQ",
45  "CALL_RSP",
46  "TRANSPORTCLOSED",
47  "U9",
48  "RESOLVE_REQ",
49  "RESOLVE_RSP",
50  "NOTIFICATION",
51  "U13",
52  "U14",
53  "ERRORRESPONSE",
54  "SESSIONCHANGENOTIFICATION",
55  "U17",
56  "SESSIONINITIALSTATENOTIFICATION",
57  "U19",
58  "PING_REQ",
59  "PING_RSP"
60 };
61 
63 : type_string("none"),
65 userid(0),
66 payload(nullptr),
67 named_payload(nullptr),
68 contextKey(nullptr)
69 {
70 
71 }
72 
74 {
77 }
78 
80 {
81  PyPacket *res = new PyPacket();
82  res->type_string = type_string;
83  res->type = type;
84  res->source = source;
85  res->dest = dest;
86  res->userid = userid;
87  res->payload = payload->Clone()->AsTuple();
88  if (named_payload == nullptr)
89  res->named_payload = nullptr;
90  else
92  return res;
93 }
94 
95 void PyPacket::Dump(LogType ltype, PyVisitor& dumper)
96 {
97  _log(ltype, "Packet:");
98  _log(ltype, " Type: %s", type_string.c_str());
99  _log(ltype, " Command: %s (%d)", MACHONETMSG_TYPE_NAMES[type], type);
100  _log(ltype, " Source:");
101  source.Dump(ltype, " ");
102  _log(ltype, " Dest:");
103  dest.Dump(ltype, " ");
104  _log(ltype, " User ID: %u", userid);
105  _log(ltype, " Payload:");
106  payload->visit( dumper );
107  if (named_payload == nullptr) {
108  _log(ltype, " Named Payload: None (null)");
109  } else {
110  _log(ltype, " Named Payload:");
111  named_payload->visit( dumper );
112  }
113 }
114 
115 bool PyPacket::Decode(PyRep **in_packet)
116 {
117  PyRep *packet = *in_packet; //assign
118  *in_packet = nullptr; //consume
119 
122  payload = nullptr;
123  named_payload = nullptr;
124 
125  if (packet == nullptr) {
126  codelog(NET__PACKET_ERROR, "PyPacket::Decode() - packet is null.");
127  return false;
128  }
129 
130  if (packet->IsChecksumedStream()) {
131  //TODO: check cs->checksum
132  packet = packet->AsChecksumedStream()->stream();
133  }
134  //Dragon nuance... it gets wrapped again
135  if (packet->IsSubStream()) {
136  PySubStream* ss = packet->AsSubStream();
137  ss->DecodeData();
138  if (ss->decoded() == nullptr) {
139  codelog(NET__PACKET_ERROR, "PyPacket::Decode() - unable to decode initial packet substream.");
140  PyDecRef(packet);
141  return false;
142  }
143 
144  packet = ss->decoded();
145  }
146 
147  if (!packet->IsObject()) {
148  codelog(NET__PACKET_ERROR, "PyPacket::Decode() - packet body is not PyObject: %s", packet->TypeString());
149  PyDecRef(packet);
150  return false;
151  }
152 
153  type_string = packet->AsObject()->type()->content();
154  if (!packet->AsObject()->arguments()->IsTuple()) {
155  codelog(NET__PACKET_ERROR, "PyPacket::Decode() - packet body does not contain a tuple");
156  return false;
157  }
158 
159  PyTuple *tuple = packet->AsObject()->arguments()->AsTuple();
160  if (tuple == nullptr) {
161  codelog(NET__PACKET_ERROR, "PyPacket::Decode() - tuple is null.");
162  return false;
163  }
164 
165  if (tuple->items.size() != 7) {
166  codelog(NET__PACKET_ERROR, "PyPacket::Decode() - packet body does not contain a tuple of length 7 (is %u)", tuple->items.size());
167  PyDecRef(packet);
168  return false;
169  }
170 
171  if (!tuple->items[0]->IsInt()) {
172  codelog(NET__PACKET_ERROR, "PyPacket::Decode() - First main tuple element is not an integer");
173  PyDecRef(packet);
174  return false;
175  }
176 
177  switch(PyRep::IntegerValue(tuple->items[0])) {
178  case AUTHENTICATION_REQ:
179  case AUTHENTICATION_RSP:
180  case IDENTIFICATION_REQ:
181  case IDENTIFICATION_RSP:
182  case CALL_REQ:
183  case CALL_RSP:
184  case TRANSPORTCLOSED:
185  case RESOLVE_REQ:
186  case RESOLVE_RSP:
187  case NOTIFICATION:
188  case ERRORRESPONSE:
191  case PING_REQ:
192  case PING_RSP: {
194  } break;
195  default: {
196  codelog(NET__PACKET_ERROR, "PyPacket::Decode() - Unknown message type %i", PyRep::IntegerValue(tuple->items[0]));
197  PyDecRef(packet);
198  return false;
199  } break;
200  }
201 
202  //source address
203  if (!source.Decode(tuple->items[1])) {
204  //error printed in decoder
205  PyDecRef(packet);
206  return false;
207  }
208  //dest address
209  if (!dest.Decode(tuple->items[2])) {
210  //error printed in decoder
211  PyDecRef(packet);
212  return false;
213  }
214 
215  userid = PyRep::IntegerValue(tuple->items[3]);
216 
217  //payload
218  if (!tuple->items[4]->IsTuple()) {
219  codelog(NET__PACKET_ERROR, "PyPacket::Decode() - Fifth main tuple element is not a tuple");
220  PyDecRef(packet);
221  return false;
222  }
223  payload = tuple->items[4]->AsTuple();
224 
225  //options dict
226  if (tuple->items[5]->IsNone()) {
227  named_payload = nullptr;
228  } else if (tuple->items[5]->IsDict()) {
229  named_payload = tuple->items[5]->AsDict();
230  } else {
231  codelog(NET__PACKET_ERROR, "PyPacket::Decode() - Sixth main tuple element is neither dict or none.");
232  PyDecRef(packet);
233  return false;
234  }
235 
236  PyDecRef(packet);
237  return true;
238 }
239 
241  PyTuple *arg_tuple = new PyTuple(7);
242  //command
243  arg_tuple->items[0] = new PyInt(type);
244  //source
245  arg_tuple->items[1] = source.Encode();
246  //dest
247  arg_tuple->items[2] = dest.Encode();
248  //userid
249  if (userid == 0)
250  arg_tuple->items[3] = PyStatic.NewNone();
251  else
252  arg_tuple->items[3] = new PyInt(userid);
253 
254  //payload
255  arg_tuple->items[4] = payload; // dont clone here. set actual rep in item, and it will be cleaned up by d'tor later
256 
257  //named arguments (OID+ or sn)
258  if (named_payload == nullptr) {
259  arg_tuple->items[5] = PyStatic.NewNone();
260  } else {
261  arg_tuple->items[5] = named_payload; // dont clone here. set actual rep in item, and it will be cleaned up by d'tor later
262  }
263 
264  // contextKey, gives the client extra information on what exactly is going on
265  // this is PyNone almost 100% of the time and seems to be used in the node<->proxy communication
266  if (contextKey == nullptr) {
267  arg_tuple->items[6] = PyStatic.NewNone();
268  } else {
269  arg_tuple->items[6] = contextKey;
270  }
271 
272  return new PyObject( type_string.c_str(), arg_tuple );
273 }
274 
276 : type(Invalid),
277 objectID(0),
278 callID(0),
279 service("")
280 {
281 
282 }
283 
284 void PyAddress::Dump(FILE *into, const char *pfx) const {
285  switch(type) {
286  case Any:
287  fprintf(into, "%sAny: service='%s' callID=%li", pfx, service.c_str(), callID);
288  break;
289  case Node:
290  fprintf(into, "%sNode: nodeID=%li service='%s' callID=%li", pfx, objectID, service.c_str(), callID);
291  break;
292  case Client:
293  fprintf(into, "%sClient: clientID=%li service='%s' callID=%li", pfx, objectID, service.c_str(), callID);
294  break;
295  case Broadcast:
296  fprintf(into, "%sBroadcast: broadcastID='%s' narrowcast=(not implemented) idtype='%s'", pfx, service.c_str(), bcast_idtype.c_str());
297  break;
298  case Invalid:
299  break;
300  //no default on purpose
301  }
302 }
303 
304 void PyAddress::Dump(LogType ltype, const char *pfx) const {
305  switch(type) {
306  case Any:
307  _log(ltype, "%sAny: service='%s' callID=%li", pfx, service.c_str(), callID);
308  break;
309  case Node:
310  _log(ltype, "%sNode: nodeID=%li service='%s' callID=%li", pfx, objectID, service.c_str(), callID);
311  break;
312  case Client:
313  _log(ltype, "%sClient: clientID=%li callID=%li service='%s'", pfx, objectID, callID, service.c_str());
314  break;
315  case Broadcast:
316  _log(ltype, "%sBroadcast: broadcastID='%s' narrowcast=(not implemented) idtype='%s'", pfx, service.c_str(), bcast_idtype.c_str());
317  break;
318  case Invalid:
319  break;
320  //no default on purpose
321  }
322 }
323 
324 void PyAddress::operator=(const PyAddress &right) {
325  type = right.type;
326  objectID = right.objectID;
327  callID = right.callID;
328  service = right.service;
329  bcast_idtype = right.bcast_idtype;
330 }
331 
332 bool PyAddress::Decode(PyRep *&in_object) {
333  PyRep *base = in_object;
334  in_object = nullptr;
335 
336  if (base == nullptr) {
337  codelog(NET__PACKET_ERROR, "PyAddress::Decode() - base is null.");
338  return false;
339  }
340 
341  if (!base->IsObject()) {
342  codelog(NET__PACKET_ERROR, "Invalid element type, expected object but got %s", base->TypeString());
343  PyDecRef(base);
344  return false;
345  }
346 
347  PyTuple *tuple = base->AsObject()->arguments()->AsTuple();
348  if (tuple == nullptr) {
349  codelog(NET__PACKET_ERROR, "PyAddress::Decode() - tuple is null.");
350  return false;
351  }
352 
353  if (tuple->items.size() < 3) {
354  codelog(NET__PACKET_ERROR, "Not enough elements in address tuple: %u", tuple->items.size());
355  tuple->Dump(NET__PACKET_ERROR, " ");
356  PyDecRef(base);
357  PyDecRef(tuple);
358  return false;
359  }
360 
361  //decode the address type.
362  if (!tuple->items[0]->IsInt()) {
363  codelog(NET__PACKET_ERROR, "Wrong type on address element (0)");
364  tuple->items[0]->Dump(NET__PACKET_ERROR, " ");
365  PyDecRef(base);
366  PySafeDecRef(tuple);
367  return false;
368  }
369 
370  switch(PyRep::IntegerValue(tuple->items[0])) {
371  case Any: {
372  if (tuple->items.size() != 3) {
373  codelog(NET__PACKET_ERROR, "Invalid number of elements in Any address tuple: %lu", tuple->items.size());
374  PyDecRef(base);
375  PySafeDecRef(tuple);
376  return false;
377  }
378  type = Any;
379 
380  if (!_DecodeService(tuple->items[1])
381  or !_DecodeCallID(tuple->items[2])) {
382  PyDecRef(base);
383  PySafeDecRef(tuple);
384  return false;
385  }
386  } break;
387  case Node: {
388  if (tuple->items.size() != 4) {
389  codelog(NET__PACKET_ERROR, "Invalid number of elements in Node address tuple: %lu", tuple->items.size());
390  PyDecRef(base);
391  PySafeDecRef(tuple);
392  return false;
393  }
394  type = Node;
395 
396  if (!_DecodeObjectID(tuple->items[1])
397  or !_DecodeService(tuple->items[2])
398  or !_DecodeCallID(tuple->items[3])) {
399  PyDecRef(base);
400  PySafeDecRef(tuple);
401  return false;
402  }
403  } break;
404  case Client: {
405  if (tuple->items.size() != 4) {
406  codelog(NET__PACKET_ERROR, "Invalid number of elements in Client address tuple: %lu", tuple->items.size());
407  PyDecRef(base);
408  PySafeDecRef(tuple);
409  return false;
410  }
411  type = Client;
412 
413  if (!_DecodeObjectID(tuple->items[1])
414  or !_DecodeCallID(tuple->items[2])
415  or !_DecodeService(tuple->items[3])) {
416  PyDecRef(base);
417  PySafeDecRef(tuple);
418  return false;
419  }
420  } break;
421  case Broadcast: {
422  if (tuple->items.size() != 4) {
423  codelog(NET__PACKET_ERROR, "Invalid number of elements in Broadcast address tuple: %lu", tuple->items.size());
424  PyDecRef(base);
425  PySafeDecRef(tuple);
426  return false;
427  }
428  type = Broadcast;
429 
430  if (!tuple->items[1]->IsString()) {
431  codelog(NET__PACKET_ERROR, "Invalid type %s for brodcastID", tuple->items[1]->TypeString());
432  PyDecRef(base);
433  PySafeDecRef(tuple);
434  return false;
435  }
436  if (!tuple->items[3]->IsString()) {
437  codelog(NET__PACKET_ERROR, "Invalid type %s for idtype", tuple->items[3]->TypeString());
438  PyDecRef(base);
439  PySafeDecRef(tuple);
440  return false;
441  }
442 
443  service = PyRep::StringContent(tuple->items[1]); //assign op
444  bcast_idtype = PyRep::StringContent(tuple->items[3]); //assign op
445 
446  //items[2] is either a list or a tuple.
447  /*
448  //PyList *nclist = (PyList *) tuple->items[2];
449  if (!nclist->items.empty()) {
450  printf("Not decoding narrowcast list:");
451  nclist->Dump(NET__PACKET_ERROR, " ");
452  }*/
453  } break;
454  default: {
455  codelog(NET__PACKET_ERROR, "Unknown address type: %i", PyRep::IntegerValue(tuple->items[0]));
456  PyDecRef(base);
457  PySafeDecRef(tuple);
458  return false;
459  }
460  }
461 
462  PyDecRef(base);
463  PySafeDecRef(tuple);
464  return true;
465 }
466 
468  PyTuple *t(nullptr);
469  switch(type) {
470  case Any: {
471  t = new PyTuple(3);
472  t->items[0] = new PyInt((int)type);
473 
474  if (service.empty())
475  t->items[1] = PyStatic.NewNone();
476  else
477  t->items[1] = new PyString(service.c_str());
478 
479  if (objectID == 0)
480  t->items[2] = PyStatic.NewNone();
481  else
482  t->items[2] = new PyLong(objectID);
483  } break;
484  case Node: {
485  t = new PyTuple(4);
486  t->items[0] = new PyInt((int)type);
487  t->items[1] = new PyLong(objectID);
488 
489  if (service.empty())
490  t->items[2] = PyStatic.NewNone();
491  else
492  t->items[2] = new PyString(service.c_str());
493 
494  if (callID == 0)
495  t->items[3] = PyStatic.NewNone();
496  else
497  t->items[3] = new PyLong(callID);
498  } break;
499  case Client: {
500  t = new PyTuple(4);
501  t->items[0] = new PyInt((int)type);
502  t->items[1] = new PyLong(objectID);
503 
504  if (callID == 0)
505  t->items[2] = PyStatic.NewNone();
506  else
507  t->items[2] = new PyLong(callID);
508 
509  if (service.empty())
510  t->items[3] = PyStatic.NewNone();
511  else
512  t->items[3] = new PyString(service.c_str());
513  } break;
514  case Broadcast: {
515  t = new PyTuple(4);
516  t->items[0] = new PyInt((int)type);
517  //broadcastID
518  if (service.empty())
519  t->items[1] = PyStatic.NewNone();
520  else
521  t->items[1] = new PyString(service.c_str());
522  //narrowcast
523  t->items[2] = new PyList(); // LSC uses tuple here, others None() or empty List()
524  //typeID
525  t->items[3] = new PyString(bcast_idtype.c_str());
526  } break;
527  case Invalid:
528  default: {
529  //this still needs to be something which will not crash us.
530  t = new_tuple(PyStatic.NewNone());
531  } break;
532  }
533 
534  return new PyObject( "macho.MachoAddress", t );
535 }
536 
539  return true;
540 }
541 
544  return true;
545 }
546 
549  return true;
550 }
551 
552 
554 : remoteObject(0),
555  method(""),
556  arg_tuple(nullptr),
557  arg_dict(nullptr)
558 {
559 }
560 
564 }
565 
567  PyCallStream *res = new PyCallStream();
568  res->remoteObject = remoteObject;
570  res->method = method;
571  res->arg_tuple = arg_tuple->Clone()->AsTuple();
572  if (arg_dict == nullptr)
573  res->arg_dict = nullptr;
574  else
575  res->arg_dict = arg_dict->Clone()->AsDict();
576 
577  return res;
578 }
579 
581 {
582  _log(type, "Call Stream:");
583  if (remoteObject == 0)
584  _log(type, " Remote Object: '%s'", remoteObjectStr.c_str());
585  else
586  _log(type, " Remote Object: %u", remoteObject);
587  _log(type, " Method: %s", method.c_str());
588  _log(type, " Arguments:");
589  arg_tuple->visit( dumper );
590  if (arg_dict == nullptr) {
591  _log(type, " Named Arguments: None");
592  } else {
593  _log(type, " Named Arguments:");
594  arg_dict->visit( dumper );
595  }
596 }
597 
598 bool PyCallStream::Decode(const std::string &type, PyTuple *&in_payload) {
599  PyTuple *payload = in_payload; //copy
600  in_payload = nullptr; //consume
601 
604  arg_tuple = nullptr;
605  arg_dict = nullptr;
606 
607  if (payload == nullptr) {
608  codelog(NET__PACKET_ERROR, "PyCallStream::Decode() - payload is null.");
609  return false;
610  }
611 
612  if (type != "macho.CallReq") {
613  codelog(NET__PACKET_ERROR, "PyCallStream::Decode() - packet payload has unknown string type '%s'", type.c_str());
614  PyDecRef(payload);
615  return false;
616  }
617 
618  if (payload->items.size() != 1) {
619  codelog(NET__PACKET_ERROR, "PyCallStream::Decode() - invalid tuple length %lu", payload->items.size());
620  PyDecRef(payload);
621  return false;
622  }
623  if (!payload->items[0]->IsTuple()) {
624  codelog(NET__PACKET_ERROR, "PyCallStream::Decode() - non tuple payload[0]");
625  PyDecRef(payload);
626  return false;
627  }
628 
629  PyTuple *payload2 = payload->items[0]->AsTuple();
630  if (payload2 == nullptr) {
631  codelog(NET__PACKET_ERROR, "PyCallStream::Decode() - payload2 is null.");
632  PyDecRef(payload);
633  PySafeDecRef(payload2);
634  return false;
635  }
636 
637  if (payload2->items.size() != 2) {
638  codelog(NET__PACKET_ERROR, "PyCallStream::Decode() - invalid tuple2 length %lu", payload2->items.size());
639  PyDecRef(payload);
640  PySafeDecRef(payload2);
641  return false;
642  }
643 
644  //decode inner payload tuple
645  //ignore tuple 0, it should be an int, dont know what it is
646  if (!payload2->items[1]->IsSubStream()) {
647  codelog(NET__PACKET_ERROR, "PyCallStream::Decode() - non-substream type");
648  PyDecRef(payload);
649  PySafeDecRef(payload2);
650  return false;
651  }
652 
653  PySubStream *ss = payload2->items[1]->AsSubStream();
654  if (ss == nullptr) {
655  codelog(NET__PACKET_ERROR, "PyCallStream::Decode() - ss is null.");
656  PyDecRef(payload);
657  PySafeDecRef(payload2);
658  return false;
659  }
660 
661  ss->DecodeData();
662  if (ss->decoded() == nullptr) {
663  codelog(NET__PACKET_ERROR, "PyCallStream::Decode() - Unable to decode call stream");
664  PyDecRef(payload);
665  PySafeDecRef(ss);
666  PySafeDecRef(payload2);
667  return false;
668  }
669 
670  if (!ss->decoded()->IsTuple()) {
671  codelog(NET__PACKET_ERROR, "PyCallStream::Decode() - packet body does not contain a tuple");
672  PyDecRef(payload);
673  PySafeDecRef(ss);
674  PySafeDecRef(payload2);
675  return false;
676  }
677 
678  PyTuple *maint = ss->decoded()->AsTuple();
679  if (maint == nullptr) {
680  codelog(NET__PACKET_ERROR, "PyCallStream::Decode() - maint is null.");
681  return false;
682  }
683  if (maint->items.size() != 4) {
684  codelog(NET__PACKET_ERROR, "PyCallStream::Decode() - packet body has %lu elements, expected %d", maint->items.size(), 4);
685  PyDecRef(payload);
686  PySafeDecRef(ss);
687  PySafeDecRef(maint);
688  PySafeDecRef(payload2);
689  return false;
690  }
691 
692  //parse first tuple element, unknown
693  if (maint->items[0]->IsInt()) {
695  remoteObjectStr = "";
696  } else if (maint->items[0]->IsString()) {
697  remoteObject = 0;
699  } else {
700  codelog(NET__PACKET_ERROR, "PyCallStream::Decode() - maint->items[0] has invalid type %s", maint->items[0]->TypeString());
701  codelog(NET__PACKET_ERROR, " in:");
702  payload->Dump(NET__PACKET_ERROR, " ");
703  PyDecRef(payload);
704  PySafeDecRef(ss);
705  PySafeDecRef(maint);
706  PySafeDecRef(payload2);
707  return false;
708  }
709 
710  //parse tuple[1]: method name
711  if (maint->items[1]->IsString()) {
712  method = PyRep::StringContent(maint->items[1]);
713  } else {
714  codelog(NET__PACKET_ERROR, "PyCallStream::Decode() - maint->items[1] has non-string type");
715  maint->items[1]->Dump(NET__PACKET_ERROR, " --> ");
716  codelog(NET__PACKET_ERROR, " in:");
717  payload->Dump(NET__PACKET_ERROR, " ");
718  PyDecRef(payload);
719  PySafeDecRef(ss);
720  PySafeDecRef(maint);
721  PySafeDecRef(payload2);
722  return false;
723  }
724 
725  //grab argument list.
726  if (!maint->items[2]->IsTuple()) {
727  codelog(NET__PACKET_ERROR, "PyCallStream::Decode() - argument list has non-tuple type");
728  maint->items[2]->Dump(NET__PACKET_ERROR, " --> ");
729  codelog(NET__PACKET_ERROR, "in:");
730  payload->Dump(NET__PACKET_ERROR, " ");
731  PyDecRef(payload);
732  PySafeDecRef(ss);
733  PySafeDecRef(maint);
734  PySafeDecRef(payload2);
735  return false;
736  }
737  arg_tuple = maint->items[2]->AsTuple();
738 
739  //options dict
740  if (maint->items[3]->IsNone()) {
741  arg_dict = nullptr;
742  } else if (maint->items[3]->IsDict()) {
743  arg_dict = maint->items[3]->AsDict();
744  } else {
745  codelog(NET__PACKET_ERROR, "PyCallStream::Decode() - tuple[3] has non-dict type");
746  maint->items[3]->Dump(NET__PACKET_ERROR, " --> ");
747  codelog(NET__PACKET_ERROR, "in:");
748  payload->Dump(NET__PACKET_ERROR, " ");
749  PyDecRef(payload);
750  PySafeDecRef(ss);
751  PySafeDecRef(maint);
752  PySafeDecRef(payload2);
753  return false;
754  }
755 
756  PyDecRef(payload);
757  PySafeDecRef(ss);
758  PySafeDecRef(maint);
759  PySafeDecRef(payload2);
760  return true;
761 }
762 
764  PyTuple *res_tuple = new PyTuple(4);
765 
766  //remoteObject
767  if (remoteObject == 0)
768  res_tuple->items[0] = new PyString(remoteObjectStr.c_str());
769  else
770  res_tuple->items[0] = new PyInt(remoteObject);
771 
772  //method name
773  res_tuple->items[1] = new PyString(method.c_str());
774 
775  //args
776  res_tuple->items[2] = arg_tuple; // no need to clone here. set actual rep in item, and it will be cleaned up by d'tor later
777 
778  //options
779  if (arg_dict == nullptr)
780  res_tuple->items[3] = PyStatic.NewNone();
781  else
782  res_tuple->items[3] = arg_dict; // no need to clone here. set actual rep in item, and it will be cleaned up by d'tor later
783 
784  //now that we have the main arg tuple, build the unknown stuff around it...
785  PyTuple *it2 = new PyTuple(2);
786  it2->items[0] = new PyInt(remoteObject==0?1:0); /* some sort of flag, "process here or call UP"....*/
787  it2->items[1] = new PySubStream(res_tuple);
788  PyTuple *it1 = new PyTuple(2);
789  it1->items[0] = it2;
790  it1->items[1] = PyStatic.NewNone(); //this is the "channel" dict if populated.
791  return it1;
792 }
793 
795 : notifyType("NO TYPE SET"),
796  remoteObject(0),
797  args(nullptr)
798 {
799 }
800 
803 }
804 
807  res->args = args->Clone()->AsTuple();
808  return res;
809 }
810 
812 {
813  _log(type, "Notification: %s", notifyType.c_str());
814  if (remoteObject == 0)
815  _log(type, " Remote Object: %s", remoteObjectStr.c_str());
816  else
817  _log(type, " Remote Object: %u", remoteObject);
818 
819  _log(type, " Arguments:");
820  args->visit( dumper );
821 }
822 
823 bool EVENotificationStream::Decode(const std::string &pkt_type, const std::string &notify_type, PyTuple *&in_payload) {
824  PyTuple *payload = in_payload; //copy
825  in_payload = nullptr; //consume
826 
828  args = nullptr;
829 
830  if (payload == nullptr) {
831  codelog(NET__PACKET_ERROR, "EVENotificationStream::Decode() - payload is null.");
832  return false;
833  }
834 
835  if (pkt_type != "macho.Notification") {
836  codelog(NET__PACKET_ERROR, "EVENotificationStream::Decode() - notification payload has unknown string type %s", pkt_type.c_str());
837  PyDecRef(payload);
838  return false;
839  }
840 
841  //decode payload tuple
842  if (payload->items.size() != 2) {
843  codelog(NET__PACKET_ERROR, "EVENotificationStream::Decode() - invalid tuple length %lu", payload->items.size());
844  PyDecRef(payload);
845  return false;
846  }
847  if (!payload->items[0]->IsTuple()) {
848  codelog(NET__PACKET_ERROR, "EVENotificationStream::Decode() - non-tuple payload[0]");
849  PyDecRef(payload);
850  return false;
851  }
852  PyTuple *payload2 = payload->items[0]->AsTuple();
853  if (payload2 == nullptr) {
854  codelog(NET__PACKET_ERROR, "EVENotificationStream::Decode() - payload2 is null.");
855  PyDecRef(payload);
856  return false;
857  }
858 
859  if (payload2->items.size() != 2) {
860  codelog(NET__PACKET_ERROR, "EVENotificationStream::Decode() - invalid tuple2 length %lu", payload2->items.size());
861  PyDecRef(payload);
862  PyDecRef(payload2);
863  return false;
864  }
865 
866  //decode inner payload tuple
867  //ignore tuple 0, it should be an int, dont know what it is
868  if (!payload2->items[1]->IsSubStream()) {
869  codelog(NET__PACKET_ERROR, "EVENotificationStream::Decode() - non-substream type");
870  PyDecRef(payload);
871  PyDecRef(payload2);
872  return false;
873  }
874 
875  PySubStream *ss(payload2->items[1]->AsSubStream());
876  if (ss == nullptr) {
877  codelog(NET__PACKET_ERROR, "EVENotificationStream::Decode() - ss is null.");
878  PyDecRef(payload);
879  PyDecRef(payload2);
880  return false;
881  }
882  ss->DecodeData();
883  if (ss->decoded() == nullptr) {
884  codelog(NET__PACKET_ERROR, "EVENotificationStream::Decode() - Unable to decode call stream");
885  PyDecRef(ss);
886  PyDecRef(payload);
887  PyDecRef(payload2);
888  return false;
889  }
890 
891  if (!ss->decoded()->IsTuple()) {
892  codelog(NET__PACKET_ERROR, "EVENotificationStream::Decode() - packet body does not contain a tuple");
893  PyDecRef(ss);
894  PyDecRef(payload);
895  PyDecRef(payload2);
896  return false;
897  }
898 
899  PyTuple *robjt = ss->decoded()->AsTuple();
900  if (robjt == nullptr) {
901  codelog(NET__PACKET_ERROR, "EVENotificationStream::Decode() - robjt is null.");
902  PyDecRef(ss);
903  PyDecRef(payload);
904  PyDecRef(payload2);
905  return false;
906  }
907  if (robjt->items.size() != 2) {
908  codelog(NET__PACKET_ERROR, "EVENotificationStream::Decode() - packet body has %lu elements, expected %d", robjt->items.size(), 2);
909  PyDecRef(ss);
910  PyDecRef(payload);
911  PyDecRef(payload2);
912  PySafeDecRef(robjt);
913  return false;
914  }
915 
916  //parse first tuple element, remote object
917  if (robjt->items[0]->IsInt()) {
919  remoteObjectStr = "";
920  } else if (robjt->items[0]->IsString()) {
921  remoteObject = 0;
923  } else {
924  codelog(NET__PACKET_ERROR, "EVENotificationStream::Decode() - main tuple[0] has invalid type %s", robjt->items[0]->TypeString());
925  _log(NET__PACKET_ERROR, " in:");
926  payload->Dump( NET__PACKET_ERROR, "" );
927  PyDecRef(ss);
928  PyDecRef(payload);
929  PyDecRef(payload2);
930  PySafeDecRef(robjt);
931  return false;
932  }
933 
934  if (!robjt->items[1]->IsTuple()) {
935  codelog(NET__PACKET_ERROR, "EVENotificationStream::Decode() - main tuple[1] has non-tuple type %s", robjt->items[0]->TypeString());
936  _log(NET__PACKET_ERROR, " it is:");
937  payload->Dump( NET__PACKET_ERROR, "" );
938  PyDecRef(ss);
939  PyDecRef(payload);
940  PyDecRef(payload2);
941  PySafeDecRef(robjt);
942  return false;
943  }
944 
945  PyTuple *subt(robjt->items[1]->AsTuple());
946  if (subt == nullptr) {
947  codelog(NET__PACKET_ERROR, "EVENotificationStream::Decode() - subt is null.");
948  PyDecRef(ss);
949  PyDecRef(payload);
950  PyDecRef(payload2);
951  PySafeDecRef(robjt);
952  return false;
953  }
954  if (subt->items.size() != 2) {
955  codelog(NET__PACKET_ERROR, "EVENotificationStream::Decode() - packet body has %lu elements, expected %d", subt->items.size(), 2);
956  PyDecRef(ss);
957  PyDecRef(payload);
958  PyDecRef(payload2);
959  PySafeDecRef(subt);
960  PySafeDecRef(robjt);
961  return false;
962  }
963 
964  //parse first tuple element, remote object
965  if (subt->items[0]->IsInt()) {
966  //PyInt *tuple0 = (PyInt *) maint->items[0];
967  //no idea what this is.
968  } else {
969  codelog(NET__PACKET_ERROR, "EVENotificationStream::Decode() - sub tuple[0] has invalid type %s", subt->items[0]->TypeString());
970  _log(NET__PACKET_ERROR, " in:");
971  payload->Dump( NET__PACKET_ERROR, "" );
972  PyDecRef(ss);
973  PyDecRef(payload);
974  PyDecRef(payload2);
975  PySafeDecRef(subt);
976  PySafeDecRef(robjt);
977  return false;
978  }
979 
980  if (!subt->items[1]->IsTuple()) {
981  codelog(NET__PACKET_ERROR, "EVENotificationStream::Decode() - subt tuple[1] has non-tuple type %s", robjt->items[0]->TypeString());
982  _log(NET__PACKET_ERROR, " it is:");
983  payload->Dump( NET__PACKET_ERROR, "" );
984  PyDecRef(ss);
985  PyDecRef(payload);
986  PyDecRef(payload2);
987  PySafeDecRef(subt);
988  PySafeDecRef(robjt);
989  return false;
990  }
991 
992  args = subt->items[1]->AsTuple();
993  notifyType = notify_type;
994 
995  PyDecRef(ss);
996  PyDecRef(payload);
997  PyDecRef(payload2);
998  PySafeDecRef(subt);
999  PySafeDecRef(robjt);
1000  return true;
1001 }
1002 
1004  PyTuple *t4 = new PyTuple(2);
1005  t4->SetItem(0, PyStatic.NewOne());
1006  t4->SetItem(1, args); // no need to clone here. set actual rep in item, and it will be cleaned up by d'tor later
1007  PyTuple *t3 = new PyTuple(2);
1008  t3->SetItem(0, new PyInt(0));
1009  t3->SetItem(1, t4);
1010  PyTuple *t2 = new PyTuple(2);
1011  t2->SetItem(0, new PyInt(0));
1012  t2->SetItem(1, new PySubStream(t3));
1013  PyTuple *t1 = new PyTuple(1);
1014  t1->SetItem(0, t2);
1015  return t1;
1016 }
PyDict * arg_dict
Definition: PyPacket.h:159
Base Python wire object.
Definition: PyRep.h:66
PyTuple * AsTuple()
Definition: PyRep.h:138
uint32 remoteObject
Definition: PyPacket.h:154
int64 callID
Definition: PyPacket.h:90
static std::string StringContent(PyRep *pRep)
Definition: PyRep.cpp:103
void Dump(LogType type, PyVisitor &dumper)
Definition: PyPacket.cpp:811
const char * MACHONETMSG_TYPE_NAMES[MACHONETMSG_TYPE_COUNT]
Definition: PyPacket.cpp:36
#define _log(type, fmt,...)
Definition: logsys.h:124
Python string.
Definition: PyRep.h:430
PyPacket()
Definition: PyPacket.cpp:62
bool IsChecksumedStream() const
Definition: PyRep.h:114
bool IsTuple() const
Definition: PyRep.h:108
PyAddress dest
Definition: PyPacket.h:117
int64 objectID
Definition: PyPacket.h:89
PyRep * Encode()
Definition: PyPacket.cpp:467
PyObject * AsObject()
Definition: PyRep.h:152
MACHONETMSG_TYPE
Definition: packet_types.h:70
bool IsObject() const
Definition: PyRep.h:115
std::string method
Definition: PyPacket.h:157
void operator=(const PyAddress &right)
Definition: PyPacket.cpp:324
bool visit(PyVisitor &v) const
Visits object.
Definition: PyRep.cpp:675
Python tuple.
Definition: PyRep.h:567
void Dump(FILE *into, const char *pfx) const
Dumps object to file.
Definition: PyRep.cpp:84
PyCallStream * Clone() const
Definition: PyPacket.cpp:566
PyRep * arguments() const
Definition: PyRep.h:845
PyTuple * payload
Definition: PyPacket.h:119
void Dump(FILE *into, const char *pfx) const
Definition: PyPacket.cpp:284
* args
PyRep * decoded() const
Definition: PyRep.h:1048
void Dump(LogType type, PyVisitor &dumper)
Definition: PyPacket.cpp:95
std::string notifyType
Definition: PyPacket.h:172
MACHONETMSG_TYPE type
Definition: PyPacket.h:115
PyRep * contextKey
Definition: PyPacket.h:121
PySubStream * AsSubStream()
Definition: PyRep.h:148
PyChecksumedStream * AsChecksumedStream()
Definition: PyRep.h:150
void DecodeData() const
Definition: PyRep.cpp:1125
Python object.
Definition: PyRep.h:826
PyRep * Clone() const
Clones object.
Definition: PyRep.cpp:548
PyTuple * new_tuple(int64 arg1)
Definition: PyRep.cpp:1160
AddrType type
Definition: PyPacket.h:88
#define codelog(type, fmt,...)
Definition: logsys.h:128
void SetItem(size_t index, PyRep *object)
Stores Python object.
Definition: PyRep.h:610
Python integer.
Definition: PyRep.h:231
PyTuple * arg_tuple
Definition: PyPacket.h:158
PyDict * AsDict()
Definition: PyRep.h:142
PyRep * Clone() const
Clones object.
Definition: PyRep.cpp:670
#define PyStatic
Definition: PyRep.h:1209
bool Decode(const std::string &pkt_type, const std::string &notify_type, PyTuple *&payload)
Definition: PyPacket.cpp:823
#define PyDecRef(op)
Definition: PyRep.h:57
Definition: Client.h:66
void Dump(LogType type, PyVisitor &dumper)
Definition: PyPacket.cpp:580
std::string bcast_idtype
Definition: PyPacket.h:93
bool Decode(PyRep *&object)
Definition: PyPacket.cpp:332
PyString * type() const
Definition: PyRep.h:844
PyTuple * Encode()
Definition: PyPacket.cpp:763
PyRep * Encode()
Definition: PyPacket.cpp:240
PyPacket * Clone() const
Definition: PyPacket.cpp:79
bool Decode(const std::string &type, PyTuple *&payload)
Definition: PyPacket.cpp:598
LogType
Definition: logsys.h:59
EVENotificationStream * Clone() const
Definition: PyPacket.cpp:805
bool _DecodeObjectID(PyRep *rep)
Definition: PyPacket.cpp:547
bool Decode(PyRep **packet)
Definition: PyPacket.cpp:115
uint32 userid
Definition: PyPacket.h:118
const std::string & content() const
Get the PyString content.
Definition: PyRep.h:458
bool visit(PyVisitor &v) const
Visits object.
Definition: PyRep.cpp:553
PyDict * named_payload
Definition: PyPacket.h:120
~PyPacket()
Definition: PyPacket.cpp:73
std::string service
Definition: PyPacket.h:92
#define PySafeDecRef(op)
Definition: PyRep.h:61
bool IsSubStream() const
Definition: PyRep.h:113
storage_type items
Definition: PyRep.h:628
bool _DecodeCallID(PyRep *rep)
Definition: PyPacket.cpp:542
std::string remoteObjectStr
Definition: PyPacket.h:155
static int64 IntegerValue(PyRep *pRep)
Definition: PyRep.cpp:118
PyAddress source
Definition: PyPacket.h:116
std::string type_string
Definition: PyPacket.h:112
const char * TypeString() const
Definition: PyRep.cpp:76
bool _DecodeService(PyRep *rep)
Definition: PyPacket.cpp:537
Python list.
Definition: PyRep.h:639
std::string remoteObjectStr
Definition: PyPacket.h:175
Python long integer.
Definition: PyRep.h:261
PyRep * stream() const
Definition: PyRep.h:1081