change HTTP access for RPC.

1. use CONNECT instead of GET.
   CONNECT has exactly the meaning
   we want; most of the time people
   connect to ip:port; we're connecting
   to /_goRPC_

2. wait for a successful HTTP response
   before assuming we are connected to
   the RPC protocol.  this allows better
   error reporting and also keeps the
   protocol alternating between speakers,
   so that the buffering in the HTTP request
   reader cannot accidentally eat some
   RPC bytes too.

gotest sometimes hangs, but not in HTTP.

gotest -match=Unknown hangs every few runs
even in a clean client.

R=r
DELTA=117  (57 added, 44 deleted, 16 changed)
OCL=31656
CL=31685
This commit is contained in:
Russ Cox 2009-07-15 10:49:47 -07:00
parent 8b7951495c
commit aa1e8064b2
3 changed files with 67 additions and 54 deletions

View file

@ -250,35 +250,26 @@ func Accept(lis net.Listener) {
server.accept(lis)
}
type bufRWC struct {
r io.Reader;
w io.Writer;
c io.Closer;
}
func (b *bufRWC) Read(p []byte) (n int, err os.Error) {
return b.r.Read(p);
}
func (b *bufRWC) Write(p []byte) (n int, err os.Error) {
return b.w.Write(p);
}
func (b *bufRWC) Close() os.Error {
return b.c.Close();
}
// Can connect to RPC service using HTTP CONNECT to rpcPath.
var rpcPath string = "/_goRPC_"
var connected = "200 Connected to Go RPC"
func serveHTTP(c *http.Conn, req *http.Request) {
if req.Method != "CONNECT" {
c.SetHeader("Content-Type", "text/plain; charset=utf-8");
c.WriteHeader(http.StatusMethodNotAllowed);
io.WriteString(c, "405 must CONNECT to " + rpcPath + "\n");
return;
}
conn, buf, err := c.Hijack();
if err != nil {
log.Stderr("rpc hijacking ", c.RemoteAddr, ": ", err.String());
return;
}
server.serve(&bufRWC{buf, conn, conn});
io.WriteString(conn, "HTTP/1.0 " + connected + "\n\n");
server.serve(conn);
}
var rpcPath string = "/_goRPC_"
// HandleHTTP registers an HTTP handler for RPC messages.
// It is still necessary to call http.Serve().
func HandleHTTP() {