diff --git a/PeerNetQt/src/PeerNetQt.pro b/PeerNetQt/src/PeerNetQt.pro index 2c35998b4..4cc639f0a 100644 --- a/PeerNetQt/src/PeerNetQt.pro +++ b/PeerNetQt/src/PeerNetQt.pro @@ -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 diff --git a/PeerNetQt/src/mainwindow.cpp b/PeerNetQt/src/mainwindow.cpp index 798d8bd53..4f4b1459d 100644 --- a/PeerNetQt/src/mainwindow.cpp +++ b/PeerNetQt/src/mainwindow.cpp @@ -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(); diff --git a/PeerNetQt/src/mainwindow.ui b/PeerNetQt/src/mainwindow.ui index f908c0cd9..3caf28807 100644 --- a/PeerNetQt/src/mainwindow.ui +++ b/PeerNetQt/src/mainwindow.ui @@ -18,17 +18,106 @@ + + 0 + - + - + + + true + - Add Peer + Peer Details + + + true - + + + TextLabel + + + + + + + + + + + + 0 + 0 + + + + Connect Options + + + + + + + TextLabel + + + + + + + proxyExtLabel + + + + + + + dhtExtLabel + + + + + + + + + + + + 0 + 0 + + + + TL1 + + + + + + + TL2 + + + + + + + proxyExtLabel + + + + + + + dhtExtLabel + + @@ -37,18 +126,32 @@ Qt::Vertical - + + + 0 + - - - true + + + -1 + + + + Add Peer + + + + + + + + + + - Peer Details - - - true + TextLabel diff --git a/PeerNetQt/src/netstatebox.cc b/PeerNetQt/src/netstatebox.cc new file mode 100644 index 000000000..b3cb56c97 --- /dev/null +++ b/PeerNetQt/src/netstatebox.cc @@ -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; + } +} + diff --git a/PeerNetQt/src/netstatebox.h b/PeerNetQt/src/netstatebox.h new file mode 100644 index 000000000..5beeab01e --- /dev/null +++ b/PeerNetQt/src/netstatebox.h @@ -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 +#include + +#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 diff --git a/PeerNetQt/src/peernet.cc b/PeerNetQt/src/peernet.cc index d64cc5e36..69b805b9a 100644 --- a/PeerNetQt/src/peernet.cc +++ b/PeerNetQt/src/peernet.cc @@ -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 &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; diff --git a/PeerNetQt/src/peernet.h b/PeerNetQt/src/peernet.h index 467a2c40e..2f26830a0 100644 --- a/PeerNetQt/src/peernet.h +++ b/PeerNetQt/src/peernet.h @@ -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;