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 asyncio Based faradayio #65

Open
kb1lqc opened this issue Mar 13, 2018 · 3 comments
Open

Implement asyncio Based faradayio #65

kb1lqc opened this issue Mar 13, 2018 · 3 comments
Assignees

Comments

@kb1lqc
Copy link
Member

kb1lqc commented Mar 13, 2018

Per #64 thanks to the help of @reillyeon and @hdkmike it's apparent I need to start looking at asyncio. This is one of the larger packages in and reasons for moving to Python 3. As discussed in #64 there's a delay in servicing packets because of waiting for timeouts to occur.

TUN

pytun does not even implement a timeout. It uses standard C reads in Linux and therefore will block until the expected amount of data is received. Therefore. I placed a timeout decorator in faradayio for the checkTUN() function. This was done in 2f582ae to stop the module from blocking.


    @timeout_decorator.timeout(1, use_signals=False)
    def checkTUN(self):
        """
        Checks the TUN adapter for data and returns any that is found.
        Returns:
            packet: Data read from the TUN adapter
        """
        packet = self._TUN._tun.read(self._TUN._tun.mtu)
return(packet)

Serial

The pyserial does not block and defaults to reading with no timeout. This means it will receive up to the amount requested but if not then it will immediately return with what it has. As shown in #64 this results in a small delay.

Running TUN and Serial Together

Currently, the TUN and serial interfaces are checked with the run() function. This is a loop that is spun off in a thread to repeatedly poll the TUN and serial ports. While this works, the obvious problem is that we must wait for timeouts to occur on each interface and cannot react when data is immediately available.

This is where asyncio comes in. The module is designed to allow asynchronous operation of "coroutines" which allow immediate action on data available on interfaces.

Testing

There is information on how to test with asyncio. However, I've had trouble before on #3 though I may know enough now to solve the issues. I am not sure if I want to embark on a test driven development path here or solve the problem. I'll think about it.

@kb1lqc
Copy link
Member Author

kb1lqc commented Mar 14, 2018

@kb1lqc
Copy link
Member Author

kb1lqc commented Mar 23, 2018

Playing with this last night I am coming to a few conclusions:

  • It's actually pretty easy to setup asyncio code
  • I need to implement pyserial-asyncio as well

The reason for pyserial-asyncio is likely due to the way pyserial blocks/accesses the serial port. In pyserial-asyncio the use of an asyncio protocol and callbacks helps produce a more asynchronous friendly access method.

I was able to get asyncio and pytest working pretty well together! Essentially, it acted more reliably than threads for starting/stopping which was nice. In most other ways it acted very similar to how a thread would work from the users perspective.

@kb1lqc
Copy link
Member Author

kb1lqc commented Mar 29, 2018

Notes from tonights work on pyserial-asyncio branch:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant