github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/core/service/subscription.go (about)

     1  /*
     2   * Copyright (C) 2020 The "MysteriumNetwork/node" Authors.
     3   *
     4   * This program is free software: you can redistribute it and/or modify
     5   * it under the terms of the GNU General Public License as published by
     6   * the Free Software Foundation, either version 3 of the License, or
     7   * (at your option) any later version.
     8   *
     9   * This program is distributed in the hope that it will be useful,
    10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12   * GNU General Public License for more details.
    13   *
    14   * You should have received a copy of the GNU General Public License
    15   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    16   */
    17  
    18  package service
    19  
    20  import (
    21  	"fmt"
    22  	"math/big"
    23  	"time"
    24  
    25  	"github.com/mysteriumnetwork/node/identity"
    26  	"github.com/mysteriumnetwork/node/p2p"
    27  	"github.com/mysteriumnetwork/node/pb"
    28  	"github.com/mysteriumnetwork/node/session/connectivity"
    29  	"github.com/mysteriumnetwork/payments/crypto"
    30  	"github.com/rs/zerolog/log"
    31  )
    32  
    33  func subscribeSessionCreate(mng *SessionManager, ch p2p.ChannelHandler) {
    34  	ch.Handle(p2p.TopicSessionCreate, func(c p2p.Context) error {
    35  		var request pb.SessionRequest
    36  		if err := c.Request().UnmarshalProto(&request); err != nil {
    37  			return err
    38  		}
    39  		if identity.FromAddress(request.GetConsumer().GetId()) != c.PeerID() {
    40  			return fmt.Errorf("wrong consumer identity in session create request. Expected: %s, got: %s",
    41  				c.PeerID().ToCommonAddress(),
    42  				identity.FromAddress(request.GetConsumer().GetId()),
    43  			)
    44  		}
    45  
    46  		log.Debug().Msgf("Received P2P message for %q: %s", p2p.TopicSessionCreate, request.String())
    47  
    48  		response, err := mng.Start(&request)
    49  		if err != nil {
    50  			return fmt.Errorf("cannot start session: %s: %w", response.ID, err)
    51  		}
    52  
    53  		return c.OkWithReply(p2p.ProtoMessage(&response))
    54  	})
    55  }
    56  
    57  func subscribeSessionStatus(ch p2p.ChannelHandler, statusStorage connectivity.StatusStorage) {
    58  	ch.Handle(p2p.TopicSessionStatus, func(c p2p.Context) error {
    59  		var ss pb.SessionStatus
    60  		if err := c.Request().UnmarshalProto(&ss); err != nil {
    61  			return err
    62  		}
    63  		if identity.FromAddress(ss.GetConsumerID()) != c.PeerID() {
    64  			return fmt.Errorf("wrong consumer identity in session status request. Expected: %s, got: %s",
    65  				c.PeerID().ToCommonAddress(),
    66  				identity.FromAddress(ss.GetConsumerID()),
    67  			)
    68  		}
    69  
    70  		log.Debug().Msgf("Received P2P session status message for %q: %s", p2p.TopicSessionStatus, ss.String())
    71  
    72  		entry := connectivity.StatusEntry{
    73  			PeerID:       identity.FromAddress(ss.GetConsumerID()),
    74  			StatusCode:   connectivity.StatusCode(ss.GetCode()),
    75  			SessionID:    ss.GetSessionID(),
    76  			Message:      ss.GetMessage(),
    77  			CreatedAtUTC: time.Now().UTC(),
    78  		}
    79  		statusStorage.AddStatusEntry(entry)
    80  
    81  		return c.OK()
    82  	})
    83  }
    84  
    85  func subscribeSessionDestroy(mng *SessionManager, ch p2p.ChannelHandler) {
    86  	ch.Handle(p2p.TopicSessionDestroy, func(c p2p.Context) error {
    87  		var si pb.SessionInfo
    88  		if err := c.Request().UnmarshalProto(&si); err != nil {
    89  			return err
    90  		}
    91  		if identity.FromAddress(si.GetConsumerID()) != c.PeerID() {
    92  			return fmt.Errorf("wrong consumer identity in session destroy request. Expected: %s, got: %s",
    93  				c.PeerID().ToCommonAddress(),
    94  				identity.FromAddress(si.GetConsumerID()),
    95  			)
    96  		}
    97  
    98  		log.Debug().Msgf("Received P2P message for %q: %s", p2p.TopicSessionDestroy, si.String())
    99  
   100  		go func() {
   101  			consumerID := identity.FromAddress(si.GetConsumerID())
   102  			sessionID := si.GetSessionID()
   103  
   104  			err := mng.Destroy(consumerID, sessionID)
   105  			if err != nil {
   106  				log.Err(err).Msgf("Could not destroy session %s: %v", sessionID, err)
   107  			}
   108  		}()
   109  
   110  		return c.OK()
   111  	})
   112  }
   113  
   114  func subscribeSessionAcknowledge(mng *SessionManager, ch p2p.ChannelHandler) {
   115  	ch.Handle(p2p.TopicSessionAcknowledge, func(c p2p.Context) error {
   116  		var si pb.SessionInfo
   117  		if err := c.Request().UnmarshalProto(&si); err != nil {
   118  			return err
   119  		}
   120  		if identity.FromAddress(si.GetConsumerID()) != c.PeerID() {
   121  			return fmt.Errorf("wrong consumer identity in session acknowledge request. Expected: %s, got: %s",
   122  				c.PeerID().ToCommonAddress(),
   123  				identity.FromAddress(si.GetConsumerID()),
   124  			)
   125  		}
   126  
   127  		log.Debug().Msgf("Received P2P message for %q: %s", p2p.TopicSessionAcknowledge, si.String())
   128  		consumerID := identity.FromAddress(si.GetConsumerID())
   129  		sessionID := si.GetSessionID()
   130  
   131  		err := mng.Acknowledge(consumerID, sessionID)
   132  		if err != nil {
   133  			return fmt.Errorf("cannot acknowledge session %s: %w", sessionID, err)
   134  		}
   135  
   136  		return c.OK()
   137  	})
   138  }
   139  
   140  const bigIntBase int = 10
   141  
   142  func subscribeSessionPayments(mng *SessionManager, ch p2p.ChannelHandler) {
   143  	ch.Handle(p2p.TopicPaymentMessage, func(c p2p.Context) error {
   144  		var msg pb.ExchangeMessage
   145  		if err := c.Request().UnmarshalProto(&msg); err != nil {
   146  			return fmt.Errorf("could not unmarshal exchange message proto: %w", err)
   147  		}
   148  		log.Debug().Msgf("Received P2P message for %q: %s", p2p.TopicPaymentMessage, msg.String())
   149  
   150  		amount, ok := new(big.Int).SetString(msg.GetPromise().GetAmount(), bigIntBase)
   151  		if !ok {
   152  			return fmt.Errorf("could not unmarshal field amount of value %v", amount)
   153  		}
   154  
   155  		fee, ok := new(big.Int).SetString(msg.GetPromise().GetFee(), bigIntBase)
   156  		if !ok {
   157  			return fmt.Errorf("could not unmarshal field fee of value %v", fee)
   158  		}
   159  
   160  		agreementID, ok := new(big.Int).SetString(msg.GetAgreementID(), bigIntBase)
   161  		if !ok {
   162  			return fmt.Errorf("could not unmarshal field agreementID of value %v", agreementID)
   163  		}
   164  
   165  		agreementTotal, ok := new(big.Int).SetString(msg.GetAgreementTotal(), bigIntBase)
   166  		if !ok {
   167  			return fmt.Errorf("could not unmarshal field agreementTotal of value %v", agreementTotal)
   168  		}
   169  
   170  		mng.paymentEngineChan <- crypto.ExchangeMessage{
   171  			Promise: crypto.Promise{
   172  				ChannelID: msg.GetPromise().GetChannelID(),
   173  				Amount:    amount,
   174  				Fee:       fee,
   175  				Hashlock:  msg.GetPromise().GetHashlock(),
   176  				R:         msg.GetPromise().GetR(),
   177  				Signature: msg.GetPromise().GetSignature(),
   178  				ChainID:   msg.GetPromise().GetChainID(),
   179  			},
   180  			AgreementID:    agreementID,
   181  			AgreementTotal: agreementTotal,
   182  			Provider:       msg.GetProvider(),
   183  			Signature:      msg.GetSignature(),
   184  			HermesID:       msg.GetHermesID(),
   185  			ChainID:        msg.GetChainID(),
   186  		}
   187  
   188  		return nil
   189  	})
   190  }