mirror of
https://github.com/amigan/aim-oscar-server.git
synced 2024-11-21 20:19:47 -05:00
figuring out FLAP, SNAC, marshal/unmarshaling
This commit is contained in:
parent
a23cdd7092
commit
5cf4d9dfcc
6 changed files with 212 additions and 39 deletions
22
0x17_authorization_registration_service.go
Normal file
22
0x17_authorization_registration_service.go
Normal file
|
@ -0,0 +1,22 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var cipher = "hey wassup"
|
||||
|
||||
type AuthorizationRegistrationService struct{}
|
||||
|
||||
func (a *AuthorizationRegistrationService) HandleSNAC(ctx context.Context, snac *SNAC) {
|
||||
// Request MD5 Auth Key
|
||||
if snac.Header.Subtype == 0x06 {
|
||||
fmt.Println("damn it's 0x06")
|
||||
// cipherData := ByteString(cipher) // []byte
|
||||
|
||||
// snac := NewSNAC(0x17, 0x07, cipherData)
|
||||
|
||||
// resp := NewFLAP(2, snac)
|
||||
}
|
||||
}
|
70
flap.go
Normal file
70
flap.go
Normal file
|
@ -0,0 +1,70 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var _ encoding.BinaryUnmarshaler = &FLAP{}
|
||||
var _ encoding.BinaryMarshaler = &FLAP{}
|
||||
|
||||
type FLAPHeader struct {
|
||||
Channel uint8
|
||||
SequenceNumber uint16
|
||||
DataLength uint16
|
||||
}
|
||||
|
||||
type FLAP struct {
|
||||
Header FLAPHeader
|
||||
Data []byte
|
||||
}
|
||||
|
||||
func NewFLAP(ctx context.Context, channel uint8, data []byte) *FLAP {
|
||||
session := ctx.Value("session").(*Session)
|
||||
session.SequenceNumber += 1
|
||||
|
||||
return &FLAP{
|
||||
Header: FLAPHeader{
|
||||
Channel: channel,
|
||||
SequenceNumber: uint16(session.SequenceNumber),
|
||||
DataLength: uint16(len(data)),
|
||||
},
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
|
||||
func (f *FLAP) UnmarshalBinary(data []byte) error {
|
||||
buf := bytes.NewBuffer(data)
|
||||
start, err := buf.ReadByte()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if start != 0x2a {
|
||||
return fmt.Errorf("FLAP missing 0x2a header")
|
||||
}
|
||||
|
||||
if err = binary.Read(buf, binary.BigEndian, &f.Header); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
f.Data = buf.Bytes()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *FLAP) MarshalBinary() ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
buf.WriteByte(0x2a)
|
||||
binary.Write(&buf, binary.BigEndian, f.Header)
|
||||
n, err := buf.Write(f.Data)
|
||||
if n != int(f.Header.DataLength) {
|
||||
return nil, fmt.Errorf("needed to write %d bytes to buffer but wrote %d", f.Header.DataLength, n)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
60
main.go
60
main.go
|
@ -1,9 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
|
@ -19,21 +17,10 @@ const (
|
|||
SRV_ADDRESS = SRV_HOST + ":" + SRV_PORT
|
||||
)
|
||||
|
||||
type Session struct {
|
||||
Conn net.Conn
|
||||
GreetedClient bool
|
||||
}
|
||||
var services = make(map[uint16]Service)
|
||||
|
||||
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 init() {
|
||||
services[0x17] = &AuthorizationRegistrationService{}
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
@ -69,7 +56,9 @@ func main() {
|
|||
|
||||
func handleTCPConnection(ctx context.Context, conn net.Conn) {
|
||||
defer (func() {
|
||||
recover()
|
||||
if r := recover(); r != nil {
|
||||
log.Println("Error handling message: ", r.(error).Error())
|
||||
}
|
||||
conn.Close()
|
||||
log.Printf("Closed connection to %v", conn.RemoteAddr())
|
||||
})()
|
||||
|
@ -79,8 +68,9 @@ func handleTCPConnection(ctx context.Context, conn net.Conn) {
|
|||
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)
|
||||
hello := NewFLAP(ctx, 1, []byte{0, 0, 0, 1})
|
||||
err := session.Send(hello)
|
||||
panicIfError(err)
|
||||
session.GreetedClient = true
|
||||
}
|
||||
|
||||
|
@ -100,26 +90,18 @@ func handleTCPConnection(ctx context.Context, conn net.Conn) {
|
|||
}
|
||||
|
||||
func handleMessage(ctx context.Context, buf []byte) {
|
||||
messageBuf := bytes.NewBuffer(buf)
|
||||
flap := &FLAP{}
|
||||
flap.UnmarshalBinary(buf)
|
||||
|
||||
start, err := messageBuf.ReadByte()
|
||||
panicIfError(err)
|
||||
if start != 0x2a {
|
||||
log.Println("FLAP message missing leading 0x2a")
|
||||
return
|
||||
if flap.Header.Channel == 1 {
|
||||
|
||||
} else if flap.Header.Channel == 2 {
|
||||
snac := &SNAC{}
|
||||
err := snac.UnmarshalBinary(flap.Data)
|
||||
panicIfError(err)
|
||||
|
||||
if service, ok := services[snac.Header.Family]; ok {
|
||||
service.HandleSNAC(ctx, snac)
|
||||
}
|
||||
}
|
||||
|
||||
type FLAP struct {
|
||||
Channel uint8
|
||||
SequenceNumber uint16
|
||||
DataLength uint16
|
||||
}
|
||||
|
||||
flap := FLAP{}
|
||||
panicIfError(binary.Read(messageBuf, binary.BigEndian, &flap))
|
||||
|
||||
// Start parsing FLAP header
|
||||
log.Println("Message for channel: ", flap.Channel)
|
||||
log.Println("Datagram Sequence Number: ", flap.SequenceNumber)
|
||||
log.Println("Data Length: ", flap.DataLength)
|
||||
}
|
||||
|
|
9
service.go
Normal file
9
service.go
Normal file
|
@ -0,0 +1,9 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
type Service interface {
|
||||
HandleSNAC(context.Context, *SNAC)
|
||||
}
|
32
session.go
Normal file
32
session.go
Normal file
|
@ -0,0 +1,32 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"fmt"
|
||||
"net"
|
||||
)
|
||||
|
||||
type Session struct {
|
||||
Conn net.Conn
|
||||
SequenceNumber uint16
|
||||
GreetedClient bool
|
||||
}
|
||||
|
||||
func NewSession(conn net.Conn) *Session {
|
||||
return &Session{
|
||||
Conn: conn,
|
||||
SequenceNumber: 0,
|
||||
GreetedClient: false,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Session) Send(m encoding.BinaryMarshaler) error {
|
||||
bytes, err := m.MarshalBinary()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("-> %v\n%s\n\n", s.Conn.RemoteAddr(), prettyBytes(bytes))
|
||||
_, err = s.Conn.Write(bytes)
|
||||
return err
|
||||
}
|
58
snac.go
Normal file
58
snac.go
Normal file
|
@ -0,0 +1,58 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type SNACHeader struct {
|
||||
Family uint16
|
||||
Subtype uint16
|
||||
Flags uint16
|
||||
RequestID uint16
|
||||
}
|
||||
|
||||
type SNAC struct {
|
||||
Header SNACHeader
|
||||
Data []byte
|
||||
}
|
||||
|
||||
func NewSNAC(family uint16, subtype uint16, data []byte) *SNAC {
|
||||
return &SNAC{
|
||||
Header: SNACHeader{
|
||||
Family: family,
|
||||
Subtype: subtype,
|
||||
Flags: 0,
|
||||
RequestID: 0,
|
||||
},
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SNAC) MarshalBinary() ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
|
||||
binary.Write(&buf, binary.BigEndian, s.Header)
|
||||
n, err := buf.Write(s.Data)
|
||||
if n != len(s.Data) {
|
||||
return nil, fmt.Errorf("needed to write %d bytes to buffer but wrote %d", len(s.Data), n)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func (s *SNAC) UnmarshalBinary(data []byte) error {
|
||||
buf := bytes.NewBuffer(data)
|
||||
|
||||
if err := binary.Read(buf, binary.BigEndian, &s.Header); s != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.Data = buf.Bytes()
|
||||
|
||||
return nil
|
||||
}
|
Loading…
Reference in a new issue