Make response waiting less hacky
This commit is contained in:
parent
50c2d45316
commit
10affb59b1
9 changed files with 126 additions and 248 deletions
|
@ -47,7 +47,7 @@ type Client struct {
|
||||||
|
|
||||||
func NewClient(authData *AuthData, logger zerolog.Logger) *Client {
|
func NewClient(authData *AuthData, logger zerolog.Logger) *Client {
|
||||||
sessionHandler := &SessionHandler{
|
sessionHandler := &SessionHandler{
|
||||||
requests: make(map[string]map[binary.ActionType]*ResponseChan),
|
responseWaiters: make(map[string]chan<- *pblite.Response),
|
||||||
responseTimeout: time.Duration(5000) * time.Millisecond,
|
responseTimeout: time.Duration(5000) * time.Millisecond,
|
||||||
}
|
}
|
||||||
if authData == nil {
|
if authData == nil {
|
||||||
|
|
|
@ -15,12 +15,7 @@ func (c *Client) ListConversations(count int64, folder binary.ListConversationsP
|
||||||
//} else {
|
//} else {
|
||||||
actionType := binary.ActionType_LIST_CONVERSATIONS
|
actionType := binary.ActionType_LIST_CONVERSATIONS
|
||||||
|
|
||||||
sentRequestId, sendErr := c.sessionHandler.completeSendMessage(actionType, true, payload)
|
response, err := c.sessionHandler.sendMessage(actionType, payload)
|
||||||
if sendErr != nil {
|
|
||||||
return nil, sendErr
|
|
||||||
}
|
|
||||||
|
|
||||||
response, err := c.sessionHandler.WaitForResponse(sentRequestId, actionType)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -37,12 +32,7 @@ func (c *Client) GetConversationType(conversationID string) (*binary.GetConversa
|
||||||
payload := &binary.ConversationTypePayload{ConversationID: conversationID}
|
payload := &binary.ConversationTypePayload{ConversationID: conversationID}
|
||||||
actionType := binary.ActionType_GET_CONVERSATION_TYPE
|
actionType := binary.ActionType_GET_CONVERSATION_TYPE
|
||||||
|
|
||||||
sentRequestId, sendErr := c.sessionHandler.completeSendMessage(actionType, true, payload)
|
response, err := c.sessionHandler.sendMessage(actionType, payload)
|
||||||
if sendErr != nil {
|
|
||||||
return nil, sendErr
|
|
||||||
}
|
|
||||||
|
|
||||||
response, err := c.sessionHandler.WaitForResponse(sentRequestId, actionType)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -63,12 +53,7 @@ func (c *Client) FetchMessages(conversationID string, count int64, cursor *binar
|
||||||
|
|
||||||
actionType := binary.ActionType_LIST_MESSAGES
|
actionType := binary.ActionType_LIST_MESSAGES
|
||||||
|
|
||||||
sentRequestId, sendErr := c.sessionHandler.completeSendMessage(actionType, true, payload)
|
response, err := c.sessionHandler.sendMessage(actionType, payload)
|
||||||
if sendErr != nil {
|
|
||||||
return nil, sendErr
|
|
||||||
}
|
|
||||||
|
|
||||||
response, err := c.sessionHandler.WaitForResponse(sentRequestId, actionType)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -84,12 +69,7 @@ func (c *Client) FetchMessages(conversationID string, count int64, cursor *binar
|
||||||
func (c *Client) SendMessage(payload *binary.SendMessagePayload) (*binary.SendMessageResponse, error) {
|
func (c *Client) SendMessage(payload *binary.SendMessagePayload) (*binary.SendMessageResponse, error) {
|
||||||
actionType := binary.ActionType_SEND_MESSAGE
|
actionType := binary.ActionType_SEND_MESSAGE
|
||||||
|
|
||||||
sentRequestId, sendErr := c.sessionHandler.completeSendMessage(actionType, true, payload)
|
response, err := c.sessionHandler.sendMessage(actionType, payload)
|
||||||
if sendErr != nil {
|
|
||||||
return nil, sendErr
|
|
||||||
}
|
|
||||||
|
|
||||||
response, err := c.sessionHandler.WaitForResponse(sentRequestId, actionType)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -106,12 +86,7 @@ func (c *Client) GetParticipantThumbnail(convID string) (*binary.ParticipantThum
|
||||||
payload := &binary.GetParticipantThumbnailPayload{ConversationID: convID}
|
payload := &binary.GetParticipantThumbnailPayload{ConversationID: convID}
|
||||||
actionType := binary.ActionType_GET_PARTICIPANTS_THUMBNAIL
|
actionType := binary.ActionType_GET_PARTICIPANTS_THUMBNAIL
|
||||||
|
|
||||||
sentRequestId, sendErr := c.sessionHandler.completeSendMessage(actionType, true, payload)
|
response, err := c.sessionHandler.sendMessage(actionType, payload)
|
||||||
if sendErr != nil {
|
|
||||||
return nil, sendErr
|
|
||||||
}
|
|
||||||
|
|
||||||
response, err := c.sessionHandler.WaitForResponse(sentRequestId, actionType)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -134,12 +109,7 @@ func (c *Client) UpdateConversation(convBuilder *ConversationBuilder) (*binary.U
|
||||||
|
|
||||||
actionType := binary.ActionType_UPDATE_CONVERSATION
|
actionType := binary.ActionType_UPDATE_CONVERSATION
|
||||||
|
|
||||||
sentRequestId, sendErr := c.sessionHandler.completeSendMessage(actionType, true, payload)
|
response, err := c.sessionHandler.sendMessage(actionType, payload)
|
||||||
if sendErr != nil {
|
|
||||||
return nil, sendErr
|
|
||||||
}
|
|
||||||
|
|
||||||
response, err := c.sessionHandler.WaitForResponse(sentRequestId, actionType)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -156,14 +126,6 @@ func (c *Client) SetTyping(convID string) error {
|
||||||
payload := &binary.TypingUpdatePayload{Data: &binary.SetTypingIn{ConversationID: convID, Typing: true}}
|
payload := &binary.TypingUpdatePayload{Data: &binary.SetTypingIn{ConversationID: convID, Typing: true}}
|
||||||
actionType := binary.ActionType_TYPING_UPDATES
|
actionType := binary.ActionType_TYPING_UPDATES
|
||||||
|
|
||||||
sentRequestId, sendErr := c.sessionHandler.completeSendMessage(actionType, true, payload)
|
_, err := c.sessionHandler.sendMessage(actionType, payload)
|
||||||
if sendErr != nil {
|
return err
|
||||||
return sendErr
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := c.sessionHandler.WaitForResponse(sentRequestId, actionType)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,34 +52,33 @@ func (r *RPC) HandleRPCMsg(msg *binary.InternalMessage) {
|
||||||
r.client.Logger.Error().Msg("nil response in rpc handler")
|
r.client.Logger.Error().Msg("nil response in rpc handler")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_, waitingForResponse := r.client.sessionHandler.requests[response.Data.RequestId]
|
|
||||||
|
|
||||||
r.client.sessionHandler.addResponseAck(response.ResponseId)
|
r.client.sessionHandler.queueMessageAck(response.ResponseID)
|
||||||
if waitingForResponse {
|
if r.client.sessionHandler.receiveResponse(response) {
|
||||||
r.client.sessionHandler.respondToRequestChannel(response)
|
r.client.Logger.Debug().Str("request_id", response.Data.RequestID).Msg("Received response")
|
||||||
} else {
|
return
|
||||||
switch response.BugleRoute {
|
}
|
||||||
case binary.BugleRoute_PairEvent:
|
switch response.BugleRoute {
|
||||||
go r.client.handlePairingEvent(response)
|
case binary.BugleRoute_PairEvent:
|
||||||
case binary.BugleRoute_DataEvent:
|
go r.client.handlePairingEvent(response)
|
||||||
if r.skipCount > 0 {
|
case binary.BugleRoute_DataEvent:
|
||||||
r.skipCount--
|
if r.skipCount > 0 {
|
||||||
r.client.Logger.Debug().
|
r.skipCount--
|
||||||
Any("action", response.Data.Action).
|
r.client.Logger.Debug().
|
||||||
Any("toSkip", r.skipCount).
|
Any("action", response.Data.Action).
|
||||||
Msg("Skipped DataEvent")
|
Int("remaining_skip_count", r.skipCount).
|
||||||
if response.Data.Decrypted != nil {
|
Msg("Skipped DataEvent")
|
||||||
r.client.Logger.Trace().
|
if response.Data.Decrypted != nil {
|
||||||
Str("proto_name", string(response.Data.Decrypted.ProtoReflect().Descriptor().FullName())).
|
r.client.Logger.Trace().
|
||||||
Str("data", base64.StdEncoding.EncodeToString(response.Data.RawDecrypted)).
|
Str("proto_name", string(response.Data.Decrypted.ProtoReflect().Descriptor().FullName())).
|
||||||
Msg("Skipped event data")
|
Str("data", base64.StdEncoding.EncodeToString(response.Data.RawDecrypted)).
|
||||||
}
|
Msg("Skipped event data")
|
||||||
return
|
|
||||||
}
|
}
|
||||||
r.client.handleUpdatesEvent(response)
|
return
|
||||||
default:
|
|
||||||
r.client.Logger.Debug().Any("res", response).Msg("Got unknown bugleroute")
|
|
||||||
}
|
}
|
||||||
|
r.client.handleUpdatesEvent(response)
|
||||||
|
default:
|
||||||
|
r.client.Logger.Debug().Any("res", response).Msg("Got unknown bugleroute")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,12 +9,7 @@ import (
|
||||||
func (c *Client) SendReaction(payload *binary.SendReactionPayload) (*binary.SendReactionResponse, error) {
|
func (c *Client) SendReaction(payload *binary.SendReactionPayload) (*binary.SendReactionResponse, error) {
|
||||||
actionType := binary.ActionType_SEND_REACTION
|
actionType := binary.ActionType_SEND_REACTION
|
||||||
|
|
||||||
sentRequestId, sendErr := c.sessionHandler.completeSendMessage(actionType, true, payload)
|
response, err := c.sessionHandler.sendMessage(actionType, payload)
|
||||||
if sendErr != nil {
|
|
||||||
return nil, sendErr
|
|
||||||
}
|
|
||||||
|
|
||||||
response, err := c.sessionHandler.WaitForResponse(sentRequestId, actionType)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -31,12 +26,7 @@ func (c *Client) DeleteMessage(messageID string) (*binary.DeleteMessageResponse,
|
||||||
payload := &binary.DeleteMessagePayload{MessageID: messageID}
|
payload := &binary.DeleteMessagePayload{MessageID: messageID}
|
||||||
actionType := binary.ActionType_DELETE_MESSAGE
|
actionType := binary.ActionType_DELETE_MESSAGE
|
||||||
|
|
||||||
sentRequestId, sendErr := c.sessionHandler.completeSendMessage(actionType, true, payload)
|
response, err := c.sessionHandler.sendMessage(actionType, payload)
|
||||||
if sendErr != nil {
|
|
||||||
return nil, sendErr
|
|
||||||
}
|
|
||||||
|
|
||||||
response, err := c.sessionHandler.WaitForResponse(sentRequestId, actionType)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -53,15 +43,6 @@ func (c *Client) MarkRead(conversationID, messageID string) error {
|
||||||
payload := &binary.MessageReadPayload{ConversationID: conversationID, MessageID: messageID}
|
payload := &binary.MessageReadPayload{ConversationID: conversationID, MessageID: messageID}
|
||||||
actionType := binary.ActionType_MESSAGE_READ
|
actionType := binary.ActionType_MESSAGE_READ
|
||||||
|
|
||||||
sentRequestId, sendErr := c.sessionHandler.completeSendMessage(actionType, true, payload)
|
_, err := c.sessionHandler.sendMessage(actionType, payload)
|
||||||
if sendErr != nil {
|
return err
|
||||||
return sendErr
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := c.sessionHandler.WaitForResponse(sentRequestId, actionType)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ type DevicePair struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type RequestData struct {
|
type RequestData struct {
|
||||||
RequestId string `json:"requestId,omitempty"`
|
RequestID string `json:"requestId,omitempty"`
|
||||||
Timestamp int64 `json:"timestamp,omitempty"`
|
Timestamp int64 `json:"timestamp,omitempty"`
|
||||||
Action binary.ActionType `json:"action,omitempty"`
|
Action binary.ActionType `json:"action,omitempty"`
|
||||||
Bool1 bool `json:"bool1,omitempty"`
|
Bool1 bool `json:"bool1,omitempty"`
|
||||||
|
@ -27,7 +27,7 @@ type RequestData struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Response struct {
|
type Response struct {
|
||||||
ResponseId string `json:"responseId,omitempty"`
|
ResponseID string `json:"responseId,omitempty"`
|
||||||
BugleRoute binary.BugleRoute `json:"bugleRoute,omitempty"`
|
BugleRoute binary.BugleRoute `json:"bugleRoute,omitempty"`
|
||||||
StartExecute string `json:"startExecute,omitempty"`
|
StartExecute string `json:"startExecute,omitempty"`
|
||||||
MessageType binary.MessageType `json:"eventType,omitempty"`
|
MessageType binary.MessageType `json:"eventType,omitempty"`
|
||||||
|
@ -76,7 +76,7 @@ func DecryptInternalMessage(internalMessage *binary.InternalMessage, cryptor *cr
|
||||||
|
|
||||||
func newResponseFromPairEvent(internalMsg *binary.InternalMessageData, data *binary.PairEvents) *Response {
|
func newResponseFromPairEvent(internalMsg *binary.InternalMessageData, data *binary.PairEvents) *Response {
|
||||||
resp := &Response{
|
resp := &Response{
|
||||||
ResponseId: internalMsg.GetResponseID(),
|
ResponseID: internalMsg.GetResponseID(),
|
||||||
BugleRoute: internalMsg.GetBugleRoute(),
|
BugleRoute: internalMsg.GetBugleRoute(),
|
||||||
StartExecute: internalMsg.GetStartExecute(),
|
StartExecute: internalMsg.GetStartExecute(),
|
||||||
MessageType: internalMsg.GetMessageType(),
|
MessageType: internalMsg.GetMessageType(),
|
||||||
|
@ -98,7 +98,7 @@ func newResponseFromPairEvent(internalMsg *binary.InternalMessageData, data *bin
|
||||||
|
|
||||||
func newResponseFromDataEvent(internalMsg *binary.InternalMessageData, internalRequestData *binary.InternalRequestData, rawData []byte, decrypted protoreflect.ProtoMessage) *Response {
|
func newResponseFromDataEvent(internalMsg *binary.InternalMessageData, internalRequestData *binary.InternalRequestData, rawData []byte, decrypted protoreflect.ProtoMessage) *Response {
|
||||||
resp := &Response{
|
resp := &Response{
|
||||||
ResponseId: internalMsg.GetResponseID(),
|
ResponseID: internalMsg.GetResponseID(),
|
||||||
BugleRoute: internalMsg.GetBugleRoute(),
|
BugleRoute: internalMsg.GetBugleRoute(),
|
||||||
StartExecute: internalMsg.GetStartExecute(),
|
StartExecute: internalMsg.GetStartExecute(),
|
||||||
MessageType: internalMsg.GetMessageType(),
|
MessageType: internalMsg.GetMessageType(),
|
||||||
|
@ -109,7 +109,7 @@ func newResponseFromDataEvent(internalMsg *binary.InternalMessageData, internalR
|
||||||
Browser: internalMsg.GetBrowser(),
|
Browser: internalMsg.GetBrowser(),
|
||||||
},
|
},
|
||||||
Data: RequestData{
|
Data: RequestData{
|
||||||
RequestId: internalRequestData.GetSessionID(),
|
RequestID: internalRequestData.GetSessionID(),
|
||||||
Timestamp: internalRequestData.GetTimestamp(),
|
Timestamp: internalRequestData.GetTimestamp(),
|
||||||
Action: internalRequestData.GetAction(),
|
Action: internalRequestData.GetAction(),
|
||||||
Bool1: internalRequestData.GetBool1(),
|
Bool1: internalRequestData.GetBool1(),
|
||||||
|
|
|
@ -1,99 +1,48 @@
|
||||||
package libgm
|
package libgm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
|
||||||
|
|
||||||
"go.mau.fi/mautrix-gmessages/libgm/pblite"
|
"go.mau.fi/mautrix-gmessages/libgm/pblite"
|
||||||
|
|
||||||
"go.mau.fi/mautrix-gmessages/libgm/binary"
|
|
||||||
"go.mau.fi/mautrix-gmessages/libgm/routes"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ResponseChan struct {
|
func (s *SessionHandler) waitResponse(requestID string) chan *pblite.Response {
|
||||||
response *pblite.Response
|
ch := make(chan *pblite.Response, 1)
|
||||||
wg sync.WaitGroup
|
s.responseWaitersLock.Lock()
|
||||||
mu sync.Mutex
|
// DEBUG
|
||||||
|
if _, ok := s.responseWaiters[requestID]; ok {
|
||||||
|
panic(fmt.Errorf("request %s already has a response waiter", requestID))
|
||||||
|
}
|
||||||
|
// END DEBUG
|
||||||
|
s.responseWaiters[requestID] = ch
|
||||||
|
s.responseWaitersLock.Unlock()
|
||||||
|
return ch
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SessionHandler) addRequestToChannel(requestId string, actionType binary.ActionType) {
|
func (s *SessionHandler) cancelResponse(requestID string, ch chan *pblite.Response) {
|
||||||
_, notOk := routes.Routes[actionType]
|
s.responseWaitersLock.Lock()
|
||||||
if !notOk {
|
close(ch)
|
||||||
panic(fmt.Errorf("missing action type: %v", actionType))
|
delete(s.responseWaiters, requestID)
|
||||||
}
|
s.responseWaitersLock.Unlock()
|
||||||
if msgMap, ok := s.requests[requestId]; ok {
|
|
||||||
responseChan := &ResponseChan{
|
|
||||||
response: &pblite.Response{},
|
|
||||||
wg: sync.WaitGroup{},
|
|
||||||
mu: sync.Mutex{},
|
|
||||||
}
|
|
||||||
responseChan.wg.Add(1)
|
|
||||||
responseChan.mu.Lock()
|
|
||||||
msgMap[actionType] = responseChan
|
|
||||||
} else {
|
|
||||||
s.requests[requestId] = make(map[binary.ActionType]*ResponseChan)
|
|
||||||
responseChan := &ResponseChan{
|
|
||||||
response: &pblite.Response{},
|
|
||||||
wg: sync.WaitGroup{},
|
|
||||||
mu: sync.Mutex{},
|
|
||||||
}
|
|
||||||
responseChan.wg.Add(1)
|
|
||||||
responseChan.mu.Lock()
|
|
||||||
s.requests[requestId][actionType] = responseChan
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SessionHandler) respondToRequestChannel(res *pblite.Response) {
|
func (s *SessionHandler) receiveResponse(resp *pblite.Response) bool {
|
||||||
requestId := res.Data.RequestId
|
s.responseWaitersLock.Lock()
|
||||||
reqChannel, ok := s.requests[requestId]
|
ch, ok := s.responseWaiters[resp.Data.RequestID]
|
||||||
actionType := res.Data.Action
|
|
||||||
if !ok {
|
if !ok {
|
||||||
s.client.Logger.Debug().Any("actionType", actionType).Any("requestId", requestId).Msg("Did not expect response for this requestId")
|
s.responseWaitersLock.Unlock()
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
actionResponseChan, ok2 := reqChannel[actionType]
|
delete(s.responseWaiters, resp.Data.RequestID)
|
||||||
if !ok2 {
|
s.responseWaitersLock.Unlock()
|
||||||
s.client.Logger.Debug().Any("actionType", actionType).Any("requestId", requestId).Msg("Did not expect response for this actionType")
|
evt := s.client.Logger.Trace().
|
||||||
return
|
Str("request_id", resp.Data.RequestID)
|
||||||
|
if evt.Enabled() && resp.Data.Decrypted != nil {
|
||||||
|
evt.Str("proto_name", string(resp.Data.Decrypted.ProtoReflect().Descriptor().FullName())).
|
||||||
|
Str("data", base64.StdEncoding.EncodeToString(resp.Data.RawDecrypted))
|
||||||
}
|
}
|
||||||
actionResponseChan.mu.Lock()
|
evt.Msg("Received response")
|
||||||
actionResponseChan, ok2 = reqChannel[actionType]
|
ch <- resp
|
||||||
if !ok2 {
|
return true
|
||||||
s.client.Logger.Debug().Any("actionType", actionType).Any("requestId", requestId).Msg("Ignoring request for action...")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
s.client.Logger.Debug().Any("actionType", actionType).Any("requestId", requestId).Msg("responding to request")
|
|
||||||
s.client.rpc.logContent(res)
|
|
||||||
actionResponseChan.response = res
|
|
||||||
actionResponseChan.wg.Done()
|
|
||||||
|
|
||||||
delete(reqChannel, actionType)
|
|
||||||
if len(reqChannel) == 0 {
|
|
||||||
delete(s.requests, requestId)
|
|
||||||
}
|
|
||||||
|
|
||||||
actionResponseChan.mu.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SessionHandler) WaitForResponse(requestId string, actionType binary.ActionType) (*pblite.Response, error) {
|
|
||||||
requestResponses, ok := s.requests[requestId]
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("no response channel found for request ID: %s (actionType: %v)", requestId, actionType)
|
|
||||||
}
|
|
||||||
|
|
||||||
routeInfo, notFound := routes.Routes[actionType]
|
|
||||||
if !notFound {
|
|
||||||
return nil, fmt.Errorf("no action exists for actionType: %v (requestId: %s)", actionType, requestId)
|
|
||||||
}
|
|
||||||
|
|
||||||
responseChan, ok2 := requestResponses[routeInfo.Action]
|
|
||||||
if !ok2 {
|
|
||||||
return nil, fmt.Errorf("no response channel found for actionType: %v (requestId: %s)", routeInfo.Action, requestId)
|
|
||||||
}
|
|
||||||
|
|
||||||
responseChan.mu.Unlock()
|
|
||||||
|
|
||||||
responseChan.wg.Wait()
|
|
||||||
|
|
||||||
return responseChan.response, nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,26 +7,17 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Client) SetActiveSession() error {
|
func (c *Client) SetActiveSession() error {
|
||||||
c.sessionHandler.ResetSessionId()
|
c.sessionHandler.ResetSessionID()
|
||||||
|
|
||||||
actionType := binary.ActionType_GET_UPDATES
|
actionType := binary.ActionType_GET_UPDATES
|
||||||
_, sendErr := c.sessionHandler.completeSendMessage(actionType, false, nil)
|
return c.sessionHandler.sendMessageNoResponse(actionType, nil)
|
||||||
if sendErr != nil {
|
|
||||||
return sendErr
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) IsBugleDefault() (*binary.IsBugleDefaultResponse, error) {
|
func (c *Client) IsBugleDefault() (*binary.IsBugleDefaultResponse, error) {
|
||||||
c.sessionHandler.ResetSessionId()
|
c.sessionHandler.ResetSessionID()
|
||||||
|
|
||||||
actionType := binary.ActionType_IS_BUGLE_DEFAULT
|
actionType := binary.ActionType_IS_BUGLE_DEFAULT
|
||||||
sentRequestId, sendErr := c.sessionHandler.completeSendMessage(actionType, true, nil)
|
|
||||||
if sendErr != nil {
|
|
||||||
return nil, sendErr
|
|
||||||
}
|
|
||||||
|
|
||||||
response, err := c.sessionHandler.WaitForResponse(sentRequestId, actionType)
|
response, err := c.sessionHandler.sendMessage(actionType, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -43,15 +34,6 @@ func (c *Client) NotifyDittoActivity() error {
|
||||||
payload := &binary.NotifyDittoActivityPayload{Success: true}
|
payload := &binary.NotifyDittoActivityPayload{Success: true}
|
||||||
actionType := binary.ActionType_NOTIFY_DITTO_ACTIVITY
|
actionType := binary.ActionType_NOTIFY_DITTO_ACTIVITY
|
||||||
|
|
||||||
sentRequestId, sendErr := c.sessionHandler.completeSendMessage(actionType, true, payload)
|
_, err := c.sessionHandler.sendMessage(actionType, payload)
|
||||||
if sendErr != nil {
|
return err
|
||||||
return sendErr
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := c.sessionHandler.WaitForResponse(sentRequestId, actionType)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,60 +16,64 @@ import (
|
||||||
"go.mau.fi/mautrix-gmessages/libgm/util"
|
"go.mau.fi/mautrix-gmessages/libgm/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
|
||||||
type Response struct {
|
|
||||||
client *Client
|
|
||||||
ResponseId string
|
|
||||||
RoutingOpCode int64
|
|
||||||
Data *binary.EncodedResponse // base64 encoded (decode -> protomessage)
|
|
||||||
|
|
||||||
StartExecute string
|
|
||||||
FinishExecute string
|
|
||||||
DevicePair *pblite.DevicePair
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
type SessionHandler struct {
|
type SessionHandler struct {
|
||||||
client *Client
|
client *Client
|
||||||
requests map[string]map[binary.ActionType]*ResponseChan
|
|
||||||
|
responseWaiters map[string]chan<- *pblite.Response
|
||||||
|
responseWaitersLock sync.Mutex
|
||||||
|
|
||||||
ackMapLock sync.Mutex
|
ackMapLock sync.Mutex
|
||||||
ackMap []string
|
ackMap []string
|
||||||
ackTicker *time.Ticker
|
ackTicker *time.Ticker
|
||||||
|
|
||||||
sessionId string
|
sessionID string
|
||||||
|
|
||||||
responseTimeout time.Duration
|
responseTimeout time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SessionHandler) SetResponseTimeout(milliSeconds int) {
|
func (s *SessionHandler) ResetSessionID() {
|
||||||
s.responseTimeout = time.Duration(milliSeconds) * time.Millisecond
|
s.sessionID = util.RandomUUIDv4()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SessionHandler) ResetSessionId() {
|
func (s *SessionHandler) sendMessageNoResponse(actionType binary.ActionType, encryptedData proto.Message) error {
|
||||||
s.sessionId = util.RandomUUIDv4()
|
_, payload, _, err := s.buildMessage(actionType, encryptedData)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = s.client.rpc.sendMessageRequest(util.SEND_MESSAGE, payload)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SessionHandler) completeSendMessage(actionType binary.ActionType, addToChannel bool, encryptedData proto.Message) (string, error) {
|
func (s *SessionHandler) sendAsyncMessage(actionType binary.ActionType, encryptedData proto.Message) (<-chan *pblite.Response, error) {
|
||||||
requestId, payload, action, buildErr := s.buildMessage(actionType, encryptedData)
|
requestID, payload, _, buildErr := s.buildMessage(actionType, encryptedData)
|
||||||
if buildErr != nil {
|
if buildErr != nil {
|
||||||
return "", buildErr
|
return nil, buildErr
|
||||||
}
|
}
|
||||||
|
|
||||||
if addToChannel {
|
ch := s.waitResponse(requestID)
|
||||||
s.addRequestToChannel(requestId, action)
|
|
||||||
}
|
|
||||||
_, reqErr := s.client.rpc.sendMessageRequest(util.SEND_MESSAGE, payload)
|
_, reqErr := s.client.rpc.sendMessageRequest(util.SEND_MESSAGE, payload)
|
||||||
if reqErr != nil {
|
if reqErr != nil {
|
||||||
return "", reqErr
|
s.cancelResponse(requestID, ch)
|
||||||
|
return nil, reqErr
|
||||||
}
|
}
|
||||||
return requestId, nil
|
return ch, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SessionHandler) sendMessage(actionType binary.ActionType, encryptedData proto.Message) (*pblite.Response, error) {
|
||||||
|
ch, err := s.sendAsyncMessage(actionType, encryptedData)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO add timeout
|
||||||
|
return <-ch, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SessionHandler) buildMessage(actionType binary.ActionType, encryptedData proto.Message) (string, []byte, binary.ActionType, error) {
|
func (s *SessionHandler) buildMessage(actionType binary.ActionType, encryptedData proto.Message) (string, []byte, binary.ActionType, error) {
|
||||||
var requestId string
|
var requestID string
|
||||||
pairedDevice := s.client.authData.DevicePair.Mobile
|
pairedDevice := s.client.authData.DevicePair.Mobile
|
||||||
sessionId := s.client.sessionHandler.sessionId
|
sessionId := s.client.sessionHandler.sessionID
|
||||||
token := s.client.authData.TachyonAuthToken
|
token := s.client.authData.TachyonAuthToken
|
||||||
|
|
||||||
routeInfo, ok := routes.Routes[actionType]
|
routeInfo, ok := routes.Routes[actionType]
|
||||||
|
@ -78,12 +82,12 @@ func (s *SessionHandler) buildMessage(actionType binary.ActionType, encryptedDat
|
||||||
}
|
}
|
||||||
|
|
||||||
if routeInfo.UseSessionID {
|
if routeInfo.UseSessionID {
|
||||||
requestId = s.sessionId
|
requestID = s.sessionID
|
||||||
} else {
|
} else {
|
||||||
requestId = util.RandomUUIDv4()
|
requestID = util.RandomUUIDv4()
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpMessage := payload.NewSendMessageBuilder(token, pairedDevice, requestId, sessionId).SetRoute(routeInfo.Action).SetSessionId(s.sessionId)
|
tmpMessage := payload.NewSendMessageBuilder(token, pairedDevice, requestID, sessionId).SetRoute(routeInfo.Action).SetSessionId(s.sessionID)
|
||||||
|
|
||||||
if encryptedData != nil {
|
if encryptedData != nil {
|
||||||
tmpMessage.SetEncryptedProtoMessage(encryptedData, s.client.authData.Cryptor)
|
tmpMessage.SetEncryptedProtoMessage(encryptedData, s.client.authData.Cryptor)
|
||||||
|
@ -98,16 +102,17 @@ func (s *SessionHandler) buildMessage(actionType binary.ActionType, encryptedDat
|
||||||
return "", nil, 0, buildErr
|
return "", nil, 0, buildErr
|
||||||
}
|
}
|
||||||
|
|
||||||
return requestId, message, routeInfo.Action, nil
|
return requestID, message, routeInfo.Action, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SessionHandler) addResponseAck(responseId string) {
|
func (s *SessionHandler) queueMessageAck(messageID string) {
|
||||||
s.client.Logger.Debug().Any("responseId", responseId).Msg("Added to ack map")
|
|
||||||
s.ackMapLock.Lock()
|
s.ackMapLock.Lock()
|
||||||
defer s.ackMapLock.Unlock()
|
defer s.ackMapLock.Unlock()
|
||||||
hasResponseId := slices.Contains(s.ackMap, responseId)
|
if !slices.Contains(s.ackMap, messageID) {
|
||||||
if !hasResponseId {
|
s.ackMap = append(s.ackMap, messageID)
|
||||||
s.ackMap = append(s.ackMap, responseId)
|
s.client.Logger.Trace().Any("message_id", messageID).Msg("Queued ack for message")
|
||||||
|
} else {
|
||||||
|
s.client.Logger.Trace().Any("message_id", messageID).Msg("Ack for message was already queued")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,9 +26,9 @@ func (c *Client) handleUserAlertEvent(res *pblite.Response, data *binary.UserAle
|
||||||
alertType := data.AlertType
|
alertType := data.AlertType
|
||||||
switch alertType {
|
switch alertType {
|
||||||
case binary.AlertType_BROWSER_ACTIVE:
|
case binary.AlertType_BROWSER_ACTIVE:
|
||||||
newSessionId := res.Data.RequestId
|
newSessionId := res.Data.RequestID
|
||||||
c.Logger.Info().Any("sessionId", newSessionId).Msg("[NEW_BROWSER_ACTIVE] Opened new browser connection")
|
c.Logger.Info().Any("sessionId", newSessionId).Msg("[NEW_BROWSER_ACTIVE] Opened new browser connection")
|
||||||
if newSessionId != c.sessionHandler.sessionId {
|
if newSessionId != c.sessionHandler.sessionID {
|
||||||
evt := events.NewBrowserActive(newSessionId)
|
evt := events.NewBrowserActive(newSessionId)
|
||||||
c.triggerEvent(evt)
|
c.triggerEvent(evt)
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue