2016-11-04 16:01:42 -07:00
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
/* Copyright (c) FIRST 2015. All Rights Reserved. */
|
|
|
|
|
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
|
|
|
|
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
|
|
|
|
/* the project. */
|
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
#include "DsClient.h"
|
|
|
|
|
|
|
|
|
|
#include "llvm/raw_ostream.h"
|
|
|
|
|
#include "llvm/SmallString.h"
|
|
|
|
|
#include "support/raw_socket_istream.h"
|
|
|
|
|
#include "tcpsockets/TCPConnector.h"
|
|
|
|
|
|
|
|
|
|
#include "Dispatcher.h"
|
|
|
|
|
#include "Log.h"
|
|
|
|
|
|
|
|
|
|
using namespace nt;
|
|
|
|
|
|
|
|
|
|
class DsClient::Thread : public wpi::SafeThread {
|
|
|
|
|
public:
|
Implement independent instances.
Previously, most of the classes were implemented as singletons so only one
instance was possible.
This change adds an instance handle-based API. In Java, this API is located
in a different package than the old API (edu.wpi.first.networktables).
Backwards compatibility with ITable and the old NetworkTable API is largely
maintained, but a handful of classes have moved to the new package in Java
(ConnectionInfo and PersistentException), and the old JNI has been completed
replaced.
Also:
- Move SetTeam implementation to Dispatcher.
- Consistently pass time through Java and C++ Value API.
- Rename nt_Value.h to NetworkTableValue.h for consistency with Java.
- Improve documentation
- Make C++ and Java APIs more consistent
- Document RPC functions and support RPC in Java.
- Add polling features for entry and connection listeners and use them to
move callback threads to Java level.
- Remove thread start and stop hooks (as polling is available).
- Make Notifiers, RpcServer, Dispatcher, and Storage mockable.
- Set NOTIFY_NEW on immediate entry notifications.
- Make GetTable("/") and GetTable("") equivalent.
- Generate local notification for flags update when loading persistent file.
And many unit test updates/changes:
- Use InitGoogleMock instead of InitGoogleTest in test main.
- Move test printers to TestPrinter.h/cpp.
- Provide printers for StringRef, EntryNotifier, and Handle.
- StorageTest: Check notifications.
- Add entry notifier unit tests.
- Storage: Add test for incoming entry assignment.
- Update connection listener tests.
- Add entry listener unit tests.
Fixes #11, #140, #189, #190, #192, #193, #221
2017-04-23 10:26:17 -07:00
|
|
|
Thread(Dispatcher& dispatcher, wpi::Logger& logger, unsigned int port)
|
|
|
|
|
: m_dispatcher(dispatcher), m_logger(logger), m_port(port) {}
|
2016-11-04 16:01:42 -07:00
|
|
|
|
|
|
|
|
void Main();
|
|
|
|
|
|
Implement independent instances.
Previously, most of the classes were implemented as singletons so only one
instance was possible.
This change adds an instance handle-based API. In Java, this API is located
in a different package than the old API (edu.wpi.first.networktables).
Backwards compatibility with ITable and the old NetworkTable API is largely
maintained, but a handful of classes have moved to the new package in Java
(ConnectionInfo and PersistentException), and the old JNI has been completed
replaced.
Also:
- Move SetTeam implementation to Dispatcher.
- Consistently pass time through Java and C++ Value API.
- Rename nt_Value.h to NetworkTableValue.h for consistency with Java.
- Improve documentation
- Make C++ and Java APIs more consistent
- Document RPC functions and support RPC in Java.
- Add polling features for entry and connection listeners and use them to
move callback threads to Java level.
- Remove thread start and stop hooks (as polling is available).
- Make Notifiers, RpcServer, Dispatcher, and Storage mockable.
- Set NOTIFY_NEW on immediate entry notifications.
- Make GetTable("/") and GetTable("") equivalent.
- Generate local notification for flags update when loading persistent file.
And many unit test updates/changes:
- Use InitGoogleMock instead of InitGoogleTest in test main.
- Move test printers to TestPrinter.h/cpp.
- Provide printers for StringRef, EntryNotifier, and Handle.
- StorageTest: Check notifications.
- Add entry notifier unit tests.
- Storage: Add test for incoming entry assignment.
- Update connection listener tests.
- Add entry listener unit tests.
Fixes #11, #140, #189, #190, #192, #193, #221
2017-04-23 10:26:17 -07:00
|
|
|
Dispatcher& m_dispatcher;
|
|
|
|
|
wpi::Logger& m_logger;
|
2016-11-04 16:01:42 -07:00
|
|
|
unsigned int m_port;
|
|
|
|
|
std::unique_ptr<wpi::NetworkStream> m_stream;
|
|
|
|
|
};
|
|
|
|
|
|
Implement independent instances.
Previously, most of the classes were implemented as singletons so only one
instance was possible.
This change adds an instance handle-based API. In Java, this API is located
in a different package than the old API (edu.wpi.first.networktables).
Backwards compatibility with ITable and the old NetworkTable API is largely
maintained, but a handful of classes have moved to the new package in Java
(ConnectionInfo and PersistentException), and the old JNI has been completed
replaced.
Also:
- Move SetTeam implementation to Dispatcher.
- Consistently pass time through Java and C++ Value API.
- Rename nt_Value.h to NetworkTableValue.h for consistency with Java.
- Improve documentation
- Make C++ and Java APIs more consistent
- Document RPC functions and support RPC in Java.
- Add polling features for entry and connection listeners and use them to
move callback threads to Java level.
- Remove thread start and stop hooks (as polling is available).
- Make Notifiers, RpcServer, Dispatcher, and Storage mockable.
- Set NOTIFY_NEW on immediate entry notifications.
- Make GetTable("/") and GetTable("") equivalent.
- Generate local notification for flags update when loading persistent file.
And many unit test updates/changes:
- Use InitGoogleMock instead of InitGoogleTest in test main.
- Move test printers to TestPrinter.h/cpp.
- Provide printers for StringRef, EntryNotifier, and Handle.
- StorageTest: Check notifications.
- Add entry notifier unit tests.
- Storage: Add test for incoming entry assignment.
- Update connection listener tests.
- Add entry listener unit tests.
Fixes #11, #140, #189, #190, #192, #193, #221
2017-04-23 10:26:17 -07:00
|
|
|
DsClient::DsClient(Dispatcher& dispatcher, wpi::Logger& logger)
|
|
|
|
|
: m_dispatcher(dispatcher), m_logger(logger) {}
|
|
|
|
|
|
2016-11-04 16:01:42 -07:00
|
|
|
void DsClient::Start(unsigned int port) {
|
|
|
|
|
auto thr = m_owner.GetThread();
|
|
|
|
|
if (!thr)
|
Implement independent instances.
Previously, most of the classes were implemented as singletons so only one
instance was possible.
This change adds an instance handle-based API. In Java, this API is located
in a different package than the old API (edu.wpi.first.networktables).
Backwards compatibility with ITable and the old NetworkTable API is largely
maintained, but a handful of classes have moved to the new package in Java
(ConnectionInfo and PersistentException), and the old JNI has been completed
replaced.
Also:
- Move SetTeam implementation to Dispatcher.
- Consistently pass time through Java and C++ Value API.
- Rename nt_Value.h to NetworkTableValue.h for consistency with Java.
- Improve documentation
- Make C++ and Java APIs more consistent
- Document RPC functions and support RPC in Java.
- Add polling features for entry and connection listeners and use them to
move callback threads to Java level.
- Remove thread start and stop hooks (as polling is available).
- Make Notifiers, RpcServer, Dispatcher, and Storage mockable.
- Set NOTIFY_NEW on immediate entry notifications.
- Make GetTable("/") and GetTable("") equivalent.
- Generate local notification for flags update when loading persistent file.
And many unit test updates/changes:
- Use InitGoogleMock instead of InitGoogleTest in test main.
- Move test printers to TestPrinter.h/cpp.
- Provide printers for StringRef, EntryNotifier, and Handle.
- StorageTest: Check notifications.
- Add entry notifier unit tests.
- Storage: Add test for incoming entry assignment.
- Update connection listener tests.
- Add entry listener unit tests.
Fixes #11, #140, #189, #190, #192, #193, #221
2017-04-23 10:26:17 -07:00
|
|
|
m_owner.Start(new Thread(m_dispatcher, m_logger, port));
|
2016-11-04 16:01:42 -07:00
|
|
|
else
|
|
|
|
|
thr->m_port = port;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DsClient::Stop() {
|
|
|
|
|
{
|
|
|
|
|
// Close the stream so the read (if any) terminates.
|
|
|
|
|
auto thr = m_owner.GetThread();
|
|
|
|
|
if (thr) {
|
|
|
|
|
thr->m_active = false;
|
|
|
|
|
if (thr->m_stream) thr->m_stream->close();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
m_owner.Stop();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DsClient::Thread::Main() {
|
|
|
|
|
unsigned int oldip = 0;
|
|
|
|
|
wpi::Logger nolog; // to silence log messages from TCPConnector
|
|
|
|
|
|
|
|
|
|
while (m_active) {
|
|
|
|
|
// wait for periodic reconnect or termination
|
|
|
|
|
auto timeout_time =
|
|
|
|
|
std::chrono::steady_clock::now() + std::chrono::milliseconds(500);
|
|
|
|
|
unsigned int port;
|
|
|
|
|
{
|
2017-11-13 09:51:05 -08:00
|
|
|
std::unique_lock<wpi::mutex> lock(m_mutex);
|
2016-11-04 16:01:42 -07:00
|
|
|
m_cond.wait_until(lock, timeout_time, [&] { return !m_active; });
|
|
|
|
|
port = m_port;
|
|
|
|
|
}
|
|
|
|
|
if (!m_active) goto done;
|
|
|
|
|
|
|
|
|
|
// Try to connect to DS on the local machine
|
|
|
|
|
m_stream =
|
|
|
|
|
wpi::TCPConnector::connect("127.0.0.1", 1742, nolog, 1);
|
|
|
|
|
if (!m_active) goto done;
|
|
|
|
|
if (!m_stream) continue;
|
|
|
|
|
|
|
|
|
|
DEBUG3("connected to DS");
|
|
|
|
|
wpi::raw_socket_istream is(*m_stream);
|
|
|
|
|
|
|
|
|
|
while (m_active && !is.has_error()) {
|
|
|
|
|
// Read JSON "{...}". This is very limited, does not handle quoted "}" or
|
|
|
|
|
// nested {}, but is sufficient for this purpose.
|
|
|
|
|
llvm::SmallString<128> json;
|
|
|
|
|
char ch;
|
|
|
|
|
|
|
|
|
|
// Throw away characters until {
|
|
|
|
|
do {
|
|
|
|
|
is.read(ch);
|
|
|
|
|
if (is.has_error()) break;
|
|
|
|
|
if (!m_active) goto done;
|
|
|
|
|
} while (ch != '{');
|
|
|
|
|
json += '{';
|
|
|
|
|
|
|
|
|
|
if (is.has_error()) {
|
|
|
|
|
m_stream = nullptr;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Read characters until }
|
|
|
|
|
do {
|
|
|
|
|
is.read(ch);
|
|
|
|
|
if (is.has_error()) break;
|
|
|
|
|
if (!m_active) goto done;
|
|
|
|
|
json += ch;
|
|
|
|
|
} while (ch != '}');
|
|
|
|
|
|
|
|
|
|
if (is.has_error()) {
|
|
|
|
|
m_stream = nullptr;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
DEBUG3("json=" << json);
|
|
|
|
|
|
|
|
|
|
// Look for "robotIP":12345, and get 12345 portion
|
|
|
|
|
size_t pos = json.find("\"robotIP\"");
|
|
|
|
|
if (pos == llvm::StringRef::npos) continue; // could not find?
|
|
|
|
|
pos += 9;
|
|
|
|
|
pos = json.find(':', pos);
|
|
|
|
|
if (pos == llvm::StringRef::npos) continue; // could not find?
|
|
|
|
|
size_t endpos = json.find_first_not_of("0123456789", pos + 1);
|
|
|
|
|
DEBUG3("found robotIP=" << json.slice(pos + 1, endpos));
|
|
|
|
|
|
|
|
|
|
// Parse into number
|
2017-12-29 20:17:47 -08:00
|
|
|
unsigned int ip = 0;
|
2016-11-04 16:01:42 -07:00
|
|
|
if (json.slice(pos + 1, endpos).getAsInteger(10, ip)) continue; // error
|
|
|
|
|
|
|
|
|
|
// If zero, clear the server override
|
|
|
|
|
if (ip == 0) {
|
Implement independent instances.
Previously, most of the classes were implemented as singletons so only one
instance was possible.
This change adds an instance handle-based API. In Java, this API is located
in a different package than the old API (edu.wpi.first.networktables).
Backwards compatibility with ITable and the old NetworkTable API is largely
maintained, but a handful of classes have moved to the new package in Java
(ConnectionInfo and PersistentException), and the old JNI has been completed
replaced.
Also:
- Move SetTeam implementation to Dispatcher.
- Consistently pass time through Java and C++ Value API.
- Rename nt_Value.h to NetworkTableValue.h for consistency with Java.
- Improve documentation
- Make C++ and Java APIs more consistent
- Document RPC functions and support RPC in Java.
- Add polling features for entry and connection listeners and use them to
move callback threads to Java level.
- Remove thread start and stop hooks (as polling is available).
- Make Notifiers, RpcServer, Dispatcher, and Storage mockable.
- Set NOTIFY_NEW on immediate entry notifications.
- Make GetTable("/") and GetTable("") equivalent.
- Generate local notification for flags update when loading persistent file.
And many unit test updates/changes:
- Use InitGoogleMock instead of InitGoogleTest in test main.
- Move test printers to TestPrinter.h/cpp.
- Provide printers for StringRef, EntryNotifier, and Handle.
- StorageTest: Check notifications.
- Add entry notifier unit tests.
- Storage: Add test for incoming entry assignment.
- Update connection listener tests.
- Add entry listener unit tests.
Fixes #11, #140, #189, #190, #192, #193, #221
2017-04-23 10:26:17 -07:00
|
|
|
m_dispatcher.ClearServerOverride();
|
2016-11-04 16:01:42 -07:00
|
|
|
oldip = 0;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If unchanged, don't reconnect
|
|
|
|
|
if (ip == oldip) continue;
|
|
|
|
|
oldip = ip;
|
|
|
|
|
|
|
|
|
|
// Convert number into dotted quad
|
|
|
|
|
json.clear();
|
|
|
|
|
llvm::raw_svector_ostream os{json};
|
|
|
|
|
os << ((ip >> 24) & 0xff) << "." << ((ip >> 16) & 0xff) << "."
|
|
|
|
|
<< ((ip >> 8) & 0xff) << "." << (ip & 0xff);
|
|
|
|
|
INFO("client: DS overriding server IP to " << os.str());
|
Implement independent instances.
Previously, most of the classes were implemented as singletons so only one
instance was possible.
This change adds an instance handle-based API. In Java, this API is located
in a different package than the old API (edu.wpi.first.networktables).
Backwards compatibility with ITable and the old NetworkTable API is largely
maintained, but a handful of classes have moved to the new package in Java
(ConnectionInfo and PersistentException), and the old JNI has been completed
replaced.
Also:
- Move SetTeam implementation to Dispatcher.
- Consistently pass time through Java and C++ Value API.
- Rename nt_Value.h to NetworkTableValue.h for consistency with Java.
- Improve documentation
- Make C++ and Java APIs more consistent
- Document RPC functions and support RPC in Java.
- Add polling features for entry and connection listeners and use them to
move callback threads to Java level.
- Remove thread start and stop hooks (as polling is available).
- Make Notifiers, RpcServer, Dispatcher, and Storage mockable.
- Set NOTIFY_NEW on immediate entry notifications.
- Make GetTable("/") and GetTable("") equivalent.
- Generate local notification for flags update when loading persistent file.
And many unit test updates/changes:
- Use InitGoogleMock instead of InitGoogleTest in test main.
- Move test printers to TestPrinter.h/cpp.
- Provide printers for StringRef, EntryNotifier, and Handle.
- StorageTest: Check notifications.
- Add entry notifier unit tests.
- Storage: Add test for incoming entry assignment.
- Update connection listener tests.
- Add entry listener unit tests.
Fixes #11, #140, #189, #190, #192, #193, #221
2017-04-23 10:26:17 -07:00
|
|
|
m_dispatcher.SetServerOverride(json.c_str(), port);
|
2016-11-04 16:01:42 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We disconnected from the DS, clear the server override
|
Implement independent instances.
Previously, most of the classes were implemented as singletons so only one
instance was possible.
This change adds an instance handle-based API. In Java, this API is located
in a different package than the old API (edu.wpi.first.networktables).
Backwards compatibility with ITable and the old NetworkTable API is largely
maintained, but a handful of classes have moved to the new package in Java
(ConnectionInfo and PersistentException), and the old JNI has been completed
replaced.
Also:
- Move SetTeam implementation to Dispatcher.
- Consistently pass time through Java and C++ Value API.
- Rename nt_Value.h to NetworkTableValue.h for consistency with Java.
- Improve documentation
- Make C++ and Java APIs more consistent
- Document RPC functions and support RPC in Java.
- Add polling features for entry and connection listeners and use them to
move callback threads to Java level.
- Remove thread start and stop hooks (as polling is available).
- Make Notifiers, RpcServer, Dispatcher, and Storage mockable.
- Set NOTIFY_NEW on immediate entry notifications.
- Make GetTable("/") and GetTable("") equivalent.
- Generate local notification for flags update when loading persistent file.
And many unit test updates/changes:
- Use InitGoogleMock instead of InitGoogleTest in test main.
- Move test printers to TestPrinter.h/cpp.
- Provide printers for StringRef, EntryNotifier, and Handle.
- StorageTest: Check notifications.
- Add entry notifier unit tests.
- Storage: Add test for incoming entry assignment.
- Update connection listener tests.
- Add entry listener unit tests.
Fixes #11, #140, #189, #190, #192, #193, #221
2017-04-23 10:26:17 -07:00
|
|
|
m_dispatcher.ClearServerOverride();
|
2016-11-04 16:01:42 -07:00
|
|
|
oldip = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
done:
|
Implement independent instances.
Previously, most of the classes were implemented as singletons so only one
instance was possible.
This change adds an instance handle-based API. In Java, this API is located
in a different package than the old API (edu.wpi.first.networktables).
Backwards compatibility with ITable and the old NetworkTable API is largely
maintained, but a handful of classes have moved to the new package in Java
(ConnectionInfo and PersistentException), and the old JNI has been completed
replaced.
Also:
- Move SetTeam implementation to Dispatcher.
- Consistently pass time through Java and C++ Value API.
- Rename nt_Value.h to NetworkTableValue.h for consistency with Java.
- Improve documentation
- Make C++ and Java APIs more consistent
- Document RPC functions and support RPC in Java.
- Add polling features for entry and connection listeners and use them to
move callback threads to Java level.
- Remove thread start and stop hooks (as polling is available).
- Make Notifiers, RpcServer, Dispatcher, and Storage mockable.
- Set NOTIFY_NEW on immediate entry notifications.
- Make GetTable("/") and GetTable("") equivalent.
- Generate local notification for flags update when loading persistent file.
And many unit test updates/changes:
- Use InitGoogleMock instead of InitGoogleTest in test main.
- Move test printers to TestPrinter.h/cpp.
- Provide printers for StringRef, EntryNotifier, and Handle.
- StorageTest: Check notifications.
- Add entry notifier unit tests.
- Storage: Add test for incoming entry assignment.
- Update connection listener tests.
- Add entry listener unit tests.
Fixes #11, #140, #189, #190, #192, #193, #221
2017-04-23 10:26:17 -07:00
|
|
|
m_dispatcher.ClearServerOverride();
|
2016-11-04 16:01:42 -07:00
|
|
|
}
|