Question

I am trying to modify iperf to support another protocol (UDT). The UDT API is written such that it mirrors the standard BSD calls:

  socket(...);
  bind(...);
  listen(...);

What I need to do then, is conditionally link with the UDT library so that these calls in iperf will use the UDT code instead of the socket interface to the TCP stack. Can this be done? I could always just load the library and have another conditional path using the UDT:: namespace but there would 1) be a lot of duplication from the TCP path and 2) be a lot of changes where maybe there need be none. Please let me know if I'm not being clear, any suggestions of how to achieve this dynamic linking is appreciated.

Edit:

Using the dlopen() family mentioned below, I could have the following program flow:

Parse cmd line params -> if UDT is requested, load library libudt -> get and store handles to all the UDT BSD functions (bind, listen, etc)

At this point I have function pointers stored with all my UDT functions. Let's say I'm storing them all in a struct called udt_calls. Now, I have a problem with the existing code which just makes calls like:

          bind(...)

rather than:

         udt_calls->bind(...)

Is there a clean way I can globally override any BSD call throughout the program with my now loaded function pointers in my udt_calls struct?

Was it helpful?

Solution

Yes this can be done. You need to use dynamic library loading. In Windows this is done using LoadLibrary. In Linux or Unix it is done using dlopen and friends.

You'll want to read the documentation and look at samples for those functions. A quick summary is that you create a bunch of function pointers (often done in a struct, and on Windows there are some tricks to make them load into a C++ virtual function class). Then you use the dynamic load functions to open a library and then assign your function pointers to point to the functions inside the library.

Then, you make your function calls using the function pointers (or C++ virtual functions).

Edit: It looks like there are ways to use C++ virtual base classes in Unix as well.

Edit: I believe that most systems make the operating system libraries use "weak" symbols. That means that you can define your own global symbols of the same name and override the OS library version. Try declaring global function pointers in your own program to provide global versions of bind and listen.

Another option may be to declare your pointers in a struct and then use preprocessor defines like:

#define bind udt_calls->bind
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top