CPLNetwork.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  1. /*====================================================================*
  2. *
  3. * Copyright (c) 2013 Qualcomm Atheros, Inc.
  4. *
  5. * All rights reserved.
  6. *
  7. *====================================================================*/
  8. /*====================================================================*
  9. *
  10. * CPLNetwork.cpp - CPLNetwork class definition;
  11. *
  12. * powerline station enumerator;
  13. *
  14. * the collection of CPLStations on a single powerline network;
  15. *
  16. * Contributor(s):
  17. * Charles Maier <charles.maier@intellon.com>
  18. *
  19. *--------------------------------------------------------------------*/
  20. #ifndef CPLNETWORK_SOURCE
  21. #define CPLNETWORK_SOURCE
  22. /*====================================================================*
  23. * system header files;
  24. *--------------------------------------------------------------------*/
  25. #include <iostream>
  26. #include <cstring>
  27. /*====================================================================*
  28. * system header files;
  29. *--------------------------------------------------------------------*/
  30. #if defined (__linux__)
  31. # include <sys/socket.h>
  32. # include <net/ethernet.h>
  33. # include <net/if.h>
  34. #elif defined (__APPLE__)
  35. # include <sys/socket.h>
  36. # include <net/ethernet.h>
  37. # include <net/if.h>
  38. #elif defined (__OpenBSD__)
  39. # include <sys/socket.h>
  40. # include <net/if.h>
  41. # include <netinet/in.h>
  42. # include <netinet/if_ether.h>
  43. #elif defined (WINPCAP)
  44. # include <pcap.h>
  45. #else
  46. #error "Unknown environment"
  47. #endif
  48. /*====================================================================*
  49. * custom header files;
  50. *--------------------------------------------------------------------*/
  51. #include "../classes/CPLNetwork.hpp"
  52. #include "../classes/ointellon.hpp"
  53. #include "../classes/ohomeplug.hpp"
  54. #include "../classes/oerror.hpp"
  55. /*====================================================================*
  56. *
  57. * bool Empty (void) const;
  58. *
  59. * return true if there are no stations;
  60. *
  61. *--------------------------------------------------------------------*/
  62. bool CPLNetwork::Empty (void) const
  63. {
  64. return (!this->mcount);
  65. }
  66. /*====================================================================*
  67. *
  68. * bool End (void) const;
  69. *
  70. * return true if the last station has been reached;
  71. *
  72. *--------------------------------------------------------------------*/
  73. bool CPLNetwork::End (void) const
  74. {
  75. return (this->mindex >= this->mcount);
  76. }
  77. /*====================================================================*
  78. *
  79. * unsigned Count (void) const;
  80. *
  81. * return the number of stations;
  82. *
  83. *--------------------------------------------------------------------*/
  84. unsigned CPLNetwork::Count (void) const
  85. {
  86. return (this->mcount);
  87. }
  88. /*====================================================================*
  89. *
  90. * unsigned Index (void) const;
  91. *
  92. * return the current powerline station index;
  93. *
  94. *--------------------------------------------------------------------*/
  95. unsigned CPLNetwork::Index (void) const
  96. {
  97. return (this->mindex);
  98. }
  99. /*====================================================================*
  100. *
  101. * CPLNetwork & SelectFirst (void);
  102. *
  103. * select first station;
  104. *
  105. *--------------------------------------------------------------------*/
  106. CPLNetwork & CPLNetwork::SelectFirst (void)
  107. {
  108. this->mindex = 0;
  109. return (*this);
  110. }
  111. /*====================================================================*
  112. *
  113. * CPLNetwork & SelectFinal (void);
  114. *
  115. * select final station;
  116. *
  117. *--------------------------------------------------------------------*/
  118. CPLNetwork & CPLNetwork::SelectFinal (void)
  119. {
  120. this->mindex = this->mcount - 1;
  121. return (*this);
  122. }
  123. /*====================================================================*
  124. *
  125. * CPLNetwork & SelectPrev (void)
  126. *
  127. * select the prev station unless the current station is the
  128. * first station; same as operator --;
  129. *
  130. *--------------------------------------------------------------------*/
  131. CPLNetwork & CPLNetwork::SelectPrev (void)
  132. {
  133. if (this->mindex > 0)
  134. {
  135. this->mindex--;
  136. }
  137. return (*this);
  138. }
  139. /*====================================================================*
  140. *
  141. * CPLNetwork & SelectNext (void)
  142. *
  143. * select the next station unless the current station is the
  144. * final station; same as operator ++;
  145. *
  146. *--------------------------------------------------------------------*/
  147. CPLNetwork & CPLNetwork::SelectNext (void)
  148. {
  149. if (this->mindex < this->mcount)
  150. {
  151. this->mindex++;
  152. }
  153. return (*this);
  154. }
  155. /*====================================================================*
  156. *
  157. * CPLNetwork & Select (unsigned index);
  158. *
  159. * select an station by number; same as operator [];
  160. *
  161. *--------------------------------------------------------------------*/
  162. CPLNetwork & CPLNetwork::Select (unsigned index)
  163. {
  164. this->mindex = index;
  165. if (this->mindex > this->mcount)
  166. {
  167. this->mindex = this->mcount;
  168. }
  169. return (*this);
  170. }
  171. /*====================================================================*
  172. *
  173. * CPLStation & operator = (unsigned index)
  174. *
  175. * select an station;
  176. *
  177. *--------------------------------------------------------------------*/
  178. CPLNetwork & CPLNetwork::operator = (unsigned index)
  179. {
  180. return (this->Select (index));
  181. }
  182. /*====================================================================*
  183. *
  184. * CPLStation & operator [] (unsigned index)
  185. *
  186. * select a station then return an instance of it;
  187. *
  188. *--------------------------------------------------------------------*/
  189. CPLStation & CPLNetwork::operator [] (unsigned index)
  190. {
  191. return (this->Select (index).Selected ());
  192. }
  193. /*====================================================================*
  194. *
  195. * CPLStation & Selected (void) const
  196. *
  197. * return the selected station;
  198. *
  199. *--------------------------------------------------------------------*/
  200. CPLStation & CPLNetwork::Selected (void) const
  201. {
  202. return (* this->mtable [this->mindex]);
  203. }
  204. /*====================================================================*
  205. *
  206. * CPLStation & Station (void) const
  207. *
  208. * return the selected station;
  209. *
  210. *--------------------------------------------------------------------*/
  211. CPLStation & CPLNetwork::Station (void) const
  212. {
  213. return (* this->mtable [this->mindex]);
  214. }
  215. /*====================================================================*
  216. *
  217. * CPLNetwork & Enumerate (void);
  218. *
  219. * interate through stations and print each on stdout but do not
  220. * change the selected station;
  221. *
  222. *--------------------------------------------------------------------*/
  223. CPLNetwork & CPLNetwork::Enumerate (void)
  224. {
  225. for (unsigned index = 0; index < this->mcount; index++)
  226. {
  227. this->mtable [index]->Print ();
  228. }
  229. return (*this);
  230. }
  231. /*====================================================================*
  232. *
  233. * void platform (CPLChannel * channel, CPLStation * station);
  234. *
  235. * update the mhardware and mfirmware members using a VS_SW_VER
  236. * management message;
  237. *
  238. *--------------------------------------------------------------------*/
  239. void CPLNetwork::platform (CPLChannel * channel, CPLStation * station)
  240. {
  241. ointellon intellon;
  242. byte message [ETHER_MAX_LEN];
  243. #ifndef __GNUC__
  244. #pragma pack (push,1)
  245. #endif
  246. struct __packed version
  247. {
  248. uint8_t MSTATUS;
  249. uint8_t MDEVICEID;
  250. uint8_t MVERSIONLENGTH;
  251. uint8_t MVERSION [128];
  252. }
  253. * version;
  254. #ifndef __GNUC__
  255. #pragma pack (pop)
  256. #endif
  257. std::memset (message, 0, sizeof (message));;
  258. intellon.ImportPeerAddress (station->NodeAddress ());
  259. intellon.ImportHostAddress (channel->HostAddress ());
  260. version = (struct version *)(intellon.ExportHeader (message));
  261. if (channel->SendMessage (message, ETHER_MIN_LEN) > 0)
  262. {
  263. while (channel->ReadMessage (message, sizeof (message)) > 0)
  264. {
  265. intellon.ImportHeader (message);
  266. if (intellon.IsMessageType (0, (VS_SW_VER | MMTYPE_CNF)))
  267. {
  268. station->mhardware = version->MDEVICEID;
  269. std::memcpy (station->mfirmware, version->MVERSION, version->MVERSIONLENGTH);
  270. break;
  271. }
  272. }
  273. }
  274. return;
  275. }
  276. /*====================================================================*
  277. *
  278. * CPLNetwork (CPLChannel * channel);
  279. *
  280. * instantiate the class with a collection of CPLStations; channel
  281. * specifies the interface and station to interrogate;
  282. *
  283. * interrogate the specified station using a VS_NE_INFO message;
  284. * for each neighbor, use a VS_SW_VER message to get the hardware
  285. * type and firmware revsion string;
  286. *
  287. * return an empty collection if channel peer address is either an
  288. * Ethernet broadcast address or an Intellon Localcast address;
  289. *
  290. * all stations are assumed to be ordinary stations unless their
  291. * hardware address is the CCO hardware address;
  292. *
  293. * the first station is first assumed to be the host bridge until
  294. * proven otherwise; successive stations are assumed to be remote
  295. * unless the BDA is the host hardware address; if that happens,
  296. * that station is the host bridge and the first station is remote;
  297. * the host hardware address is the peer address for confirmation
  298. * messages;
  299. *
  300. *--------------------------------------------------------------------*/
  301. CPLNetwork::CPLNetwork (CPLChannel * channel)
  302. {
  303. ointellon intellon;
  304. byte message [ETHER_MAX_LEN];
  305. #ifndef __GNUC__
  306. #pragma pack (push,1)
  307. #endif
  308. struct __packed station
  309. {
  310. uint8_t MAC [ETHER_ADDR_LEN];
  311. uint8_t TEI;
  312. uint8_t BDA [ETHER_ADDR_LEN];
  313. uint8_t AVGTX;
  314. uint8_t AVGRX;
  315. }
  316. * station;
  317. struct __packed network
  318. {
  319. uint8_t NID [7];
  320. uint8_t SNID;
  321. uint8_t TEI;
  322. uint8_t ROLE;
  323. uint8_t CCO_MAC [ETHER_ADDR_LEN];
  324. uint8_t CCO_TEI;
  325. uint8_t NUMSTAS;
  326. struct station station [1];
  327. }
  328. * network;
  329. struct __packed networks
  330. {
  331. uint8_t NUMAVLNS;
  332. struct network network [1];
  333. }
  334. * networks;
  335. #ifndef __GNUC__
  336. #pragma pack (pop)
  337. #endif
  338. this->mindex = 0;
  339. this->mcount = 0;
  340. this->mtable = new CPLStation * [CPLCHANNEL_DEVICES_MAX];
  341. if (!std::memcmp (channel->PeerAddress (), oethernet::EmptycastAddress, ETHER_ADDR_LEN))
  342. {
  343. oerror::error (0, ECANCELED, "Emptycast used to instantiate CPLNetwork");
  344. return;
  345. }
  346. if (!std::memcmp (channel->PeerAddress (), oethernet::BroadcastAddress, ETHER_ADDR_LEN))
  347. {
  348. oerror::error (0, ECANCELED, "Broadcast used to instantiate CPLNetwork");
  349. return;
  350. }
  351. if (!std::memcmp (channel->PeerAddress (), ointellon::LocalcastAddress, ETHER_ADDR_LEN))
  352. {
  353. oerror::error (0, ECANCELED, "Localcast used to instantiate CPLNetwork");
  354. return;
  355. }
  356. std::memset (message, 0, sizeof (message));
  357. intellon.ImportPeerAddress (channel->PeerAddress ());
  358. intellon.ImportHostAddress (channel->HostAddress ());
  359. intellon.SetMessageType (VS_NW_INFO | MMTYPE_REQ);
  360. networks = (struct networks *)(intellon.ExportHeader (message));
  361. if (channel->SendMessage (message, ETHER_MIN_LEN) <= 0)
  362. {
  363. oerror::error (0, errno, CPLCHANNEL_CANTSEND);
  364. return;
  365. }
  366. if (channel->ReadMessage (message, sizeof (message)) <= 0)
  367. {
  368. oerror::error (0, errno, CPLCHANNEL_CANTREAD);
  369. return;
  370. }
  371. intellon.ImportHeader (message);
  372. network = (struct network *)(&networks->network);
  373. while (networks->NUMAVLNS--)
  374. {
  375. CPLStation * bridge = new CPLStation;
  376. bridge->mstation = network->TEI;
  377. bridge->mlink = CPLSTATION_BRIDGE;
  378. bridge->mrole = (network->TEI == network->CCO_TEI);
  379. bridge->mtxrate = 0;
  380. bridge->mrxrate = 0;
  381. intellon.ExportPeerAddress (bridge->mhostaddr);
  382. intellon.ExportHostAddress (bridge->mnodeaddr);
  383. CPLNetwork::platform (channel, bridge);
  384. this->mtable [this->mcount++] = bridge;
  385. station = (struct station *)(&network->station);
  386. while (network->NUMSTAS--)
  387. {
  388. if (std::memcmp (station->MAC, oethernet::BroadcastAddress, ETHER_ADDR_LEN))
  389. {
  390. CPLStation * device = new CPLStation;
  391. device->mstation = station->TEI;
  392. device->mlink = CPLSTATION_REMOTE;
  393. if (!std::memcmp (station->BDA, intellon.PeerAddress (), ETHER_ADDR_LEN))
  394. {
  395. device->mlink = CPLSTATION_BRIDGE;
  396. bridge->mlink = CPLSTATION_REMOTE;
  397. }
  398. device->mrole = (station->TEI == network->CCO_TEI);
  399. device->mtxrate = station->AVGTX;
  400. device->mrxrate = station->AVGRX;
  401. std::memcpy (device->mnodeaddr, station->MAC, sizeof (device->mnodeaddr));
  402. std::memcpy (device->mhostaddr, station->BDA, sizeof (device->mhostaddr));
  403. CPLNetwork::platform (channel, device);
  404. this->mtable [this->mcount++] = device;
  405. }
  406. station++;
  407. }
  408. network = (struct network *)(station);
  409. }
  410. return;
  411. }
  412. /*====================================================================*
  413. *
  414. * ~CPLNetwork ()
  415. *
  416. * delete table after deleting stations;
  417. *
  418. *--------------------------------------------------------------------*/
  419. CPLNetwork::~CPLNetwork ()
  420. {
  421. while (this->mcount--)
  422. {
  423. delete this->mtable [this->mcount];
  424. }
  425. delete [] this->mtable;
  426. return;
  427. }
  428. /*====================================================================*
  429. * end definition;
  430. *--------------------------------------------------------------------*/
  431. #endif