Introduce a basic logger and some code for testing

This commit is contained in:
Jan Philipp Timme 2019-05-12 19:05:56 +02:00
parent 955860cd50
commit 2e4d5eae8a
4 changed files with 218 additions and 0 deletions

11
README.md Normal file
View File

@ -0,0 +1,11 @@
# Milter experiment
This project is for educational purposes.
Any attempts to run this in production WILL FAIL!
Use this code as inspiration, but do not blame me for your losses.
# References
* [The source code of sendmail-jilter](https://sourceforge.net/projects/sendmail-jilter/)
* [The Sendmail source code](https://ftp.sendmail.org/)

137
logger.go Normal file
View File

@ -0,0 +1,137 @@
package main
import (
"io"
"log"
)
// Loglevel is used to set the current loglevel of Logger.
type Loglevel int
const (
// NONE is a loglevel for Logger.
NONE Loglevel = 0
// ERROR is a loglevel for Logger.
ERROR Loglevel = 1
// WARN is a loglevel for Logger.
WARN Loglevel = 2
// INFO is a loglevel for Logger.
INFO Loglevel = 3
// DEBUG is a loglevel for Logger.
DEBUG Loglevel = 4
)
// Logger uses multiple instances of log.Logger to provide logging methods for multiple loglevels.
type Logger struct {
debug *log.Logger
info *log.Logger
warn *log.Logger
error *log.Logger
logDebug bool
logInfo bool
logWarn bool
logError bool
}
// NewLogger prepares a new instance of Logger for custom use.
func NewLogger(stdOut io.Writer, stdErr io.Writer, logLevel Loglevel) Logger {
newLogger := Logger{}
newLogger.debug = log.New(stdOut, "DEBUG ", 0)
newLogger.info = log.New(stdOut, "INFO ", 0)
newLogger.warn = log.New(stdErr, "WARN ", 0)
newLogger.error = log.New(stdErr, "ERROR ", 0)
newLogger.SetLogLevel(logLevel)
return newLogger
}
// SetLogLevel can be used to change the loglevel of Logger on the fly.
func (l *Logger) SetLogLevel(logLevel Loglevel) {
l.logDebug = (logLevel >= DEBUG)
l.logInfo = (logLevel >= INFO)
l.logWarn = (logLevel >= WARN)
l.logError = (logLevel >= ERROR)
}
// Debug is an alias for log.Logger.Print() with severity DEBUG.
func (l *Logger) Debug(v ...interface{}) {
if l.logDebug {
l.debug.Print(v...)
}
}
// Debugln is an alias for log.Logger.Println() with severity DEBUG.
func (l *Logger) Debugln(v ...interface{}) {
if l.logDebug {
l.debug.Println(v...)
}
}
// Debugf is an alias for log.Logger.Printf() with severity DEBUG.
func (l *Logger) Debugf(format string, v ...interface{}) {
if l.logDebug {
l.debug.Printf(format, v...)
}
}
// Info is an alias for log.Logger.Print() with severity INFO.
func (l *Logger) Info(v ...interface{}) {
if l.logInfo {
l.info.Print(v...)
}
}
// Infoln is an alias for log.Logger.Println() with severity INFO.
func (l *Logger) Infoln(v ...interface{}) {
if l.logInfo {
l.info.Println(v...)
}
}
// Infof is an alias for log.Logger.Printf() with severity INFO.
func (l *Logger) Infof(format string, v ...interface{}) {
if l.logInfo {
l.info.Printf(format, v...)
}
}
// Warn is an alias for log.Logger.Print() with severity WARN.
func (l *Logger) Warn(v ...interface{}) {
if l.logWarn {
l.warn.Print(v...)
}
}
// Warnln is an alias for log.Logger.Println() with severity WARN.
func (l *Logger) Warnln(v ...interface{}) {
if l.logWarn {
l.warn.Println(v...)
}
}
// Warnf is an alias for log.Logger.Printf() with severity WARN.
func (l *Logger) Warnf(format string, v ...interface{}) {
if l.logWarn {
l.warn.Printf(format, v...)
}
}
// Error is an alias for log.Logger.Print() with severity ERROR.
func (l *Logger) Error(v ...interface{}) {
if l.logError {
l.error.Print(v...)
}
}
// Errorln is an alias for log.Logger.Println() with severity ERROR.
func (l *Logger) Errorln(v ...interface{}) {
if l.logError {
l.error.Println(v...)
}
}
// Errorf is an alias for log.Logger.Printf() with severity ERROR.
func (l *Logger) Errorf(format string, v ...interface{}) {
if l.logError {
l.error.Printf(format, v...)
}
}

42
main.go Normal file
View File

@ -0,0 +1,42 @@
package main
import (
"bufio"
"bytes"
"encoding/binary"
"encoding/hex"
"os"
)
var (
logger Logger
)
func handleMtaConnection(clientConnection *bufio.ReadWriter) {
buf := make([]byte, 4096)
for {
bytesRead, err := clientConnection.Read(buf)
if err != nil {
logger.Errorln("Error reading from clientConnection:", err.Error())
break
} else {
logger.Infof("Read %d bytes from connection\n", bytesRead)
logger.Debugf("%s", hex.Dump(buf[0:bytesRead]))
// First 4 Bytes will be some integer thing "length"
// Let's parse that
var packetLength uint32
bytesReader := bytes.NewReader(buf[0:4])
err := binary.Read(bytesReader, binary.BigEndian, &packetLength)
if err != nil {
logger.Errorln(err.Error())
}
logger.Debugf("Parsed length: %d\n", packetLength)
}
}
}
func main() {
logger = NewLogger(os.Stdout, os.Stderr, DEBUG)
runServer()
}

28
socket.go Normal file
View File

@ -0,0 +1,28 @@
package main
import (
"bufio"
"net"
"os"
)
func runServer() {
serverSocket, err := net.Listen("tcp", "127.0.0.1:7777")
if err != nil {
logger.Errorf("Could not create listening socket: %s\n", err.Error())
os.Exit(1)
} else {
logger.Infof("Now listening for incoming connections.\n")
defer serverSocket.Close()
}
for {
clientConnection, err := serverSocket.Accept()
if err != nil {
logger.Warnf("Could not accept client connection: %s\n", err.Error())
} else {
logger.Infof("Accepted client connection.\n")
milterReadWriter := bufio.NewReadWriter(bufio.NewReader(clientConnection), bufio.NewWriter(clientConnection))
go handleMtaConnection(milterReadWriter)
}
}
}