123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501 |
- /*====================================================================*
- *
- * Copyright (c) 2013 Qualcomm Atheros, Inc.
- *
- * All rights reserved.
- *
- *====================================================================*/
- /*====================================================================*
- *
- * CPLNetwork.cpp - CPLNetwork class definition;
- *
- * powerline station enumerator;
- *
- * the collection of CPLStations on a single powerline network;
- *
- * Contributor(s):
- * Charles Maier <charles.maier@intellon.com>
- *
- *--------------------------------------------------------------------*/
- #ifndef CPLNETWORK_SOURCE
- #define CPLNETWORK_SOURCE
- /*====================================================================*
- * system header files;
- *--------------------------------------------------------------------*/
- #include <iostream>
- #include <cstring>
- /*====================================================================*
- * system header files;
- *--------------------------------------------------------------------*/
- #if defined (__linux__)
- # include <sys/socket.h>
- # include <net/ethernet.h>
- # include <net/if.h>
- #elif defined (__APPLE__)
- # include <sys/socket.h>
- # include <net/ethernet.h>
- # include <net/if.h>
- #elif defined (__OpenBSD__)
- # include <sys/socket.h>
- # include <net/if.h>
- # include <netinet/in.h>
- # include <netinet/if_ether.h>
- #elif defined (WINPCAP)
- # include <pcap.h>
- #else
- #error "Unknown environment"
- #endif
- /*====================================================================*
- * custom header files;
- *--------------------------------------------------------------------*/
- #include "../classes/CPLNetwork.hpp"
- #include "../classes/ointellon.hpp"
- #include "../classes/ohomeplug.hpp"
- #include "../classes/oerror.hpp"
- /*====================================================================*
- *
- * bool Empty (void) const;
- *
- * return true if there are no stations;
- *
- *--------------------------------------------------------------------*/
- bool CPLNetwork::Empty (void) const
- {
- return (!this->mcount);
- }
- /*====================================================================*
- *
- * bool End (void) const;
- *
- * return true if the last station has been reached;
- *
- *--------------------------------------------------------------------*/
- bool CPLNetwork::End (void) const
- {
- return (this->mindex >= this->mcount);
- }
- /*====================================================================*
- *
- * unsigned Count (void) const;
- *
- * return the number of stations;
- *
- *--------------------------------------------------------------------*/
- unsigned CPLNetwork::Count (void) const
- {
- return (this->mcount);
- }
- /*====================================================================*
- *
- * unsigned Index (void) const;
- *
- * return the current powerline station index;
- *
- *--------------------------------------------------------------------*/
- unsigned CPLNetwork::Index (void) const
- {
- return (this->mindex);
- }
- /*====================================================================*
- *
- * CPLNetwork & SelectFirst (void);
- *
- * select first station;
- *
- *--------------------------------------------------------------------*/
- CPLNetwork & CPLNetwork::SelectFirst (void)
- {
- this->mindex = 0;
- return (*this);
- }
- /*====================================================================*
- *
- * CPLNetwork & SelectFinal (void);
- *
- * select final station;
- *
- *--------------------------------------------------------------------*/
- CPLNetwork & CPLNetwork::SelectFinal (void)
- {
- this->mindex = this->mcount - 1;
- return (*this);
- }
- /*====================================================================*
- *
- * CPLNetwork & SelectPrev (void)
- *
- * select the prev station unless the current station is the
- * first station; same as operator --;
- *
- *--------------------------------------------------------------------*/
- CPLNetwork & CPLNetwork::SelectPrev (void)
- {
- if (this->mindex > 0)
- {
- this->mindex--;
- }
- return (*this);
- }
- /*====================================================================*
- *
- * CPLNetwork & SelectNext (void)
- *
- * select the next station unless the current station is the
- * final station; same as operator ++;
- *
- *--------------------------------------------------------------------*/
- CPLNetwork & CPLNetwork::SelectNext (void)
- {
- if (this->mindex < this->mcount)
- {
- this->mindex++;
- }
- return (*this);
- }
- /*====================================================================*
- *
- * CPLNetwork & Select (unsigned index);
- *
- * select an station by number; same as operator [];
- *
- *--------------------------------------------------------------------*/
- CPLNetwork & CPLNetwork::Select (unsigned index)
- {
- this->mindex = index;
- if (this->mindex > this->mcount)
- {
- this->mindex = this->mcount;
- }
- return (*this);
- }
- /*====================================================================*
- *
- * CPLStation & operator = (unsigned index)
- *
- * select an station;
- *
- *--------------------------------------------------------------------*/
- CPLNetwork & CPLNetwork::operator = (unsigned index)
- {
- return (this->Select (index));
- }
- /*====================================================================*
- *
- * CPLStation & operator [] (unsigned index)
- *
- * select a station then return an instance of it;
- *
- *--------------------------------------------------------------------*/
- CPLStation & CPLNetwork::operator [] (unsigned index)
- {
- return (this->Select (index).Selected ());
- }
- /*====================================================================*
- *
- * CPLStation & Selected (void) const
- *
- * return the selected station;
- *
- *--------------------------------------------------------------------*/
- CPLStation & CPLNetwork::Selected (void) const
- {
- return (* this->mtable [this->mindex]);
- }
- /*====================================================================*
- *
- * CPLStation & Station (void) const
- *
- * return the selected station;
- *
- *--------------------------------------------------------------------*/
- CPLStation & CPLNetwork::Station (void) const
- {
- return (* this->mtable [this->mindex]);
- }
- /*====================================================================*
- *
- * CPLNetwork & Enumerate (void);
- *
- * interate through stations and print each on stdout but do not
- * change the selected station;
- *
- *--------------------------------------------------------------------*/
- CPLNetwork & CPLNetwork::Enumerate (void)
- {
- for (unsigned index = 0; index < this->mcount; index++)
- {
- this->mtable [index]->Print ();
- }
- return (*this);
- }
- /*====================================================================*
- *
- * void platform (CPLChannel * channel, CPLStation * station);
- *
- * update the mhardware and mfirmware members using a VS_SW_VER
- * management message;
- *
- *--------------------------------------------------------------------*/
- void CPLNetwork::platform (CPLChannel * channel, CPLStation * station)
- {
- ointellon intellon;
- byte message [ETHER_MAX_LEN];
- #ifndef __GNUC__
- #pragma pack (push,1)
- #endif
- struct __packed version
- {
- uint8_t MSTATUS;
- uint8_t MDEVICEID;
- uint8_t MVERSIONLENGTH;
- uint8_t MVERSION [128];
- }
- * version;
- #ifndef __GNUC__
- #pragma pack (pop)
- #endif
- std::memset (message, 0, sizeof (message));;
- intellon.ImportPeerAddress (station->NodeAddress ());
- intellon.ImportHostAddress (channel->HostAddress ());
- version = (struct version *)(intellon.ExportHeader (message));
- if (channel->SendMessage (message, ETHER_MIN_LEN) > 0)
- {
- while (channel->ReadMessage (message, sizeof (message)) > 0)
- {
- intellon.ImportHeader (message);
- if (intellon.IsMessageType (0, (VS_SW_VER | MMTYPE_CNF)))
- {
- station->mhardware = version->MDEVICEID;
- std::memcpy (station->mfirmware, version->MVERSION, version->MVERSIONLENGTH);
- break;
- }
- }
- }
- return;
- }
- /*====================================================================*
- *
- * CPLNetwork (CPLChannel * channel);
- *
- * instantiate the class with a collection of CPLStations; channel
- * specifies the interface and station to interrogate;
- *
- * interrogate the specified station using a VS_NE_INFO message;
- * for each neighbor, use a VS_SW_VER message to get the hardware
- * type and firmware revsion string;
- *
- * return an empty collection if channel peer address is either an
- * Ethernet broadcast address or an Intellon Localcast address;
- *
- * all stations are assumed to be ordinary stations unless their
- * hardware address is the CCO hardware address;
- *
- * the first station is first assumed to be the host bridge until
- * proven otherwise; successive stations are assumed to be remote
- * unless the BDA is the host hardware address; if that happens,
- * that station is the host bridge and the first station is remote;
- * the host hardware address is the peer address for confirmation
- * messages;
- *
- *--------------------------------------------------------------------*/
- CPLNetwork::CPLNetwork (CPLChannel * channel)
- {
- ointellon intellon;
- byte message [ETHER_MAX_LEN];
- #ifndef __GNUC__
- #pragma pack (push,1)
- #endif
- struct __packed station
- {
- uint8_t MAC [ETHER_ADDR_LEN];
- uint8_t TEI;
- uint8_t BDA [ETHER_ADDR_LEN];
- uint8_t AVGTX;
- uint8_t AVGRX;
- }
- * station;
- struct __packed network
- {
- uint8_t NID [7];
- uint8_t SNID;
- uint8_t TEI;
- uint8_t ROLE;
- uint8_t CCO_MAC [ETHER_ADDR_LEN];
- uint8_t CCO_TEI;
- uint8_t NUMSTAS;
- struct station station [1];
- }
- * network;
- struct __packed networks
- {
- uint8_t NUMAVLNS;
- struct network network [1];
- }
- * networks;
- #ifndef __GNUC__
- #pragma pack (pop)
- #endif
- this->mindex = 0;
- this->mcount = 0;
- this->mtable = new CPLStation * [CPLCHANNEL_DEVICES_MAX];
- if (!std::memcmp (channel->PeerAddress (), oethernet::EmptycastAddress, ETHER_ADDR_LEN))
- {
- oerror::error (0, ECANCELED, "Emptycast used to instantiate CPLNetwork");
- return;
- }
- if (!std::memcmp (channel->PeerAddress (), oethernet::BroadcastAddress, ETHER_ADDR_LEN))
- {
- oerror::error (0, ECANCELED, "Broadcast used to instantiate CPLNetwork");
- return;
- }
- if (!std::memcmp (channel->PeerAddress (), ointellon::LocalcastAddress, ETHER_ADDR_LEN))
- {
- oerror::error (0, ECANCELED, "Localcast used to instantiate CPLNetwork");
- return;
- }
- std::memset (message, 0, sizeof (message));
- intellon.ImportPeerAddress (channel->PeerAddress ());
- intellon.ImportHostAddress (channel->HostAddress ());
- intellon.SetMessageType (VS_NW_INFO | MMTYPE_REQ);
- networks = (struct networks *)(intellon.ExportHeader (message));
- if (channel->SendMessage (message, ETHER_MIN_LEN) <= 0)
- {
- oerror::error (0, errno, CPLCHANNEL_CANTSEND);
- return;
- }
- if (channel->ReadMessage (message, sizeof (message)) <= 0)
- {
- oerror::error (0, errno, CPLCHANNEL_CANTREAD);
- return;
- }
- intellon.ImportHeader (message);
- network = (struct network *)(&networks->network);
- while (networks->NUMAVLNS--)
- {
- CPLStation * bridge = new CPLStation;
- bridge->mstation = network->TEI;
- bridge->mlink = CPLSTATION_BRIDGE;
- bridge->mrole = (network->TEI == network->CCO_TEI);
- bridge->mtxrate = 0;
- bridge->mrxrate = 0;
- intellon.ExportPeerAddress (bridge->mhostaddr);
- intellon.ExportHostAddress (bridge->mnodeaddr);
- CPLNetwork::platform (channel, bridge);
- this->mtable [this->mcount++] = bridge;
- station = (struct station *)(&network->station);
- while (network->NUMSTAS--)
- {
- if (std::memcmp (station->MAC, oethernet::BroadcastAddress, ETHER_ADDR_LEN))
- {
- CPLStation * device = new CPLStation;
- device->mstation = station->TEI;
- device->mlink = CPLSTATION_REMOTE;
- if (!std::memcmp (station->BDA, intellon.PeerAddress (), ETHER_ADDR_LEN))
- {
- device->mlink = CPLSTATION_BRIDGE;
- bridge->mlink = CPLSTATION_REMOTE;
- }
- device->mrole = (station->TEI == network->CCO_TEI);
- device->mtxrate = station->AVGTX;
- device->mrxrate = station->AVGRX;
- std::memcpy (device->mnodeaddr, station->MAC, sizeof (device->mnodeaddr));
- std::memcpy (device->mhostaddr, station->BDA, sizeof (device->mhostaddr));
- CPLNetwork::platform (channel, device);
- this->mtable [this->mcount++] = device;
- }
- station++;
- }
- network = (struct network *)(station);
- }
- return;
- }
- /*====================================================================*
- *
- * ~CPLNetwork ()
- *
- * delete table after deleting stations;
- *
- *--------------------------------------------------------------------*/
- CPLNetwork::~CPLNetwork ()
- {
- while (this->mcount--)
- {
- delete this->mtable [this->mcount];
- }
- delete [] this->mtable;
- return;
- }
- /*====================================================================*
- * end definition;
- *--------------------------------------------------------------------*/
- #endif
|