Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement TCPServerCommProvider #241

Closed
wants to merge 3 commits into from

Conversation

MichaelElmore1
Copy link

@MichaelElmore1 MichaelElmore1 commented Sep 29, 2023

I added a TCPServerCommProvider, which allows OSH to act as a server and send/receive data from a number of clients.

The TCP and UDP comm providers only allow a single connection, and so have been using getInputStream and getOutputStream. Since a server can have many connections, I had to implement a way to serve up the input and output stream, and do so in a way that all the comm providers can get access to the input and output streams regardless of whether server or client.

Now, rather than using getInputStream and getOutputStream, you can register code to call in onConnection:

commProvider.onConnection(args -> {
//do stuff with args.getInputStream() and getOutputStream()
})

or (alt syntax)

commProvider.onConnection(this::handleConnection)

...

handleConnection(ConnectionEventArgs args) {
//do stuff with args.getInputStream() and getOutputStream()
}

onConnection is called whenever a connection is established. For TCP and UDP comm providers, this connection always happens in start(), so the onConnection event should be registered before the comm module is started:

var moduleReg = getParentHub().getModuleRegistry();
commProvider = (ICommProvider<?>) moduleReg.loadSubModule(config.commSettings, true);
commProvider.onConnection(this::handleConnection);
commProvider.start();

In your onConnection method, you can handle getting the input and output streams the same way, regardless of whether OSH is acting as a client or server.

Please let me know if I need to make any changes, write unit tests, or anything else.

Copy link
Collaborator

@nickgaray nickgaray left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really good job! A couple of concerns listed in the review comments.

static final Logger log = LoggerFactory.getLogger(TCPCommProvider.class.getSimpleName());

private final Set<Consumer<ConnectionEventArgs>> listeners = new HashSet<>();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 Questions:

  1. Why a Set<> and why not just a simple ArrayList<>?
  2. There should be a single commProvider per "driver" and a single "Consumer" pre comm provider shouldn't there? Maybe I am not thinking about this right but what is the use case for 1 CommProvider to multiple listeners?

if (config.enableTLS) {
var sslServerSocketFactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
try (var sslServerSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(config.localPort)) {
while (true) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would not use a loop like this, I would create a variable that is synchronized like an AtomicBoolean to control execution of the loop(s) (here and line 64). In the doStop method I would set that AtomicBoolean false so that the active loop in the thread knows when to exit.

Interrupt causes an InterruptedException to be thrown by the thread. As a general rule using interrupts are expensive computationally and when possible, should be avoided to control program logic and flow. Exceptions should be exceptional.

static final Logger log = LoggerFactory.getLogger(UDPCommProvider.class.getSimpleName());

private final Set<Consumer<ConnectionEventArgs>> listeners = new HashSet<>();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as in TCP Comm Provider regarding need for or understanding need for more than one listener as well as choice of Set over ArrayList

@alexrobin
Copy link
Member

Sorry I didn't really have time to look at this in details.
Are you guys happy with the current version or does this PR need more work?
Thanks

@MichaelElmore1
Copy link
Author

It does need more work

@MichaelElmore1 MichaelElmore1 marked this pull request as draft November 14, 2023 14:40
@MichaelElmore1
Copy link
Author

#245

This PR is obsolete, and the above is the new version.

@MichaelElmore1 MichaelElmore1 deleted the feature-server-comm-provider branch June 4, 2024 20:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants