forest-net
an overlay networks for large-scale virtual worlds
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
PacketLog.cpp
Go to the documentation of this file.
1 
9 #include "PacketLog.h"
10 
11 namespace forest {
12 
16  evec = new EventStruct[MAX_EVENTS];
18  fvec = new PacketFilter[MAX_FILTERS+1];
19  filters = new UiSetPair(MAX_FILTERS);
20 
22  dumpTime = 0;
23 
24  // default behavior just logs all packets to stdout
25  logOn = true; logLocal = true;
26  numOut = numDataOut = 0;
27 }
28 
30 PacketLog::~PacketLog() { delete [] evec; delete [] fvec; delete filters; }
31 
44 void PacketLog::log(pktx px, int lnk, bool sendFlag, uint64_t now) {
45  if (!logOn) return;
46  if (firstFilter() != 0) {
47  for (fltx f = firstFilter(); f != 0; f = nextFilter(f)) {
48  if (match(f,px,lnk,sendFlag)) break;
49  if (nextFilter(f) == 0) return; // no filters match
50  }
51  }
52  // reach here if no filters or packet matched some filter
53  // make a record in event vector
54  int px1 = ps->fullCopy(px);
55  if (px1 == 0 || eventCount == MAX_EVENTS) { // record gap
56  if (px1 != 0) ps->free(px1);
57  // use px == 0 to indicate gap in sequence
58  // for these records, link field is used to record
59  // number of packets that were missed (size of gap)
60  if (eventCount > 0 && evec[lastEvent].px == 0) {
61  // existing gap record
62  evec[lastEvent].link++;
63  } else {
64  // convert last record to a gap record
65  evec[lastEvent].px = 0;
66  evec[lastEvent].link = 1;
67  evec[lastEvent].time = now;
68  if (eventCount == 0) eventCount = 1;
69  }
70  } else {
71  // common case - just add new record for packet
72  if (eventCount > 0)
73  if (++lastEvent >= MAX_EVENTS) lastEvent = 0;
74  eventCount++;
75  evec[lastEvent].px = px1;
76  evec[lastEvent].sendFlag = sendFlag;
77  evec[lastEvent].link = lnk;
78  evec[lastEvent].time = now;
79  }
80  if (!logLocal) return;
81  // optionally write log entries to cout once per second
82  if (now < dumpTime + 1000000000) return;
83  dumpTime = now;
84  write(cout);
85  // stop logging when we hit the output limit while logging locally
86  // can stil re-enable logging
87  if (numOut > OUT_LIMIT) logOn = logLocal = false;
88 }
89 
93 void PacketLog::write(ostream& out) {
94  stringstream ss;
95  while (eventCount > 0) {
96  int px = evec[firstEvent].px;
97  if (numOut <= OUT_LIMIT) {
98  string s;
99  out << Misc::nstime2string(evec[firstEvent].time,s);
100  if (px == 0) {
101  out << " missing " << evec[firstEvent].link
102  << " packets " << endl;
103  numOut++;
104  } else {
105  Packet& p = ps->getPacket(px);
106  if (p.type != Forest::CLIENT_DATA ||
108  if (evec[firstEvent].sendFlag)
109  out << " send ";
110  else
111  out << " recv ";
112  out << "link " << setw(2)
113  << evec[firstEvent].link;
114  out << " " << p.toString(s);
115  numOut++;
116  if (p.type == Forest::CLIENT_DATA)
117  numDataOut++;
118  }
119  }
120  }
121  ps->free(px);
122  if (--eventCount > 0)
123  if (++firstEvent >= MAX_EVENTS) firstEvent = 0;
124  }
125  out.flush();
126 }
127 
131  while (eventCount > 0) {
132  ps->free(evec[firstEvent].px);
133  eventCount--;
134  if (++firstEvent >= MAX_EVENTS) firstEvent = 0;
135  }
136 }
137 
146 int PacketLog::extract(int maxLen, string& s) {
147  if (firstFilter() == 0) { return 0; }
148  logLocal = false;
149  stringstream ss;
150  int count = 0; s = "";
151  while (eventCount > 0) {
152  ss.str("");
153  int px = evec[firstEvent].px;
154  string s1;
155  ss << Misc::nstime2string(evec[firstEvent].time,s1);
156  if (px == 0) {
157  ss << " missing " << evec[firstEvent].link
158  << " packets " << endl;
159  } else {
160  if (evec[firstEvent].sendFlag) ss << " send ";
161  else ss << " recv ";
162  ss << "link " << setw(2) << evec[firstEvent].link;
163  ss << " " << ps->getPacket(px).toString(s1);
164  }
165  if (s.length() + ss.str().length() > maxLen) break;
166  s += ss.str();
167  ps->free(px);
168  count++;
169  if (--eventCount > 0)
170  if (++firstEvent >= MAX_EVENTS) firstEvent = 0;
171  }
172  return count;
173 }
174 
180  fltx f = filters->firstOut();
181  if (f == 0) return 0;
182  filters->swap(f); disable(f);
183  return f;
184 }
185 
187 void PacketLog::dropFilter(fltx f) {
188  if (!filters->isIn(f)) return;
189  disable(f); filters->swap(f);
190 }
191 
192 } // ends namespace
193