Skip to content

jfixemer/AsioSelectAdapter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AsioSelectAdapter

Helps applications using fd_set integrate with ASIO.

Status: Basically working. Your mileage may vary.

Goal is to convert and old, select based event loop to a new event loop run by ASIO.

Building:

  • copy adapter/AsioSelect.hpp and source/AdpterSelect.cpp into your project. --or--
  • Use this project's CMake configuration:
    • include: %ROOT%/include,
    • link: %BUILD%/libselectadapter.a

Why not header only: I don't fully understand the voodoo of this strategy and would probably create something that wouldn't offer the inlining and optimization benefits.

Why: This is up to you but some of the items:

  • modernization, moving from select to a poll/epoll system
  • modernization, moving toward future C++ NetworkTS compilance
  • wanting to add Other network or HTTP services with Asio/Beast (REST, WebSockets)

What this does not do:

  • Provide portability to Windows (because asio::posix is not enabled on Windows)

The big problem you have hit is

  • to many legacy interfaces to convert all at once.
  • some old or third party code cannot be converted (e.g. NetSNMP)

Given an Old event loop:

int main(...)
{
    legacy_initialize(); // create some sockets and stuff
    while(true)
    {
        fd_set read_fd_set;
        FD_ZERO(read_fd_set);
        int max_fd = 0;
        int blocking=1;
        struct timeval tv;

        // Read info about sockets and the next timeout.
        // e.g. snmp_select_info
        legacy_select_info(&max_fd, &read_fd_set, &tv, &blocking);

        struct timeval *tvp = (blocking ? null : &tv);

        // Ignoring write and exception fds for this UDP example...
        int num_ready = select(max_fd, &read_fd_set, NULL, NULL, tvp);

        if(num_ready < 0)
            if(check_fatal_error(...)) 
                break;

        // Alt: Some may prefer to dispatch sockets before handling timeouts.
        legacy_timeout();  // e.g. netsnmp::snmp_timeout

        if(num_ready > 0 )
            legacy_read(&read_fd_set); // e.g. netsnmp::snmp_read
    }
}

This would transform into A helper function / functor / lambda and a modified 'main' loop based on asio io/executor.run()

Helper function:

#include <sys/select.h>
#include <boost/system/error_codes.hpp>

typedef std::shared_ptr<adapter::AsioSelect> Adapter_sptr;

int legacy_dispatch_wrapper(int num_ready, fd_set* read_fd_set, boost::system::error_code error);
{
    if(error && check_fatal_error(...))        
        return -1; 

    legacy_timeout();

    if(num_ready > 0 )
        legacy_read(read_fd_set);
}

The modified 'main' event loop...

#include "adapter/AsioSelect.hpp"
...

int main(...)
{
    asio::io_context asio_io;

    std::shared_ptr<adapter::AsioSelect> MyAdapter = adapter::AsioSelect::make(asio_io);

    initialize_legacy_service();
    create_asio_native_services(asio_io, ...);

    MyAdapter->setup(legacy_dispatch_wrapper, legacy_select_info);

    //If sockets were not ready at setup:  reactor_sp->update();
    asio_io.run();
}

About

Helps applications using fd_set integrate with ASIO.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published