package main import ( "bufio" "bytes" "encoding/binary" "encoding/hex" "milter-experiment/logging" "os" ) var ( // Global logger for application wide logging. Not sure if this is a good pattern yet. logger logging.Logger ) type milterPacket struct { payloadLength uint32 message string payload []byte } type smficOptineg struct { version uint32 actions uint32 protocol uint32 } func readRequestPacket(clientConnection *bufio.ReadWriter) (milterPacket, error) { buf := make([]byte, 4096) bytesRead, err := clientConnection.Read(buf) if err != nil { logger.Errorln("Error reading from clientConnection:", err.Error()) return milterPacket{}, err } logger.Infof("Read %d bytes from connection\n", bytesRead) logger.Debugf("Hexdump of bytes read:\n%s", hex.Dump(buf[0:bytesRead])) reqPacket := milterPacket{} // First 4 Bytes will be some integer thing "length" bytesReader := bytes.NewReader(buf[0:4]) err = binary.Read(bytesReader, binary.BigEndian, &reqPacket.payloadLength) if err != nil { logger.Errorln(err.Error()) } logger.Debugf("Parsed length: %d\n", reqPacket.payloadLength) // Next up is a character, indicating the milter command logger.Debugf("Parsing command from byte: %X\n", buf[4]) reqPacket.message = string(buf[4]) logger.Debugf("Parsed packet command: %s\n", reqPacket.message) // Last part is data with lenght len-1 reqPacket.payload = buf[5 : 5+reqPacket.payloadLength-1] logger.Debugf("Hexdump of packet payload read:\n%s", hex.Dump(reqPacket.payload)) // That's it, we're done. return reqPacket, nil } func handleMtaConnection(clientConnection *bufio.ReadWriter) { for { request, _ := readRequestPacket(clientConnection) if request.message == "O" { responsePayload := smficOptineg{2, 0, 2} //clientConnection.Write() } } } func main() { logger = logging.NewLogger(os.Stdout, os.Stderr, logging.DEBUG) err := runServer("127.0.0.1:7777") if err != nil { logger.Errorf("Could not run server: %s\n", err.Error()) os.Exit(1) } }