Merge from mainline (167278:168000).
[official-gcc/graphite-test-results.git] / libgo / go / http / persist.go
blob8bfc09755898b98f95caf3a07a6330f757d1cc65
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.
5 package http
7 import (
8 "bufio"
9 "container/list"
10 "io"
11 "net"
12 "os"
13 "sync"
16 var ErrPersistEOF = &ProtocolError{"persistent connection closed"}
18 // A ServerConn reads requests and sends responses over an underlying
19 // connection, until the HTTP keepalive logic commands an end. ServerConn
20 // does not close the underlying connection. Instead, the user calls Close
21 // and regains control over the connection. ServerConn supports pipe-lining,
22 // i.e. requests can be read out of sync (but in the same order) while the
23 // respective responses are sent.
24 type ServerConn struct {
25 c net.Conn
26 r *bufio.Reader
27 clsd bool // indicates a graceful close
28 re, we os.Error // read/write errors
29 lastBody io.ReadCloser
30 nread, nwritten int
31 lk sync.Mutex // protected read/write to re,we
34 // NewServerConn returns a new ServerConn reading and writing c. If r is not
35 // nil, it is the buffer to use when reading c.
36 func NewServerConn(c net.Conn, r *bufio.Reader) *ServerConn {
37 if r == nil {
38 r = bufio.NewReader(c)
40 return &ServerConn{c: c, r: r}
43 // Close detaches the ServerConn and returns the underlying connection as well
44 // as the read-side bufio which may have some left over data. Close may be
45 // called before Read has signaled the end of the keep-alive logic. The user
46 // should not call Close while Read or Write is in progress.
47 func (sc *ServerConn) Close() (c net.Conn, r *bufio.Reader) {
48 sc.lk.Lock()
49 defer sc.lk.Unlock()
50 c = sc.c
51 r = sc.r
52 sc.c = nil
53 sc.r = nil
54 return
57 // Read returns the next request on the wire. An ErrPersistEOF is returned if
58 // it is gracefully determined that there are no more requests (e.g. after the
59 // first request on an HTTP/1.0 connection, or after a Connection:close on a
60 // HTTP/1.1 connection). Read can be called concurrently with Write, but not
61 // with another Read.
62 func (sc *ServerConn) Read() (req *Request, err os.Error) {
64 sc.lk.Lock()
65 if sc.we != nil { // no point receiving if write-side broken or closed
66 defer sc.lk.Unlock()
67 return nil, sc.we
69 if sc.re != nil {
70 defer sc.lk.Unlock()
71 return nil, sc.re
73 sc.lk.Unlock()
75 // Make sure body is fully consumed, even if user does not call body.Close
76 if sc.lastBody != nil {
77 // body.Close is assumed to be idempotent and multiple calls to
78 // it should return the error that its first invokation
79 // returned.
80 err = sc.lastBody.Close()
81 sc.lastBody = nil
82 if err != nil {
83 sc.lk.Lock()
84 defer sc.lk.Unlock()
85 sc.re = err
86 return nil, err
90 req, err = ReadRequest(sc.r)
91 if err != nil {
92 sc.lk.Lock()
93 defer sc.lk.Unlock()
94 if err == io.ErrUnexpectedEOF {
95 // A close from the opposing client is treated as a
96 // graceful close, even if there was some unparse-able
97 // data before the close.
98 sc.re = ErrPersistEOF
99 return nil, sc.re
100 } else {
101 sc.re = err
102 return
105 sc.lastBody = req.Body
106 sc.nread++
107 if req.Close {
108 sc.lk.Lock()
109 defer sc.lk.Unlock()
110 sc.re = ErrPersistEOF
111 return req, sc.re
113 return
116 // Pending returns the number of unanswered requests
117 // that have been received on the connection.
118 func (sc *ServerConn) Pending() int {
119 sc.lk.Lock()
120 defer sc.lk.Unlock()
121 return sc.nread - sc.nwritten
124 // Write writes a repsonse. To close the connection gracefully, set the
125 // Response.Close field to true. Write should be considered operational until
126 // it returns an error, regardless of any errors returned on the Read side.
127 // Write can be called concurrently with Read, but not with another Write.
128 func (sc *ServerConn) Write(resp *Response) os.Error {
130 sc.lk.Lock()
131 if sc.we != nil {
132 defer sc.lk.Unlock()
133 return sc.we
135 sc.lk.Unlock()
136 if sc.nread <= sc.nwritten {
137 return os.NewError("persist server pipe count")
140 if resp.Close {
141 // After signaling a keep-alive close, any pipelined unread
142 // requests will be lost. It is up to the user to drain them
143 // before signaling.
144 sc.lk.Lock()
145 sc.re = ErrPersistEOF
146 sc.lk.Unlock()
149 err := resp.Write(sc.c)
150 if err != nil {
151 sc.lk.Lock()
152 defer sc.lk.Unlock()
153 sc.we = err
154 return err
156 sc.nwritten++
158 return nil
161 // A ClientConn sends request and receives headers over an underlying
162 // connection, while respecting the HTTP keepalive logic. ClientConn is not
163 // responsible for closing the underlying connection. One must call Close to
164 // regain control of that connection and deal with it as desired.
165 type ClientConn struct {
166 c net.Conn
167 r *bufio.Reader
168 re, we os.Error // read/write errors
169 lastBody io.ReadCloser
170 nread, nwritten int
171 reqm list.List // request methods in order of execution
172 lk sync.Mutex // protects read/write to reqm,re,we
175 // NewClientConn returns a new ClientConn reading and writing c. If r is not
176 // nil, it is the buffer to use when reading c.
177 func NewClientConn(c net.Conn, r *bufio.Reader) *ClientConn {
178 if r == nil {
179 r = bufio.NewReader(c)
181 return &ClientConn{c: c, r: r}
184 // Close detaches the ClientConn and returns the underlying connection as well
185 // as the read-side bufio which may have some left over data. Close may be
186 // called before the user or Read have signaled the end of the keep-alive
187 // logic. The user should not call Close while Read or Write is in progress.
188 func (cc *ClientConn) Close() (c net.Conn, r *bufio.Reader) {
189 cc.lk.Lock()
190 c = cc.c
191 r = cc.r
192 cc.c = nil
193 cc.r = nil
194 cc.reqm.Init()
195 cc.lk.Unlock()
196 return
199 // Write writes a request. An ErrPersistEOF error is returned if the connection
200 // has been closed in an HTTP keepalive sense. If req.Close equals true, the
201 // keepalive connection is logically closed after this request and the opposing
202 // server is informed. An ErrUnexpectedEOF indicates the remote closed the
203 // underlying TCP connection, which is usually considered as graceful close.
204 // Write can be called concurrently with Read, but not with another Write.
205 func (cc *ClientConn) Write(req *Request) os.Error {
207 cc.lk.Lock()
208 if cc.re != nil { // no point sending if read-side closed or broken
209 defer cc.lk.Unlock()
210 return cc.re
212 if cc.we != nil {
213 defer cc.lk.Unlock()
214 return cc.we
216 cc.lk.Unlock()
218 if req.Close {
219 // We write the EOF to the write-side error, because there
220 // still might be some pipelined reads
221 cc.lk.Lock()
222 cc.we = ErrPersistEOF
223 cc.lk.Unlock()
226 err := req.Write(cc.c)
227 if err != nil {
228 cc.lk.Lock()
229 defer cc.lk.Unlock()
230 cc.we = err
231 return err
233 cc.nwritten++
234 cc.lk.Lock()
235 cc.reqm.PushBack(req.Method)
236 cc.lk.Unlock()
238 return nil
241 // Pending returns the number of unanswered requests
242 // that have been sent on the connection.
243 func (cc *ClientConn) Pending() int {
244 cc.lk.Lock()
245 defer cc.lk.Unlock()
246 return cc.nwritten - cc.nread
249 // Read reads the next response from the wire. A valid response might be
250 // returned together with an ErrPersistEOF, which means that the remote
251 // requested that this be the last request serviced. Read can be called
252 // concurrently with Write, but not with another Read.
253 func (cc *ClientConn) Read() (resp *Response, err os.Error) {
255 cc.lk.Lock()
256 if cc.re != nil {
257 defer cc.lk.Unlock()
258 return nil, cc.re
260 cc.lk.Unlock()
262 if cc.nread >= cc.nwritten {
263 return nil, os.NewError("persist client pipe count")
266 // Make sure body is fully consumed, even if user does not call body.Close
267 if cc.lastBody != nil {
268 // body.Close is assumed to be idempotent and multiple calls to
269 // it should return the error that its first invokation
270 // returned.
271 err = cc.lastBody.Close()
272 cc.lastBody = nil
273 if err != nil {
274 cc.lk.Lock()
275 defer cc.lk.Unlock()
276 cc.re = err
277 return nil, err
281 cc.lk.Lock()
282 m := cc.reqm.Front()
283 cc.reqm.Remove(m)
284 cc.lk.Unlock()
285 resp, err = ReadResponse(cc.r, m.Value.(string))
286 if err != nil {
287 cc.lk.Lock()
288 defer cc.lk.Unlock()
289 cc.re = err
290 return
292 cc.lastBody = resp.Body
294 cc.nread++
296 if resp.Close {
297 cc.lk.Lock()
298 defer cc.lk.Unlock()
299 cc.re = ErrPersistEOF // don't send any more requests
300 return resp, cc.re
302 return