Listening over the Network - TCP Recommended:
An additional type, fbListener_t, is used to build Collecting Processes to listen for connections from IPFIX Exporting Processes via the network. To use a listener, first create an fbInfoModel_t using fbInfoModelAlloc() and any additional, vendor-specific information elements using fbInfoModelAddElement() or fbInfoModelAddElementArray(). Next create an fbSession_t using fbSessionAlloc() and add internal templates via fbSessionAddTemplate(). Instead of maintaining state for a particular Transport Session, this fbSession_t instance will be used as a template for each Transport Session created by the listener.
Then create an fbListener_t to encapsulate a passive socket on the network to wait for connections from Exporting Processes using the fbListenerAlloc() call.
To wait for a connection from an Exporting Process, call fbListenerWait(), which handles the cloning of the fbSession_t, the creation of the fbCollector_t, and the creation of the buffer for reading from that collector, and returns the newly created fBuf_t instance.
A listener binds to each address returned by getaddrinfo(). Once a packet has been received, the collector will only read packets on the address it received the first packet UNLESS fbListenerWait() is called again. If the application is expecting multiple connections or IPFIX records from multiple IPFIX (UDP) exporters, then the application should put the fBuf_t returned from fbListenerWait() into to manual mode by calling fBufSetAutomaticMode(fbuf, FALSE) and handle FB_ERROR_EOM errors returned from fBufNext() by calling fbListenerWait() again.
Each listener tracks every active collector/buffer (i.e., each active Session) it created; the fbListenerWait() call will return an fBuf_t from which another IPFIX Message may be read if no new connections are available. The preferred parameter may be used to request an fBuf_t to try first, to minimize switching among available Sessions. See the documentation for fbListenerWait() for more details.
If an application wants to wait for connections on multiple ports or multiple transport protocols, the application can use fbListenerGroupWait() to accept multiple connections. The application should create separate sessions and fbConnSpec_ts for each fbListener and call fbListenerAlloc() to allocate each listener. Create an fbListenerGroup_t by calling fbListenerGroupAlloc() and add each listener to the group using fbListenerGroupAddListener(). Instead of calling fbListenerWait(), use the function fbListenerGroupWait() to listen on all addresses in the group. fbListenerGroupWait() returns an fbListenerGroupResult_t which is a linked list of results. The fbListenerGroupResult_t contains a pointer to an fBuf_t and the fbListener_t that created the fBuf_t as well as a pointer to the next result, if available. Use fbListenerFreeGroupResult() to free the result when fBufNext() has been called on each fBuf_t.
The application could also use fbListenerWaitNoCollectors() to handle only the initial accepting of a connection (for TCP). Once the application returns to fbListenerWaitNoCollectors(), fixbuf will ignore that socket descriptor for the length of the connection.
Additionally, the application can use fbListenerOwnSocketCollectorTCP() to provide its own socket for listening instead of libfixbuf creating one for it.
To reject incoming connections, the application should use the fbListenerAppInit function callback. This will be called right after accept() is called (in the TCP case). The application can veto the connection by returning FALSE. Once the connection is vetoed, fixbuf will not listen on that socket descriptor. If the appinit() function should reject a connection the application should set the error code to FB_ERROR_NLREAD and the application should ignore FB_ERROR_NLREAD error codes. The appinit() function works slightly different for UDP. See the udp instructions for how to use appinit() for collecting IPFIX over UDP.