// Generic connection handler // // This redelegates to more specific proxy handlers that contain the // main proxy loop logic. func handleConnection(cConn net.Conn, serverAddr string) { var err error // Log disconnections defer func() { if err != nil && err != io.EOF { fmt.Printf("Session exits with error: %v\n", err) } else { fmt.Printf("Session exits cleanly\n") } }() defer cConn.Close() c := femebe.NewClientMessageStream( "Client", newBufWriteCon(cConn)) unencryptServerConn, err := autoDial(serverAddr) if err != nil { fmt.Printf("Could not connect to server: %v\n", err) } tlsConf := tls.Config{} tlsConf.InsecureSkipVerify = true sConn, err := femebe.NegotiateTLS( unencryptServerConn, "prefer", &tlsConf) if err != nil { fmt.Printf("Could not negotiate TLS: %v\n", err) } s := femebe.NewServerMessageStream("Server", newBufWriteCon(sConn)) if err != nil { fmt.Printf("Could not initialize connection to server: %v\n", err) } done := make(chan error) NewSimpleProxySession(done, &ProxyPair{c, cConn}, &ProxyPair{s, sConn}).start() // Both sides must exit to finish _ = <-done _ = <-done }
func logWorker(die dieCh, rwc io.ReadWriteCloser, cfg logplexc.Config, sr *serveRecord) { var err error stream := femebe.NewServerMessageStream("", rwc) var exit exitFn exit = func(args ...interface{}) { if len(args) == 1 { log.Printf("Disconnect client: %v", args[0]) } else if len(args) > 1 { if s, ok := args[0].(string); ok { log.Printf(s, args[1:]...) } else { // Not an intended use case, but do // one's best to print something. log.Printf("Got a malformed exit: %v", args) } } panic(&exit) } // Recovers from panic and exits in an orderly manner if (and // only if) exit() is called; otherwise propagate the panic // normally. defer func() { rwc.Close() // &exit is used as a sentinel value. if r := recover(); r != nil && r != &exit { panic(r) } }() var msgInit msgInit msgInit = func(m *femebe.Message, exit exitFn) { err = stream.Next(m) if err == io.EOF { exit("client disconnects") } else if err != nil { exit("could not read next message: %v", err) } } // Protocol start-up; packets that are only received once. processVerMsg(msgInit, exit) ident := processIdentMsg(msgInit, exit) log.Printf("client connects with identifier %q", ident) // Resolve the identifier to a serve if sr.I != ident { exit("got unexpected identifier for socket: "+ "path %s, expected %s, got %s", sr.P, sr.I, ident) } // Set up client with serve cfg.Token = sr.T client, err := logplexc.NewClient(&cfg) if err != nil { exit(err) } defer client.Close() processLogMsg(die, client, msgInit, sr, exit) }
// Generic connection handler // // This redelegates to more specific proxy handlers that contain the // main proxy loop logic. func handleConnection(cConn net.Conn, rt *routingTable) { var err error // Log disconnections defer func() { if err != nil && err != io.EOF { log.Printf("Session exits with error: %v\n", err) } else { log.Printf("Session exits cleanly\n") } }() defer cConn.Close() c := femebe.NewClientMessageStream( "Client", newBufWriteCon(cConn)) // Must interpret Startup and Cancel requests. // // SSL Negotiation requests not handled for now. var firstPacket femebe.Message c.Next(&firstPacket) // Handle Startup packets var sup *pgproto.Startup if sup, err = pgproto.ReadStartupMessage(&firstPacket); err != nil { log.Print(err) return } var ent *routingEntry if ent = rt.rewrite(sup); ent == nil { log.Print("Could not route startup packet") return } unencryptServerConn, err := autoDial(ent.addr) if err != nil { log.Printf("Could not connect to server: %v\n", err) return } tlsConf := tls.Config{} tlsConf.InsecureSkipVerify = true sConn, err := femebe.NegotiateTLS( unencryptServerConn, "prefer", &tlsConf) if err != nil { log.Printf("Could not negotiate TLS: %v\n", err) return } s := femebe.NewServerMessageStream("Server", newBufWriteCon(sConn)) if err != nil { log.Printf("Could not initialize connection to server: %v\n", err) return } var rewrittenStatupMessage femebe.Message sup.FillMessage(&rewrittenStatupMessage) err = s.Send(&rewrittenStatupMessage) if err != nil { return } err = s.Flush() if err != nil { return } done := make(chan error) NewSimpleProxySession(done, &ProxyPair{c, cConn}, &ProxyPair{s, sConn}).start() // Both sides must exit to finish _ = <-done _ = <-done }
func newTestServerStream(t *testing.T) (*femebe.MessageStream, *inMemRwc) { rwc := NewInMemRwc() return femebe.NewServerMessageStream("TestServerConn", rwc), rwc }