source: project/wiki/socket @ 8743

Last change on this file since 8743 was 8743, checked in by Jim Ursetto, 13 years ago

Changes applied for zbigniew (67.167.53.235) through svnwiki:

socket: add wiki doc

File size: 10.3 KB
Line 
1[[tags:egg net]]
2
3'''socket''' provides an interface to BSD sockets.
4
5[[toc:]]
6
7== Overview
8
9This extension provides a basic interface to BSD sockets.  The current implementation
10provides both a high-level and low-level interface to socket options; it also provides
11integer constants for socket levels, socket types, socket options, and address and
12protocol families.
13
14This extension is incomplete.  It has yet to provide socket calls ({{bind}}, {{accept}})
15and it does not provide a wrapper type to sockets; all access is done via file descriptor.
16However, other units do provide more specific socket access: see [[Unit tcp|tcp]],
17[[udp]] and [[raw-sockets]].
18
19== Socket options interface
20
21BSD socket option values are of substantially differing types: boolean flags
22(TCP_NODELAY), integers (SO_SNDBUF), structures (SO_LINGER), and so on.  Still, we want a
23consistent interface and an element of type-safety as well.  So for each option, we
24provide a unique getter and a setter procedure which does the type-checking and marshals
25(or unmarshals) the data as needed.
26
27Each getter takes a socket argument; setters take a socket and a value.
28The "socket" is simply a file descriptor number, as returned by a socket() call.
29SRFI-17 generalized set! is supported and recommended.
30
31 (tcp-no-delay s)            ; => #t or #f
32 (tcp-no-delay-set! s #t)
33 (set! (tcp-no-delay s) #t)
34
35An error is thrown if the socket call fails, or if the value passed is of
36incorrect type.
37
38=== Socket options
39
40Below is a list of option procedures and their value type.  The procedure names are
41verbose variants of their associated constant names.  So, {{SO_REUSEADDR}} becomes
42{{socket-reuse-address}}.
43
44Only booleans and integers and their read-only variants are currently supported.  The
45intention is to additionally support timevals, linger, ip_mreq structs and ipoptions, at
46least.  There is an example of linger support in the low-level interface below.
47
48==== Booleans
49
50 socket-reuse-address      [so/reuseaddr]
51 socket-accept-connections [so/acceptconn] (read-only)
52 socket-debug              [so/debug]
53 socket-keep-alive         [so/keepalive]
54 socket-dont-route         [so/dontroute]
55 socket-broadcast          [so/broadcast]
56 socket-oob-inline         [so/oobinline]
57
58==== Integers
59
60 socket-send-buffer        [so/sndbuf]
61 socket-receive-buffer     [so/rcvbuf]
62 socket-send-low-water     [so/sndlowat]
63 socket-receive-low-water  [so/rcvlowat]
64 socket-error              [so/error]      (read-only)
65 socket-type               [so/type]       (read-only)
66
67=== TCP options
68
69 tcp-no-delay              [tcp/nodelay]   (boolean)
70
71=== IP options
72
73 ip-header-included        [ip/hdrincl]    (boolean)
74 ip-type-of-service        [ip/tos]        (integer)
75 ip-time-to-live           [ip/ttl]        (integer)
76
77== Constants
78
79Integer constants are provided for socket levels, socket types, socket
80options, and address and protocol families, as prescribed by BSD.
81They are renamed slightly, and consistently, to achieve a more
82Schemely appearance: for example, C's {{SO_REUSEADDR}} becomes
83{{so/reuseaddr}}.
84
85Not every possible value is currently available.
86
87=== Socket options
88
89 so/reuseaddr
90 so/debug
91 so/acceptconn
92 so/keepalive
93 so/dontroute
94 so/broadcast
95 so/linger
96 so/oobinline
97 so/sndbuf
98 so/rcvbuf
99 so/sndlowat
100 so/rcvlowat
101 so/sndtimeo
102 so/rcvtimeo
103 so/error
104 so/type
105
106=== TCP options
107
108 tcp/nodelay
109
110=== IP options
111
112 ip/options
113 ip/hdrincl
114 ip/tos
115 ip/ttl
116 ip/recvopts
117 ip/recvretopts
118 ip/retopts
119 ip/multicast-if
120 ip/multicast-ttl
121 ip/multicast-loop
122 ip/add-membership
123 ip/drop-membership
124
125=== Socket types
126
127 sock/stream
128 sock/dgram
129 sock/raw
130 sock/seqpacket
131
132=== Socket and protocol levels
133
134 sol/socket
135 ipproto/ip
136 ipproto/ipv6
137 ipproto/tcp
138 ipproto/icmp
139 ipproto/udp
140
141=== Address families
142
143 af/unspec
144 af/unix
145 af/local
146 af/inet
147 af/inet6
148
149=== Protocol families
150
151 pf/unspec
152 pf/local
153 pf/unix
154 pf/inet
155 pf/inet6
156
157== Low-level options interface
158
159We provide a lower-level options interface based directly on {{setsockopt}} and
160{{getsockopt}}.  This is intended to let you use the constants defined above (or your own)
161when there is no high-level interface implemented.  This interface can get or set
162arbitrary option contents; you're not limited to predefined types such as integer or
163boolean.  No checking is done that the passed option value is appropriate, as that's the job
164of the high-level interface.
165
166''Warning: This interface may change or go away completely.''
167
168=== set-socket-option!
169
170 '''procedure:''' (set-socket-option! s level name val)
171
172Set the value of option {{NAME}} at socket level {{LEVEL}} on socket {{S}} to {{VAL}}.
173{{VAL}} may be a fixnum or a boolean.  It may also be a blob or a string; if so, the raw
174contents are passed to the option, which is useful when a structure is required.
175
176Note: due to the vagaries of structure member alignment (and 32 vs. 64-bit sizes), it's
177not generally safe to pack raw data yourself into a blob or a SRFI-4 vector.  Instead, you
178should treat the blob contents as a C struct.  See the longer example down the page
179for more.
180
181 (set-socket-option! S ipproto/tcp tcp/nodelay 1)
182 (set-socket-option! S ipproto/tcp tcp/nodelay (make-string 4 #\x0))
183 (set-socket-option! S sol/socket so/rcvlowat (u32vector->blob/shared (u32vector #x01020304)))
184
185=== get-socket-option!
186
187 '''procedure:''' (get-socket-option! s level name . storage)
188
189Get the value of option {{NAME}} at socket level {{LEVEL}} on socket {{S}}.  {{STORAGE}} is
190an optional blob or string value used as a buffer to hold the result; you must allocate
191enough space yourself.  If {{STORAGE}} is not present, we assume the option returns
192an integer value.  This procedure returns the option value.
193
194We don't convert automatically to boolean values---if you expect a boolean flag, assume
195zero means {{#f}} and non-zero means {{#t}}.  Don't be surprised if boolean flags return
196different non-zero integer values from those you put in; that's an implementation detail.
197You can only rely on true being some non-zero value.
198
199 (get-socket-option! S ipproto/tcp tcp/nodelay)     ; => 8, perhaps, meaning #t
200 (get-socket-option! S ipproto/tcp tcp/nodelay (make-blob 4))     ; => #<blob of size 4>
201
202=== Longer example
203
204This is a pretty hairy example of getting and setting the {{so/linger}} option, which does
205not currently have a high-level equivalent.  {{so/linger}} usually takes and returns a
206{{struct linger}} value which consists of an on/off flag and a linger timeout in seconds.
207(But not always!)
208
209The approach below encases the {{struct linger}} in an appropriately-sized blob and
210creates an encoder and decoder for this structure.  A similar approach would be to use
211define-foreign-record to create the structure accessors for us; however, those usually
212operate on c-pointers and malloced data rather than using a blob for backing store.
213
214The complexity of this example illustrates why the low-level interface may be revamped or
215removed---it might be simpler to just write this in C.  Any useful option taking a structure
216value should have a high-level interface created for it regardless.
217
218 (define (make-linger-storage)
219   (make-blob (foreign-value "sizeof(struct linger)" int)))
220 (define (encode-linger-option state time)
221   (let ((blob (make-linger-storage)))
222     ((foreign-lambda* void ((scheme-pointer ptr) (int onoff) (int linger))
223                       "struct linger *p = ptr;"
224                       "p->l_onoff = onoff; p->l_linger = linger;")
225      blob state time)
226     blob))
227 (define (decode-linger-option blob)
228   ; sanity checking on parameter recommended here
229   (list ((foreign-lambda* int ((scheme-pointer p))
230          "return(((struct linger *)p)->l_onoff);") blob)
231         ((foreign-lambda* int ((scheme-pointer p))
232          "return(((struct linger *)p)->l_linger);") blob)))
233
234 (set-socket-option! S sol/socket so/linger (encode-linger-option 1 100))
235 (decode-linger-option
236  (get-socket-option! S sol/socket so/linger (make-linger-storage)))
237    ; => (128 100)
238
239== Socket interface
240
241Not yet implemented.
242
243== Examples
244
245This egg works well with others.
246
247=== Disable Nagle's Algorithm on TCP listener socket
248
249The [[Unit tcp|tcp unit]] does not support setting arbitrary socket
250options on sockets it creates.  However, you can obtain a listener's
251socket file descriptor after the fact.
252
253 (define L (tcp-listen 8080))
254 (define S (tcp-listener-fileno L))
255 (set! (tcp-no-delay s) #t)
256
257=== Set socket options on HTTP server
258
259This is similar to the above.  HTTP servers may see some performance
260gain when Nagle's algorithm is disabled.  This is generally the
261default on Linux, but not Solaris or OS X.
262
263 (parameterize ((http:listen-procedure
264                (lambda (port backlog host)
265                 (let ((L (tcp-listen port backlog host)))
266                   (set! (tcp-no-delay (tcp-listener-fileno L) #t))
267                   L))))
268   ((http:make-server ...)))
269
270== About this egg
271
272=== Author
273
274[[http://3e8.org|Jim Ursetto]]
275
276=== Version history
277
278; 0.1 : Initial release.  Socket options support.
279
280=== License
281
282 Copyright (c) 2008 Jim Ursetto.  All rights reserved.
283 
284 Redistribution and use in source and binary forms, with or without
285 modification, are permitted provided that the following conditions are met:
286 
287   Redistributions of source code must retain the above copyright notice,
288   this list of conditions and the following disclaimer. Redistributions in
289   binary form must reproduce the above copyright notice, this list of
290   conditions and the following disclaimer in the documentation and/or
291   other materials provided with the distribution. Neither the name of the
292   author nor the names of its contributors may be used to endorse or
293   promote products derived from this software without specific prior
294   written permission.
295 
296 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
297 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
298 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
299 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
300 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
301 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
302 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
303 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
304 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
305 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
306 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
307
Note: See TracBrowser for help on using the repository browser.