...

Source file src/edge-infra.dev/pkg/sds/lanoutage/detector/socket.go

Documentation: edge-infra.dev/pkg/sds/lanoutage/detector

     1  package detector
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"net"
     7  	"os"
     8  	"time"
     9  )
    10  
    11  const (
    12  	SocketReadTimeout  time.Duration = 30 * time.Second
    13  	SocketWriteTimeout time.Duration = 300 * time.Second
    14  )
    15  
    16  type SocketResponse struct {
    17  	Message string `json:"message,omitempty"`
    18  	Error   string `json:"error,omitempty"`
    19  }
    20  
    21  type SocketHandler struct {
    22  	listener net.Listener
    23  	path     string
    24  }
    25  
    26  // NewSocketHandler creates a new SocketHandler, clearing any stale sockets
    27  func NewSocketHandler(path string) (*SocketHandler, error) {
    28  	sh := &SocketHandler{
    29  		path: path,
    30  	}
    31  
    32  	if err := sh.Clear(); err != nil {
    33  		return nil, fmt.Errorf("failed to clear stale sockets: %w", err)
    34  	}
    35  
    36  	listener, err := net.Listen("unix", sh.path)
    37  	if err != nil {
    38  		return nil, fmt.Errorf("failed to connect to socket at %v: %w", sh.path, err)
    39  	}
    40  
    41  	sh.listener = listener
    42  
    43  	return sh, nil
    44  }
    45  
    46  // Clear removes the socket file
    47  func (s *SocketHandler) Clear() error {
    48  	return os.RemoveAll(s.path)
    49  }
    50  
    51  // ReceiveConnection waits for a connection and returns it
    52  func (s *SocketHandler) ReceiveConnection() (*Conn, error) {
    53  	conn, err := s.listener.Accept()
    54  	if err != nil {
    55  		return nil, err
    56  	}
    57  
    58  	if err := conn.SetReadDeadline(time.Now().Add(SocketReadTimeout)); err != nil {
    59  		return nil, fmt.Errorf("failed to set read deadline on connection: %w", err)
    60  	}
    61  
    62  	if err := conn.SetWriteDeadline(time.Now().Add(SocketWriteTimeout)); err != nil {
    63  		return nil, fmt.Errorf("failed to set write deadline on connection: %w", err)
    64  	}
    65  
    66  	return &Conn{
    67  		conn: conn,
    68  	}, nil
    69  }
    70  
    71  type Conn struct {
    72  	conn net.Conn
    73  }
    74  
    75  // Receive reads from the connection
    76  func (c *Conn) Receive() (string, error) {
    77  	buf := make([]byte, 512)
    78  	size, err := c.conn.Read(buf)
    79  	if err != nil {
    80  		return "", fmt.Errorf("failed to read from buffer: %w", err)
    81  	}
    82  	data := buf[0:size]
    83  
    84  	return string(data), nil
    85  }
    86  
    87  // Respond writes to the connection
    88  func (c *Conn) Respond(response string, errMessage string) error {
    89  	sr := &SocketResponse{
    90  		Message: response,
    91  		Error:   errMessage,
    92  	}
    93  
    94  	data, err := json.Marshal(sr)
    95  	if err != nil {
    96  		return fmt.Errorf("failed to marshal response: %w", err)
    97  	}
    98  
    99  	_, err = c.conn.Write(data)
   100  	return err
   101  }
   102  

View as plain text