github.com/mit-dci/lit@v0.0.0-20221102210550-8c3d3b49f2ce/lnp2p/msgproc.go (about)

     1  package lnp2p
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/mit-dci/lit/logging"
     6  	"sync"
     7  )
     8  
     9  // ParseFuncType is the type of a Message parser function.
    10  type ParseFuncType func([]byte) (Message, error)
    11  
    12  // HandleFuncType is the type of a Message handler function, handling for a particular peer.
    13  type HandleFuncType func(*Peer, Message) error
    14  
    15  type messagehandler struct {
    16  	parseFunc  ParseFuncType
    17  	handleFunc HandleFuncType
    18  }
    19  
    20  // MessageProcessor is can be given messages and figures out how to parse them and which function to call.
    21  type MessageProcessor struct {
    22  	handlers [256]*messagehandler
    23  
    24  	// This is for keeping track of if we're making changes to the message
    25  	// processor.  Locking and unlocking is slow and shouldn't be necessary when
    26  	// handling messages, but we don't want to be handling messages while making
    27  	// changes to the handlerset.
    28  	// TODO Evaluate if this mutex is even necessary?
    29  	active bool
    30  	actmtx *sync.Mutex
    31  }
    32  
    33  // NewMessageProcessor processes messages coming in from over the network.
    34  func NewMessageProcessor() MessageProcessor {
    35  	return MessageProcessor{
    36  		handlers: [256]*messagehandler{},
    37  		active:   false,
    38  		actmtx:   &sync.Mutex{},
    39  	}
    40  }
    41  
    42  // DefineMessage defines processing routines for a particular message type.
    43  func (mp *MessageProcessor) DefineMessage(mtype uint8, pfunc ParseFuncType, hfunc HandleFuncType) {
    44  	mp.actmtx.Lock()
    45  	act := mp.active
    46  	mp.active = false
    47  
    48  	// Actually set the handler.
    49  	mp.handlers[mtype] = &messagehandler{
    50  		parseFunc:  pfunc,
    51  		handleFunc: hfunc,
    52  	}
    53  
    54  	logging.Debugf("msgproc: Setup message type %x\n", mtype)
    55  
    56  	mp.active = act
    57  	mp.actmtx.Unlock()
    58  }
    59  
    60  // Activate sets the MessageProcessor to be "active"
    61  func (mp *MessageProcessor) Activate() {
    62  	mp.active = true
    63  }
    64  
    65  // IsActive returns the activiation state for the MessageProcessor.
    66  func (mp *MessageProcessor) IsActive() bool {
    67  	return mp.active
    68  }
    69  
    70  // HandleMessage runs through the normal handling procedure for the message, returning any errors.
    71  func (mp *MessageProcessor) HandleMessage(peer *Peer, buf []byte) error {
    72  	if !mp.active {
    73  		return fmt.Errorf("message processor not active, retry later")
    74  	}
    75  
    76  	var err error
    77  
    78  	// First see if we have handlers defined for this message type.
    79  	mtype := buf[0]
    80  	h := mp.handlers[mtype]
    81  	if h == nil {
    82  		return fmt.Errorf("no handler found for messasge of type %x", mtype)
    83  	}
    84  
    85  	// Parse the message.
    86  	parsed, err := h.parseFunc(buf[1:])
    87  	if err != nil {
    88  		logging.Warnf("msgproc: Malformed message of type %x from peer %s\n", mtype, peer.GetPrettyName())
    89  		return err
    90  	}
    91  
    92  	// If ok, then actually handle the message.
    93  	err = h.handleFunc(peer, parsed)
    94  	if err != nil {
    95  		return err
    96  	}
    97  
    98  	return nil
    99  }