forest-net
an overlay networks for large-scale virtual worlds
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
CtlPktSav.cpp
1 
24 #include "CtlPkt.h"
25 
26 namespace forest {
27 
28 
31 CtlPkt::CtlPkt() { payload = 0; reset(); }
32 
33 CtlPkt::CtlPkt(CpTypeIndex cpt, CpRrType rrt, uint64_t seq)
34  : cpType(cpt), rrType(rrt), seqNum(seq) {
35  payload = 0; reset();
36 }
37 
39 CtlPkt::~CtlPkt() { }
40 
43 void CtlPkt::reset() {
44  for (int i = CPA_START; i < CPA_END; i++) aSet[i] = false;
45 }
46 void CtlPkt::reset(CpTypeIndex cpt, CpRrType rrt, uint64_t seq) {
47  cpType = cpt; rrType = rrt; seqNum = seq;
48  payload = 0; reset();
49 }
50 
56 int CtlPkt::pack(uint32_t* pl) {
57  payload = pl;
58  if (!CpType::validIndex(cpType))
59  return 0;
60  if (rrType != REQUEST && rrType != POS_REPLY && rrType != NEG_REPLY)
61  return 0;
62  pp = 0;
63  payload[pp++] = htonl(CpType::getCode(cpType));
64  payload[pp++] = htonl(rrType);
65  payload[pp++] = htonl((uint32_t) (seqNum >> 32));
66  payload[pp++] = htonl((uint32_t) (seqNum & 0xffffffff));
67 
68  if (rrType == REQUEST) {
69  // pack all request attributes and confirm that
70  // required attributes are present
71  for (int i = CPA_START + 1; i < CPA_END; i++) {
72  CpAttrIndex ii = CpAttrIndex(i);
73  if (CpType::isReqAttr(cpType, ii)) {
74  if (isSet(ii)) packAttr(ii);
75  else if (CpType::isReqReqAttr(cpType,ii))
76  return 0;
77  }
78  }
79  } else if (rrType == POS_REPLY) {
80  for (int i = CPA_START + 1; i < CPA_END; i++) {
81  CpAttrIndex ii = CpAttrIndex(i);
82  if (CpType::isRepAttr(cpType, ii)) {
83  if (isSet(ii)) packAttr(ii);
84  else {
85  return 0;
86  }
87  }
88  }
89  } else {
90  int j = Util::strnlen(errMsg,MAX_MSG_LEN);
91  if (j == MAX_MSG_LEN) errMsg[MAX_MSG_LEN] = 0;
92  strncpy((char*) &payload[pp], errMsg, j+1);
93  return 4*pp + j+1;
94  }
95 
96  return 4*pp;
97 }
98 
104 bool CtlPkt::unpack(uint32_t* pl, int pleng) {
105  payload = pl;
106  pleng /= 4; // to get length in 32 bit words
107  if (pleng < 4) return false; // too short for control packet
108 
109  pp = 0;
110  cpType = CpType::getIndexByCode(ntohl(payload[pp++]));
111  rrType = (CpRrType) ntohl(payload[pp++]);
112  seqNum = ntohl(payload[pp++]); seqNum <<= 32;
113  seqNum |= ntohl(payload[pp++]);
114 
115  if (!CpType::validIndex(cpType)) return false;
116  if (rrType != REQUEST && rrType != POS_REPLY && rrType != NEG_REPLY)
117  return false;
118 
119  if (rrType == NEG_REPLY) {
120  strncpy(errMsg,(char*) &payload[pp], MAX_MSG_LEN);
121  errMsg[MAX_MSG_LEN] = 0;
122  return true;
123  }
124 
125  // unpack all attribute/value pairs
126  while (pp < pleng-1) { if (unpackAttr() == 0) return false; }
127 
128  if (rrType == REQUEST) {
129  // confirm that required attributes are present
130  for (int i = CPA_START + 1; i < CPA_END; i++) {
131  CpAttrIndex ii = CpAttrIndex(i);
132  if (CpType::isReqReqAttr(cpType, ii) && !isSet(ii)) {
133  return false;
134  }
135  }
136  } else {
137  // confirm that all reply attributes are present
138  for (int i = CPA_START + 1; i < CPA_END; i++) {
139  CpAttrIndex ii = CpAttrIndex(i);
140  if (CpType::isRepAttr(cpType, ii) && !isSet(ii)) {
141  return false;
142  }
143  }
144  }
145 
146  return true;
147 }
148 
154 string& CtlPkt::avPair2string(CpAttrIndex ii, string& s) {
155  stringstream ss;
156  ss << CpAttr::getName(ii) << "=";
157  if (!isSet(ii)) {
158  ss << "(missing)"; s = ss.str(); return s;
159  }
160  int32_t val = getAttr(ii);
161  if (ii == COMTREE_OWNER || ii == LEAF_ADR ||
162  ii == PEER_ADR || ii == PEER_DEST ||
163  ii == RTR_ADR || ii == CLIENT_ADR ||
164  ii == FIRST_LEAF_ADR || ii == LAST_LEAF_ADR ||
165  ii == DEST_ADR) {
166  ss << Forest::fAdr2string((fAdr_t) val,s);
167  } else if (ii == LOCAL_IP || ii == PEER_IP ||
168  ii == CLIENT_IP || ii == RTR_IP) {
169  ss << Np4d::ip2string(val,s);
170  } else if (ii == PEER_TYPE) {
171  ss << Forest::nodeType2string((ntyp_t) val,s);
172  } else {
173  ss << val;
174  }
175  s = ss.str();
176  return s;
177 }
178 
183 string& CtlPkt::toString(string& s) {
184  stringstream ss;
185  bool reqPkt = (rrType == REQUEST);
186 
187  ss << CpType::getName(cpType);
188  if (reqPkt) ss << " (request,";
189  else if (rrType == POS_REPLY) ss << " (pos reply,";
190  else ss << " (neg reply,";
191  ss << seqNum << "):";
192 
193  if (rrType == REQUEST) {
194  for (int i = CPA_START+1; i < CPA_END; i++) {
195  CpAttrIndex ii = CpAttrIndex(i);
196  if (!CpType::isReqAttr(cpType,ii)) continue;
197  if (!CpType::isReqReqAttr(cpType,ii) && !isSet(ii))
198  continue;
199  ss << " " << avPair2string(ii,s);
200  }
201  } else if (rrType == POS_REPLY) {
202  for (int i = CPA_START+1; i < CPA_END; i++) {
203  CpAttrIndex ii = CpAttrIndex(i);
204  if (!CpType::isRepAttr(cpType,ii)) continue;
205  ss << " " << avPair2string(ii,s);
206  }
207  } else {
208  ss << " errMsg=" << errMsg;
209  }
210  ss << endl;
211  s = ss.str();
212  return s;
213 }
214 
215 } // ends namespace
216