func (c *simpleConnector) dial() (core.Stream, error) { bareConn, err := util.AutoDial(c.backendAddr) if err != nil { return nil, fmt.Errorf("could not connect to %v: %v", c.backendAddr, err) } // the simpleConnector always prefers TLS beConn, err := util.NegotiateTLS(bareConn, &util.SSLConfig{ Mode: util.SSLPrefer, Config: tls.Config{InsecureSkipVerify: true}, }) if err != nil { return nil, fmt.Errorf("could not negotiate TLS: %v", err) } return core.NewBackendStream(beConn), nil }
func logWorker(die dieCh, l net.Listener, cfg logplexc.Config, sr *serveRecord) { // Make world-writable so anything can connect and send logs. // This may be be worth locking down more, but as-is unless // pg_logplexcollector and the Postgres server share the same // running user common umasks will be useless. fi, err := os.Stat(sr.P) if err != nil { log.Fatalf( "exiting, cannot stat just created socket %q: %v", sr.P, err) } err = os.Chmod(sr.P, fi.Mode().Perm()|0222) if err != nil { log.Fatalf( "exiting, cannot make just created socket "+ "world-writable %q: %v", sr.P, err) } for { select { case <-die: log.Print("listener exits normally from die request") return default: break } conn, err := l.Accept() if err != nil { log.Printf("accept error: %v", err) } if err != nil { log.Fatalf("serve database suffers unrecoverable "+ "error: %v", err) } go func() { stream := core.NewBackendStream(conn) 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() { conn.Close() // &exit is used as a sentinel value. if r := recover(); r != nil && r != &exit { panic(r) } }() var msgInit msgInit msgInit = func(m *core.Message, exit exitFn) { err = stream.Next(m) if err == io.EOF { exit("postgres 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 client := func(cfg logplexc.Config, url *url.URL) *logplexc.Client { cfg.Logplex = *url client, err := logplexc.NewClient(&cfg) if err != nil { exit(err) } return client } primary := client(cfg, &sr.u) var audit *logplexc.Client if sr.audit != nil { audit = client(cfg, sr.audit) } defer func() { primary.Close() if audit != nil { audit.Close() } }() processLogMsg(die, primary, audit, msgInit, sr, exit) }() } }