2020-06-19 13:31:20 +00:00
|
|
|
package net
|
|
|
|
|
|
|
|
import (
|
|
|
|
"flag"
|
|
|
|
"fmt"
|
|
|
|
"github.com/maride/afl-transmit/logistic"
|
2021-04-20 08:28:03 +00:00
|
|
|
"github.com/maride/afl-transmit/stats"
|
2020-06-19 13:31:20 +00:00
|
|
|
"io"
|
2020-06-19 23:06:47 +00:00
|
|
|
"io/ioutil"
|
2020-06-19 13:31:20 +00:00
|
|
|
"log"
|
|
|
|
"net"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
port int
|
2021-04-19 21:38:36 +00:00
|
|
|
restrictToPeers bool
|
2020-06-19 13:31:20 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Registers the flags required for the listener
|
|
|
|
func RegisterListenFlags() {
|
|
|
|
flag.IntVar(&port, "port", ServerPort, "Port to bind server component to")
|
2021-04-19 21:38:36 +00:00
|
|
|
flag.BoolVar(&restrictToPeers, "restrict-to-peers", false, "Only allow connections from peers")
|
2020-06-19 13:31:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Sets up a listener and listens forever for packets on the given port, storing their contents in the outputDirectory
|
|
|
|
func Listen(outputDirectory string) error {
|
|
|
|
// Create listener
|
|
|
|
addrStr := fmt.Sprintf(":%v", port)
|
|
|
|
listener, listenErr := net.Listen("tcp", addrStr)
|
|
|
|
if listenErr != nil {
|
|
|
|
return listenErr
|
|
|
|
}
|
|
|
|
|
|
|
|
// Prepare output directory path
|
|
|
|
outputDirectory = strings.TrimRight(outputDirectory, "/")
|
|
|
|
|
|
|
|
// Listen forever
|
|
|
|
for {
|
|
|
|
// Accept connection
|
|
|
|
conn, connErr := listener.Accept()
|
|
|
|
if connErr != nil {
|
|
|
|
log.Printf("Encountered error while accepting from %s: %s", conn.RemoteAddr().String(), connErr)
|
|
|
|
continue
|
|
|
|
}
|
2021-04-19 21:38:36 +00:00
|
|
|
|
|
|
|
// Check if we should restrict connections from peers
|
|
|
|
handleConnection := true
|
|
|
|
if restrictToPeers {
|
|
|
|
found := false
|
|
|
|
// Loop over peers
|
|
|
|
for _, p := range peers {
|
|
|
|
// Check if we found the remote address in our peers list
|
|
|
|
if p.Address == conn.RemoteAddr().String() {
|
|
|
|
found = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle connection only if its a peer
|
|
|
|
handleConnection = found
|
|
|
|
}
|
|
|
|
|
|
|
|
if handleConnection {
|
|
|
|
// Handle in a separate thread
|
|
|
|
go handle(conn, outputDirectory)
|
|
|
|
}
|
2020-06-19 13:31:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handles a single connection, and unpacks the received data into outputDirectory
|
|
|
|
func handle(conn net.Conn, outputDirectory string) {
|
|
|
|
// Make sure to close connection on return
|
|
|
|
defer conn.Close()
|
|
|
|
|
2020-06-19 23:06:47 +00:00
|
|
|
// Read raw content
|
|
|
|
cont, contErr := ioutil.ReadAll(conn) // bufio.NewReader(conn).ReadString('\x00')
|
2020-06-19 13:31:20 +00:00
|
|
|
|
2021-04-23 14:17:44 +00:00
|
|
|
// Check if we are able to decrypt
|
|
|
|
if CryptApplicable() {
|
|
|
|
// Decrypt packet
|
|
|
|
var decryptErr error
|
|
|
|
cont, decryptErr = Decrypt(cont)
|
|
|
|
if decryptErr != nil {
|
|
|
|
log.Printf("Failed to decrypt packet from %s: %s", conn.RemoteAddr().String(), decryptErr)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-19 23:06:47 +00:00
|
|
|
if contErr == nil || contErr == io.EOF {
|
|
|
|
// We received the whole content, time to process it
|
2021-04-23 14:17:44 +00:00
|
|
|
unpackErr := logistic.UnpackInto(cont, outputDirectory)
|
2020-06-19 23:06:47 +00:00
|
|
|
if unpackErr != nil {
|
|
|
|
log.Printf("Encountered error processing packet from %s: %s", conn.RemoteAddr().String(), unpackErr)
|
2020-06-19 13:31:20 +00:00
|
|
|
}
|
|
|
|
|
2021-04-20 08:28:03 +00:00
|
|
|
// Push read bytes to stats
|
|
|
|
stats.PushStat(stats.Stat{ReceivedBytes: uint64(len(cont))})
|
|
|
|
|
2020-06-19 23:06:47 +00:00
|
|
|
return
|
|
|
|
} else {
|
|
|
|
// We encountered an error on that connection
|
|
|
|
log.Printf("Encountered error while reading from %s: %s", conn.RemoteAddr().String(), contErr)
|
|
|
|
return
|
2020-06-19 13:31:20 +00:00
|
|
|
}
|
|
|
|
}
|