To be able to use DPF, applications must call DPF functions. We call this process of making an application DPF-aware DPFnize. A DPFnized program must calls the following functions instead of regular counterparts:
- Sockets calls: DPF_socket, DPF_bind, DPF_listen, DPF_connect, DPF_accept, DPF_recv, DPF_recvfrom, DPF_send, DPF_sendto, DPF_getsockname, DPF_getsockaddr, DPF_getsockopt
- File system related calls: DPF_select, DPF_read, DPF_write, DPF_close, DPF_dup, DPF_dup2, DPF_fcntl
- Process control calls: DPF_fork, DPF_execve
You can make an application DPFnized either by:
- explicilty (re)writing the application to call DPF functions. If you have source codes of the application, the this may be the best option to take. Please read DPF-friendly Guide.
- statically interposing the application. Some linkers such as GNU linker provide options to replace (or wrap) system calls with arbitrary function. If you are using one of these linkers, then you can DPFnize your application using this mechanism. Currently we have a simple file for static interposition with GNU linker. Please refer GNU linker manual (search for --wrap option). Copy this file, read the file carefully, and then link your program with DPF library and the file.
- dynamically interposing the application. If you don't even have object file to relink with DPF or your linker does not have wrapping option, then you need to resort to one of dynamic interposition mechanism. Check parrot or other site you know of.
Note: even if you choose to use the 2nd or 3rd option, I would recommend you to still read DPF-friendly Guide. Even though I tried my best to make DPF calls have the same semantics as the corresponding Berkeley socket calls, some DPF calls have slightly different semantics from corresponding socket calls.
Because of address leasing (See How DPF Works) and extra communications with the DPF inagent, DPF has different semantics for some calls and therefore has a serveral programming constraints.
- It is always safe to use DPF functions instead of regular socket calls even for non-DPF socket and regular file descriptors. For example, you can safely use DPF_close for a regular file. DPF knows what fds it is in charge of. Especially it is very unsafe for applications to blindly call close. This happens in some applications because calling close for invalid fd does not do any harm. For example, a child process of some applications blindly closes every fd except a few that it needs to use. To communicate with the inagent, DPF may create sockets without application's notice. If these sockets that DPF uses for its own purpose are closed without DPF's awareness, DPF will have a bad information
- Applications should not choose private IP address to bind a socket. This means that, if a machine does not have a public IP, applications must call DPF_bind with IP = INADDR_ANY and ask DPF, by calling DPF_getsockname, when it needs to know the address that the socket is bound to. Applications can still designate port number to bind.
- DPF_bind and DPF_listen are blocking calls, meaning that these calls may take from few micro seconds to few ten seconds in the worst case and the application will be blocked until the operation completes. This does not affect programming much and, because these are one-time operations for socket lifetime, I believe that they have little performance effect.