mirror of
https://github.com/amigan/aim-oscar-server.git
synced 2024-11-22 04:29:47 -05:00
Explore rewriting Auth server in Go
This commit is contained in:
parent
f2ab2ced48
commit
27aea95084
4 changed files with 170 additions and 0 deletions
3
go.mod
Normal file
3
go.mod
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
module aim-oscar
|
||||||
|
|
||||||
|
go 1.16
|
122
main.go
Normal file
122
main.go
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
SRV_HOST = ""
|
||||||
|
SRV_PORT = "5190"
|
||||||
|
SRV_ADDRESS = SRV_HOST + ":" + SRV_PORT
|
||||||
|
)
|
||||||
|
|
||||||
|
type Session struct {
|
||||||
|
Conn net.Conn
|
||||||
|
GreetedClient bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSession(conn net.Conn) *Session {
|
||||||
|
return &Session{
|
||||||
|
Conn: conn,
|
||||||
|
GreetedClient: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Session) Send(bytes []byte) {
|
||||||
|
fmt.Printf("-> %v\n%s\n\n", s.Conn.RemoteAddr(), prettyBytes(bytes))
|
||||||
|
s.Conn.Write(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
listener, err := net.Listen("tcp", SRV_ADDRESS)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error listening: ", err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
defer listener.Close()
|
||||||
|
|
||||||
|
exitChan := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(exitChan, os.Interrupt, syscall.SIGINT, syscall.SIGTERM, syscall.SIGABRT)
|
||||||
|
go func() {
|
||||||
|
<-exitChan
|
||||||
|
fmt.Println("Shutting down")
|
||||||
|
os.Exit(1)
|
||||||
|
}()
|
||||||
|
|
||||||
|
fmt.Println("OSCAR listening on " + SRV_ADDRESS)
|
||||||
|
for {
|
||||||
|
conn, err := listener.Accept()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error accepting connection: ", err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := context.WithValue(context.Background(), "session", NewSession(conn))
|
||||||
|
log.Printf("Connection from %v", conn.RemoteAddr())
|
||||||
|
|
||||||
|
go handleTCPConnection(ctx, conn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleTCPConnection(ctx context.Context, conn net.Conn) {
|
||||||
|
defer (func() {
|
||||||
|
recover()
|
||||||
|
conn.Close()
|
||||||
|
log.Printf("Closed connection to %v", conn.RemoteAddr())
|
||||||
|
})()
|
||||||
|
|
||||||
|
buf := make([]byte, 1024)
|
||||||
|
for {
|
||||||
|
session := ctx.Value("session").(*Session)
|
||||||
|
if !session.GreetedClient {
|
||||||
|
// send a hello
|
||||||
|
hello := []byte{0x2a, 1, 0, 0, 0, 4, 0, 0, 0, 1}
|
||||||
|
session.Send(hello)
|
||||||
|
session.GreetedClient = true
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err := conn.Read(buf)
|
||||||
|
if err != nil && err != io.EOF {
|
||||||
|
log.Println("Read Error: ", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if n == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("%v ->\n%s\n\n", conn.RemoteAddr(), prettyBytes(buf[:n]))
|
||||||
|
handleMessage(ctx, buf[:n])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleMessage(ctx context.Context, buf []byte) {
|
||||||
|
messageBuf := bytes.NewBuffer(buf)
|
||||||
|
|
||||||
|
start, err := messageBuf.ReadByte()
|
||||||
|
panicIfError(err)
|
||||||
|
if start != 0x2a {
|
||||||
|
log.Println("FLAP message missing leading 0x2a")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start parsing FLAP header
|
||||||
|
channel := mustReadNBytes(messageBuf, 1)[0]
|
||||||
|
log.Println("Message for channel: ", channel)
|
||||||
|
|
||||||
|
datagramSeqNum := mustReadNBytes(messageBuf, 2)
|
||||||
|
log.Println("Datagram Sequence Number: ", binary.BigEndian.Uint16(datagramSeqNum))
|
||||||
|
|
||||||
|
dataLength := mustReadNBytes(messageBuf, 2)
|
||||||
|
log.Println("Data Length: ", binary.BigEndian.Uint16(dataLength))
|
||||||
|
|
||||||
|
}
|
|
@ -5,6 +5,7 @@
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev:tsc": "tsc --watch",
|
"dev:tsc": "tsc --watch",
|
||||||
|
"dev:nodemon:auth-go": "nodemon --watch ./ -e go --delay 200ms --exec 'go run *.go || exit 1' --signal SIGTERM",
|
||||||
"dev:nodemon:auth": "nodemon --watch ./dist --delay 200ms dist/src/main-auth.js",
|
"dev:nodemon:auth": "nodemon --watch ./dist --delay 200ms dist/src/main-auth.js",
|
||||||
"dev:nodemon:chat": "nodemon --watch ./dist --delay 200ms dist/src/main-chat.js",
|
"dev:nodemon:chat": "nodemon --watch ./dist --delay 200ms dist/src/main-chat.js",
|
||||||
"start": "tsc && node ./dist/index.js"
|
"start": "tsc && node ./dist/index.js"
|
||||||
|
|
44
util.go
Normal file
44
util.go
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
func prettyBytes(bytes []byte) string {
|
||||||
|
res := ""
|
||||||
|
hexStr := hex.EncodeToString(bytes)
|
||||||
|
for i := 0; i < len(hexStr); i++ {
|
||||||
|
if i > 0 && i%16 == 0 {
|
||||||
|
res += "\n"
|
||||||
|
} else if i > 0 && i%2 == 0 {
|
||||||
|
res += " "
|
||||||
|
}
|
||||||
|
res += string(hexStr[i])
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func printBytes(bytes []byte) {
|
||||||
|
fmt.Printf("%s\n", prettyBytes(bytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
func panicIfError(err error) {
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func readNBytes(buf *bytes.Buffer, n int) ([]byte, error) {
|
||||||
|
res := make([]byte, n)
|
||||||
|
_, err := io.ReadFull(buf, res)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func mustReadNBytes(buf *bytes.Buffer, n int) []byte {
|
||||||
|
res, err := readNBytes(buf, n)
|
||||||
|
panicIfError(err)
|
||||||
|
return res
|
||||||
|
}
|
Loading…
Reference in a new issue