2021-12-16 19:45:32 -05:00
|
|
|
package oscar
|
|
|
|
|
|
|
|
import (
|
2021-12-17 19:01:22 -05:00
|
|
|
"aim-oscar/util"
|
2022-01-23 13:22:05 -05:00
|
|
|
"bytes"
|
2021-12-18 16:48:13 -05:00
|
|
|
"context"
|
|
|
|
"encoding/binary"
|
2022-01-22 20:57:27 -05:00
|
|
|
"fmt"
|
2021-12-16 19:45:32 -05:00
|
|
|
"io"
|
|
|
|
"log"
|
|
|
|
"net"
|
2021-12-18 16:48:13 -05:00
|
|
|
"strings"
|
2022-02-11 13:28:20 -05:00
|
|
|
"time"
|
2021-12-16 19:45:32 -05:00
|
|
|
)
|
|
|
|
|
2021-12-18 16:48:13 -05:00
|
|
|
type HandlerFunc func(context.Context, *FLAP) context.Context
|
2021-12-18 17:10:00 -05:00
|
|
|
type HandleCloseFn func(context.Context, *Session)
|
2021-12-17 19:01:22 -05:00
|
|
|
|
2021-12-18 17:10:00 -05:00
|
|
|
type Handler struct {
|
|
|
|
handle HandlerFunc
|
|
|
|
handleClose HandleCloseFn
|
|
|
|
}
|
2021-12-16 19:45:32 -05:00
|
|
|
|
2021-12-18 17:10:00 -05:00
|
|
|
func NewHandler(fn HandlerFunc, handleClose HandleCloseFn) *Handler {
|
2021-12-16 19:45:32 -05:00
|
|
|
return &Handler{
|
2021-12-18 17:10:00 -05:00
|
|
|
handle: fn,
|
|
|
|
handleClose: handleClose,
|
2021-12-16 19:45:32 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *Handler) Handle(conn net.Conn) {
|
2021-12-18 16:48:13 -05:00
|
|
|
ctx := NewContextWithSession(context.Background(), conn)
|
|
|
|
session, _ := SessionFromContext(ctx)
|
|
|
|
|
2022-01-23 13:22:05 -05:00
|
|
|
var buf bytes.Buffer
|
2021-12-16 19:45:32 -05:00
|
|
|
for {
|
|
|
|
if !session.GreetedClient {
|
|
|
|
// send a hello
|
|
|
|
hello := NewFLAP(1)
|
|
|
|
hello.Data.Write([]byte{0, 0, 0, 1})
|
2022-01-22 20:57:27 -05:00
|
|
|
session.Send(hello)
|
2021-12-16 19:45:32 -05:00
|
|
|
session.GreetedClient = true
|
|
|
|
}
|
|
|
|
|
2022-02-11 13:28:20 -05:00
|
|
|
// Never timeout
|
|
|
|
conn.SetReadDeadline(time.Time{})
|
|
|
|
|
2022-01-23 13:22:05 -05:00
|
|
|
incoming := make([]byte, 512)
|
|
|
|
n, err := conn.Read(incoming)
|
2021-12-16 19:45:32 -05:00
|
|
|
if err != nil && err != io.EOF {
|
2021-12-18 16:48:13 -05:00
|
|
|
if strings.Contains(err.Error(), "use of closed network connection") {
|
|
|
|
session.Disconnect()
|
2021-12-18 17:10:00 -05:00
|
|
|
h.handleClose(ctx, session)
|
2021-12-18 16:48:13 -05:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Println("OSCAR Read Error: ", err.Error())
|
2021-12-16 19:45:32 -05:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if n == 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-01-23 13:22:05 -05:00
|
|
|
buf.Write(incoming[:n])
|
|
|
|
|
2021-12-16 19:45:32 -05:00
|
|
|
// Try to parse all of the FLAPs in the buffer if we have enough bytes to
|
|
|
|
// fill a FLAP header
|
2022-01-23 13:22:05 -05:00
|
|
|
for buf.Len() >= 6 && buf.Bytes()[0] == 0x2a {
|
|
|
|
bufBytes := buf.Bytes()
|
|
|
|
dataLength := binary.BigEndian.Uint16(bufBytes[4:6])
|
2021-12-16 19:45:32 -05:00
|
|
|
flapLength := int(dataLength) + 6
|
2022-01-23 13:22:05 -05:00
|
|
|
if len(bufBytes) < flapLength {
|
|
|
|
log.Printf("not enough data, expected %d bytes but have %d bytes\n", flapLength, len(bufBytes))
|
|
|
|
fmt.Printf("%s\n", util.PrettyBytes(bufBytes))
|
2021-12-16 19:45:32 -05:00
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
flap := &FLAP{}
|
2022-01-23 13:22:05 -05:00
|
|
|
flapBuf := make([]byte, flapLength)
|
|
|
|
buf.Read(flapBuf)
|
|
|
|
if err := flap.UnmarshalBinary(flapBuf); err != nil {
|
2022-02-03 14:06:33 -05:00
|
|
|
log.Printf("could not unmarshal FLAP: %w", err)
|
|
|
|
// Toss out everything
|
|
|
|
buf.Reset()
|
|
|
|
break
|
2021-12-16 19:45:32 -05:00
|
|
|
}
|
2022-01-23 13:22:05 -05:00
|
|
|
|
2021-12-18 16:48:13 -05:00
|
|
|
ctx = h.handle(ctx, flap)
|
2021-12-16 19:45:32 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|