func (p *proxy) handleConnection(conn net.Conn, serverAddr string) { var err error defer func() { if p := recover(); p != nil { fmt.Printf("error in handling connection: %v", p) conn.Close() } else { // Log disconnections: right now, we still return EOF // errors for connections that are closed "cleanly" // (e.g., client disconnects or server crashes) rather // than due to any problems encountered during // protocol manipulation. We assume that any // connectivity errors are "clean" and we ignore them // for now. if err != nil && err != io.EOF { log.Print("Session exits with error: ", err) } else { log.Print("Session exits cleanly") } } }() feStream := core.NewFrontendStream(util.NewBufferedReadWriteCloser(conn)) var m core.Message err = feStream.Next(&m) if err != nil { panic(fmt.Errorf("could not read client startup message: %v", err)) } if proto.IsStartupMessage(&m) { startup, err := proto.ReadStartupMessage(&m) if err != nil { panic(fmt.Errorf("could not parse client startup message: %v", err)) } connector := p.resolver.Resolve(startup.Params) beStream, err := connector.Startup() if err != nil { panic(fmt.Errorf("could not connect to backend: %v", err)) } router := femebe.NewSimpleRouter(feStream, beStream) session := femebe.NewSimpleSession(router, connector) err = p.manager.RunSession(session) } else if proto.IsSSLRequest(&m) { log.Print("SSL not supported; try with PGSSLMODE=disable") } else if proto.IsCancelRequest(&m) { cancel, err := proto.ReadCancelRequest(&m) if err != nil { panic(fmt.Errorf("could not parse cancel message: %v", err)) } err = p.manager.Cancel(cancel.BackendPid, cancel.SecretKey) if err != nil { panic(fmt.Errorf("could not process cancellation: %v", err)) } err = conn.Close() if err != nil { fmt.Println(err) } } else { panic(fmt.Errorf("could not understand client")) } }
// Generic connection handler // // This redelegates to more specific proxy handlers that contain the // main proxy loop logic. func (p *proxy) handleConnection(cConn net.Conn) { defer cConn.Close() var err error // Log disconnections defer func() { if pn := recover(); pn != nil { fmt.Printf("error in handling connection: %v", pn) cConn.Close() } else { if err != nil && err != io.EOF { log.Print("Session exits with error: ", err) } else { log.Print("Session exits cleanly") } } }() feStream := core.NewFrontendStream(util.NewBufferedReadWriteCloser(cConn)) var m core.Message err = feStream.Next(&m) if err != nil { panic(fmt.Errorf("could not read client startup message: %v", err)) } if proto.IsStartupMessage(&m) { startup, err := proto.ReadStartupMessage(&m) if err != nil { panic(fmt.Errorf("could not parse client startup message: %v", err)) } log.Print("Accept connection with startup message:") connector := p.resolver.Resolve(startup.Params) beStream, err := connector.Startup() if err != nil { panic(fmt.Errorf("could not connect to backend: %v", err)) } router := NewSniffingRouter(feStream, beStream, p.frontend, p.backend) session := femebe.NewSimpleSession(router, connector) err = p.manager.RunSession(session) } else if proto.IsCancelRequest(&m) { cancel, err := proto.ReadCancelRequest(&m) if err != nil { panic(fmt.Errorf("could not parse cancel message: %v", err)) } err = p.manager.Cancel(cancel.BackendPid, cancel.SecretKey) if err != nil { panic(fmt.Errorf("could not process cancellation: %v", err)) } err = cConn.Close() if err != nil { fmt.Println(err) } } else { panic(fmt.Errorf("could not understand client")) } }