Fortran: default-initialization of derived-type function results [PR98454]
[official-gcc.git] / libgo / go / net / http / httputil / persist.go
blob84b116df8cf8bfbcd63639ea4acf576e8f7cacf6
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 httputil
7 import (
8 "bufio"
9 "errors"
10 "io"
11 "net"
12 "net/http"
13 "net/textproto"
14 "sync"
17 var (
18 // Deprecated: No longer used.
19 ErrPersistEOF = &http.ProtocolError{ErrorString: "persistent connection closed"}
21 // Deprecated: No longer used.
22 ErrClosed = &http.ProtocolError{ErrorString: "connection closed by user"}
24 // Deprecated: No longer used.
25 ErrPipeline = &http.ProtocolError{ErrorString: "pipeline error"}
28 // This is an API usage error - the local side is closed.
29 // ErrPersistEOF (above) reports that the remote side is closed.
30 var errClosed = errors.New("i/o operation on closed connection")
32 // ServerConn is an artifact of Go's early HTTP implementation.
33 // It is low-level, old, and unused by Go's current HTTP stack.
34 // We should have deleted it before Go 1.
36 // Deprecated: Use the Server in package net/http instead.
37 type ServerConn struct {
38 mu sync.Mutex // read-write protects the following fields
39 c net.Conn
40 r *bufio.Reader
41 re, we error // read/write errors
42 lastbody io.ReadCloser
43 nread, nwritten int
44 pipereq map[*http.Request]uint
46 pipe textproto.Pipeline
49 // NewServerConn is an artifact of Go's early HTTP implementation.
50 // It is low-level, old, and unused by Go's current HTTP stack.
51 // We should have deleted it before Go 1.
53 // Deprecated: Use the Server in package net/http instead.
54 func NewServerConn(c net.Conn, r *bufio.Reader) *ServerConn {
55 if r == nil {
56 r = bufio.NewReader(c)
58 return &ServerConn{c: c, r: r, pipereq: make(map[*http.Request]uint)}
61 // Hijack detaches the ServerConn and returns the underlying connection as well
62 // as the read-side bufio which may have some left over data. Hijack may be
63 // called before Read has signaled the end of the keep-alive logic. The user
64 // should not call Hijack while Read or Write is in progress.
65 func (sc *ServerConn) Hijack() (net.Conn, *bufio.Reader) {
66 sc.mu.Lock()
67 defer sc.mu.Unlock()
68 c := sc.c
69 r := sc.r
70 sc.c = nil
71 sc.r = nil
72 return c, r
75 // Close calls Hijack and then also closes the underlying connection.
76 func (sc *ServerConn) Close() error {
77 c, _ := sc.Hijack()
78 if c != nil {
79 return c.Close()
81 return nil
84 // Read returns the next request on the wire. An ErrPersistEOF is returned if
85 // it is gracefully determined that there are no more requests (e.g. after the
86 // first request on an HTTP/1.0 connection, or after a Connection:close on a
87 // HTTP/1.1 connection).
88 func (sc *ServerConn) Read() (*http.Request, error) {
89 var req *http.Request
90 var err error
92 // Ensure ordered execution of Reads and Writes
93 id := sc.pipe.Next()
94 sc.pipe.StartRequest(id)
95 defer func() {
96 sc.pipe.EndRequest(id)
97 if req == nil {
98 sc.pipe.StartResponse(id)
99 sc.pipe.EndResponse(id)
100 } else {
101 // Remember the pipeline id of this request
102 sc.mu.Lock()
103 sc.pipereq[req] = id
104 sc.mu.Unlock()
108 sc.mu.Lock()
109 if sc.we != nil { // no point receiving if write-side broken or closed
110 defer sc.mu.Unlock()
111 return nil, sc.we
113 if sc.re != nil {
114 defer sc.mu.Unlock()
115 return nil, sc.re
117 if sc.r == nil { // connection closed by user in the meantime
118 defer sc.mu.Unlock()
119 return nil, errClosed
121 r := sc.r
122 lastbody := sc.lastbody
123 sc.lastbody = nil
124 sc.mu.Unlock()
126 // Make sure body is fully consumed, even if user does not call body.Close
127 if lastbody != nil {
128 // body.Close is assumed to be idempotent and multiple calls to
129 // it should return the error that its first invocation
130 // returned.
131 err = lastbody.Close()
132 if err != nil {
133 sc.mu.Lock()
134 defer sc.mu.Unlock()
135 sc.re = err
136 return nil, err
140 req, err = http.ReadRequest(r)
141 sc.mu.Lock()
142 defer sc.mu.Unlock()
143 if err != nil {
144 if err == io.ErrUnexpectedEOF {
145 // A close from the opposing client is treated as a
146 // graceful close, even if there was some unparse-able
147 // data before the close.
148 sc.re = ErrPersistEOF
149 return nil, sc.re
150 } else {
151 sc.re = err
152 return req, err
155 sc.lastbody = req.Body
156 sc.nread++
157 if req.Close {
158 sc.re = ErrPersistEOF
159 return req, sc.re
161 return req, err
164 // Pending returns the number of unanswered requests
165 // that have been received on the connection.
166 func (sc *ServerConn) Pending() int {
167 sc.mu.Lock()
168 defer sc.mu.Unlock()
169 return sc.nread - sc.nwritten
172 // Write writes resp in response to req. To close the connection gracefully, set the
173 // Response.Close field to true. Write should be considered operational until
174 // it returns an error, regardless of any errors returned on the Read side.
175 func (sc *ServerConn) Write(req *http.Request, resp *http.Response) error {
177 // Retrieve the pipeline ID of this request/response pair
178 sc.mu.Lock()
179 id, ok := sc.pipereq[req]
180 delete(sc.pipereq, req)
181 if !ok {
182 sc.mu.Unlock()
183 return ErrPipeline
185 sc.mu.Unlock()
187 // Ensure pipeline order
188 sc.pipe.StartResponse(id)
189 defer sc.pipe.EndResponse(id)
191 sc.mu.Lock()
192 if sc.we != nil {
193 defer sc.mu.Unlock()
194 return sc.we
196 if sc.c == nil { // connection closed by user in the meantime
197 defer sc.mu.Unlock()
198 return ErrClosed
200 c := sc.c
201 if sc.nread <= sc.nwritten {
202 defer sc.mu.Unlock()
203 return errors.New("persist server pipe count")
205 if resp.Close {
206 // After signaling a keep-alive close, any pipelined unread
207 // requests will be lost. It is up to the user to drain them
208 // before signaling.
209 sc.re = ErrPersistEOF
211 sc.mu.Unlock()
213 err := resp.Write(c)
214 sc.mu.Lock()
215 defer sc.mu.Unlock()
216 if err != nil {
217 sc.we = err
218 return err
220 sc.nwritten++
222 return nil
225 // ClientConn is an artifact of Go's early HTTP implementation.
226 // It is low-level, old, and unused by Go's current HTTP stack.
227 // We should have deleted it before Go 1.
229 // Deprecated: Use Client or Transport in package net/http instead.
230 type ClientConn struct {
231 mu sync.Mutex // read-write protects the following fields
232 c net.Conn
233 r *bufio.Reader
234 re, we error // read/write errors
235 lastbody io.ReadCloser
236 nread, nwritten int
237 pipereq map[*http.Request]uint
239 pipe textproto.Pipeline
240 writeReq func(*http.Request, io.Writer) error
243 // NewClientConn is an artifact of Go's early HTTP implementation.
244 // It is low-level, old, and unused by Go's current HTTP stack.
245 // We should have deleted it before Go 1.
247 // Deprecated: Use the Client or Transport in package net/http instead.
248 func NewClientConn(c net.Conn, r *bufio.Reader) *ClientConn {
249 if r == nil {
250 r = bufio.NewReader(c)
252 return &ClientConn{
253 c: c,
254 r: r,
255 pipereq: make(map[*http.Request]uint),
256 writeReq: (*http.Request).Write,
260 // NewProxyClientConn is an artifact of Go's early HTTP implementation.
261 // It is low-level, old, and unused by Go's current HTTP stack.
262 // We should have deleted it before Go 1.
264 // Deprecated: Use the Client or Transport in package net/http instead.
265 func NewProxyClientConn(c net.Conn, r *bufio.Reader) *ClientConn {
266 cc := NewClientConn(c, r)
267 cc.writeReq = (*http.Request).WriteProxy
268 return cc
271 // Hijack detaches the ClientConn and returns the underlying connection as well
272 // as the read-side bufio which may have some left over data. Hijack may be
273 // called before the user or Read have signaled the end of the keep-alive
274 // logic. The user should not call Hijack while Read or Write is in progress.
275 func (cc *ClientConn) Hijack() (c net.Conn, r *bufio.Reader) {
276 cc.mu.Lock()
277 defer cc.mu.Unlock()
278 c = cc.c
279 r = cc.r
280 cc.c = nil
281 cc.r = nil
282 return
285 // Close calls Hijack and then also closes the underlying connection.
286 func (cc *ClientConn) Close() error {
287 c, _ := cc.Hijack()
288 if c != nil {
289 return c.Close()
291 return nil
294 // Write writes a request. An ErrPersistEOF error is returned if the connection
295 // has been closed in an HTTP keep-alive sense. If req.Close equals true, the
296 // keep-alive connection is logically closed after this request and the opposing
297 // server is informed. An ErrUnexpectedEOF indicates the remote closed the
298 // underlying TCP connection, which is usually considered as graceful close.
299 func (cc *ClientConn) Write(req *http.Request) error {
300 var err error
302 // Ensure ordered execution of Writes
303 id := cc.pipe.Next()
304 cc.pipe.StartRequest(id)
305 defer func() {
306 cc.pipe.EndRequest(id)
307 if err != nil {
308 cc.pipe.StartResponse(id)
309 cc.pipe.EndResponse(id)
310 } else {
311 // Remember the pipeline id of this request
312 cc.mu.Lock()
313 cc.pipereq[req] = id
314 cc.mu.Unlock()
318 cc.mu.Lock()
319 if cc.re != nil { // no point sending if read-side closed or broken
320 defer cc.mu.Unlock()
321 return cc.re
323 if cc.we != nil {
324 defer cc.mu.Unlock()
325 return cc.we
327 if cc.c == nil { // connection closed by user in the meantime
328 defer cc.mu.Unlock()
329 return errClosed
331 c := cc.c
332 if req.Close {
333 // We write the EOF to the write-side error, because there
334 // still might be some pipelined reads
335 cc.we = ErrPersistEOF
337 cc.mu.Unlock()
339 err = cc.writeReq(req, c)
340 cc.mu.Lock()
341 defer cc.mu.Unlock()
342 if err != nil {
343 cc.we = err
344 return err
346 cc.nwritten++
348 return nil
351 // Pending returns the number of unanswered requests
352 // that have been sent on the connection.
353 func (cc *ClientConn) Pending() int {
354 cc.mu.Lock()
355 defer cc.mu.Unlock()
356 return cc.nwritten - cc.nread
359 // Read reads the next response from the wire. A valid response might be
360 // returned together with an ErrPersistEOF, which means that the remote
361 // requested that this be the last request serviced. Read can be called
362 // concurrently with Write, but not with another Read.
363 func (cc *ClientConn) Read(req *http.Request) (resp *http.Response, err error) {
364 // Retrieve the pipeline ID of this request/response pair
365 cc.mu.Lock()
366 id, ok := cc.pipereq[req]
367 delete(cc.pipereq, req)
368 if !ok {
369 cc.mu.Unlock()
370 return nil, ErrPipeline
372 cc.mu.Unlock()
374 // Ensure pipeline order
375 cc.pipe.StartResponse(id)
376 defer cc.pipe.EndResponse(id)
378 cc.mu.Lock()
379 if cc.re != nil {
380 defer cc.mu.Unlock()
381 return nil, cc.re
383 if cc.r == nil { // connection closed by user in the meantime
384 defer cc.mu.Unlock()
385 return nil, errClosed
387 r := cc.r
388 lastbody := cc.lastbody
389 cc.lastbody = nil
390 cc.mu.Unlock()
392 // Make sure body is fully consumed, even if user does not call body.Close
393 if lastbody != nil {
394 // body.Close is assumed to be idempotent and multiple calls to
395 // it should return the error that its first invocation
396 // returned.
397 err = lastbody.Close()
398 if err != nil {
399 cc.mu.Lock()
400 defer cc.mu.Unlock()
401 cc.re = err
402 return nil, err
406 resp, err = http.ReadResponse(r, req)
407 cc.mu.Lock()
408 defer cc.mu.Unlock()
409 if err != nil {
410 cc.re = err
411 return resp, err
413 cc.lastbody = resp.Body
415 cc.nread++
417 if resp.Close {
418 cc.re = ErrPersistEOF // don't send any more requests
419 return resp, cc.re
421 return resp, err
424 // Do is convenience method that writes a request and reads a response.
425 func (cc *ClientConn) Do(req *http.Request) (*http.Response, error) {
426 err := cc.Write(req)
427 if err != nil {
428 return nil, err
430 return cc.Read(req)