mirror of
				https://github.com/coredns/coredns.git
				synced 2025-11-03 18:53:13 -05:00 
			
		
		
		
	
		
			
	
	
		
			87 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			87 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| 
								 | 
							
								package out
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import (
							 | 
						||
| 
								 | 
							
									"fmt"
							 | 
						||
| 
								 | 
							
									"net"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									fs "github.com/farsightsec/golang-framestream"
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Socket is a Frame Streams encoder over a UNIX socket.
							 | 
						||
| 
								 | 
							
								type Socket struct {
							 | 
						||
| 
								 | 
							
									path string
							 | 
						||
| 
								 | 
							
									enc  *fs.Encoder
							 | 
						||
| 
								 | 
							
									conn net.Conn
							 | 
						||
| 
								 | 
							
									err  error
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func openSocket(s *Socket) error {
							 | 
						||
| 
								 | 
							
									conn, err := net.Dial("unix", s.path)
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									s.conn = conn
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									enc, err := fs.NewEncoder(conn, &fs.EncoderOptions{
							 | 
						||
| 
								 | 
							
										ContentType:   []byte("protobuf:dnstap.Dnstap"),
							 | 
						||
| 
								 | 
							
										Bidirectional: true,
							 | 
						||
| 
								 | 
							
									})
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									s.enc = enc
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									s.err = nil
							 | 
						||
| 
								 | 
							
									return nil
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// NewSocket will always return a new Socket.
							 | 
						||
| 
								 | 
							
								// err if nothing is listening to it, it will attempt to reconnect on the next Write.
							 | 
						||
| 
								 | 
							
								func NewSocket(path string) (s *Socket, err error) {
							 | 
						||
| 
								 | 
							
									s = &Socket{path: path}
							 | 
						||
| 
								 | 
							
									if err = openSocket(s); err != nil {
							 | 
						||
| 
								 | 
							
										err = fmt.Errorf("open socket: %s", err)
							 | 
						||
| 
								 | 
							
										s.err = err
							 | 
						||
| 
								 | 
							
										return
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Write a single Frame Streams frame.
							 | 
						||
| 
								 | 
							
								func (s *Socket) Write(frame []byte) (int, error) {
							 | 
						||
| 
								 | 
							
									if s.err != nil {
							 | 
						||
| 
								 | 
							
										// is the dnstap tool listening?
							 | 
						||
| 
								 | 
							
										if err := openSocket(s); err != nil {
							 | 
						||
| 
								 | 
							
											return 0, fmt.Errorf("open socket: %s", err)
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									n, err := s.enc.Write(frame)
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										// the dnstap command line tool is down
							 | 
						||
| 
								 | 
							
										s.conn.Close()
							 | 
						||
| 
								 | 
							
										s.err = err
							 | 
						||
| 
								 | 
							
										return 0, err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return n, nil
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Close the socket and flush the remaining frames.
							 | 
						||
| 
								 | 
							
								func (s *Socket) Close() error {
							 | 
						||
| 
								 | 
							
									if s.err != nil {
							 | 
						||
| 
								 | 
							
										// nothing to close
							 | 
						||
| 
								 | 
							
										return nil
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									defer s.conn.Close()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if err := s.enc.Flush(); err != nil {
							 | 
						||
| 
								 | 
							
										return fmt.Errorf("flush: %s", err)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									if err := s.enc.Close(); err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return nil
							 | 
						||
| 
								 | 
							
								}
							 |