1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4
5 #include <IceUtil/Mutex.h>
6 #include <IceUtil/MutexPtrLock.h>
7 #include <Ice/StringUtil.h>
8 #include <Ice/TraceUtil.h>
9 #include <Ice/Instance.h>
10 #include <Ice/Object.h>
11 #include <Ice/Proxy.h>
12 #include <Ice/TraceLevels.h>
13 #include <Ice/Logger.h>
14 #include <Ice/OutputStream.h>
15 #include <Ice/InputStream.h>
16 #include <Ice/Protocol.h>
17 #include <Ice/ReplyStatus.h>
18 #include <set>
19
20 using namespace std;
21 using namespace Ice;
22 using namespace IceInternal;
23
24 static void
printIdentityFacetOperation(ostream & s,InputStream & stream)25 printIdentityFacetOperation(ostream& s, InputStream& stream)
26 {
27 ToStringMode toStringMode = ICE_ENUM(ToStringMode, Unicode);
28 if(stream.instance())
29 {
30 toStringMode = stream.instance()->toStringMode();
31 }
32
33 Identity identity;
34 stream.read(identity);
35 s << "\nidentity = " << Ice::identityToString(identity, toStringMode);
36
37 vector<string> facet;
38 stream.read(facet);
39 s << "\nfacet = ";
40 if(!facet.empty())
41 {
42 s << escapeString(facet[0], "", toStringMode);
43 }
44
45 string operation;
46 stream.read(operation, false);
47 s << "\noperation = " << operation;
48 }
49
50 static string
getMessageTypeAsString(Byte type)51 getMessageTypeAsString(Byte type)
52 {
53 switch(type)
54 {
55 case requestMsg:
56 return "request";
57 case requestBatchMsg:
58 return "batch request";
59 case replyMsg:
60 return "reply";
61 case closeConnectionMsg:
62 return "close connection";
63 case validateConnectionMsg:
64 return "validate connection";
65 default:
66 return "unknown";
67 }
68 }
69
70 static void
printRequestHeader(ostream & s,InputStream & stream)71 printRequestHeader(ostream& s, InputStream& stream)
72 {
73 printIdentityFacetOperation(s, stream);
74
75 Byte mode;
76 stream.read(mode);
77 s << "\nmode = " << static_cast<int>(mode) << ' ';
78 switch(static_cast<OperationMode>(mode))
79 {
80 case ICE_ENUM(OperationMode, Normal):
81 {
82 s << "(normal)";
83 break;
84 }
85
86 case ICE_ENUM(OperationMode, Nonmutating):
87 {
88 s << "(nonmutating)";
89 break;
90 }
91
92 case ICE_ENUM(OperationMode, Idempotent):
93 {
94 s << "(idempotent)";
95 break;
96 }
97
98 default:
99 {
100 s << "(unknown)";
101 break;
102 }
103 }
104
105 Int sz = stream.readSize();
106 s << "\ncontext = ";
107 while(sz--)
108 {
109 pair<string, string> pair;
110 stream.read(pair.first);
111 stream.read(pair.second);
112 s << pair.first << '/' << pair.second;
113 if(sz)
114 {
115 s << ", ";
116 }
117 }
118
119 Ice::EncodingVersion v = stream.skipEncapsulation();
120 if(v > Ice::Encoding_1_0)
121 {
122 s << "\nencoding = " << v;
123 }
124 }
125
126 static Byte
printHeader(ostream & s,InputStream & stream)127 printHeader(ostream& s, InputStream& stream)
128 {
129 Byte magicNumber;
130 stream.read(magicNumber); // Don't bother printing the magic number
131 stream.read(magicNumber);
132 stream.read(magicNumber);
133 stream.read(magicNumber);
134
135 Byte pMajor;
136 Byte pMinor;
137 stream.read(pMajor);
138 stream.read(pMinor);
139 // s << "\nprotocol version = " << static_cast<unsigned>(pMajor)
140 // << "." << static_cast<unsigned>(pMinor);
141
142 Byte eMajor;
143 Byte eMinor;
144 stream.read(eMajor);
145 stream.read(eMinor);
146 // s << "\nencoding version = " << static_cast<unsigned>(eMajor)
147 // << "." << static_cast<unsigned>(eMinor);
148
149 Byte type;
150 stream.read(type);
151 s << "\nmessage type = " << static_cast<int>(type) << " (" << getMessageTypeAsString(type) << ')';
152
153 Byte compress;
154 stream.read(compress);
155 s << "\ncompression status = " << static_cast<int>(compress) << ' ';
156
157 switch(compress)
158 {
159 case 0:
160 {
161 s << "(not compressed; do not compress response, if any)";
162 break;
163 }
164
165 case 1:
166 {
167 s << "(not compressed; compress response, if any)";
168 break;
169 }
170
171 case 2:
172 {
173 s << "(compressed; compress response, if any)";
174 break;
175 }
176
177 default:
178 {
179 s << "(unknown)";
180 break;
181 }
182 }
183
184 Int size;
185 stream.read(size);
186 s << "\nmessage size = " << size;
187
188 return type;
189 }
190
191 static void
printRequest(ostream & s,InputStream & stream)192 printRequest(ostream& s, InputStream& stream)
193 {
194 Int requestId;
195 stream.read(requestId);
196 s << "\nrequest id = " << requestId;
197 if(requestId == 0)
198 {
199 s << " (oneway)";
200 }
201
202 printRequestHeader(s, stream);
203 }
204
205 static void
printBatchRequest(ostream & s,InputStream & stream)206 printBatchRequest(ostream& s, InputStream& stream)
207 {
208 int batchRequestNum;
209 stream.read(batchRequestNum);
210 s << "\nnumber of requests = " << batchRequestNum;
211
212 for(int i = 0; i < batchRequestNum; ++i)
213 {
214 s << "\nrequest #" << i << ':';
215 printRequestHeader(s, stream);
216 }
217 }
218
219 static void
printReply(ostream & s,InputStream & stream)220 printReply(ostream& s, InputStream& stream)
221 {
222 Int requestId;
223 stream.read(requestId);
224 s << "\nrequest id = " << requestId;
225
226 Byte replyStatus;
227 stream.read(replyStatus);
228 s << "\nreply status = " << static_cast<int>(replyStatus) << ' ';
229 switch(replyStatus)
230 {
231 case replyOK:
232 {
233 s << "(ok)";
234 break;
235 }
236
237 case replyUserException:
238 {
239 s << "(user exception)";
240 break;
241 }
242
243 case replyObjectNotExist:
244 case replyFacetNotExist:
245 case replyOperationNotExist:
246 {
247 switch(replyStatus)
248 {
249 case replyObjectNotExist:
250 {
251 s << "(object not exist)";
252 break;
253 }
254
255 case replyFacetNotExist:
256 {
257 s << "(facet not exist)";
258 break;
259 }
260
261 case replyOperationNotExist:
262 {
263 s << "(operation not exist)";
264 break;
265 }
266
267 default:
268 {
269 assert(false);
270 break;
271 }
272 }
273
274 printIdentityFacetOperation(s, stream);
275 break;
276 }
277
278 case replyUnknownException:
279 case replyUnknownLocalException:
280 case replyUnknownUserException:
281 {
282 switch(replyStatus)
283 {
284 case replyUnknownException:
285 {
286 s << "(unknown exception)";
287 break;
288 }
289
290 case replyUnknownLocalException:
291 {
292 s << "(unknown local exception)";
293 break;
294 }
295
296 case replyUnknownUserException:
297 {
298 s << "(unknown user exception)";
299 break;
300 }
301
302 default:
303 {
304 assert(false);
305 break;
306 }
307 }
308
309 string unknown;
310 stream.read(unknown, false);
311 s << "\nunknown = " << unknown;
312 break;
313 }
314
315 default:
316 {
317 s << "(unknown)";
318 break;
319 }
320 }
321
322 if(replyStatus == replyOK || replyStatus == replyUserException)
323 {
324 Ice::EncodingVersion v = stream.skipEncapsulation();
325 if(v > Ice::Encoding_1_0)
326 {
327 s << "\nencoding = " << v;
328 }
329 }
330 }
331
332 static Byte
printMessage(ostream & s,InputStream & stream)333 printMessage(ostream& s, InputStream& stream)
334 {
335 Byte type = printHeader(s, stream);
336
337 switch(type)
338 {
339 case closeConnectionMsg:
340 case validateConnectionMsg:
341 {
342 // We're done.
343 break;
344 }
345
346 case requestMsg:
347 {
348 printRequest(s, stream);
349 break;
350 }
351
352 case requestBatchMsg:
353 {
354 printBatchRequest(s, stream);
355 break;
356 }
357
358 case replyMsg:
359 {
360 printReply(s, stream);
361 break;
362 }
363
364 default:
365 {
366 break;
367 }
368 }
369
370 return type;
371 }
372
373 namespace
374 {
375
376 IceUtil::Mutex* slicingMutex = 0;
377
378 class Init
379 {
380 public:
381
Init()382 Init()
383 {
384 slicingMutex = new IceUtil::Mutex;
385 }
386
~Init()387 ~Init()
388 {
389 delete slicingMutex;
390 slicingMutex = 0;
391 }
392 };
393
394 Init init;
395
396 }
397
398 void
traceSlicing(const char * kind,const string & typeId,const char * slicingCat,const LoggerPtr & logger)399 IceInternal::traceSlicing(const char* kind, const string& typeId, const char* slicingCat, const LoggerPtr& logger)
400 {
401 IceUtilInternal::MutexPtrLock<IceUtil::Mutex> lock(slicingMutex);
402 static set<string> slicingIds;
403 if(slicingIds.insert(typeId).second)
404 {
405 string s("unknown ");
406 s += kind;
407 s += " type `" + typeId + "'";
408 logger->trace(slicingCat, s);
409 }
410 }
411
412 void
traceSend(const OutputStream & str,const LoggerPtr & logger,const TraceLevelsPtr & tl)413 IceInternal::traceSend(const OutputStream& str, const LoggerPtr& logger, const TraceLevelsPtr& tl)
414 {
415 if(tl->protocol >= 1)
416 {
417 OutputStream& stream = const_cast<OutputStream&>(str);
418 InputStream is(stream.instance(), stream.getEncoding(), stream);
419 is.i = is.b.begin();
420
421 ostringstream s;
422 Byte type = printMessage(s, is);
423
424 logger->trace(tl->protocolCat, "sending " + getMessageTypeAsString(type) + " " + s.str());
425 }
426 }
427
428 void
traceRecv(const InputStream & str,const LoggerPtr & logger,const TraceLevelsPtr & tl)429 IceInternal::traceRecv(const InputStream& str, const LoggerPtr& logger, const TraceLevelsPtr& tl)
430 {
431 if(tl->protocol >= 1)
432 {
433 InputStream& stream = const_cast<InputStream&>(str);
434 InputStream::Container::iterator p = stream.i;
435 stream.i = stream.b.begin();
436
437 ostringstream s;
438 Byte type = printMessage(s, stream);
439
440 logger->trace(tl->protocolCat, "received " + getMessageTypeAsString(type) + " " + s.str());
441 stream.i = p;
442 }
443 }
444
445 void
trace(const char * heading,const OutputStream & str,const LoggerPtr & logger,const TraceLevelsPtr & tl)446 IceInternal::trace(const char* heading, const OutputStream& str, const LoggerPtr& logger, const TraceLevelsPtr& tl)
447 {
448 if(tl->protocol >= 1)
449 {
450 OutputStream& stream = const_cast<OutputStream&>(str);
451 InputStream is(stream.instance(), stream.getEncoding(), stream);
452 is.i = is.b.begin();
453
454 ostringstream s;
455 s << heading;
456 printMessage(s, is);
457
458 logger->trace(tl->protocolCat, s.str());
459 }
460 }
461
462 void
trace(const char * heading,const InputStream & str,const LoggerPtr & logger,const TraceLevelsPtr & tl)463 IceInternal::trace(const char* heading, const InputStream& str, const LoggerPtr& logger, const TraceLevelsPtr& tl)
464 {
465 if(tl->protocol >= 1)
466 {
467 InputStream& stream = const_cast<InputStream&>(str);
468 InputStream::Container::iterator p = stream.i;
469 stream.i = stream.b.begin();
470
471 ostringstream s;
472 s << heading;
473 printMessage(s, stream);
474
475 logger->trace(tl->protocolCat, s.str());
476 stream.i = p;
477 }
478 }
479