Mike 2 лет назад
Родитель
Сommit
5bffaa5c55
6 измененных файлов с 54 добавлено и 30 удалено
  1. 26 20
      cmd/main.go
  2. 1 0
      go.mod
  3. 6 0
      go.sum
  4. 2 2
      oscar/bucp.go
  5. 4 4
      oscar/oservice.go
  6. 15 4
      oscar/protocol.go

+ 26 - 20
cmd/main.go

@@ -2,6 +2,7 @@ package main
 
 import (
 	"fmt"
+	"github.com/kelseyhightower/envconfig"
 	"github.com/mkaminski/goaim/oscar"
 	"io"
 	"log"
@@ -13,6 +14,12 @@ const testFile string = "/Users/mike/dev/goaim/aim.db"
 
 func main() {
 
+	var cfg oscar.Config
+	err := envconfig.Process("", &cfg)
+	if err != nil {
+		log.Fatal(err.Error())
+	}
+
 	fm, err := oscar.NewFeedbagStore(testFile)
 	if err != nil {
 		log.Fatal(err)
@@ -21,17 +28,16 @@ func main() {
 	sm := oscar.NewSessionManager()
 	cr := oscar.NewChatRegistry()
 
-	go listenBOS(sm, fm, cr)
-	go listenChat(fm, cr)
+	go listenBOS(cfg, sm, fm, cr)
+	go listenChat(cfg, fm, cr)
 
-	listener, err := net.Listen("tcp", ":5190")
+	listener, err := net.Listen("tcp", oscar.Address("", cfg.OSCARPort))
 	if err != nil {
 		log.Fatal(err)
 	}
-
 	defer listener.Close()
 
-	fmt.Println("Server is listening on port 5190")
+	fmt.Printf("OSCAR server listening on %s\n", oscar.Address(cfg.OSCARHost, cfg.OSCARPort))
 
 	for {
 		conn, err := listener.Accept()
@@ -40,7 +46,7 @@ func main() {
 			continue
 		}
 
-		go handleAuthConnection(sm, fm, conn)
+		go handleAuthConnection(cfg, sm, fm, conn)
 	}
 }
 
@@ -55,14 +61,14 @@ func webServer(ch chan string) {
 	}
 }
 
-func listenBOS(sm *oscar.SessionManager, fm *oscar.FeedbagStore, cr *oscar.ChatRegistry) {
-	listener, err := net.Listen("tcp", ":5191")
+func listenBOS(cfg oscar.Config, sm *oscar.SessionManager, fm *oscar.FeedbagStore, cr *oscar.ChatRegistry) {
+	listener, err := net.Listen("tcp", oscar.Address("", cfg.BOSPort))
 	if err != nil {
 		log.Fatal(err)
 	}
 	defer listener.Close()
 
-	fmt.Println("Server is listening on port 5191")
+	fmt.Printf("BOS server listening on %s\n", oscar.Address(cfg.OSCARHost, cfg.BOSPort))
 
 	for {
 		conn, err := listener.Accept()
@@ -70,18 +76,18 @@ func listenBOS(sm *oscar.SessionManager, fm *oscar.FeedbagStore, cr *oscar.ChatR
 			log.Println(err)
 			continue
 		}
-		go handleBOSConnection(sm, fm, cr, conn)
+		go handleBOSConnection(cfg, sm, fm, cr, conn)
 	}
 }
 
-func listenChat(fm *oscar.FeedbagStore, cr *oscar.ChatRegistry) {
-	listener, err := net.Listen("tcp", ":5192")
+func listenChat(cfg oscar.Config, fm *oscar.FeedbagStore, cr *oscar.ChatRegistry) {
+	listener, err := net.Listen("tcp", oscar.Address("", cfg.ChatPort))
 	if err != nil {
 		log.Fatal(err)
 	}
 	defer listener.Close()
 
-	fmt.Println("Server is listening on port 5192")
+	fmt.Printf("Chat server listening on %s\n", oscar.Address(cfg.OSCARHost, cfg.ChatPort))
 
 	for {
 		// Accept incoming connections
@@ -90,11 +96,11 @@ func listenChat(fm *oscar.FeedbagStore, cr *oscar.ChatRegistry) {
 			log.Println(err)
 			continue
 		}
-		go handleChatConnection(fm, cr, conn)
+		go handleChatConnection(cfg, fm, cr, conn)
 	}
 }
 
-func handleAuthConnection(sm *oscar.SessionManager, fm *oscar.FeedbagStore, conn net.Conn) {
+func handleAuthConnection(cfg oscar.Config, sm *oscar.SessionManager, fm *oscar.FeedbagStore, conn net.Conn) {
 	defer conn.Close()
 	seq := uint32(100)
 	_, err := oscar.SendAndReceiveSignonFrame(conn, &seq)
@@ -114,14 +120,14 @@ func handleAuthConnection(sm *oscar.SessionManager, fm *oscar.FeedbagStore, conn
 		return
 	}
 
-	err = oscar.ReceiveAndSendBUCPLoginRequest(sess, fm, conn, conn, &seq)
+	err = oscar.ReceiveAndSendBUCPLoginRequest(cfg, sess, fm, conn, conn, &seq)
 	if err != nil {
 		log.Println(err)
 		return
 	}
 }
 
-func handleBOSConnection(sm *oscar.SessionManager, fm *oscar.FeedbagStore, cr *oscar.ChatRegistry, conn net.Conn) {
+func handleBOSConnection(cfg oscar.Config, sm *oscar.SessionManager, fm *oscar.FeedbagStore, cr *oscar.ChatRegistry, conn net.Conn) {
 	defer conn.Close()
 
 	sess, seq, err := oscar.VerifyLogin(sm, conn)
@@ -142,7 +148,7 @@ func handleBOSConnection(sm *oscar.SessionManager, fm *oscar.FeedbagStore, cr *o
 	}
 
 	foodGroups := []uint16{0x0001, 0x0002, 0x0003, 0x0004, 0x0009, 0x0013, 0x000D}
-	if err := oscar.ReadBos(onClientReady, sess, seq, sm, fm, cr, conn, foodGroups); err != nil && err != io.EOF {
+	if err := oscar.ReadBos(cfg, onClientReady, sess, seq, sm, fm, cr, conn, foodGroups); err != nil && err != io.EOF {
 		if err != io.EOF {
 			fmt.Printf("user disconnected with error: %s\n", err.Error())
 		} else {
@@ -151,7 +157,7 @@ func handleBOSConnection(sm *oscar.SessionManager, fm *oscar.FeedbagStore, cr *o
 	}
 }
 
-func handleChatConnection(fm *oscar.FeedbagStore, cr *oscar.ChatRegistry, conn net.Conn) {
+func handleChatConnection(cfg oscar.Config, fm *oscar.FeedbagStore, cr *oscar.ChatRegistry, conn net.Conn) {
 	defer conn.Close()
 
 	cookie, seq, err := oscar.VerifyChatLogin(conn)
@@ -179,7 +185,7 @@ func handleChatConnection(fm *oscar.FeedbagStore, cr *oscar.ChatRegistry, conn n
 		return oscar.SetOnlineChatUsers(sm, w, sequence)
 	}
 
-	if err := oscar.ReadBos(onClientReady, chatSess, seq, room.SessionManager, fm, cr, conn, foodGroups); err != nil && err != io.EOF {
+	if err := oscar.ReadBos(cfg, onClientReady, chatSess, seq, room.SessionManager, fm, cr, conn, foodGroups); err != nil && err != io.EOF {
 		if err != io.EOF {
 			fmt.Printf("user disconnected with error: %s\n", err.Error())
 		} else {

+ 1 - 0
go.mod

@@ -4,5 +4,6 @@ go 1.20
 
 require (
 	github.com/google/uuid v1.3.0 // indirect
+	github.com/kelseyhightower/envconfig v1.4.0 // indirect
 	github.com/mattn/go-sqlite3 v1.14.17 // indirect
 )

+ 6 - 0
go.sum

@@ -0,0 +1,6 @@
+github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
+github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
+github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
+github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM=
+github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=

+ 2 - 2
oscar/bucp.go

@@ -124,7 +124,7 @@ func (s *snacBUCPLoginRequest) read(r io.Reader) error {
 	})
 }
 
-func ReceiveAndSendBUCPLoginRequest(sess *Session, fm *FeedbagStore, r io.Reader, w io.Writer, sequence *uint32) error {
+func ReceiveAndSendBUCPLoginRequest(cfg Config, sess *Session, fm *FeedbagStore, r io.Reader, w io.Writer, sequence *uint32) error {
 	flap := flapFrame{}
 	if err := flap.read(r); err != nil {
 		return err
@@ -180,7 +180,7 @@ func ReceiveAndSendBUCPLoginRequest(sess *Session, fm *FeedbagStore, r io.Reader
 				},
 				{
 					tType: 0x05,
-					val:   "192.168.64.1:5191",
+					val:   Address(cfg.OSCARHost, cfg.BOSPort),
 				},
 				{
 					tType: 0x06,

+ 4 - 4
oscar/oservice.go

@@ -49,7 +49,7 @@ const (
 	OServiceBartReply2               = 0x0023
 )
 
-func routeOService(ready OnReadyCB, wg *sync.WaitGroup, cr *ChatRegistry, sm *SessionManager, fm *FeedbagStore, sess *Session, flap flapFrame, snac *snacFrame, r io.Reader, w io.Writer, sequence *uint32) error {
+func routeOService(cfg Config, ready OnReadyCB, wg *sync.WaitGroup, cr *ChatRegistry, sm *SessionManager, fm *FeedbagStore, sess *Session, flap flapFrame, snac *snacFrame, r io.Reader, w io.Writer, sequence *uint32) error {
 	switch snac.subGroup {
 	case OServiceErr:
 		panic("not implemented")
@@ -60,7 +60,7 @@ func routeOService(ready OnReadyCB, wg *sync.WaitGroup, cr *ChatRegistry, sm *Se
 	case OServiceHostOnline:
 		panic("not implemented")
 	case OServiceServiceRequest:
-		return ReceiveAndSendServiceRequest(cr, sess, flap, snac, r, w, sequence)
+		return ReceiveAndSendServiceRequest(cfg, cr, sess, flap, snac, r, w, sequence)
 	case OServiceRateParamsQuery:
 		return ReceiveAndSendServiceRateParams(flap, snac, r, w, sequence)
 	case OServiceRateParamsSubAdd:
@@ -599,7 +599,7 @@ const (
 	OserviceTlvTagsSslState             = 0x8E
 )
 
-func ReceiveAndSendServiceRequest(cr *ChatRegistry, sess *Session, flap flapFrame, snac *snacFrame, r io.Reader, w io.Writer, sequence *uint32) error {
+func ReceiveAndSendServiceRequest(cfg Config, cr *ChatRegistry, sess *Session, flap flapFrame, snac *snacFrame, r io.Reader, w io.Writer, sequence *uint32) error {
 	fmt.Printf("receiveAndSendServiceRequest read SNAC frame: %+v\n", snac)
 
 	snacPayload := &snacServiceRequest{}
@@ -662,7 +662,7 @@ func ReceiveAndSendServiceRequest(cr *ChatRegistry, sess *Session, flap flapFram
 			TLVs: []*TLV{
 				{
 					tType: OserviceTlvTagsReconnectHere,
-					val:   "192.168.64.1:5192",
+					val:   Address(cfg.OSCARHost, cfg.ChatPort),
 				},
 				{
 					tType: OserviceTlvTagsLoginCookie,

+ 15 - 4
oscar/protocol.go

@@ -58,6 +58,17 @@ var (
 	CapChat, _ = uuid.MustParse("748F2420-6287-11D1-8222-444553540000").MarshalBinary()
 )
 
+type Config struct {
+	OSCARHost string `envconfig:"OSCAR_HOST" required:"true"`
+	OSCARPort int    `envconfig:"OSCAR_PORT" default:"5190"`
+	BOSPort   int    `envconfig:"BOS_PORT" default:"5191"`
+	ChatPort  int    `envconfig:"CHAT_PORT" default:"5192"`
+}
+
+func Address(host string, port int) string {
+	return fmt.Sprintf("%s:%d", host, port)
+}
+
 type snacError struct {
 	code uint16
 	TLVPayload
@@ -566,7 +577,7 @@ func Signout(sess *Session, sm *SessionManager, fm *FeedbagStore) {
 	sm.Remove(sess)
 }
 
-func ReadBos(ready OnReadyCB, sess *Session, seq uint32, sm *SessionManager, fm *FeedbagStore, cr *ChatRegistry, rwc io.ReadWriter, foodGroups []uint16) error {
+func ReadBos(cfg Config, ready OnReadyCB, sess *Session, seq uint32, sm *SessionManager, fm *FeedbagStore, cr *ChatRegistry, rwc io.ReadWriter, foodGroups []uint16) error {
 	if err := WriteOServiceHostOnline(foodGroups, rwc, &seq); err != nil {
 		return err
 	}
@@ -582,7 +593,7 @@ func ReadBos(ready OnReadyCB, sess *Session, seq uint32, sm *SessionManager, fm
 	for {
 		select {
 		case m := <-msgCh:
-			if err := routeIncomingRequests(ready, &wg, sm, sess, fm, cr, rwc, &seq, m.snac, m.flap, m.buf); err != nil {
+			if err := routeIncomingRequests(cfg, ready, &wg, sm, sess, fm, cr, rwc, &seq, m.snac, m.flap, m.buf); err != nil {
 				return err
 			}
 		case m := <-sess.RecvMessage():
@@ -596,10 +607,10 @@ func ReadBos(ready OnReadyCB, sess *Session, seq uint32, sm *SessionManager, fm
 	}
 }
 
-func routeIncomingRequests(ready OnReadyCB, wg *sync.WaitGroup, sm *SessionManager, sess *Session, fm *FeedbagStore, cr *ChatRegistry, rw io.ReadWriter, sequence *uint32, snac *snacFrame, flap flapFrame, buf io.Reader) error {
+func routeIncomingRequests(cfg Config, ready OnReadyCB, wg *sync.WaitGroup, sm *SessionManager, sess *Session, fm *FeedbagStore, cr *ChatRegistry, rw io.ReadWriter, sequence *uint32, snac *snacFrame, flap flapFrame, buf io.Reader) error {
 	switch snac.foodGroup {
 	case OSERVICE:
-		if err := routeOService(ready, wg, cr, sm, fm, sess, flap, snac, buf, rw, sequence); err != nil {
+		if err := routeOService(cfg, ready, wg, cr, sm, fm, sess, flap, snac, buf, rw, sequence); err != nil {
 			return err
 		}
 	case LOCATE: