mirror of
https://github.com/amigan/aim-oscar-server.git
synced 2024-11-22 04:29: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
|
||||||
|
}
|
56
main.go
56
main.go
|
@ -1,9 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
|
@ -19,21 +17,10 @@ const (
|
||||||
SRV_ADDRESS = SRV_HOST + ":" + SRV_PORT
|
SRV_ADDRESS = SRV_HOST + ":" + SRV_PORT
|
||||||
)
|
)
|
||||||
|
|
||||||
type Session struct {
|
var services = make(map[uint16]Service)
|
||||||
Conn net.Conn
|
|
||||||
GreetedClient bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewSession(conn net.Conn) *Session {
|
func init() {
|
||||||
return &Session{
|
services[0x17] = &AuthorizationRegistrationService{}
|
||||||
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() {
|
func main() {
|
||||||
|
@ -69,7 +56,9 @@ func main() {
|
||||||
|
|
||||||
func handleTCPConnection(ctx context.Context, conn net.Conn) {
|
func handleTCPConnection(ctx context.Context, conn net.Conn) {
|
||||||
defer (func() {
|
defer (func() {
|
||||||
recover()
|
if r := recover(); r != nil {
|
||||||
|
log.Println("Error handling message: ", r.(error).Error())
|
||||||
|
}
|
||||||
conn.Close()
|
conn.Close()
|
||||||
log.Printf("Closed connection to %v", conn.RemoteAddr())
|
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)
|
session := ctx.Value("session").(*Session)
|
||||||
if !session.GreetedClient {
|
if !session.GreetedClient {
|
||||||
// send a hello
|
// send a hello
|
||||||
hello := []byte{0x2a, 1, 0, 0, 0, 4, 0, 0, 0, 1}
|
hello := NewFLAP(ctx, 1, []byte{0, 0, 0, 1})
|
||||||
session.Send(hello)
|
err := session.Send(hello)
|
||||||
|
panicIfError(err)
|
||||||
session.GreetedClient = true
|
session.GreetedClient = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,26 +90,18 @@ func handleTCPConnection(ctx context.Context, conn net.Conn) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMessage(ctx context.Context, buf []byte) {
|
func handleMessage(ctx context.Context, buf []byte) {
|
||||||
messageBuf := bytes.NewBuffer(buf)
|
flap := &FLAP{}
|
||||||
|
flap.UnmarshalBinary(buf)
|
||||||
|
|
||||||
start, err := messageBuf.ReadByte()
|
if flap.Header.Channel == 1 {
|
||||||
|
|
||||||
|
} else if flap.Header.Channel == 2 {
|
||||||
|
snac := &SNAC{}
|
||||||
|
err := snac.UnmarshalBinary(flap.Data)
|
||||||
panicIfError(err)
|
panicIfError(err)
|
||||||
if start != 0x2a {
|
|
||||||
log.Println("FLAP message missing leading 0x2a")
|
if service, ok := services[snac.Header.Family]; ok {
|
||||||
return
|
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