Add functionality for getting the current network mode (#202)

Use bit flags to indicate a combination of network mode and status.
This commit is contained in:
Sam Carlberg
2017-06-02 20:25:20 -04:00
committed by Peter Johnson
parent 417cf33f90
commit f43675e2bd
10 changed files with 78 additions and 12 deletions

View File

@@ -57,6 +57,15 @@ enum NT_NotifyKind {
NT_NOTIFY_FLAGS = 0x20 /* flags changed */
};
/** Client/server modes */
enum NT_NetworkMode {
NT_NET_MODE_NONE = 0x00, /* not running */
NT_NET_MODE_SERVER = 0x01, /* running in server mode */
NT_NET_MODE_CLIENT = 0x02, /* running in client mode */
NT_NET_MODE_STARTING = 0x04, /* flag for starting (either client or server) */
NT_NET_MODE_FAILURE = 0x08, /* flag for failure (either client or server) */
};
/*
* Structures
*/
@@ -345,6 +354,11 @@ struct NT_Value** NT_UnpackRpcValues(const char* packed, size_t packed_len,
*/
void NT_SetNetworkIdentity(const char* name, size_t name_len);
/**
* Get the current network mode.
*/
unsigned int NT_GetNetworkMode();
/** Start Server
* Starts a server using the specified filename, listening address, and port.
*

View File

@@ -252,6 +252,7 @@ std::vector<std::shared_ptr<Value>> UnpackRpcValues(StringRef packed,
* Client/Server Functions
*/
void SetNetworkIdentity(StringRef name);
unsigned int GetNetworkMode();
void StartServer(StringRef persist_filename, const char* listen_address,
unsigned int port);
void StopServer();

View File

@@ -1502,6 +1502,17 @@ JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
nt::StopClient();
}
/*
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
* Method: getNetworkMode
* Signature: ()
*/
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_getNetworkMode
(JNIEnv *, jclass)
{
return nt::GetNetworkMode();
}
/*
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
* Method: setServer

View File

@@ -67,6 +67,12 @@ public class NetworkTablesJNI {
}
}
public static final int NT_NET_MODE_NONE = 0x00;
public static final int NT_NET_MODE_SERVER = 0x01;
public static final int NT_NET_MODE_CLIENT = 0x02;
public static final int NT_NET_MODE_STARTING = 0x04;
public static final int NT_NET_MODE_FAILURE = 0x08;
public static native boolean containsKey(String key);
public static native int getType(String key);
@@ -148,6 +154,7 @@ public class NetworkTablesJNI {
// public static native byte[] getRpcResultNonblocking(int callUid) throws RpcNoResponseException;
public static native void setNetworkIdentity(String name);
public static native int getNetworkMode();
public static native void startServer(String persistFilename, String listenAddress, int port);
public static native void stopServer();
public static native void startClient();

View File

@@ -119,6 +119,8 @@ NT_StartDSClient @119
NT_StopDSClient @120
NT_StartClientNone @121
NT_GetNetworkMode @122
; JNI functions
JNI_OnLoad
JNI_OnUnload
@@ -194,3 +196,4 @@ Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_setDefaultRaw
Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_setDefaultBooleanArray
Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_setDefaultDoubleArray
Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_setDefaultStringArray
Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_getNetworkMode

View File

@@ -118,3 +118,5 @@ NT_SetServerMulti @118
NT_StartDSClient @119
NT_StopDSClient @120
NT_StartClientNone @121
NT_GetNetworkMode @122

View File

@@ -75,6 +75,10 @@ DispatcherBase::~DispatcherBase() {
Stop();
}
unsigned int DispatcherBase::GetNetworkMode() const {
return m_networkMode;
}
void DispatcherBase::StartServer(
StringRef persist_filename,
std::unique_ptr<wpi::NetworkAcceptor> acceptor) {
@@ -83,7 +87,7 @@ void DispatcherBase::StartServer(
if (m_active) return;
m_active = true;
}
m_server = true;
m_networkMode = NT_NET_MODE_SERVER | NT_NET_MODE_STARTING;
m_persist_filename = persist_filename;
m_server_acceptor = std::move(acceptor);
@@ -103,7 +107,7 @@ void DispatcherBase::StartServer(
using namespace std::placeholders;
m_storage.SetOutgoing(std::bind(&Dispatcher::QueueOutgoing, this, _1, _2, _3),
m_server);
(m_networkMode & NT_NET_MODE_SERVER) != 0);
m_dispatch_thread = std::thread(&Dispatcher::DispatchThreadMain, this);
m_clientserver_thread = std::thread(&Dispatcher::ServerThreadMain, this);
@@ -115,10 +119,10 @@ void DispatcherBase::StartClient() {
if (m_active) return;
m_active = true;
}
m_server = false;
m_networkMode = NT_NET_MODE_CLIENT | NT_NET_MODE_STARTING;
using namespace std::placeholders;
m_storage.SetOutgoing(std::bind(&Dispatcher::QueueOutgoing, this, _1, _2, _3),
m_server);
(m_networkMode & NT_NET_MODE_SERVER) != 0);
m_dispatch_thread = std::thread(&Dispatcher::DispatchThreadMain, this);
m_clientserver_thread = std::thread(&Dispatcher::ClientThreadMain, this);
@@ -243,7 +247,7 @@ void DispatcherBase::DispatchThreadMain() {
if (!m_active) break; // in case we were woken up to terminate
// perform periodic persistent save
if (m_server && !m_persist_filename.empty() && start > next_save_time) {
if ((m_networkMode & NT_NET_MODE_SERVER) != 0 && !m_persist_filename.empty() && start > next_save_time) {
next_save_time += save_delta_time;
// handle loop taking too long
if (start > next_save_time) next_save_time = start + save_delta_time;
@@ -264,10 +268,10 @@ void DispatcherBase::DispatchThreadMain() {
// post outgoing messages if connection is active
// only send keep-alives on client
if (conn->state() == NetworkConnection::kActive)
conn->PostOutgoing(!m_server);
conn->PostOutgoing((m_networkMode & NT_NET_MODE_CLIENT) != 0);
// if client, reconnect if connection died
if (!m_server && conn->state() == NetworkConnection::kDead)
if ((m_networkMode & NT_NET_MODE_CLIENT) != 0 && conn->state() == NetworkConnection::kDead)
reconnect = true;
}
// reconnect if we disconnected (and a reconnect is not in progress)
@@ -297,15 +301,20 @@ void DispatcherBase::QueueOutgoing(std::shared_ptr<Message> msg,
void DispatcherBase::ServerThreadMain() {
if (m_server_acceptor->start() != 0) {
m_active = false;
m_networkMode = NT_NET_MODE_SERVER | NT_NET_MODE_FAILURE;
return;
}
m_networkMode = NT_NET_MODE_SERVER;
while (m_active) {
auto stream = m_server_acceptor->accept();
if (!stream) {
m_active = false;
return;
}
if (!m_active) return;
if (!m_active) {
m_networkMode = NT_NET_MODE_NONE;
return;
}
DEBUG("server: client connection from " << stream->getPeerIP() << " port "
<< stream->getPeerPort());
@@ -333,6 +342,7 @@ void DispatcherBase::ServerThreadMain() {
conn->Start();
}
}
m_networkMode = NT_NET_MODE_NONE;
}
void DispatcherBase::ClientThreadMain() {
@@ -348,7 +358,10 @@ void DispatcherBase::ClientThreadMain() {
if (m_client_connector_override) {
connect = m_client_connector_override;
} else {
if (m_client_connectors.empty()) continue;
if (m_client_connectors.empty()) {
m_networkMode = NT_NET_MODE_CLIENT | NT_NET_MODE_FAILURE;
continue;
}
if (i >= m_client_connectors.size()) i = 0;
connect = m_client_connectors[i++];
}
@@ -357,8 +370,12 @@ void DispatcherBase::ClientThreadMain() {
// try to connect (with timeout)
DEBUG("client trying to connect");
auto stream = connect();
if (!stream) continue; // keep retrying
if (!stream) {
m_networkMode = NT_NET_MODE_CLIENT | NT_NET_MODE_FAILURE;
continue; // keep retrying
}
DEBUG("client connected");
m_networkMode = NT_NET_MODE_CLIENT;
std::unique_lock<std::mutex> lock(m_user_mutex);
using namespace std::placeholders;
@@ -381,6 +398,7 @@ void DispatcherBase::ClientThreadMain() {
m_do_reconnect = false;
m_reconnect_cv.wait(lock, [&] { return !m_active || m_do_reconnect; });
}
m_networkMode = NT_NET_MODE_NONE;
}
bool DispatcherBase::ClientHandshake(
@@ -551,7 +569,7 @@ bool DispatcherBase::ServerHandshake(
}
void DispatcherBase::ClientReconnect(unsigned int proto_rev) {
if (m_server) return;
if ((m_networkMode & NT_NET_MODE_SERVER) != 0) return;
{
std::lock_guard<std::mutex> lock(m_user_mutex);
m_reconnect_proto_rev = proto_rev;

View File

@@ -39,6 +39,7 @@ class DispatcherBase {
virtual ~DispatcherBase();
unsigned int GetNetworkMode() const;
void StartServer(llvm::StringRef persist_filename,
std::unique_ptr<wpi::NetworkAcceptor> acceptor);
void StartClient();
@@ -84,7 +85,7 @@ class DispatcherBase {
Storage& m_storage;
Notifier& m_notifier;
bool m_server = false;
unsigned int m_networkMode = NT_NET_MODE_NONE;
std::string m_persist_filename;
std::thread m_dispatch_thread;
std::thread m_clientserver_thread;

View File

@@ -365,6 +365,10 @@ void NT_SetNetworkIdentity(const char* name, size_t name_len) {
nt::SetNetworkIdentity(StringRef(name, name_len));
}
unsigned int NT_GetNetworkMode() {
return nt::GetNetworkMode();
}
void NT_StartServer(const char* persist_filename, const char* listen_address,
unsigned int port) {
nt::StartServer(persist_filename, listen_address, port);

View File

@@ -240,6 +240,11 @@ void SetNetworkIdentity(StringRef name) {
Dispatcher::GetInstance().SetIdentity(name);
}
unsigned int GetNetworkMode() {
auto& d = Dispatcher::GetInstance();
return d.GetNetworkMode();
}
void StartServer(StringRef persist_filename, const char* listen_address,
unsigned int port) {
Dispatcher::GetInstance().StartServer(persist_filename, listen_address, port);