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")) } }
func (c *FrontendConnection) startup(startupParameters map[string]string, dbcfg VirtualDatabaseConfiguration) bool { var message fbcore.Message var err error for { err = c.stream.Next(&message) if err != nil { elog.Logf("error while reading startup packet: %s", err) return false } if fbproto.IsStartupMessage(&message) { break } else if fbproto.IsSSLRequest(&message) { _, err = message.Force() if err != nil { elog.Logf("error while reading SSLRequest: %s", err) return false } err = c.stream.SendSSLRequestResponse(fbcore.RejectSSLRequest) if err != nil { elog.Logf("error during startup sequence: %s", err) return false } err = c.FlushStream() if err != nil { elog.Logf("error during startup sequence: %s", err) } } else if fbproto.IsCancelRequest(&message) { _ = c.stream.Close() return false } else { elog.Warningf("unrecognized frontend message type 0x%x during startup", message.MsgType()) return false } } sm, err := fbproto.ReadStartupMessage(&message) if err != nil { elog.Logf("error while reading startup packet: %s", err) return false } if !c.auth(dbcfg, sm) { // error already logged _ = c.stream.Close() return false } fbproto.InitAuthenticationOk(&message) err = c.WriteMessage(&message) if err != nil { elog.Logf("error during startup sequence: %s", err) return false } for k, v := range startupParameters { buf := &bytes.Buffer{} fbbuf.WriteCString(buf, k) fbbuf.WriteCString(buf, v) message.InitFromBytes(fbproto.MsgParameterStatusS, buf.Bytes()) err = c.WriteMessage(&message) if err != nil { elog.Logf("error during startup sequence: %s", err) return false } } fbproto.InitReadyForQuery(&message, fbproto.RfqIdle) err = c.WriteMessage(&message) if err != nil { elog.Logf("error during startup sequence: %s", err) return false } err = c.FlushStream() if err != nil { elog.Logf("error during startup sequence: %s", err) return false } return true }