Introduce a basic logger and some code for testing
This commit is contained in:
parent
955860cd50
commit
2e4d5eae8a
|
@ -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/)
|
|
@ -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...)
|
||||||
|
}
|
||||||
|
}
|
|
@ -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()
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue