123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125 |
- #LyX 1.3 created this file. For more info see http://www.lyx.org/
- \lyxformat 221
- \textclass article
- \language english
- \inputencoding latin1
- \fontscheme pslatex
- \graphics default
- \paperfontsize default
- \spacing single
- \papersize letterpaper
- \paperpackage a4
- \use_geometry 1
- \use_amsmath 0
- \use_natbib 0
- \use_numerical_citations 0
- \paperorientation portrait
- \leftmargin 10mm
- \topmargin 10mm
- \rightmargin 10mm
- \bottommargin 15mm
- \secnumdepth 4
- \tocdepth 3
- \paragraph_separation skip
- \defskip medskip
- \quotes_language english
- \quotes_times 2
- \papercolumns 1
- \papersides 1
- \paperpagestyle default
- \bullet 1
- 0
- 6
- -1
- \end_bullet
- \bullet 2
- 0
- 0
- -1
- \end_bullet
- \layout Title
- \color black
- Flowreplay Design Notes
- \layout Author
- \color black
- Aaron Turner
- \newline
- http://tcpreplay.synfin.net/
- \layout Date
- \color black
- Last Edited:
- \newline
- October 23, 2003
- \layout Section
- \pagebreak_top
- \color black
- Overview
- \layout Standard
- \color black
- Tcpreplay
- \begin_inset Foot
- collapsed true
- \layout Standard
- \color black
- http://tcpreplay.sourceforge.net/
- \end_inset
- was designed to replay traffic previously captured in the pcap format back
- onto the wire for testing NIDS and other passive devices.
- Over time, it was enhanced to be able to test in-line network devices.
- However, a re-occurring feature request for tcpreplay is to connect to
- a server in order to test applications and host TCP/IP stacks.
- It was determined early on, that adding this feature to tcpreplay was far
- too complex, so I decided to create a new tool specifically designed for
- this.
- \layout Standard
- \color black
- Flowreplay is designed to replay traffic at Layer 4 or 7 depending on the
- protocol rather then at Layer 2 like tcpreplay does.
- This allows flowreplay to connect to one or more servers using a pcap savefile
- as the basis of the connections.
- Hence, flowreplay allows the testing of applications running on real servers
- rather then passive devices.
-
- \layout Section
- \color black
- Features
- \layout Subsection
- \color black
- Requirements
- \layout Enumerate
- \color black
- Full TCP/IP support, including IP fragments and TCP stream reassembly.
- \layout Enumerate
- \color black
- Support replaying TCP and UDP flows.
- \layout Enumerate
- \color black
- Code should handle each flow/service independently.
- \layout Enumerate
- \color black
- Should be able to connect to the server(s) in the pcap file or to a user
- specified IP address.
- \layout Enumerate
- \color black
- Support a plug-in architecture to allow adding application layer intelligence.
- \layout Enumerate
- \color black
- Plug-ins must be able to support multi-flow protocols like FTP.
- \layout Enumerate
- \color black
- Ship with a default plug-in which will work
- \begin_inset Quotes eld
- \end_inset
- well enough
- \begin_inset Quotes erd
- \end_inset
- for simple single-flow protocols like HTTP and telnet.
- \layout Enumerate
- \color black
- Flows being replayed
- \begin_inset Quotes eld
- \end_inset
- correctly
- \begin_inset Quotes erd
- \end_inset
- is more important then performance (Mbps).
- \layout Enumerate
- \color black
- Portable to run on common flavors of Unix and Unix-like systems.
- \layout Subsection
- \color black
- Wishes
- \layout Enumerate
- \color black
- Support clients connecting to flowreplay on a limited basis.
- Flowreplay would replay the server side of the connection.
- \layout Enumerate
- \color black
- Support other IP based traffic (ICMP, VRRP, OSPF, etc) via plug-ins.
- \layout Enumerate
- \color black
- Support non-IP traffic (ARP, STP, CDP, etc) via plug-ins.
- \layout Enumerate
- \color black
- Limit which flows are replayed using user defined filters.
- (bpf filter syntax?)
- \layout Enumerate
- \color black
- Process pcap files directly with no intermediary file conversions.
- \layout Enumerate
- \color black
- Should be able to scale to pcap files in the 100's of MB in size and 100+
- simultaneous flows on a P3 500MHz w/ 256MB of RAM.
- \layout Section
- \color black
- Design Thoughts
- \layout Subsection
- \color black
- Sending and Receiving traffic
- \layout Standard
- \color black
- Flowreplay must be able to process multiple connections to one or more devices.
- There are two options:
- \layout Enumerate
- \color black
- Use sockets
- \begin_inset Foot
- collapsed true
- \layout Standard
- \color black
- socket(2)
- \end_inset
- to send and receive data
- \layout Enumerate
- \color black
- Use libpcap
- \begin_inset Foot
- collapsed true
- \layout Standard
- \color black
- http://www.tcpdump.org/
- \end_inset
- to receive packets and libnet
- \begin_inset Foot
- collapsed true
- \layout Standard
- \color black
- http://www.packetfactory.net/projects/libnet/
- \end_inset
- to send packets
- \layout Standard
- \color black
- Although using libpcap/libnet would allow more simultaneous connections
- and greater flexibility, there would be a very high complexity cost associated
- with it.
- With that in mind, I've decided to use sockets to send and receive data.
- \layout Subsection
- \color black
- Handling Multiple Connections
- \layout Standard
- \color black
- Because a pcap file can contain multiple simultaneous flows, we need to
- be able to support that too.
- The biggest problem with this is reading packet data in a different order
- then stored in the pcap file.
-
- \layout Standard
- \color black
- Reading and writing to multiple sockets is easy with select() or poll(),
- however a pcap file has it's data stored serially, but we need to access
- it randomly.
- There are a number of possible solutions for this such as caching packets
- in RAM where they can be accessed more randomly, creating an index of the
- packets in the pcap file, or converting the pcap file to another format
- altogether.
- Alternatively, I've started looking at libpcapnav
- \begin_inset Foot
- collapsed true
- \layout Standard
- http://netdude.sourceforge.net/
- \end_inset
- as an alternate means to navigate a pcap file and process packets out of
- order.
- \layout Subsection
- \color black
- Data Synchronization
- \layout Standard
- \color black
- Knowing when to start sending client traffic in response to the server will
- be "tricky".
- Without understanding the actual protocol involved, probably the best general
- solution is waiting for a given period of time after no more data from
- the server has been received.
- Not sure what to do if the client traffic doesn't elicit a response from
- the server (implement some kind of timeout?).
- This will be the basis for the default plug-in.
- \layout Subsection
- \color black
- TCP/IP
- \layout Standard
- \color black
- Dealing with IP fragmentation and TCP stream reassembly will be another
- really complex problem.
- We're basically talking about implementing a significant portion of a TCP/IP
- stack.
- One thought is to use libnids
- \begin_inset Foot
- collapsed true
- \layout Standard
- \color black
- http://www.avet.com.pl/~nergal/libnids/
- \end_inset
- which basically implements a Linux 2.0.37 TCP/IP stack in user-space.
- Other solutions include porting a TCP/IP stack from Open/Net/FreeBSD or
- writing our own custom stack from scratch.
- \layout Section
- \color black
- Multiple Independent Flows
- \layout Standard
- \color black
- The biggest asynchronous problem, that pcap files are serial, has to be
- solved in a scaleable manner.
- Not much can be assumed about the network traffic contained in a pcap savefile
- other then Murphy's Law will be in effect.
- This means we'll have to deal with:
- \layout Itemize
- \color black
- Thousands of small simultaneous flows (captured on a busy network)
- \layout Itemize
- \color black
- Flows which
- \begin_inset Quotes eld
- \end_inset
- hang
- \begin_inset Quotes erd
- \end_inset
- mid-stream (an exploit against a server causes it to crash)
- \layout Itemize
- \color black
- Flows which contain large quantities of data (FTP transfers of ISO's for
- example)
- \layout Standard
- \color black
- How we implement parallel processing of the pcap savefile will dramatically
- effect how well we can scale.
- A few considerations:
- \layout Itemize
- Most Unix systems limit the maximum number of open file descriptors a single
- process can have.
- Generally speaking this shouldn't be a problem except for highly parallel
- pcap's.
- \layout Itemize
- While RAM isn't limitless, we can use mmap() to get around this.
- \layout Itemize
- Many Unix systems have enhanced solutions to poll() which will improve flow
- management.
- \layout Comment
- \color black
- Unix systems implement a maximum limit on the number of file descriptors
- a single process can open.
- My Linux box for example craps out at 1021 (it's really 1024, but 3 are
- reserved for STDIN, STDOUT, STDERR), which seems to be pretty standard
- for recent Unix's.
- This means we're limited to at most 1020 simultaneous flows if the pcap
- savefile is opened once and half that (510 flows) if the savefile is re-opened
- for each flow.
- \begin_inset Foot
- collapsed true
- \layout Standard
- \color black
- It appears that most Unix-like OS's allow root to increase the
- \begin_inset Quotes eld
- \end_inset
- hard-limit
- \begin_inset Quotes erd
- \end_inset
- beyond 1024.
- Compiling a list of methods to do this for common OS's should be added
- to the flowreplay documentation.
- \end_inset
- \layout Comment
- \color black
- RAM isn't limitless.
- Caching packets in memory may cause problems when one or more flows with
- a lot of data
- \begin_inset Quotes eld
- \end_inset
- hang
- \begin_inset Quotes erd
- \end_inset
- and their packets have to be cached so that other flows can be processed.
- If you work with large pcaps containing malicious traffic (say packet captures
- from DefCon), this sort of thing may be a real problem.
- Dealing with this situation would require complicated buffer limits and
- error handling.
- \layout Comment
- \color black
- Jumping around in the pcap file via fgetpos() and fsetpos() is probably
- the most disk I/O intensive solution and may effect performance.
- However, on systems with enough free memory, one would hope the system
- disk cache will provide a dramatic speedup.
- The
- \begin_inset Quotes eld
- \end_inset
- bookmarks
- \begin_inset Quotes erd
- \end_inset
- used by fgetpos/fsetpos are just 64 bit integers which are relatively space
- efficent compared to other solutions.
- \layout Comment
- \color black
- The other typical asynchronous issue is dealing with multiple sockets, which
- we will solve via poll()
- \begin_inset Foot
- collapsed true
- \layout Standard
- \color black
- poll(2)
- \end_inset
- .
- Each flow will define a
- \emph on
- struct pollfd
- \emph default
- and the amount of time in ms to timeout.
- Then prior to calling poll() we walk the list of flows and create the array
- of pollfd's and determine the flow(s) with the smallest timeout.
- A list of these flows is saved for when poll() returns.
- Finally, the current time is tucked away and the timeout and array of pollfd's
- is passed to poll().
- \layout Comment
- \color black
- When poll() returns, the sockets that returned ready have their plug-in
- called.
- If no sockets are ready, then the flows saved prior to calling poll() are
- processed.
- \layout Comment
- \color black
- Once all flows are processed, all the flows not processed have their timeout
- decremented by the time difference of the current time and when poll was
- last called and we start again.
- \layout Subsection
- \color black
- IP Fragments and TCP Streams
- \layout Standard
- \color black
- There are five major complications with flowreplay:
- \layout Enumerate
- \color black
- The IP datagrams may be fragmented- we won't be able to use the standard
- 5-tuple (src/dst IP, src/dst port, protocol) to lookup which flow a packet
- belongs to.
- \layout Enumerate
- \color black
- IP fragments may arrive out of order which will complicate ordering of data
- to be sent.
- \layout Enumerate
- \color black
- The TCP segments may arrive out of order which will complicate ordering
- of data to be sent.
- \layout Enumerate
- \color black
- Packets may be missing in the pcap file because they were dropped during
- capture.
- \layout Enumerate
- \color black
- There are tools like fragrouter which intentionally create non-deterministic
- situations.
- \layout Standard
- \color black
- First off, I've decided, that I'm not going to worry about fragrouter or
- it's cousins.
- I'll handle non-deterministic situations one and only one way, so that
- the way flowreplay handles the traffic will be deterministic.
- Perhaps, I'll make it easy for others to write a plug-in which will change
- it, but that's not something I'm going to concern myself with now.
- \layout Standard
- \color black
- Missing packets in the pcap file will probably make that flow unplayable.
- There are proabably certain situation where we can make an educated guess,
- but this is far too complex to worry about for the first stable release.
- \layout Standard
- \color black
- That still leaves creating a basic TCP/IP stack in user space.
- The good news it that there is already a library which does this called
- libnids.
- As of version 1.17, libnids can process packets from a pcap savefile (it's
- not documented in the man page, but the code is there).
- \layout Standard
- \color black
- A potential problem with libnids though is that it has to maintain it's
- own state/cache system.
- This not only means additional overhead, but jumping around in the pcap
- file as I'm planning on doing to handle multiple simultaneous flows is
- likely to really confuse libnids' state engine.
- Also, libnids is licensed under the GPL, but I want flowreplay released
- under a BSD-like license; I need to research if the two are compatible
- in this way.
- \layout Standard
- \color black
- Possible solutions:
- \layout Itemize
- \color black
- Developing a custom wedge between the capture file and libnids which will
- cause each packet to only be processed a single time.
- \layout Itemize
- \color black
- Use libnids to process the pcap file into a new flow-based format, effectively
- putting the TCP/IP stack into a dedicated utility.
- \layout Itemize
- \color black
- Develop a custom user-space TCP/IP stack, perhaps based on a BSD TCP/IP
- stack, much like libnids is based on Linux 2.0.37.
- \layout Itemize
- \color black
- Screw it and say that IP fragmentation and out of order IP packets/TCP segments
- are not supported.
- Not sure if this will meet the needs of potential users.
- \layout Subsection
- \color black
- Blocking
- \layout Standard
- \color black
- As earlier stated, one of the main goals of this project is to keep things
- single threaded to make coding plugins easier.
- One caveat of that is that any function which blocks will cause serious
- problems.
- \layout Standard
- \color black
- There are three major cases where blocking is likely to occur:
- \layout Enumerate
- \color black
- Opening a socket
- \layout Enumerate
- \color black
- Reading from a socket
- \layout Enumerate
- \color black
- Writing to a socket
- \layout Standard
- \color black
- Reading from sockets in a non-blocking manner is easy to solve for using
- poll() or select().
- Writing to a socket, or merely opening a TCP socket via connect() however
- requires a different method:
- \layout Quotation
- \color black
- It is possible to do non-blocking IO on sockets by setting the O_NONBLOCK
- flag on a socket file descriptor using fcntl(2).
- Then all operations that would block will (usually) return with EAGAIN
- (operation should be retried later); connect(2) will return EINPROGRESS
- error.
- The user can then wait for various events via poll(2) or select(2).
- \begin_inset Foot
- collapsed true
- \layout Standard
- \color black
- socket(7)
- \end_inset
- \layout Standard
- \color black
- If connect() returns EINPROGRESS, then we'll just have to do something like
- this:
- \layout LyX-Code
- \color black
- int e, len=sizeof(e);
- \layout LyX-Code
- \color black
- if (getsockopt(conn->s, SOL_SOCKET, SO_ERROR, &e, &len) < 0) {
- \layout LyX-Code
- \color black
- /* not yet */
- \layout LyX-Code
- \color black
- if(errno != EINPROGRESS){ /* yuck.
- kill it.
- */
- \layout LyX-Code
- \color black
- log_fn(LOG_DEBUG,"in-progress connect failed.
- Removing.");
- \layout LyX-Code
- \color black
- return -1;
- \layout LyX-Code
- \color black
- } else {
- \layout LyX-Code
- \color black
- return 0; /* no change, see if next time is better */
- \layout LyX-Code
- \color black
- }
- \layout LyX-Code
- \color black
- }
- \layout LyX-Code
- \color black
- /* the connect has finished.
- */
- \layout Quote
- \color black
- Note: It may not be totally right, but it works ok.
- (that chunk of code gets called after poll returns the socket as writable.
- if poll returns it as readable, then it's probably because of eof, connect
- fails.
- You must poll for both.
- \layout Section
- \color black
- pcap vs flow File Format
- \layout Standard
- \color black
- As stated before, the pcap file format really isn't well suited for flowreplay
- because it uses the raw packet as a container for data.
- Flowreplay however isn't interested in packets, it's interested in data
- streams
- \begin_inset Foot
- collapsed true
- \layout Standard
- \color black
- A
- \begin_inset Quotes eld
- \end_inset
- data stream
- \begin_inset Quotes erd
- \end_inset
- as I call it is a simplex communication from the client or server which
- is a complete query, response or message.
- \end_inset
- which may span one or more TCP/UDP segments, each comprised of an IP datagram
- which may be comprised of multiple IP fragments.
- Handling all this additional complexity requires a full TCP/IP stack in
- user space which would have additional feature requirements specific to
- flowreplay.
- \layout Standard
- \color black
- Rather then trying to do that, I've decided to create a pcap preprocessor
- for flowreplay called: flowprep.
- Flowprep will handle all the TCP/IP defragmentation/reassembly and write
- out a file containing the data streams for each flow.
- \layout Standard
- \color black
- A flow file will contain three sections:
- \layout Enumerate
- \color black
- A header which identifies this as a flowprep file and the file version
- \layout Enumerate
- \color black
- An index of all the flows contained in the file
- \layout Enumerate
- \color black
- The data streams themselves
- \layout Standard
- \align center
- \color black
- \begin_inset Graphics
- filename flowheader.eps
- \end_inset
- \layout Standard
- \color black
- At startup, the file header is validated and the data stream indexes are
- loaded into memory.
- Then the first data stream header from each flow is read.
- Then each flow and subsequent data stream is processed based upon the timestamp
- s and plug-ins.
- \layout Section
- \color black
- Plug-ins
- \layout Standard
- \color black
- Plug-ins will provide the
- \begin_inset Quotes eld
- \end_inset
- intelligence
- \begin_inset Quotes erd
- \end_inset
- in flowreplay.
- Flowreplay is designed to be a mere framework for connecting captured flows
- in a flow file with socket file handles.
- How data is processed and what should be done with it will be done via
- plug-ins.
- \layout Standard
- \color black
- Plug-ins will allow proper handling of a variety of protocols while hopefully
- keeping things simple.
- Another part of the consideration will be making it easy for others to
- contribute to flowreplay.
- I don't want to have to write all the protocol logic myself.
- \layout Subsection
- \color black
- Plug-in Basics
- \layout Standard
- \color black
- Each plug-in provides the logic for handling one or more services.
- The main purpose of a plug-in is to decide when flowreplay should send
- data via one or more sockets.
- The plug-in can use any
- \emph on
- non-blocking
- \emph default
- method of determining if it appropriate to send data or wait for data to
- received.
- If necessary, a plug-in can also modify the data sent.
- \layout Standard
- \color black
- Each time poll() returns, flowreplay calls the plug-ins for the flows which
- either have data waiting or in the case of a timeout, those flows which
- timed out.
- Afterwords, all the flows are processed and poll() is called on those flows
- which have their state set to POLL.
- And the process repeats until there are no more nodes in the tree.
- \layout Subsection
- \color black
- The Default Plug-in
- \layout Standard
- \color black
- Initially, flowreplay will ship with one basic plug-in called
- \begin_inset Quotes eld
- \end_inset
- default
- \begin_inset Quotes erd
- \end_inset
- .
- Any flow which doesn't have a specific plug-in defined, will use default.
- The goal of the default plug-in is to work
- \begin_inset Quotes eld
- \end_inset
- good enough
- \begin_inset Quotes erd
- \end_inset
- for a majority of single-flow protocols such as SMTP, HTTP, and Telnet.
- Protocols which use encryption (SSL, SSH, etc) or multiple flows (FTP,
- RPC, etc) will never work with the default plug-in.
- Furthermore, the default plug-in will only support connections
- \emph on
- to
- \emph default
- a server, it will not support accepting connections from clients.
- \layout Standard
- \color black
- The default plug-in will provide no data level manipulation and only a simple
- method for detecting when it is time to send data to the server.
- Detecting when to send data will be done by a
- \begin_inset Quotes eld
- \end_inset
- no more data
- \begin_inset Quotes erd
- \end_inset
- timeout value.
- Basically, by using the pcap file as a means to determine the order of
- the exchange, anytime it is the servers turn to send data, flowreplay will
- wait for the first byte of data and then start the
- \begin_inset Quotes eld
- \end_inset
- no more data
- \begin_inset Quotes erd
- \end_inset
- timer.
- Every time more data is received, the timer is reset.
- If the timer reaches zero, then flowreplay sends the next portion of the
- client side of the connection.
- This is repeated until the the flow has been completely replayed or a
- \begin_inset Quotes eld
- \end_inset
- server hung
- \begin_inset Quotes erd
- \end_inset
- timeout is reached.
- The server hung timeout is used to detect a server which crashed and never
- starts sending any data which would start the
- \begin_inset Quotes eld
- \end_inset
- no more data
- \begin_inset Quotes erd
- \end_inset
- timer.
- \layout Standard
- \color black
- Both the
- \begin_inset Quotes eld
- \end_inset
- no more data
- \begin_inset Quotes erd
- \end_inset
- and
- \begin_inset Quotes eld
- \end_inset
- server hung
- \begin_inset Quotes erd
- \end_inset
- timers will be user defined values and global to all flows using the default
- plug-in.
- \layout Subsection
- \color black
- Plug-in Details
- \layout Standard
- \color black
- Each plug-in will be comprised of the following:
- \layout Enumerate
- \color black
- An optional global data structure, for intra-flow communication
- \layout Enumerate
- \color black
- Per-flow data structure, for tracking flow state information
- \layout Enumerate
- \color black
- A list of functions which flow replay will call when certain well-defined
- conditions are met.
- \begin_deeper
- \layout Itemize
- \color black
- Required functions:
- \begin_deeper
- \layout Itemize
- \color black
- initialize_node() - called when a node in the tree created using this plug-in
- \layout Itemize
- \color black
- post_poll_timeout() - called when the poll() returned due to a timeout for
- this node
- \layout Itemize
- \color black
- post_poll_read() - called when the poll() returned due to the socket being
- ready
- \layout Itemize
- \color black
- buffer_full() - called when a the packet buffer for this flow is full
- \layout Itemize
- \color black
- delete_node() - called just prior to the node being free()'d
- \end_deeper
- \layout Itemize
- \color black
- Optional functions:
- \begin_deeper
- \layout Itemize
- \color black
- pre_send_data() - called before data is sent
- \layout Itemize
- \color black
- post_send_data() - called after data is sent
- \layout Itemize
- \color black
- pre_poll() - called prior to poll()
- \layout Itemize
- \color black
- post_poll_default() - called when poll() returns and neither the socket
- was ready or the node timed out
- \layout Itemize
- \color black
- open_socket() - called after the socket is opened
- \layout Itemize
- \color black
- close_socket() - called after the socket is closed
- \end_deeper
- \end_deeper
- \layout LyX-Code
- \layout LyX-Code
- \the_end
|