2023-03-11 15:03:45 +00:00
|
|
|
package listener
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"net"
|
|
|
|
"net/http"
|
|
|
|
"os"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Listener struct {
|
|
|
|
ctx context.Context
|
|
|
|
cancel context.CancelFunc
|
|
|
|
httpSrv *http.Server
|
|
|
|
exportChan chan string
|
|
|
|
errorChan chan error
|
|
|
|
listener net.Listener
|
|
|
|
handler *http.ServeMux
|
|
|
|
}
|
|
|
|
|
|
|
|
func New(sockPath string) (*Listener, error) {
|
|
|
|
if err := os.Remove(sockPath); err != nil && !errors.Is(err, os.ErrNotExist) {
|
|
|
|
return nil, fmt.Errorf("failed to cleanup previously existing socket: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
sock, err := net.Listen("unix", sockPath)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("failed to create unix socket: %w", err)
|
|
|
|
}
|
2023-03-11 19:42:21 +00:00
|
|
|
if err := os.Chmod(sockPath, 0o777); err != nil {
|
|
|
|
return nil, fmt.Errorf("failed to set permissions to unix socket: %w", err)
|
|
|
|
}
|
2023-03-11 15:03:45 +00:00
|
|
|
|
|
|
|
m := http.NewServeMux()
|
|
|
|
|
|
|
|
return &Listener{
|
|
|
|
handler: m,
|
|
|
|
httpSrv: &http.Server{
|
|
|
|
Handler: m,
|
|
|
|
},
|
|
|
|
listener: sock,
|
|
|
|
exportChan: make(chan string, 10),
|
|
|
|
errorChan: make(chan error, 10),
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Listener) initMux() {
|
|
|
|
l.handler.HandleFunc("/", l.sendMessageHandler)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Listener) Run(ctx context.Context) {
|
|
|
|
l.ctx, l.cancel = context.WithCancel(ctx)
|
|
|
|
l.initMux()
|
|
|
|
if err := l.httpSrv.Serve(l.listener); err != nil {
|
|
|
|
l.errorChan <- fmt.Errorf("failed to serve HTTP server: %w", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Listener) sendMessage(message string) {
|
|
|
|
l.exportChan <- message
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Listener) sendMessageHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
if r.Method != http.MethodPost {
|
|
|
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: use max length instead of writing everything
|
|
|
|
bod, err := ioutil.ReadAll(r.Body)
|
|
|
|
if err != nil {
|
|
|
|
l.errorChan <- fmt.Errorf("failed to read body: %w", err)
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
l.sendMessage(string(bod))
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Listener) ExportChan() <-chan string {
|
|
|
|
return l.exportChan
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Listener) ErrorChan() <-chan error {
|
|
|
|
return l.errorChan
|
|
|
|
}
|