Add (and use) generic reference counter, to improve signal:noise ratio
[people/holger/gpxe.git] / src / include / gpxe / xfer.h
1 #ifndef _GPXE_XFER_H
2 #define _GPXE_XFER_H
3
4 /** @file
5  *
6  * Data transfer interfaces
7  *
8  */
9
10 #include <stddef.h>
11 #include <stdarg.h>
12 #include <gpxe/interface.h>
13 #include <gpxe/iobuf.h>
14
15 struct xfer_interface;
16
17 /** Data transfer interface operations */
18 struct xfer_interface_operations {
19
20         /* Missing features:
21          *
22          * notification of non-close status - e.g. connected/opened, ...
23          *
24          * seek
25          *
26          * prompt for data delivery
27          *
28          * I/O buffer preparation
29          *
30          */
31
32
33         /** Close interface
34          *
35          * @v xfer              Data transfer interface
36          * @v rc                Reason for close
37          */
38         void ( * close ) ( struct xfer_interface *xfer, int rc );
39         /** Redirect to new location
40          *
41          * @v xfer              Data transfer interface
42          * @v type              New location type
43          * @v args              Remaining arguments depend upon location type
44          * @ret rc              Return status code
45          */
46         int ( * vredirect ) ( struct xfer_interface *xfer, int type,
47                               va_list args );
48         /** Seek to position
49          *
50          * @v xfer              Data transfer interface
51          * @v pos               New position
52          * @ret rc              Return status code
53          */
54         int ( * seek ) ( struct xfer_interface *xfer, size_t pos );
55         /** Deliver datagram
56          *
57          * @v xfer              Data transfer interface
58          * @v iobuf             Datagram I/O buffer
59          * @ret rc              Return status code
60          *
61          * A data transfer interface that wishes to support only raw
62          * data delivery should set this method to
63          * deliver_as_raw().
64          */
65         int ( * deliver ) ( struct xfer_interface *xfer,
66                             struct io_buffer *iobuf );
67         /** Deliver datagram as raw data
68          *
69          * @v xfer              Data transfer interface
70          * @v data              Data buffer
71          * @v len               Length of data buffer
72          * @ret rc              Return status code
73          *
74          * A data transfer interface that wishes to support only I/O
75          * buffer delivery should set this method to
76          * deliver_as_iobuf().
77          */
78         int ( * deliver_raw ) ( struct xfer_interface *xfer,
79                                 const void *data, size_t len );
80 };
81
82 /** A data transfer interface */
83 struct xfer_interface {
84         /** Generic object communication interface */
85         struct interface intf;
86         /** Operations for received messages */
87         struct xfer_interface_operations *op;
88 };
89
90 extern struct xfer_interface null_xfer;
91 extern struct xfer_interface_operations null_xfer_ops;
92
93 extern void close ( struct xfer_interface *xfer, int rc );
94 extern int seek ( struct xfer_interface *xfer, size_t pos );
95 extern int vredirect ( struct xfer_interface *xfer, int type, va_list args );
96 extern int redirect ( struct xfer_interface *xfer, int type, ... );
97 extern int deliver ( struct xfer_interface *xfer, struct io_buffer *iobuf );
98 extern int deliver_raw ( struct xfer_interface *xfer,
99                          const void *data, size_t len );
100
101 extern void ignore_close ( struct xfer_interface *xfer, int rc );
102 extern int ignore_vredirect ( struct xfer_interface *xfer,
103                               int type, va_list args );
104 extern int ignore_seek ( struct xfer_interface *xfer, size_t pos );
105 extern int deliver_as_raw ( struct xfer_interface *xfer,
106                             struct io_buffer *iobuf );
107 extern int deliver_as_iobuf ( struct xfer_interface *xfer,
108                               const void *data, size_t len );
109 extern int ignore_deliver_raw ( struct xfer_interface *xfer,
110                                 const void *data __unused, size_t len );
111
112 /**
113  * Initialise a data transfer interface
114  *
115  * @v xfer              Data transfer interface
116  * @v op                Data transfer interface operations
117  * @v refcnt            Containing object reference counter, or NULL
118  */
119 static inline void xfer_init ( struct xfer_interface *xfer,
120                                struct xfer_interface_operations *op,
121                                struct refcnt *refcnt ) {
122         xfer->intf.dest = &null_xfer.intf;
123         xfer->intf.refcnt = refcnt;
124         xfer->op = op;
125 }
126
127 /**
128  * Get data transfer interface from generic object communication interface
129  *
130  * @v intf              Generic object communication interface
131  * @ret xfer            Data transfer interface
132  */
133 static inline struct xfer_interface *
134 intf_to_xfer ( struct interface *intf ) {
135         return container_of ( intf, struct xfer_interface, intf );
136 }
137
138 /**
139  * Get destination data transfer interface
140  *
141  * @v xfer              Data transfer interface
142  * @ret dest            Destination interface
143  */
144 static inline struct xfer_interface *
145 xfer_dest ( struct xfer_interface *xfer ) {
146         return intf_to_xfer ( xfer->intf.dest );
147 }
148
149 /**
150  * Plug a data transfer interface into a new destination interface
151  *
152  * @v xfer              Data transfer interface
153  * @v dest              New destination interface
154  */
155 static inline void xfer_plug ( struct xfer_interface *xfer,
156                                struct xfer_interface *dest ) {
157         plug ( &xfer->intf, &dest->intf );
158 }
159
160 /**
161  * Unplug a data transfer interface
162  *
163  * @v xfer              Data transfer interface
164  */
165 static inline void xfer_unplug ( struct xfer_interface *xfer ) {
166         plug ( &xfer->intf, &null_xfer.intf );
167 }
168
169 /**
170  * Stop using a data transfer interface
171  *
172  * @v xfer              Data transfer interface
173  *
174  * After calling this method, no further messages will be received via
175  * the interface.
176  */
177 static inline void xfer_nullify ( struct xfer_interface *xfer ) {
178         xfer->op = &null_xfer_ops;
179 };
180
181 #endif /* _GPXE_XFER_H */