Skip to content

Commit

Permalink
Merge pull request #47 from jgknight/fix-missing-chatroom-disconnect
Browse files Browse the repository at this point in the history
Fix missing chatroom disconnect
  • Loading branch information
mk6i authored Jul 1, 2024
2 parents ca2b8e5 + 23cbee7 commit 107c6d3
Show file tree
Hide file tree
Showing 4 changed files with 557 additions and 57 deletions.
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,21 @@ This request lists sessions for all logged in users.
Invoke-WebRequest -Uri http://localhost:8080/session -Method Get
```

#### Create Public Chat Room

```powershell
Invoke-WebRequest -Uri http://localhost:8080/chat/room/public `
-Body '{"name":"Office Hijinks"}' `
-Method Post `
-ContentType "application/json"
```

#### List Public Chat Rooms

```powershell
Invoke-WebRequest -Uri http://localhost:8080/chat/room/public -Method Get
```

### macOS / Linux

#### List Users
Expand Down Expand Up @@ -131,6 +146,18 @@ This request lists sessions for all logged in users.
curl http://localhost:8080/session
```

#### Create Public Chat Room

```shell
curl -d'{"name":"Office Hijinks"}' http://localhost:8080/chat/room/public
```

#### List Public Chat Rooms

```shell
curl http://localhost:8080/chat/room/public
```

## 🔗 Acknowledgements

- [aim-oscar-server](https://github.com/ox/aim-oscar-server) is another cool open source AIM server project.
Expand Down
46 changes: 34 additions & 12 deletions foodgroup/chat_nav.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ var defaultExchangeCfg = wire.TLVBlock{
},
}

var (
errChatNavRoomNameMissing = errors.New("unable to find chat name in TLV payload")
errChatNavRoomCreateFailed = errors.New("unable to create chat room")
errChatNavRetrieveFailed = errors.New("unable to retrieve chat room chat room")
errChatNavMismatchedExchange = errors.New("chat room exchange does not match requested exchange")
)

// NewChatNavService creates a new instance of NewChatNavService.
func NewChatNavService(logger *slog.Logger, chatRoomManager ChatRoomRegistry, fnNewChatRoom func() state.ChatRoom) *ChatNavService {
return &ChatNavService{
Expand Down Expand Up @@ -73,15 +80,16 @@ func (s ChatNavService) RequestChatRights(_ context.Context, inFrame wire.SNACFr
// chat room.
func (s ChatNavService) CreateRoom(_ context.Context, sess *state.Session, inFrame wire.SNACFrame, inBody wire.SNAC_0x0E_0x02_ChatRoomInfoUpdate) (wire.SNACMessage, error) {
if err := validateExchange(inBody.Exchange); err != nil {
return wire.SNACMessage{}, err
s.logger.Debug("error validating exchange: " + err.Error())
return sendChatNavErrorSNAC(inFrame, wire.ErrorCodeNotSupportedByHost)
}
if inBody.Cookie != "create" {
s.logger.Info("got a non-create cookie", "value", inBody.Cookie)
}

name, hasName := inBody.String(wire.ChatRoomTLVRoomName)
if !hasName {
return wire.SNACMessage{}, errors.New("unable to find chat name in TLV payload")
return wire.SNACMessage{}, errChatNavRoomNameMissing
}

// todo call ChatRoomByName and CreateChatRoom in a txn
Expand All @@ -90,8 +98,8 @@ func (s ChatNavService) CreateRoom(_ context.Context, sess *state.Session, inFra
switch {
case errors.Is(err, state.ErrChatRoomNotFound):
if inBody.Exchange == state.PublicExchange {
return wire.SNACMessage{}, fmt.Errorf("community chat rooms can only be created on exchange %d",
state.PrivateExchange)
s.logger.Debug(fmt.Sprintf("public chat room not found: %s:%d", name, inBody.Exchange))
return sendChatNavErrorSNAC(inFrame, wire.ErrorCodeNoMatch)
}

room = s.fnNewChatRoom()
Expand All @@ -102,14 +110,12 @@ func (s ChatNavService) CreateRoom(_ context.Context, sess *state.Session, inFra
room.Name = name

if err := s.chatRoomManager.CreateChatRoom(room); err != nil {
return wire.SNACMessage{}, fmt.Errorf("unable to create chat room: %w", err)
return wire.SNACMessage{}, fmt.Errorf("%w: %w", errChatNavRoomCreateFailed, err)
}
break
case err != nil:
return wire.SNACMessage{}, fmt.Errorf("unable to retrieve chat room chat room %s on exchange %d: %w",
name, inBody.Exchange, err)
return wire.SNACMessage{}, fmt.Errorf("%w: %w", errChatNavRetrieveFailed, err)
}

return wire.SNACMessage{
Frame: wire.SNACFrame{
FoodGroup: wire.ChatNav,
Expand Down Expand Up @@ -138,16 +144,17 @@ func (s ChatNavService) CreateRoom(_ context.Context, sess *state.Session, inFra
// the chat room specified in the inFrame.hmacCookie.
func (s ChatNavService) RequestRoomInfo(_ context.Context, inFrame wire.SNACFrame, inBody wire.SNAC_0x0D_0x04_ChatNavRequestRoomInfo) (wire.SNACMessage, error) {
if err := validateExchange(inBody.Exchange); err != nil {
return wire.SNACMessage{}, err
s.logger.Debug("error validating exchange: " + err.Error())
return sendChatNavErrorSNAC(inFrame, wire.ErrorCodeNotSupportedByHost)
}

room, err := s.chatRoomManager.ChatRoomByCookie(inBody.Cookie)
if err != nil {
return wire.SNACMessage{}, fmt.Errorf("unable to find chat room: %w", err)
return wire.SNACMessage{}, fmt.Errorf("%w: %w", state.ErrChatRoomNotFound, err)
}

if room.Exchange != inBody.Exchange {
return wire.SNACMessage{}, errors.New("chat room exchange does not match requested exchange")
return wire.SNACMessage{}, errChatNavMismatchedExchange
}

return wire.SNACMessage{
Expand Down Expand Up @@ -176,7 +183,8 @@ func (s ChatNavService) RequestRoomInfo(_ context.Context, inFrame wire.SNACFram

func (s ChatNavService) ExchangeInfo(_ context.Context, inFrame wire.SNACFrame, inBody wire.SNAC_0x0D_0x03_ChatNavRequestExchangeInfo) (wire.SNACMessage, error) {
if err := validateExchange(inBody.Exchange); err != nil {
return wire.SNACMessage{}, err
s.logger.Debug("error validating exchange: " + err.Error())
return sendChatNavErrorSNAC(inFrame, wire.ErrorCodeNotSupportedByHost)
}
return wire.SNACMessage{
Frame: wire.SNACFrame{
Expand All @@ -198,6 +206,20 @@ func (s ChatNavService) ExchangeInfo(_ context.Context, inFrame wire.SNACFrame,
}, nil
}

// sendChatNavErrorSNAC returns a ChatNavErr SNAC and logs an error for the operator
func sendChatNavErrorSNAC(inFrame wire.SNACFrame, errorCode uint16) (wire.SNACMessage, error) {
return wire.SNACMessage{
Frame: wire.SNACFrame{
FoodGroup: wire.ChatNav,
SubGroup: wire.ChatNavErr,
RequestID: inFrame.RequestID,
},
Body: wire.SNACError{
Code: errorCode,
},
}, nil
}

func validateExchange(exchange uint16) error {
if !(exchange == state.PrivateExchange || exchange == state.PublicExchange) {
return fmt.Errorf("only exchanges %d and %d are supported", state.PrivateExchange, state.PublicExchange)
Expand Down
Loading

0 comments on commit 107c6d3

Please sign in to comment.