EvEmu  0.8.4
11 September 2021
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
EVECollectDisp.cpp
Go to the documentation of this file.
1 
2 #include "EVECollectDisp.h"
3 #include "../common/logsys.h"
4 #include "../common/PyPacket.h"
5 #include "../common/PyRep.h"
6 #include "../packets/AccountPkts.h"
7 #include "../packets/General.h"
8 #include "../packets/LSCPkts.h"
9 #include "../common/PyDumpVisitor.h"
10 #include "../common/PyXMLGenerator.h"
11 #include "../common/CachedObjectMgr.h"
12 #include "../common/RowsetReader.h"
13 
14 
15 
18 {
19 #define CALL_REQ_HANDLER(c) m_callReqDisp[#c] = &EVECollectDispatcher::Req_##c;
20 #define CALL_RSP_HANDLER(c) m_callRspDisp[#c] = &EVECollectDispatcher::Rsp_##c;
21 #define BOUND_CALL_RSP_HANDLER(c) m_callRspDisp[#c] = &EVECollectDispatcher::Bound_Rsp_##c;
22 #define NOTIFY_HANDLER(c) m_notifyDisp[#c] = &EVECollectDispatcher::Notify_##c;
23  #include "method_types.h"
24 
25 #define DESTINY_HANDLER(c) m_destinyDisp[#c] = &EVECollectDispatcher::Destiny_##c;
26  #include "destiny_types.h"
27 }
28 
30 }
31 
32 
33 void EVECollectDispatcher::Handle_AuthenticationReq(const PyPacket *packet, AuthenticationReq **call) {
34  _log(COLLECT__MESSAGE, "Saw AuthenticationReq for %s", (*call)->login.c_str());
35 }
36 
37 void EVECollectDispatcher::Handle_AuthenticationRsp(const PyPacket *packet, AuthenticationRsp **rsp) {
38  _log(COLLECT__MESSAGE, "Saw AuthenticationRsp");
39 }
40 
42  PyCallStream *call = *in_call;
43  *in_call = NULL;
44 
45  pendingCalls[packet->source.callID] = call->method;
46 
47 
48  _log(COLLECT__CALL_SUMMARY, "Call ID %" PRIu64 ": %s (svc %s)", packet->source.callID, call->method.c_str(), packet->dest.service.c_str());
49  packet->source.Dump(COLLECT__PACKET_SRC, " Src: ");
50  packet->dest.Dump(COLLECT__PACKET_DEST, " Dest: ");
51  if(is_log_enabled(COLLECT__CALL_DUMP)) {
52  PyLookupDump dumper(&lookResolver, COLLECT__CALL_DUMP);
53  call->Dump(COLLECT__CALL_DUMP, &dumper);
54  }
55 
56 
57  if(call->method != "MachoBindObject") { //this is handled elsewhere...
58  if(is_log_enabled(COLLECT__CALL_XML)) {
59  printf("<element name=\"Call%s\">\n", call->method.c_str());
60  PyXMLGenerator gen(stdout);
61  call->arg_tuple->visit(&gen);
62  printf("</element>\n");
63  }
64  }
65 
66  //send it to a dispatcher if there is one registered
67  std::map<std::string, _CallReqDispatch>::const_iterator res;
68  res = m_callReqDisp.find(call->method);
69  if(res != m_callReqDisp.end()) {
70  _CallReqDispatch dsp = res->second;
71  (this->*dsp)(packet, &call);
72  }
73 
74  delete call;
75 }
76 
77 void EVECollectDispatcher::Handle_CallRsp(const PyPacket *packet, PyRepTuple **in_result) {
78  PyRepTuple *result = *in_result;
79  *in_result = NULL;
80 
81  std::map<uint32, std::string>::iterator res;
82  res = pendingCalls.find(packet->dest.callID);
83  if(res != pendingCalls.end()) {
84  const char *pfx = "";
85  if(result->items.size() == 1 && result->items[0]->CheckType(PyRep::SubStream)) {
86  PyRepSubStream *ss = (PyRepSubStream *) result->items[0];
87  ss->DecodeData();
88  if(ss->decoded != NULL) {
89  if(ss->decoded->CheckType(PyRep::None))
90  pfx = "Empty ";
91 
92  //decode any nested substreams.
93  SubStreamDecoder ssd;
94  ss->decoded->visit(&ssd);
95  }
96  }
97 
98  _log(COLLECT__CALL_SUMMARY, "%sCall Response for ID %" PRIu64 ": %s (svc %s)", pfx, packet->dest.callID, res->second.c_str(), packet->source.service.c_str());
99 
100  packet->source.Dump(COLLECT__PACKET_SRC, " Src: ");
101  packet->dest.Dump(COLLECT__PACKET_DEST, " Dest: ");
102 
103  if(is_log_enabled(COLLECT__CALL_DUMP)) {
104  if(res->second != "GetCachableObject") { //these get dumped elsewhere
105  SubStreamDecoder v;
106  result->visit(&v);
107  PyLookupDump dumper(&lookResolver, COLLECT__CALL_DUMP);
108  result->visit(&dumper);
109  }
110  } //end "is dump enabled"
111 
112  if(is_log_enabled(COLLECT__CALLRSP_SQL)
113  && result != NULL
114  && res->second != "MachoBindObject" //bind object nested calls dumped elsewhere.
115  ) {
116  //run through the result looking for SQL tables, and dump them.
117  SetSQLDumper sql_dumper(stdout, res->second.c_str());
118  result->visit(&sql_dumper);
119  }
120 
121  if(is_log_enabled(COLLECT__CALLRSP_XML)
122  && result != NULL
123  && res->second != "MachoBindObject" //bind object nested calls dumped elsewhere.
124  ) {
125  printf("<element name=\"Rsp%s\">\n", res->second.c_str());
126  PyXMLGenerator gen(stdout);
127  result->visit(&gen);
128  printf("</element>\n");
129  }
130 
131  //send it to a dispatcher if there is one registered
132  std::map<std::string, _CallRspDispatch>::const_iterator res2;
133  res2 = m_callRspDisp.find(res->second);
134  if(res2 != m_callRspDisp.end()) {
135  _CallRspDispatch dsp = res2->second;
136  (this->*dsp)(packet, &result);
137  }/* else {
138  _log(COLLECT__ERROR, "Unable to find handler for '%s'", res->second.c_str());
139  }*/
140 
141  pendingCalls.erase(res);
142  } else {
143  _log(COLLECT__CALL_SUMMARY, "Call Response for unknonw call ID %" PRIu64, packet->dest.callID);
144  }
145  delete result;
146 }
147 
149  EVENotificationStream *notify = *in_notify;
150  *in_notify = NULL;
151 
152  _log(COLLECT__NOTIFY_SUMMARY, "Notification of type %s", packet->dest.service.c_str());
153  packet->source.Dump(COLLECT__PACKET_SRC, " Src: ");
154  packet->dest.Dump(COLLECT__PACKET_DEST, " Dest: ");
155  if(is_log_enabled(COLLECT__NOTIFY_DUMP)) {
156  PyLookupDump dumper(&lookResolver, COLLECT__NOTIFY_DUMP);
157  notify->Dump(COLLECT__NOTIFY_DUMP, &dumper);
158  }
159 
160  if(is_log_enabled(COLLECT__NOTIFY_XML)) {
161  printf("<element name=\"Notify%s\">\n", packet->dest.service.c_str());
162  PyXMLGenerator gen(stdout);
163  notify->args->visit(&gen);
164  printf("</element>\n");
165  }
166 
167  //send it to a dispatcher if there is one registered
168  std::map<std::string, _NotifyDispatch>::const_iterator res;
169  res = m_notifyDisp.find(packet->dest.service);
170  if(res != m_notifyDisp.end()) {
171  _NotifyDispatch dsp = res->second;
172  (this->*dsp)(packet, &notify);
173  }
174 
175  delete notify;
176 }
177 
178 void EVECollectDispatcher::Handle_SessionChange(const PyPacket *packet, SessionChangeNotification **notify) {
179  _log(COLLECT__ERROR, "Unprocessed SessionChange");
180 }
181 
182 void EVECollectDispatcher::Handle_ErrorResponse(const PyPacket *packet, ErrorResponseBody **body) {
183  _log(COLLECT__ERROR, "Unprocessed ErrorResponse");
184 }
185 
187  PyPacket *packet = *in_packet;
188  *in_packet = NULL;
189 
190  //everything else...
191  if(is_log_enabled(COLLECT__CALL_DUMP)) {
192  //semi-hack: if we are dumping general stuff, dump the misc packets directly.
193 
194  //decode substreams to facilitate dumping better:
195  SubStreamDecoder v;
196  packet->payload->visit(&v);
197 
198  _log(COLLECT__OTHER_DUMP, "Misc Packet:");
199 
200  packet->source.Dump(COLLECT__PACKET_SRC, " Src: ");
201  packet->dest.Dump(COLLECT__PACKET_DEST, " Dest: ");
202 
203  PyLookupDump dumper(&lookResolver, COLLECT__CALL_DUMP);
204  packet->Dump(COLLECT__CALL_DUMP, &dumper);
205  }
206  if(is_log_enabled(COLLECT__MISC_XML)) {
207  printf("<element name=\"??\">\n");
208  PyXMLGenerator gen(stdout);
209  packet->payload->visit(&gen);
210  printf("</element>\n");
211  }
212 
213  delete packet;
214 }
215 
216 
217 void EVECollectDispatcher::Rsp_MachoBindObject(const PyPacket *packet, PyRepTuple **res) {
218  if( (*res)->items.size() != 1
219  || !(*res)->items[0]->CheckType(PyRep::SubStream)) {
220  _log(COLLECT__ERROR, "Invalid MachoBindObject RSP");
221  return;
222  }
223  PyRepSubStream *ss = (PyRepSubStream *) (*res)->items[0];
224  ss->DecodeData();
225  if(ss->decoded == NULL) {
226  _log(COLLECT__ERROR, "Unable to decode MachoBindObject RSP");
227  return;
228  }
229 
230  std::string method_name = "UNKNOWN";
231  std::map<uint32, std::string>::iterator resp;
232  resp = pendingBinds.find(packet->dest.callID);
233  if(resp != pendingBinds.end()) {
234  method_name = resp->second;
235  pendingBinds.erase(resp);
236  }
237 
238  RspMachoBindObject c;
239  if(c.Decode(res)) {
240  _log(COLLECT__CALL_SUMMARY, "Call Response for Bind Call ID %" PRIu64 ": %s", packet->dest.callID, method_name.c_str());
241 
242  if(is_log_enabled(COLLECT__CALLRSP_SQL)) {
243  //run through the result looking for SQL tables, and dump them.
244  SetSQLDumper sql_dumper(stdout, method_name.c_str());
245  c.call_return->visit(&sql_dumper);
246  }
247 
248  if(is_log_enabled(COLLECT__CALLRSP_XML)) {
249  printf("<element name=\"Call%s\">\n", method_name.c_str());
250  PyXMLGenerator gen(stdout);
251  c.call_return->visit(&gen);
252  printf("</element>\n");
253  }
254  }
255 }
256 
257 void EVECollectDispatcher::Req_MachoBindObject(const PyPacket *packet, PyCallStream **call) {
258  //TODO: dispatch the call
259  _log(COLLECT__ERROR, "UN-dispatched MachoBindObject call");
260  CallMachoBindObject obj;
261  if(obj.Decode(&(*call)->arg_tuple)) {
262  if(!obj.call->CheckType(PyRep::None)) {
263  CallMachoBindObject_call c;
264  if(c.Decode(&obj.call)) {
265  _log(COLLECT__CALL_SUMMARY, "Nested Call ID %" PRIu64 ": %s", packet->source.callID, c.method_name.c_str());
266 
267  //register the bind
268  pendingBinds[packet->source.callID] = c.method_name;
269 
270  if(is_log_enabled(COLLECT__CALL_XML)) {
271  printf("<element name=\"Call%s\">\n", c.method_name.c_str());
272  PyXMLGenerator gen(stdout);
273  c.arguments->visit(&gen);
274  printf("</element>\n");
275  }
276  }
277  }
278  }
279 }
280 
281 void EVECollectDispatcher::Rsp_GetCachableObject(const PyPacket *packet, PyRepTuple **in_result) {
282  PyRepTuple *result = *in_result;
283  *in_result = NULL;
284 
285  if(result->items.size() == 1 &&
286  result->items[0]->CheckType(PyRep::SubStream)) {
287  PyRepSubStream *s = (PyRepSubStream *) result->items[0];
288  result->items[0] = NULL;
289 
291  if(!cobj.Decode(&s)) {
292  _log(CLIENT__ERROR, "Failed to decode GetCachableObject response");
293  } else {
294 
295  //decode the body
296  SubStreamDecoder v;
297  cobj.cache->visit(&v);
298 
299  _log(COLLECT__CALL_DUMP, "GetCachableObject reply decoded:");
300  if(is_log_enabled(COLLECT__CALL_DUMP))
301  cobj.Dump(stdout, " ", true);
302 
303  if(is_log_enabled(COLLECT__CALLRSP_SQL)) {
304  //run through the result looking for SQL tables, and dump them.
305  SetSQLDumper sql_dumper(stdout, "GetCachableObject");
306  cobj.cache->visit(&sql_dumper);
307  }
308  }
309  }
310 
311  delete result;
312 }
313 
314 void EVECollectDispatcher::Notify_OnLSC(const PyPacket *packet, EVENotificationStream **in_notify) {
315  EVENotificationStream *notify = *in_notify;
316  *in_notify = NULL;
317 
318  NotifyOnLSC lsc;
319  if(!lsc.Decode(&notify->args)) {
320  delete notify;
321  codelog(COLLECT__ERROR, "Unable to decode OnLSC update main.");
322  return;
323  }
324 
325  _log(COLLECT__NOTIFY_SUMMARY, " LSC Method on channel %u: %s", lsc.channelID, lsc.method.c_str());
326 }
327 
328 
329 
330 
331 
332 
333 
334 
335 
336 
337 
338 
339 
340 
341 
int64 callID
Definition: PyPacket.h:90
void Dump(LogType type, PyVisitor &dumper)
Definition: PyPacket.cpp:811
void(EVECollectDispatcher::* _CallReqDispatch)(const PyPacket *packet, PyCallStream **call)
#define _log(type, fmt,...)
Definition: logsys.h:124
PyAddress dest
Definition: PyPacket.h:117
virtual void Handle_Notify(const PyPacket *packet, EVENotificationStream **notify)
std::map< uint32, std::string > pendingBinds
Python object SQL dumper.
Definition: RowsetReader.h:191
virtual void Handle_Other(PyPacket **packet)
std::string method
Definition: PyPacket.h:157
virtual void Handle_CallRsp(const PyPacket *packet, PyRepTuple **res)
void(EVECollectDispatcher::* _NotifyDispatch)(const PyPacket *packet, EVENotificationStream **notify)
PyTuple * payload
Definition: PyPacket.h:119
void Dump(FILE *into, const char *pfx) const
Definition: PyPacket.cpp:284
#define is_log_enabled(type)
Definition: logsys.h:78
void Dump(LogType type, PyVisitor &dumper)
Definition: PyPacket.cpp:95
void(EVECollectDispatcher::* _CallRspDispatch)(const PyPacket *packet, PyRepTuple **res)
virtual ~EVECollectDispatcher()
std::map< std::string, _CallReqDispatch > m_callReqDisp
#define codelog(type, fmt,...)
Definition: logsys.h:128
virtual void Handle_ErrorResponse(const PyPacket *packet, ErrorResponseBody **body)
virtual void Handle_CallReq(const PyPacket *packet, PyCallStream **call)
PyTuple * arg_tuple
Definition: PyPacket.h:158
std::map< uint32, std::string > pendingCalls
std::map< std::string, _NotifyDispatch > m_notifyDisp
void Dump(LogType type, PyVisitor &dumper)
Definition: PyPacket.cpp:580
virtual void Handle_AuthenticationReq(const PyPacket *packet, AuthenticationReq **call)
virtual void Handle_AuthenticationRsp(const PyPacket *packet, AuthenticationRsp **call)
virtual void Handle_SessionChange(const PyPacket *packet, SessionChangeNotification **notify)
#define PRIu64
Definition: eve-compat.h:85
PyLookupResolver lookResolver
bool visit(PyVisitor &v) const
Visits object.
Definition: PyRep.cpp:553
std::string service
Definition: PyPacket.h:92
PyAddress source
Definition: PyPacket.h:116
std::map< std::string, _CallRspDispatch > m_callRspDisp