OSDN Git Service

libgo: Update to weekly 2011-11-09.
[pf3gnuchains/gcc-fork.git] / libgo / go / net / http / httputil / persist.go
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // Package httputil provides HTTP utility functions, complementing the
6 // more common ones in the net/http package.
7 package httputil
8
9 import (
10         "bufio"
11         "errors"
12         "io"
13         "net"
14         "net/http"
15         "net/textproto"
16         "os"
17         "sync"
18 )
19
20 var (
21         ErrPersistEOF = &http.ProtocolError{"persistent connection closed"}
22         ErrPipeline   = &http.ProtocolError{"pipeline error"}
23 )
24
25 // A ServerConn reads requests and sends responses over an underlying
26 // connection, until the HTTP keepalive logic commands an end. ServerConn
27 // also allows hijacking the underlying connection by calling Hijack
28 // to regain control over the connection. ServerConn supports pipe-lining,
29 // i.e. requests can be read out of sync (but in the same order) while the
30 // respective responses are sent.
31 //
32 // ServerConn is low-level and should not be needed by most applications.
33 // See Server.
34 type ServerConn struct {
35         lk              sync.Mutex // read-write protects the following fields
36         c               net.Conn
37         r               *bufio.Reader
38         re, we          error // read/write errors
39         lastbody        io.ReadCloser
40         nread, nwritten int
41         pipereq         map[*http.Request]uint
42
43         pipe textproto.Pipeline
44 }
45
46 // NewServerConn returns a new ServerConn reading and writing c.  If r is not
47 // nil, it is the buffer to use when reading c.
48 func NewServerConn(c net.Conn, r *bufio.Reader) *ServerConn {
49         if r == nil {
50                 r = bufio.NewReader(c)
51         }
52         return &ServerConn{c: c, r: r, pipereq: make(map[*http.Request]uint)}
53 }
54
55 // Hijack detaches the ServerConn and returns the underlying connection as well
56 // as the read-side bufio which may have some left over data. Hijack may be
57 // called before Read has signaled the end of the keep-alive logic. The user
58 // should not call Hijack while Read or Write is in progress.
59 func (sc *ServerConn) Hijack() (c net.Conn, r *bufio.Reader) {
60         sc.lk.Lock()
61         defer sc.lk.Unlock()
62         c = sc.c
63         r = sc.r
64         sc.c = nil
65         sc.r = nil
66         return
67 }
68
69 // Close calls Hijack and then also closes the underlying connection
70 func (sc *ServerConn) Close() error {
71         c, _ := sc.Hijack()
72         if c != nil {
73                 return c.Close()
74         }
75         return nil
76 }
77
78 // Read returns the next request on the wire. An ErrPersistEOF is returned if
79 // it is gracefully determined that there are no more requests (e.g. after the
80 // first request on an HTTP/1.0 connection, or after a Connection:close on a
81 // HTTP/1.1 connection).
82 func (sc *ServerConn) Read() (req *http.Request, err error) {
83
84         // Ensure ordered execution of Reads and Writes
85         id := sc.pipe.Next()
86         sc.pipe.StartRequest(id)
87         defer func() {
88                 sc.pipe.EndRequest(id)
89                 if req == nil {
90                         sc.pipe.StartResponse(id)
91                         sc.pipe.EndResponse(id)
92                 } else {
93                         // Remember the pipeline id of this request
94                         sc.lk.Lock()
95                         sc.pipereq[req] = id
96                         sc.lk.Unlock()
97                 }
98         }()
99
100         sc.lk.Lock()
101         if sc.we != nil { // no point receiving if write-side broken or closed
102                 defer sc.lk.Unlock()
103                 return nil, sc.we
104         }
105         if sc.re != nil {
106                 defer sc.lk.Unlock()
107                 return nil, sc.re
108         }
109         if sc.r == nil { // connection closed by user in the meantime
110                 defer sc.lk.Unlock()
111                 return nil, os.EBADF
112         }
113         r := sc.r
114         lastbody := sc.lastbody
115         sc.lastbody = nil
116         sc.lk.Unlock()
117
118         // Make sure body is fully consumed, even if user does not call body.Close
119         if lastbody != nil {
120                 // body.Close is assumed to be idempotent and multiple calls to
121                 // it should return the error that its first invocation
122                 // returned.
123                 err = lastbody.Close()
124                 if err != nil {
125                         sc.lk.Lock()
126                         defer sc.lk.Unlock()
127                         sc.re = err
128                         return nil, err
129                 }
130         }
131
132         req, err = http.ReadRequest(r)
133         sc.lk.Lock()
134         defer sc.lk.Unlock()
135         if err != nil {
136                 if err == io.ErrUnexpectedEOF {
137                         // A close from the opposing client is treated as a
138                         // graceful close, even if there was some unparse-able
139                         // data before the close.
140                         sc.re = ErrPersistEOF
141                         return nil, sc.re
142                 } else {
143                         sc.re = err
144                         return req, err
145                 }
146         }
147         sc.lastbody = req.Body
148         sc.nread++
149         if req.Close {
150                 sc.re = ErrPersistEOF
151                 return req, sc.re
152         }
153         return req, err
154 }
155
156 // Pending returns the number of unanswered requests
157 // that have been received on the connection.
158 func (sc *ServerConn) Pending() int {
159         sc.lk.Lock()
160         defer sc.lk.Unlock()
161         return sc.nread - sc.nwritten
162 }
163
164 // Write writes resp in response to req. To close the connection gracefully, set the
165 // Response.Close field to true. Write should be considered operational until
166 // it returns an error, regardless of any errors returned on the Read side.
167 func (sc *ServerConn) Write(req *http.Request, resp *http.Response) error {
168
169         // Retrieve the pipeline ID of this request/response pair
170         sc.lk.Lock()
171         id, ok := sc.pipereq[req]
172         delete(sc.pipereq, req)
173         if !ok {
174                 sc.lk.Unlock()
175                 return ErrPipeline
176         }
177         sc.lk.Unlock()
178
179         // Ensure pipeline order
180         sc.pipe.StartResponse(id)
181         defer sc.pipe.EndResponse(id)
182
183         sc.lk.Lock()
184         if sc.we != nil {
185                 defer sc.lk.Unlock()
186                 return sc.we
187         }
188         if sc.c == nil { // connection closed by user in the meantime
189                 defer sc.lk.Unlock()
190                 return os.EBADF
191         }
192         c := sc.c
193         if sc.nread <= sc.nwritten {
194                 defer sc.lk.Unlock()
195                 return errors.New("persist server pipe count")
196         }
197         if resp.Close {
198                 // After signaling a keep-alive close, any pipelined unread
199                 // requests will be lost. It is up to the user to drain them
200                 // before signaling.
201                 sc.re = ErrPersistEOF
202         }
203         sc.lk.Unlock()
204
205         err := resp.Write(c)
206         sc.lk.Lock()
207         defer sc.lk.Unlock()
208         if err != nil {
209                 sc.we = err
210                 return err
211         }
212         sc.nwritten++
213
214         return nil
215 }
216
217 // A ClientConn sends request and receives headers over an underlying
218 // connection, while respecting the HTTP keepalive logic. ClientConn
219 // supports hijacking the connection calling Hijack to
220 // regain control of the underlying net.Conn and deal with it as desired.
221 //
222 // ClientConn is low-level and should not be needed by most applications.
223 // See Client.
224 type ClientConn struct {
225         lk              sync.Mutex // read-write protects the following fields
226         c               net.Conn
227         r               *bufio.Reader
228         re, we          error // read/write errors
229         lastbody        io.ReadCloser
230         nread, nwritten int
231         pipereq         map[*http.Request]uint
232
233         pipe     textproto.Pipeline
234         writeReq func(*http.Request, io.Writer) error
235 }
236
237 // NewClientConn returns a new ClientConn reading and writing c.  If r is not
238 // nil, it is the buffer to use when reading c.
239 func NewClientConn(c net.Conn, r *bufio.Reader) *ClientConn {
240         if r == nil {
241                 r = bufio.NewReader(c)
242         }
243         return &ClientConn{
244                 c:        c,
245                 r:        r,
246                 pipereq:  make(map[*http.Request]uint),
247                 writeReq: (*http.Request).Write,
248         }
249 }
250
251 // NewProxyClientConn works like NewClientConn but writes Requests
252 // using Request's WriteProxy method.
253 func NewProxyClientConn(c net.Conn, r *bufio.Reader) *ClientConn {
254         cc := NewClientConn(c, r)
255         cc.writeReq = (*http.Request).WriteProxy
256         return cc
257 }
258
259 // Hijack detaches the ClientConn and returns the underlying connection as well
260 // as the read-side bufio which may have some left over data. Hijack may be
261 // called before the user or Read have signaled the end of the keep-alive
262 // logic. The user should not call Hijack while Read or Write is in progress.
263 func (cc *ClientConn) Hijack() (c net.Conn, r *bufio.Reader) {
264         cc.lk.Lock()
265         defer cc.lk.Unlock()
266         c = cc.c
267         r = cc.r
268         cc.c = nil
269         cc.r = nil
270         return
271 }
272
273 // Close calls Hijack and then also closes the underlying connection
274 func (cc *ClientConn) Close() error {
275         c, _ := cc.Hijack()
276         if c != nil {
277                 return c.Close()
278         }
279         return nil
280 }
281
282 // Write writes a request. An ErrPersistEOF error is returned if the connection
283 // has been closed in an HTTP keepalive sense. If req.Close equals true, the
284 // keepalive connection is logically closed after this request and the opposing
285 // server is informed. An ErrUnexpectedEOF indicates the remote closed the
286 // underlying TCP connection, which is usually considered as graceful close.
287 func (cc *ClientConn) Write(req *http.Request) (err error) {
288
289         // Ensure ordered execution of Writes
290         id := cc.pipe.Next()
291         cc.pipe.StartRequest(id)
292         defer func() {
293                 cc.pipe.EndRequest(id)
294                 if err != nil {
295                         cc.pipe.StartResponse(id)
296                         cc.pipe.EndResponse(id)
297                 } else {
298                         // Remember the pipeline id of this request
299                         cc.lk.Lock()
300                         cc.pipereq[req] = id
301                         cc.lk.Unlock()
302                 }
303         }()
304
305         cc.lk.Lock()
306         if cc.re != nil { // no point sending if read-side closed or broken
307                 defer cc.lk.Unlock()
308                 return cc.re
309         }
310         if cc.we != nil {
311                 defer cc.lk.Unlock()
312                 return cc.we
313         }
314         if cc.c == nil { // connection closed by user in the meantime
315                 defer cc.lk.Unlock()
316                 return os.EBADF
317         }
318         c := cc.c
319         if req.Close {
320                 // We write the EOF to the write-side error, because there
321                 // still might be some pipelined reads
322                 cc.we = ErrPersistEOF
323         }
324         cc.lk.Unlock()
325
326         err = cc.writeReq(req, c)
327         cc.lk.Lock()
328         defer cc.lk.Unlock()
329         if err != nil {
330                 cc.we = err
331                 return err
332         }
333         cc.nwritten++
334
335         return nil
336 }
337
338 // Pending returns the number of unanswered requests
339 // that have been sent on the connection.
340 func (cc *ClientConn) Pending() int {
341         cc.lk.Lock()
342         defer cc.lk.Unlock()
343         return cc.nwritten - cc.nread
344 }
345
346 // Read reads the next response from the wire. A valid response might be
347 // returned together with an ErrPersistEOF, which means that the remote
348 // requested that this be the last request serviced. Read can be called
349 // concurrently with Write, but not with another Read.
350 func (cc *ClientConn) Read(req *http.Request) (resp *http.Response, err error) {
351         // Retrieve the pipeline ID of this request/response pair
352         cc.lk.Lock()
353         id, ok := cc.pipereq[req]
354         delete(cc.pipereq, req)
355         if !ok {
356                 cc.lk.Unlock()
357                 return nil, ErrPipeline
358         }
359         cc.lk.Unlock()
360
361         // Ensure pipeline order
362         cc.pipe.StartResponse(id)
363         defer cc.pipe.EndResponse(id)
364
365         cc.lk.Lock()
366         if cc.re != nil {
367                 defer cc.lk.Unlock()
368                 return nil, cc.re
369         }
370         if cc.r == nil { // connection closed by user in the meantime
371                 defer cc.lk.Unlock()
372                 return nil, os.EBADF
373         }
374         r := cc.r
375         lastbody := cc.lastbody
376         cc.lastbody = nil
377         cc.lk.Unlock()
378
379         // Make sure body is fully consumed, even if user does not call body.Close
380         if lastbody != nil {
381                 // body.Close is assumed to be idempotent and multiple calls to
382                 // it should return the error that its first invokation
383                 // returned.
384                 err = lastbody.Close()
385                 if err != nil {
386                         cc.lk.Lock()
387                         defer cc.lk.Unlock()
388                         cc.re = err
389                         return nil, err
390                 }
391         }
392
393         resp, err = http.ReadResponse(r, req)
394         cc.lk.Lock()
395         defer cc.lk.Unlock()
396         if err != nil {
397                 cc.re = err
398                 return resp, err
399         }
400         cc.lastbody = resp.Body
401
402         cc.nread++
403
404         if resp.Close {
405                 cc.re = ErrPersistEOF // don't send any more requests
406                 return resp, cc.re
407         }
408         return resp, err
409 }
410
411 // Do is convenience method that writes a request and reads a response.
412 func (cc *ClientConn) Do(req *http.Request) (resp *http.Response, err error) {
413         err = cc.Write(req)
414         if err != nil {
415                 return
416         }
417         return cc.Read(req)
418 }