An additional type, fbListener_t, is used to build Collecting Processes to listen for connections from IPFIX Exporting Processes via the network.
The initial steps to creating a Listener are the same as the previous examples:
First create an fbInfoModel_t using fbInfoModelAlloc() and any additional, vendor-specific information elements using fbInfoModelAddElement(), fbInfoModelAddElementArray(), fbInfoModelReadXMLFile(), or fbInfoModelReadXMLData().
Create an fbSession_t using fbSessionAlloc(). Instead of maintaining state for a particular Transport Session, this Session instance is used as a model for each Transport Session created by the Listener. (Each incoming connection is a unique Session. If a single connection contains multiple observation domains, each domain is also a unique Session.)
For each record you expect to receive, create an fbTemplate_t via fbSessionAddTemplate(), specify its elements (fbTemplateAppendSpecArray(), fbTemplateAppendSpec(), or fbTemplateAppend()), and add it as an internal Template to the Session uinsg fbSessionAddTemplate().
To specify the host and port where the Listener should wait for connections, define an fbConnSpec_t object.
Create the fbListener_t using the fbListenerAlloc() call. The Listener encapsulates a passive socket on the network that waits for connections from Exporting Processes.
To wait for a connection, call fbListenerWait(). When a new connection arrives, the function clones the fbSession_t, creates an fbCollector_t, and creates a Buffer (fBuf_t) for reading from that Collector, and returns the newly created Buffer.
A Listener binds to each address returned by getaddrinfo(). Once a packet is received from an address, the Collector only reads packets on that address UNLESS fbListenerWait() is called again. If the application is expecting multiple connections or IPFIX records from multiple IPFIX (UDP) exporters, the application should put the fBuf_t returned from fbListenerWait() into to manual mode by calling fBufSetAutomaticNextMessage() with FALSE as the second argument 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 returns an fBuf_t from which another IPFIX Message may be read if no new connections are available. To minimize switching among available Sessions, the most recent fBuf_t is returned if it has data available.
The application may also use fbListenerWaitNoCollectors() to handle only the initial accepting of a connection (for TCP). Once an fBuf_t and its associated fbCollector_t are returned by this function, that connection is ignored by subsequent calls to fbListenerWaitNoCollectors() for the duration of the connection.
If an application wants to wait for connections on multiple ports or multiple transport protocols, the application may use fbListenerGroupWait() to accept multiple connections. The application should create separate a fbSession_t and fbConnSpec_t for each fbListener_t and call fbListenerAlloc() to allocate each listener. Allocate an fbListenerGroup_t (fbListenerGroupAlloc()) and add each Listener to the Group using fbListenerGroupAddListener(). Instead of calling fbListenerWait(), use 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.
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_fn 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 differently for UDP. See the UDP instructions for how to use appinit() for collecting IPFIX over UDP.
Previous: Template Definition | Next: UDP Collectors