Skip to content

Commit

Permalink
Lineproto code refactor
Browse files Browse the repository at this point in the history
Big refactor of line protocol code. Now with simple reload for
lookuptables.
  • Loading branch information
securitym0nkey committed Jul 10, 2024
1 parent 45090be commit edb17e5
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 26 deletions.
33 changes: 28 additions & 5 deletions cmd/icalm-server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ func main() {
os.Exit(1)
}

servers := make([]*lineproto.LineServer,0)
toclose := make([]io.Closer, 0)

lookuptable, err := config.LoadLookupTableFromFile(*cidrfileFlag)
Expand All @@ -61,22 +62,44 @@ func main() {
if err != nil {
log.Fatal(err)
}
log.Printf("Listening on %v for lineproto requests \n", lineserver.Addr())
toclose = append(toclose, lineserver)
log.Printf("Listening on %v for lineproto requests \n", lineserver.Listener.Addr())
toclose = append(toclose, lineserver.Listener)
servers = append(servers, lineserver)
}

if *lineunixFlag != "" {
lineunixserver, err := lineproto.NewLineServer("unix", *lineunixFlag, lookuptable)
if err != nil {
log.Fatal(err)
}
log.Printf("Serving lineproto @ %v \n", lineunixserver.Addr())
toclose = append(toclose, lineunixserver)
log.Printf("Serving lineproto @ %v \n", lineunixserver.Listener.Addr())
toclose = append(toclose, lineunixserver.Listener)
servers = append(servers, lineunixserver)
}

sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
<-sigChan

sigHupChan := make(chan os.Signal, 1)
signal.Notify(sigHupChan, syscall.SIGHUP)


run := true
for run {
select {
case <-sigChan:
run = false
case <-sigHupChan:
for _, serv := range servers {
lookuptable, err := config.LoadLookupTableFromFile(*cidrfileFlag)
if err != nil {
log.Fatal(err)
}
serv.Reload(lookuptable)
log.Printf("Reloaded lookuptable (%v entries)\n", lookuptable.Size())
}
}
}

log.Println("Shutting down")

Expand Down
128 changes: 107 additions & 21 deletions internal/lineproto/lineproto.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,44 +5,130 @@ import (
"github.com/securitym0nkey/icalm/pkg/iplookup"
"io"
"net"
"log"
"sync"
)

func ServLineProto(r io.Reader, w io.Writer, table iplookup.LookupTable) {
scanner := bufio.NewScanner(r)

type LineServerConnection struct {
conn net.Conn
update_chan chan *iplookup.LookupTable
}

type LineServer struct {
Listener net.Listener
clients map[net.Conn]*LineServerConnection
table iplookup.LookupTable
clientsMutex sync.Mutex
}



func ServLineProto(r io.Reader, w io.Writer, inittable *iplookup.LookupTable, newtable_chan chan *iplookup.LookupTable) {

quit_chan := make(chan int)
defer close(quit_chan)

request_chan := make(chan string)
defer close(request_chan)


wr := bufio.NewWriter(w)
table := *(inittable)

for scanner.Scan() {
i := scanner.Text()
ip := net.ParseIP(i)
if ip != nil {
s, o := table.Lookup(ip)
if o {
wr.WriteString(s)
}

// wait for new request (lines) in separate goroutine
go func(){
scanner := bufio.NewScanner(r)
for scanner.Scan() {
r := scanner.Text()
request_chan <- r
}
quit_chan <- 0
}()


// main loop per client
for {
select {
case request := <- request_chan:
ip := net.ParseIP(request)
s, o := table.Lookup(ip)
if o {
wr.WriteString(s)
}
wr.WriteString("\n")
wr.Flush()
case newtable := <- newtable_chan:
table = *(newtable)
case <-quit_chan:
return
}
wr.WriteString("\n")
wr.Flush()
}

}

func NewLineServer(network string, addr string, table iplookup.LookupTable) (net.Listener, error) {
server, err := net.Listen(network, addr)
func (s *LineServer) AddClientConnection(c *LineServerConnection) {
s.clientsMutex.Lock()
defer s.clientsMutex.Unlock()
log.Printf("Client %s connected", c.conn.RemoteAddr())
s.clients[c.conn] = c
}


func (s *LineServer) RemoveClientConnection(c *LineServerConnection) {
s.clientsMutex.Lock()
defer s.clientsMutex.Unlock()
log.Printf("Client %s disconnected", c.conn.RemoteAddr())
delete(s.clients, c.conn)
}

func (s *LineServer) Reload(newtable iplookup.LookupTable){
s.clientsMutex.Lock()
defer s.clientsMutex.Unlock()

s.table = newtable
for _, client := range s.clients {
client.update_chan <- &(newtable)
}

}

func NewLineServer(network string, addr string, table iplookup.LookupTable) (*LineServer, error) {
listener, err := net.Listen(network, addr)

if err != nil {
return nil, err
}
go func(s net.Listener) {
defer s.Close()

server := &LineServer {
Listener: listener,
clients: make(map[net.Conn]*LineServerConnection),
table: table,
}

go func(s *LineServer) {
defer s.Listener.Close()
for {
conn, err := s.Accept()
conn, err := s.Listener.Accept()
if err != nil {
break
}
go func(c net.Conn) {
defer c.Close()
ServLineProto(c, c, table)
}(conn)

client := &LineServerConnection{
conn: conn,
update_chan: make(chan *iplookup.LookupTable),
}
server.AddClientConnection(client)

go func(c *LineServerConnection) {
defer c.conn.Close()
defer server.RemoveClientConnection(c)
ServLineProto(c.conn, c.conn, &server.table, c.update_chan)

}(client)
}
}(server)

return server, nil
}

0 comments on commit edb17e5

Please sign in to comment.