Added PeerNetStateBox. The idea is a single class which takes all the inputs and

determines the Network State (Good, Bad, Firewalled etc) & if a Reset is required 
Using this we should be able to provide very good feedback to the user to help them 
get RS working optimally. Unfortunately it is quite a complex state box to get right!
	* Outlined basics of PeerNetStateBox. (Lots still to do!)
	* Added initial inputs for PeerNetStateBox.
	* Added NetState, NetworkMode, NatType, NatHole, ConnectMode outputs.
	* piped output through to GUI.



git-svn-id: http://svn.code.sf.net/p/retroshare/code/branches/v0.5-peernet@4274 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
drbob 2011-06-16 16:14:30 +00:00
parent aee6879561
commit ba77a0dd16
7 changed files with 1065 additions and 24 deletions

View file

@ -17,10 +17,12 @@ QT += network xml script
SOURCES += main.cpp\
mainwindow.cpp \
peernet.cc
peernet.cc \
netstatebox.cc
HEADERS += mainwindow.h \
peernet.h
peernet.h \
netstatebox.h
FORMS += mainwindow.ui

View file

@ -61,8 +61,139 @@ void MainWindow::update()
void MainWindow::updateNetStatus()
{
QString status = QString::fromStdString(mPeerNet->getPeerStatusString());
QString oldstatus = ui->peerLine->text();
if (oldstatus != status)
{
ui->peerLine->setText(status);
}
uint32_t netMode = mPeerNet->getNetStateNetworkMode();
QLabel *label = ui->networkLabel;
switch(netMode)
{
case PNSB_NETWORK_UNKNOWN:
label->setText("Unknown NetState");
break;
case PNSB_NETWORK_OFFLINE:
label->setText("Offline");
break;
case PNSB_NETWORK_LOCALNET:
label->setText("Local Net");
break;
case PNSB_NETWORK_BEHINDNAT:
label->setText("Behind NAT");
break;
case PNSB_NETWORK_EXTERNALIP:
label->setText("External IP");
break;
}
label = ui->natTypeLabel;
switch(mPeerNet->getNetStateNatTypeMode())
{
case PNSB_NATTYPE_UNKNOWN:
label->setText("UNKNOWN NAT STATE");
break;
case PNSB_NATTYPE_SYMMETRIC:
label->setText("SYMMETRIC NAT");
break;
case PNSB_NATTYPE_RESTRICTED_CONE:
label->setText("RESTRICTED CONE NAT");
break;
case PNSB_NATTYPE_FULL_CONE:
label->setText("FULL CONE NAT");
break;
case PNSB_NATTYPE_OTHER:
label->setText("OTHER NAT");
break;
case PNSB_NATTYPE_NONE:
label->setText("NO NAT");
break;
}
label = ui->natHoleLabel;
switch(mPeerNet->getNetStateNatHoleMode())
{
case PNSB_NATHOLE_UNKNOWN:
label->setText("UNKNOWN NAT HOLE STATUS");
break;
case PNSB_NATHOLE_NONE:
label->setText("NO NAT HOLE");
break;
case PNSB_NATHOLE_UPNP:
label->setText("UPNP FORWARD");
break;
case PNSB_NATHOLE_NATPMP:
label->setText("NATPMP FORWARD");
break;
case PNSB_NATHOLE_FORWARDED:
label->setText("MANUAL FORWARD");
break;
}
label = ui->connectLabel;
std::ostringstream connOut;
uint32_t connect = mPeerNet->getNetStateConnectModes();
if (connect & PNSB_CONNECT_OUTGOING_TCP)
{
connOut << "TCP_OUT ";
}
if (connect & PNSB_CONNECT_ACCEPT_TCP)
{
connOut << "TCP_IN ";
}
if (connect & PNSB_CONNECT_DIRECT_UDP)
{
connOut << "DIRECT_UDP ";
}
if (connect & PNSB_CONNECT_PROXY_UDP)
{
connOut << "PROXY_UDP ";
}
if (connect & PNSB_CONNECT_RELAY_UDP)
{
connOut << "RELAY_UDP ";
}
label->setText(QString::fromStdString(connOut.str()));
label = ui->netStatusLabel;
switch(mPeerNet->getNetStateNetStateMode())
{
case PNSB_NETSTATE_BAD_UNKNOWN:
label->setText("NET BAD: Unknown State");
break;
case PNSB_NETSTATE_BAD_OFFLINE:
label->setText("NET BAD: Offline");
break;
case PNSB_NETSTATE_BAD_NATSYM:
label->setText("NET BAD: Behind Symmetric NAT");
break;
case PNSB_NETSTATE_BAD_NODHT_NAT:
label->setText("NET BAD: Behind NAT & No DHT");
break;
case PNSB_NETSTATE_WARNING_RESTART:
label->setText("NET WARNING: NET Restart");
break;
case PNSB_NETSTATE_WARNING_NATTED:
label->setText("NET WARNING: Behind NAT");
break;
case PNSB_NETSTATE_WARNING_NODHT:
label->setText("NET WARNING: No DHT");
break;
case PNSB_NETSTATE_GOOD:
label->setText("NET STATE GOOD!");
break;
case PNSB_NETSTATE_ADV_FORWARD:
label->setText("CAUTION: UNVERIFABLE FORWARD!");
break;
case PNSB_NETSTATE_ADV_DARK_FORWARD:
label->setText("CAUTION: UNVERIFABLE FORWARD & NO DHT");
break;
}
}
@ -171,13 +302,6 @@ void MainWindow::updateDhtPeers()
void MainWindow::updateNetPeers()
{
QString status = QString::fromStdString(mPeerNet->getPeerStatusString());
QString oldstatus = ui->peerLine->text();
if (oldstatus != status)
{
ui->peerLine->setText(status);
}
QTreeWidget *peerTreeWidget = ui->peerTreeWidget;
@ -187,6 +311,21 @@ void MainWindow::updateNetPeers()
mPeerNet->get_net_peers(peerIds);
mPeerNet->get_net_failedpeers(failedPeerIds);
/* collate peer stats */
int nPeers = peerIds.size();
// from DHT peers
int nOnlinePeers = 0;
int nUnreachablePeers = 0;
int nOfflinePeers = 0;
// Connect States.
int nDisconnPeers = 0;
int nDirectPeers = 0;
int nProxyPeers = 0;
int nRelayPeers = 0;
#define PTW_COL_PEERID 0
#define PTW_COL_DHT_STATUS 1
#define PTW_COL_DHT_ADDRESS 2
@ -274,8 +413,54 @@ void MainWindow::updateNetPeers()
peer_item -> setData(PTW_COL_PEER_STATUS, Qt::DisplayRole, QString::fromStdString(status.mPeerStatusMsg));
peer_item -> setData(PTW_COL_PEER_ADDRESS, Qt::DisplayRole, QString::fromStdString(peeripstr.str()));
peer_item -> setData(PTW_COL_PEER_UPDATETS, Qt::DisplayRole, QString::fromStdString(peerupdatestr.str()));
switch(status.mDhtState)
{
default:
case PN_DHT_STATE_UNKNOWN:
case PN_DHT_STATE_SEARCHING:
case PN_DHT_STATE_FAILURE:
case PN_DHT_STATE_OFFLINE:
nOfflinePeers++;
break;
case PN_DHT_STATE_UNREACHABLE:
nUnreachablePeers++;
break;
case PN_DHT_STATE_ONLINE:
nOnlinePeers++;
break;
}
switch(status.mPeerState)
{
default:
case PN_PEER_STATE_DISCONNECTED:
nDisconnPeers++;
break;
case PN_PEER_STATE_CONNECTED:
{
switch(status.mPeerConnectMode)
{
default:
case PN_CONNECT_UDP_DIRECT:
nDirectPeers++;
break;
case PN_CONNECT_UDP_PROXY:
nProxyPeers++;
break;
case PN_CONNECT_UDP_RELAY:
nRelayPeers++;
break;
}
}
break;
}
}
for(it = failedPeerIds.begin(); it != failedPeerIds.end(); it++)
{
/* find the entry */
@ -324,9 +509,26 @@ void MainWindow::updateNetPeers()
peer_item -> setData(PTW_COL_PEER_ADDRESS, Qt::DisplayRole, QString::fromStdString(peeripstr.str()));
peer_item -> setData(PTW_COL_PEER_UPDATETS, Qt::DisplayRole, QString::fromStdString(peerupdatestr.str()));
}
std::ostringstream connstr;
connstr << "#Peers: " << nPeers;
connstr << " DHT: (#off:" << nOfflinePeers;
connstr << ",unreach:" << nUnreachablePeers;
connstr << ",online:" << nOnlinePeers;
connstr << ") Connections: (#dis:" << nDisconnPeers;
connstr << ",#dir:" << nDirectPeers;
connstr << ",#proxy:" << nProxyPeers;
connstr << ",#relay:" << nRelayPeers;
connstr << ")";
QLabel *label = ui->peerSummaryLabel;
label->setText(QString::fromStdString(connstr.str()));
}
void MainWindow::addPeer()
{
std::string id = ui->peerLineEdit->text().toStdString();

View file

@ -18,17 +18,106 @@
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="spacing">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QPushButton" name="addButton">
<widget class="QLineEdit" name="peerLine">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Add Peer</string>
<string>Peer Details</string>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="peerLineEdit"/>
<widget class="QLabel" name="netStatusLabel">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="connectLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Connect Options</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="networkLabel">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="natTypeLabel">
<property name="text">
<string>proxyExtLabel</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="natHoleLabel">
<property name="text">
<string>dhtExtLabel</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QLabel" name="connectStateLabel_2">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>TL1</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="extraLabel_2">
<property name="text">
<string>TL2</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="proxyExtLabel">
<property name="text">
<string>proxyExtLabel</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="dhtExtLabel">
<property name="text">
<string>dhtExtLabel</string>
</property>
</widget>
</item>
</layout>
</item>
@ -37,18 +126,32 @@
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QWidget" name="layoutWidget">
<widget class="QWidget" name="">
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="peerLine">
<property name="enabled">
<bool>true</bool>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>-1</number>
</property>
<item>
<widget class="QPushButton" name="addButton">
<property name="text">
<string>Add Peer</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="peerLineEdit"/>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="peerSummaryLabel">
<property name="text">
<string>Peer Details</string>
</property>
<property name="readOnly">
<bool>true</bool>
<string>TextLabel</string>
</property>
</widget>
</item>

View file

@ -0,0 +1,507 @@
#include "netstatebox.h"
#include "util/rsnet.h"
// External Interface.
void PeerNetStateBox::setAddressStunDht(struct sockaddr_in *addr, bool stable)
{
if ((!mStunDhtSet) || (mStunDhtStable != stable) ||
(addr->sin_addr.s_addr != mStunDhtAddr.sin_addr.s_addr) ||
(addr->sin_port != mStunDhtAddr.sin_port))
{
mStunDhtSet = true;
mStunDhtStable = stable;
mStunDhtAddr = *addr;
mStatusOkay = false;
}
mStunDhtTS = time(NULL);
}
void PeerNetStateBox::setAddressStunProxy(struct sockaddr_in *addr, bool stable)
{
if ((!mStunProxySet) || (mStunProxyStable != stable) ||
(addr->sin_addr.s_addr != mStunProxyAddr.sin_addr.s_addr) ||
(addr->sin_port != mStunProxyAddr.sin_port))
{
mStunProxySet = true;
mStunProxyStable = stable;
mStunProxyAddr = *addr;
mStatusOkay = false;
}
mStunProxyTS = time(NULL);
}
void PeerNetStateBox::setAddressUPnP(bool active, struct sockaddr_in *addr)
{
if ((!mUPnPSet) || (mUPnPActive != active) ||
(addr->sin_addr.s_addr != mUPnPAddr.sin_addr.s_addr) ||
(addr->sin_port != mUPnPAddr.sin_port))
{
mUPnPSet = true;
mUPnPAddr = *addr;
mUPnPActive = active;
mStatusOkay = false;
}
mUPnPTS = time(NULL);
}
void PeerNetStateBox::setAddressNatPMP(bool active, struct sockaddr_in *addr)
{
if ((!mNatPMPSet) || (mNatPMPActive != active) ||
(addr->sin_addr.s_addr != mNatPMPAddr.sin_addr.s_addr) ||
(addr->sin_port != mNatPMPAddr.sin_port))
{
mNatPMPSet = true;
mNatPMPAddr = *addr;
mNatPMPActive = active;
mStatusOkay = false;
}
mNatPMPTS = time(NULL);
}
void PeerNetStateBox::setAddressWebIP(bool active, struct sockaddr_in *addr)
{
if ((!mWebIPSet) || (mWebIPActive != active) ||
(addr->sin_addr.s_addr != mWebIPAddr.sin_addr.s_addr) ||
(addr->sin_port != mWebIPAddr.sin_port))
{
mWebIPSet = true;
mWebIPAddr = *addr;
mWebIPActive = active;
mStatusOkay = false;
}
mWebIPTS = time(NULL);
}
/* Extract Net State */
uint32_t PeerNetStateBox::getNetworkMode()
{
updateNetState();
return mNetworkMode;
}
uint32_t PeerNetStateBox::getNatTypeMode()
{
updateNetState();
return mNatTypeMode;
}
uint32_t PeerNetStateBox::getNatHoleMode()
{
updateNetState();
return mNatHoleMode;
}
uint32_t PeerNetStateBox::getConnectModes()
{
updateNetState();
return mConnectModes;
}
uint32_t PeerNetStateBox::getNetStateMode()
{
updateNetState();
return mNetStateMode;
}
/******************************** Internal Workings *******************************/
PeerNetStateBox::PeerNetStateBox()
{
mStatusOkay = false;
//time_t mStatusTS;
mNetworkMode = PNSB_NETWORK_UNKNOWN;
mNatTypeMode = PNSB_NATTYPE_UNKNOWN;
mNatHoleMode = PNSB_NATHOLE_UNKNOWN;
mConnectModes = PNSB_CONNECT_NONE;
mNetStateMode = PNSB_NETSTATE_BAD_UNKNOWN;
/* Parameters set externally */
mStunDhtSet = false;
//time_t mStunDhtTS;
//bool mStunDhtStable;
//struct sockaddr_in mStunDhtAddr;
mStunProxySet = false;
//time_t mStunProxyTS;
//bool mStunProxyStable;
//struct sockaddr_in mStunProxyAddr;
mUPnPSet = false;
mUPnPActive = false;
//struct sockaddr_in mUPnPAddr;
mNatPMPSet = false;
mNatPMPActive = false;
//struct sockaddr_in mNatPMPAddr;
mWebIPSet = false;
mWebIPActive = false;
//struct sockaddr_in mWebIPAddr;
mPortForwardedSet = false;
mPortForwarded = 0;
mDhtActive = false;
}
#define NETSTATE_PARAM_TIMEOUT 600
#define NETSTATE_TIMEOUT 60
/* check/update Net State */
int PeerNetStateBox::statusOkay()
{
if (!mStatusOkay)
{
return 0;
}
time_t now = time(NULL);
if (now - mStatusTS > NETSTATE_TIMEOUT)
{
return 0;
}
return 1;
}
int PeerNetStateBox::updateNetState()
{
if (!statusOkay())
{
determineNetworkState();
}
return 1;
}
void PeerNetStateBox::clearOldNetworkData()
{
/* check if any measurements are too old to consider */
time_t now = time(NULL);
if (now - mStunProxyTS > NETSTATE_PARAM_TIMEOUT)
{
mStunProxySet = false;
}
if (now - mStunDhtTS > NETSTATE_PARAM_TIMEOUT)
{
mStunDhtSet = false;
}
}
void PeerNetStateBox::determineNetworkState()
{
clearOldNetworkData();
time_t now = time(NULL);
/* now we use the remaining valid input to determine network state */
/* Most important Factor is whether we have DHT(STUN) info to ID connection */
if (mDhtActive)
{
/* firstly lets try to identify OFFLINE / UNKNOWN */
if ((!mStunProxySet) || (!mStunDhtSet))
{
mNetworkMode = PNSB_NETWORK_UNKNOWN;
// Assume these.
mNatTypeMode = PNSB_NATTYPE_UNKNOWN;
mNatHoleMode = PNSB_NATHOLE_NONE;
mNetStateMode = PNSB_NETSTATE_BAD_UNKNOWN;
//mExtAddress = .... unknown;
//mExtAddrStable = false;
}
else // Both Are Set!
{
if (!mStunDhtStable)
{
//mExtAddress = mStunDhtExtAddress;
//mExtAddrStable = false;
if (!mStunProxyStable)
{
/* both unstable, Symmetric NAT, Firewalled, No UDP Hole */
mNetworkMode = PNSB_NETWORK_BEHINDNAT;
mNatTypeMode = PNSB_NATTYPE_SYMMETRIC;
mNatHoleMode = PNSB_NATHOLE_NONE;
mNetStateMode = PNSB_NETSTATE_BAD_NATSYM;
}
else
{
/* if DhtStun Unstable, but ProxyStable, then we have
* an interesting case. This is close to a Debian Firewall
* I tested in the past....
*
* The big difference between DhtStun and ProxyStun is
* that Dht Port receives unsolicated packets,
* while Proxy Port always sends an outgoing one first.
*
* In the case of the debian firewall, the unsolicated pkts
* caused the outgoing port to change.
*
* We will label this difference RESTRICTED vs FULL CONE,
* but that label is really fully accurate. (gray area).
*/
mNetworkMode = PNSB_NETWORK_BEHINDNAT;
mNatTypeMode = PNSB_NATTYPE_RESTRICTED_CONE;
mNatHoleMode = PNSB_NATHOLE_NONE;
mNetStateMode = PNSB_NETSTATE_WARNING_NATTED;
}
}
else // Dht Stable.
{
/* DHT Stable port can be caused by:
* 1) Forwarded Port (UPNP, NATPMP, FORWARDED)
* 2) FULL CONE NAT.
* 3) EXT Port.
* Must look at Proxy Stability.
* - if Proxy Unstable, then must be forwarded port.
* - if Proxy Stable, then we cannot tell.
* -> Must use User Info (Upnp, PMP, Forwarded Flag).
* -> Also possible to be EXT Port (Check against iface)
*/
//mExtAddress = mStunDhtExtAddress;
//mExtAddrStable = true;
// Initial Fallback Guess at firewall state.
if (!mStunProxyStable)
{
/* must be a forwarded port/ext or something similar */
mNetworkMode = PNSB_NETWORK_BEHINDNAT;
mNatTypeMode = PNSB_NATTYPE_SYMMETRIC;
mNatHoleMode = PNSB_NATHOLE_FORWARDED;
mNetStateMode = PNSB_NETSTATE_GOOD;
}
else
{
/* fallback is FULL CONE NAT */
mNetworkMode = PNSB_NETWORK_BEHINDNAT;
mNatTypeMode = PNSB_NATTYPE_FULL_CONE;
mNatHoleMode = PNSB_NATHOLE_NONE;
mNetStateMode = PNSB_NETSTATE_WARNING_NATTED;
}
if (mUPnPActive)
{
// This Mode is OKAY.
mNetworkMode = PNSB_NETWORK_BEHINDNAT;
// Use Fallback Guess.
//mNatTypeMode = PNSB_NATTYPE_UNKNOWN;
mNatHoleMode = PNSB_NATHOLE_UPNP;
mNetStateMode = PNSB_NETSTATE_GOOD;
//mExtAddress = ... from UPnP, should match StunDht.
//mExtAddrStable = true;
}
else if (mNatPMPActive)
{
// This Mode is OKAY.
mNetworkMode = PNSB_NETWORK_BEHINDNAT;
// Use Fallback Guess.
//mNatTypeMode = PNSB_NATTYPE_UNKNOWN;
mNatHoleMode = PNSB_NATHOLE_NATPMP;
mNetStateMode = PNSB_NETSTATE_GOOD;
//mExtAddress = ... from NatPMP, should match NatPMP
//mExtAddrStable = true;
}
else
{
bool isExtAddress = false;
if (isExtAddress)
{
mNetworkMode = PNSB_NETWORK_EXTERNALIP;
mNatTypeMode = PNSB_NATTYPE_NONE;
mNatHoleMode = PNSB_NATHOLE_NONE;
mNetStateMode = PNSB_NETSTATE_GOOD;
//mExtAddrStable = true;
}
else if (mPortForwardedSet)
{
mNetworkMode = PNSB_NETWORK_BEHINDNAT;
// Use Fallback Guess.
//mNatTypeMode = PNSB_NATTYPE_UNKNOWN;
mNatHoleMode = PNSB_NATHOLE_FORWARDED;
mNetStateMode = PNSB_NETSTATE_ADV_FORWARD;
//mExtAddrStable = true; // Probably, makin assumption.
}
else
{
/* At this point, we go with the fallback guesses */
}
}
}
}
}
else // DHT Inactive, must use other means...
{
/* If we get here we are dealing with a silly peer in "DarkMode".
* We have to primarily rely on the feedback from UPnP, PMP or WebSite "WhatsMyIp".
* This is in the "Advanced" Settings and liable to be set wrong.
* but thats the users fault!
*/
if (mUPnPActive)
{
// This Mode is OKAY.
mNetworkMode = PNSB_NETWORK_BEHINDNAT;
mNatTypeMode = PNSB_NATTYPE_UNKNOWN;
mNatHoleMode = PNSB_NATHOLE_UPNP;
//mExtAddress = ... from UPnP.
//mExtAddrStable = true;
mNetStateMode = PNSB_NETSTATE_WARNING_NODHT;
}
else if (mNatPMPActive)
{
// This Mode is OKAY.
mNetworkMode = PNSB_NETWORK_BEHINDNAT;
mNatTypeMode = PNSB_NATTYPE_UNKNOWN;
mNatHoleMode = PNSB_NATHOLE_NATPMP;
//mExtAddress = ... from NatPMP.
//mExtAddrStable = true;
mNetStateMode = PNSB_NETSTATE_WARNING_NODHT;
}
else
{
/* if we reach this point, we really need a Web "WhatsMyIp" Check of our Ext Ip Address. */
/* Check for the possibility of an EXT address ... */
bool isExtAddress = false;
//mExtAddress = ... from WhatsMyIp.
if (isExtAddress)
{
mNetworkMode = PNSB_NETWORK_EXTERNALIP;
mNatTypeMode = PNSB_NATTYPE_NONE;
mNatHoleMode = PNSB_NATHOLE_NONE;
//mExtAddrStable = true;
mNetStateMode = PNSB_NETSTATE_WARNING_NODHT;
}
else if (mPortForwardedSet)
{
mNetworkMode = PNSB_NETWORK_BEHINDNAT;
mNatTypeMode = PNSB_NATTYPE_UNKNOWN;
mNatHoleMode = PNSB_NATHOLE_FORWARDED;
//mExtAddrStable = true; // Probably, makin assumption.
mNetStateMode = PNSB_NETSTATE_WARNING_NODHT;
}
else
{
/* At this point we must assume firewalled.
* These people have destroyed the possibility of making connections ;(
* Should WARN about this.
*/
mNetworkMode = PNSB_NETWORK_BEHINDNAT;
mNatTypeMode = PNSB_NATTYPE_UNKNOWN;
mNatHoleMode = PNSB_NATHOLE_NONE;
mNetStateMode = PNSB_NETSTATE_BAD_NODHT_NAT;
//mExtAddrStable = false; // Unlikely to be stable.
}
}
}
workoutNetworkMode();
/* say that things are okay */
mStatusOkay = true;
mStatusTS = now;
}
/* based on calculated settings, what is the network mode
*/
void PeerNetStateBox::workoutNetworkMode()
{
/* connectModes are dependent on the other modes */
mConnectModes = PNSB_CONNECT_NONE;
switch(mNetworkMode)
{
case PNSB_NETWORK_UNKNOWN:
case PNSB_NETWORK_OFFLINE:
case PNSB_NETWORK_LOCALNET:
/* nothing here */
break;
case PNSB_NETWORK_EXTERNALIP:
mConnectModes = PNSB_CONNECT_OUTGOING_TCP;
mConnectModes |= PNSB_CONNECT_ACCEPT_TCP;
if (mDhtActive)
{
mConnectModes |= PNSB_CONNECT_DIRECT_UDP;
/* if open port. don't want PROXY or RELAY connect
* because we should be able to do direct with EVERYONE.
* Ability to do Proxy is dependent on FIREWALL status.
* Technically could do RELAY, but disable both.
*/
//mConnectModes |= PNSB_CONNECT_PROXY_UDP;
//mConnectModes |= PNSB_CONNECT_RELAY_UDP;
}
break;
case PNSB_NETWORK_BEHINDNAT:
mConnectModes = PNSB_CONNECT_OUTGOING_TCP;
/* we're okay if there's a NAT HOLE */
if ((mNatHoleMode == PNSB_NATHOLE_UPNP) ||
(mNatHoleMode == PNSB_NATHOLE_NATPMP) ||
(mNatHoleMode == PNSB_NATHOLE_FORWARDED))
{
mConnectModes |= PNSB_CONNECT_ACCEPT_TCP;
if (mDhtActive)
{
mConnectModes |= PNSB_CONNECT_DIRECT_UDP;
/* dont want PROXY | RELAY with open ports */
}
}
else
{
/* If behind NAT without NATHOLE, this is where RELAY | PROXY
* are useful. We Flag DIRECT connections, cos we can do these
* with peers with Open Ports. (but not with other NATted peers).
*/
if (mDhtActive)
{
mConnectModes |= PNSB_CONNECT_DIRECT_UDP;
mConnectModes |= PNSB_CONNECT_RELAY_UDP;
if ((mNatTypeMode == PNSB_NATTYPE_RESTRICTED_CONE) ||
(mNatTypeMode == PNSB_NATTYPE_FULL_CONE))
{
mConnectModes |= PNSB_CONNECT_PROXY_UDP;
}
}
}
break;
}
}

139
PeerNetQt/src/netstatebox.h Normal file
View file

@ -0,0 +1,139 @@
#ifndef PEER_NET_STATUS_BOX_H
#define PEER_NET_STATUS_BOX_H
/* a little state box to determine network status */
#include <string>
#include <list>
#include "bitdht/bdiface.h"
/*** Network state
* Want this to be all encompassing.
*
*/
#define PNSB_NETWORK_UNKNOWN 1
#define PNSB_NETWORK_RESTARTING 2
#define PNSB_NETWORK_OFFLINE 3
#define PNSB_NETWORK_LOCALNET 4
#define PNSB_NETWORK_BEHINDNAT 5
#define PNSB_NETWORK_EXTERNALIP 6
// WHAT TYPE OF FIREWALL?
#define PNSB_NATTYPE_NONE 1
#define PNSB_NATTYPE_UNKNOWN 2
#define PNSB_NATTYPE_SYMMETRIC 3
#define PNSB_NATTYPE_RESTRICTED_CONE 4
#define PNSB_NATTYPE_FULL_CONE 5
#define PNSB_NATTYPE_OTHER 6
// WHAT TYPE OF HOLE?
#define PNSB_NATHOLE_UNKNOWN 0
#define PNSB_NATHOLE_NONE 1
#define PNSB_NATHOLE_UPNP 2
#define PNSB_NATHOLE_NATPMP 3
#define PNSB_NATHOLE_FORWARDED 4
// Types of Connections.
#define PNSB_CONNECT_NONE 0x0000
#define PNSB_CONNECT_ACCEPT_TCP 0x0001
#define PNSB_CONNECT_OUTGOING_TCP 0x0002
#define PNSB_CONNECT_DIRECT_UDP 0x0100
#define PNSB_CONNECT_PROXY_UDP 0x0200
#define PNSB_CONNECT_RELAY_UDP 0x0400
// net state (good, okay, bad)
// BAD. (RED)
#define PNSB_NETSTATE_BAD_UNKNOWN 1
#define PNSB_NETSTATE_BAD_OFFLINE 2
#define PNSB_NETSTATE_BAD_NATSYM 3
#define PNSB_NETSTATE_BAD_NODHT_NAT 4
// CAUTION. (ORANGE)
#define PNSB_NETSTATE_WARNING_RESTART 5
#define PNSB_NETSTATE_WARNING_NATTED 6
#define PNSB_NETSTATE_WARNING_NODHT 7
// GOOD (GREEN)
// NAT with forwarded port, or EXT port.
#define PNSB_NETSTATE_GOOD 8
// ADVANCED MODE (BLUE)
// If the user knows what they are doing... we cannot confirm this.
#define PNSB_NETSTATE_ADV_FORWARD 9
#define PNSB_NETSTATE_ADV_DARK_FORWARD 10
class PeerNetStateBox
{
public:
PeerNetStateBox();
/* input network bits */
void setAddressStunDht(struct sockaddr_in *, bool stable);
void setAddressStunProxy(struct sockaddr_in *, bool stable);
void setAddressUPnP(bool active, struct sockaddr_in *addr);
void setAddressNatPMP(bool active, struct sockaddr_in *addr);
void setAddressWebIP(bool active, struct sockaddr_in *addr);
uint32_t getNetStateMode();
uint32_t getNetworkMode();
uint32_t getNatTypeMode();
uint32_t getNatHoleMode();
uint32_t getConnectModes();
private:
/* calculate network state */
void clearOldNetworkData();
void determineNetworkState();
int statusOkay();
int updateNetState();
/* more internal fns */
void workoutNetworkMode();
bool mStatusOkay;
time_t mStatusTS;
uint32_t mNetworkMode;
uint32_t mNatTypeMode;
uint32_t mNatHoleMode;
uint32_t mConnectModes;
uint32_t mNetStateMode;
/* Parameters set externally */
bool mStunDhtSet;
time_t mStunDhtTS;
bool mStunDhtStable;
struct sockaddr_in mStunDhtAddr;
bool mStunProxySet;
time_t mStunProxyTS;
bool mStunProxyStable;
struct sockaddr_in mStunProxyAddr;
bool mUPnPSet;
struct sockaddr_in mUPnPAddr;
bool mUPnPActive;
time_t mUPnPTS;
bool mNatPMPSet;
struct sockaddr_in mNatPMPAddr;
bool mNatPMPActive;
time_t mNatPMPTS;
bool mWebIPSet;
struct sockaddr_in mWebIPAddr;
bool mWebIPActive;
time_t mWebIPTS;
bool mPortForwardedSet;
uint16_t mPortForwarded;
bool mDhtActive;
};
#endif

View file

@ -392,8 +392,30 @@ std::string PeerNet::getPeerStatusString()
return out.str();
}
uint32_t PeerNet::getNetStateNetworkMode()
{
return mNetStateBox.getNetworkMode();
}
uint32_t PeerNet::getNetStateNatTypeMode()
{
return mNetStateBox.getNatTypeMode();
}
uint32_t PeerNet::getNetStateNatHoleMode()
{
return mNetStateBox.getNatHoleMode();
}
uint32_t PeerNet::getNetStateConnectModes()
{
return mNetStateBox.getConnectModes();
}
uint32_t PeerNet::getNetStateNetStateMode()
{
return mNetStateBox.getNetStateMode();
}
int PeerNet::get_net_peers(std::list<std::string> &peerIds)
@ -634,6 +656,31 @@ int PeerNet::dhtPeerCallback(const bdId *id, uint32_t status)
it->second.mDhtStatusMsg = "Peer Unreachable";
it->second.mDhtState = PN_DHT_STATE_UNREACHABLE;
it->second.mDhtAddr = id->addr;
if ((it->second.mPeerState == PN_PEER_STATE_CONNECTION_INITIATED) ||
(it->second.mPeerState == PN_PEER_STATE_CONNECTION_AUTHORISED) ||
(it->second.mPeerState == PN_PEER_STATE_UDP_STARTED) ||
(it->second.mPeerState == PN_PEER_STATE_CONNECTED))
{
std::cerr << "dhtPeerCallback. Peer Unreachable, but connection already underway: ";
bdStdPrintId(std::cerr, id);
std::cerr << std::endl;
}
else
{
std::cerr << "dhtPeerCallback. Peer Unreachable, triggering Proxy Connection for: ";
bdStdPrintId(std::cerr, id);
std::cerr << std::endl;
/* Push Back PeerAction */
PeerAction ca;
ca.mType = PEERNET_ACTION_TYPE_CONNECT;
ca.mMode = BITDHT_CONNECT_MODE_PROXY;
ca.mDestId = *id;
mActions.push_back(ca);
}
}
break;
case BITDHT_MGR_QUERY_PEER_ONLINE:
@ -699,6 +746,21 @@ int PeerNet::dhtConnectCallback(const bdId *srcId, const bdId *proxyId, const bd
{
std::cerr << "PeerNet::dhtConnectCallback()";
std::cerr << std::endl;
std::cerr << "srcId: ";
bdStdPrintId(std::cerr, srcId);
std::cerr << std::endl;
std::cerr << "proxyId: ";
bdStdPrintId(std::cerr, proxyId);
std::cerr << std::endl;
std::cerr << "destId: ";
bdStdPrintId(std::cerr, destId);
std::cerr << std::endl;
std::cerr << "mode: " << mode;
std::cerr << " point: " << point;
std::cerr << " cbtype: " << cbtype;
std::cerr << std::endl;
/* we handle MID and START/END points differently... this is biggest difference.
* so handle first.
@ -955,9 +1017,18 @@ int PeerNet::doActions()
std::cerr << " mode: " << action.mMode;
std::cerr << std::endl;
struct sockaddr_in laddr; // THIS CANNOT BE FILLED UNTIL STUN IS FUNCTIONAL XXX.
sockaddr_clear(&laddr);
mUdpBitDht->ConnectionRequest(&laddr, &(action.mDestId.id), action.mMode);
if (action.mMode == BITDHT_CONNECT_MODE_DIRECT)
{
struct sockaddr_in laddr; // THIS CANNOT BE FILLED UNTIL STUN IS FUNCTIONAL XXX.
sockaddr_clear(&laddr);
mUdpBitDht->ConnectionRequest(&laddr, &(action.mDestId.id), action.mMode);
}
else if (action.mMode == BITDHT_CONNECT_MODE_PROXY)
{
struct sockaddr_in laddr; // THIS CANNOT BE FILLED UNTIL STUN IS FUNCTIONAL XXX.
sockaddr_clear(&laddr);
mUdpBitDht->ConnectionRequest(&laddr, &(action.mDestId.id), action.mMode);
}
}
break;

View file

@ -16,6 +16,8 @@
#include "tcponudp/udppeer.h"
#include "tcponudp/udprelay.h"
#include "netstatebox.h"
#define PN_DHT_STATE_UNKNOWN 0
#define PN_DHT_STATE_SEARCHING 1
#define PN_DHT_STATE_FAILURE 2
@ -35,6 +37,12 @@
#define PN_PEER_STATE_UDP_STARTED 9
#define PN_PEER_STATE_CONNECTED 10
#define PN_CONNECT_UDP_DIRECT 1
#define PN_CONNECT_UDP_PROXY 2
#define PN_CONNECT_UDP_RELAY 3
class DhtPeer
{
public:
@ -59,6 +67,7 @@ class PeerStatus
time_t mPeerUpdateTS;
int mPeerFd;
uint32_t mPeerConnectMode;
time_t mPeerConnTS;
std::string mPeerIncoming;
};
@ -95,6 +104,13 @@ class PeerNet: public BitDhtCallback
int add_peer(std::string id);
int remove_peer(std::string id);
uint32_t getNetStateNetworkMode();
uint32_t getNetStateNatTypeMode();
uint32_t getNetStateNatHoleMode();
uint32_t getNetStateConnectModes();
uint32_t getNetStateNetStateMode();
std::string getPeerStatusString();
std::string getDhtStatusString();
int get_dht_peers(int lvl, bdBucket &peers);
@ -160,6 +176,7 @@ virtual int dhtConnectCallback(const bdId *srcId, const bdId *proxyId, const bdI
UdpStunner *mProxyStunner;
// Dont need reference to PROXY UDP Receiver.
PeerNetStateBox mNetStateBox;
bdNodeId mOwnId;