Esempio n. 1
0
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 NewFrontendConnection(c net.Conn, dispatcher *notifydispatcher.NotifyDispatcher, connStatusNotifier chan struct{}) *FrontendConnection {
	io := &frontendConnectionIO{
		c:    c,
		bufw: bufio.NewWriterSize(c, 128),
	}

	fc := &FrontendConnection{
		remoteAddr: c.RemoteAddr().String(),

		stream:     fbcore.NewFrontendStream(io),
		dispatcher: dispatcher,

		connStatusNotifier: connStatusNotifier,
		notify:             make(chan *pq.Notification, 32),
		queryResultCh:      make(chan queryResultSync, 8),

		listenChannels: make(map[string]struct{}),
	}
	return fc
}