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

Event system #14

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open

Event system #14

wants to merge 4 commits into from

Conversation

HosseyNJF
Copy link

@HosseyNJF HosseyNJF commented May 9, 2020

There is one event class implemented now, the ClientEvent class is handling events coming from client interaction. I wrote two threads for the connection process with sockets; They're working as expected but probably this PR requires much more testing to be mergeable.

@HosseyNJF HosseyNJF changed the title Event systemEvents Event system May 9, 2020
@HosseyNJF
Copy link
Author

Any feedback?

@Jamie-
Copy link
Owner

Jamie- commented Jun 13, 2020

Thanks for the PR, I'm incredibly busy at the moment on other projects I'm trying to push live so don't have the time yet to review these changes as they're quite big. Sorry it's slow. I'll get to them.

@Jamie- Jamie- mentioned this pull request Aug 15, 2020
@Jamie-
Copy link
Owner

Jamie- commented Aug 15, 2020

Master has since changed so I've created a branch and fixed the conflicts: https://github.com/Jamie-/openvpn-api/tree/event-system

@jkroepke jkroepke mentioned this pull request Aug 15, 2020
Copy link
Owner

@Jamie- Jamie- left a comment

Choose a reason for hiding this comment

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

I now have more time and have got to reviewing this now.

Good start, thanks for the contribution!

I've created a branch event-system where I've taken the code from here, rebased it onto the new head of master and changed some of the things I've already mentioned in comments.



def register_callback(callback: typing.Callable[[typing.Type], typing.Any]) -> None:
_callbacks.append(callback)
Copy link
Owner

Choose a reason for hiding this comment

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

Ok so callbacks are global, if I have multiple instances of VPN I cannot assign a callback for an event to just one of them, equally, when the callback is called I have no idea which instance they came from.

Copy link
Author

Choose a reason for hiding this comment

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

Good point, I didn't think about having multiple instances at that time. :)


from openvpn_api.events import client

event_types = [importlib.import_module(".client", __name__)]
Copy link
Owner

Choose a reason for hiding this comment

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

Personally, I think this implementation of different event types (I presume client/server) is a bit gross. You're using a module like a class, what's wrong with an actual class?

By switching to a class you also don't have to do this importlib shenanigans to get all the possible types, you can create a decorator which you apply to all event type classes you have and it stores them in a registry which you can call on later.

Copy link
Author

Choose a reason for hiding this comment

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

Well, I was more of a module guy than a class guy, but it's changed nowadays. ( Long time from May :D )
I don't exactly remember why I chose module, but I guess it was because of the singleton nature of the event module/class, which would make more sense for it to be a module.

if not environment:
raise errors.ParseError("This event type (%s) doesn't support empty environment." % event_type)

return ClientEvent(event_type=event_type, cid=cid, kid=kid, pri=pri, addr=addr, environment=environment)
Copy link
Owner

Choose a reason for hiding this comment

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

As said in the first comment, this should all be a class really.

self._send_queue = queue.Queue()

self._active_event = None

Copy link
Owner

Choose a reason for hiding this comment

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

These need type hinting now as mypy checks are enabled in master

else:
self._socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
self._socket.connect(self._mgmt_socket)

self._socket_file = self._socket.makefile("r")
Copy link
Owner

Choose a reason for hiding this comment

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

From what I've understood so far I don't see why you use the socket in a file-like mode for receiving and not for sending. I'm not sure what benefit you're getting using a file-like object over the regular socket.recv(buff_size).

@@ -67,6 +93,8 @@ def disconnect(self, _quit=True) -> None:
if self._socket is not None:
if _quit:
self._socket_send("quit\n")

self._socket_file.close()
self._socket.close()
self._socket = None
Copy link
Owner

Choose a reason for hiding this comment

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

You're spawning threads up but they never get torn down. If we call disconnect, we should also stop the threads

Copy link
Owner

Choose a reason for hiding this comment

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

I partially take that back, they do break when self.is_connected is False but the're no waiting for shutdown in the disconnect method

@HosseyNJF
Copy link
Author

Thank you :) You've already done most of the reviews; Is there anything that I could add to it or should we merge it?
I guess it still needs some real-life and high-stress testing.

@Jamie-
Copy link
Owner

Jamie- commented Aug 17, 2020

Have also just discovered sockets are not thread safe, so having two threads (a send and a receive) is a "bad thing". Just about to commit a fix for that which puts all socket communication into one thread.

But yes, as you say, it does need more unittest testing, and some real life testing, and ideally some load testing too. That would be cool

@HosseyNJF
Copy link
Author

HosseyNJF commented Aug 29, 2020

I discovered that 4096 is a real low buffer size, and the client-connect event never reaches the callback because it gets split up with the low buffer, and an exception gets thrown. maybe we should increase it? It won't even fit a single event, not to mention multiple events coming at the same time.

Edit: seems like OpenVPN actually sends one event in multiple packets, and the bug won't be fixed by just increasing buffer size.

@HosseyNJF
Copy link
Author

HosseyNJF commented Aug 29, 2020

I fixed this bug and some others in my repo: HosseyNJF/openvpn-api

@HosseyNJF
Copy link
Author

I've been using this on a production server for 4 months now, and everything's looking stable, although my fix of the buffer bug isn't waterproof and probably is going to fail sometime. Any updates?

@HosseyNJF
Copy link
Author

Hi @Jamie-. I know this is an ancient PR, but it would be a waste to abandon this feature :) If you are up for it. I can start testing the event-system branch present on this repo (not my fork) on a production server, and give feedback so that this feature could be present in the master.

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.

2 participants