smppth

package module
v0.4.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 16, 2021 License: Apache-2.0 Imports: 15 Imported by: 1

README

smppth

Overview

This repository golang libraries intended to make the creating of SMPP test tools.

Libraries

github.com/blorticus/smpp provides methods for encoding and decoding SMPP PDUs. smppth adds SMPP Agents, which can operate as an ESME (meaning it initiates the outbound flow toward one or more peers) or an SMSC (meaning it listens for inbound flows from one or more peers). An AgentGroup instance is responsible for launching a group of agents and provides a method for routing PDUs to Agents for delivery to peers. The AgentGroup also provides an event channel. When specific events happen on an Agent, the Agent sends a message on the event channel describing that event. Events include:

  • Receipt of a PDU from a peer
  • Delivery of a PDU to a peer
  • Completion of a bind on a transport

The configuration of the Agents in an AgentGroup can be defined in a YAML file. A YAMLConfigReader can be used to read the YAML file, with the resulting objects supplied to the AgentGroup.

Documentation

Index

Constants

View Source
const (
	SendPDU = iota
	Help
	Quit
)

Constants describing the type of user command instruction

Variables

This section is empty.

Functions

This section is empty.

Types

type Agent

type Agent interface {
	Name() string
	StartEventLoop()
	SendMessageToPeer(message *MessageDescriptor) error
	SetAgentEventChannel(chan<- *AgentEvent)
}

Agent is either a testharness agent, either an ESME or an SMSC

type AgentEvent

type AgentEvent struct {
	Type           AgentEventType
	SourceAgent    Agent
	RemotePeerName string
	SmppPDU        *smpp.PDU
	Error          error
}

AgentEvent is an event from an smpp agent. SourceAgent is always the Agent that sourced this event. RemotePeerName is always the name of the remote peer for the event. For CompletedBind, the SmppPDU is the transceiver-bind-resp. For CompletedUnbind, it is the unbind-resp. For PeerTransportClosed, it is nil. Error is always nil, except for the AgentEvents of type Error (e.g., TransportError). For TransportError, RemotePeerName will be set to the remote peer name -- unless it is at connection setup, in which case, it will be "" -- and SmppPDU will be nil. For ApplicationError, RemotePeerName may be empty or may have a value, and SmppPDU may be nil or may be defined. If SmppPDU is defined for ApplicationError, then the error relates to the PDU in some way.

type AgentEventType

type AgentEventType int

AgentEventType is an enum of the types of AgentEvents that can be raised.

const (
	// ReceivedPDU is the AgentEvent type when an SMPP PDU is received from a peer.
	ReceivedPDU AgentEventType = iota
	// SentPDU is the AgentEvent type when the local Agent sent an SMPP PDU to a peer.
	SentPDU
	// CompletedBind is the AgentEvent type when an agent completes a bind sequence with a peer.
	CompletedBind
	// CompletedUnbind is the AgentEvent type after an SMSC receives an unbind and sends an unbind-resp,
	// or after an ESME sends an unbind and receives an ubind-resp
	CompletedUnbind
	// PeerTransportClosed is the AgentEvent type after the TCP transport toward a peer closes
	PeerTransportClosed
	// TransportError is the AgentEvent type when an Agent experiences some sort of error at the
	// transport layer
	TransportError
	// ApplicationError is the AgentEvent type when an Agent experiences some sort of error at the
	// SMPP layer
	ApplicationError
)

type AgentGroup

type AgentGroup struct {
	// contains filtered or unexported fields
}

AgentGroup manages a group of Agents, routing messages for delivery to them, and providing them with a common event channel

func NewAgentGroup

func NewAgentGroup(listOfManagedAgents []Agent) *AgentGroup

NewAgentGroup creates a new AgentGroup and adds to it the provided list of managed agents

func (*AgentGroup) AddAgent

func (group *AgentGroup) AddAgent(agent Agent)

AddAgent adds a agent to the AgentGroup for management. This will silently replace an already managed agent with the same name.

func (*AgentGroup) AddAgents

func (group *AgentGroup) AddAgents(agents []Agent)

AddAgents adds multiple agents to the AgentGroup for management. This will silently replace any managed agents that have a name matching an already managed agent

func (*AgentGroup) AttachDebugLoggerWriter

func (group *AgentGroup) AttachDebugLoggerWriter(writer io.Writer)

AttachDebugLoggerWriter enables debug logging, sending messages to the provided Writer.

func (*AgentGroup) RemoveAgent

func (group *AgentGroup) RemoveAgent(agent Agent)

RemoveAgent removes an agent under management by name. If there is no agent with a matching name under management, it is silently ignored. If the provided agent does not match the managed agent by name, the agent is removed anyway

func (*AgentGroup) RemoveAgents

func (group *AgentGroup) RemoveAgents(agents []Agent)

RemoveAgents remove multiple agents under management by their names. For each agent in the list, if there is no agent with a matching name under management, it is silently ignored. Also, for each agent in the list, if the provided agent does not match the managed agent by name, the agent is removed anyway

func (*AgentGroup) RoutePduToAgentForSending

func (group *AgentGroup) RoutePduToAgentForSending(nameOfSourcePeer string, nameOfDestinationPeer string, pduToSend *smpp.PDU) error

RoutePduToAgentForSending accepts an SMPP PDU, and routes it to the named source peer, so that peer can send it to the named destination peer

func (*AgentGroup) SetOfManagedAgents

func (group *AgentGroup) SetOfManagedAgents() []Agent

SetOfManagedAgents returns the current list of agents that are under management in this group

func (*AgentGroup) SharedAgentEventChannel

func (group *AgentGroup) SharedAgentEventChannel() <-chan *AgentEvent

SharedAgentEventChannel returns the shared event channel used by all of the managed agents

func (*AgentGroup) StartAllAgents

func (group *AgentGroup) StartAllAgents()

StartAllAgents executes StartEventLoop() on all managed agents, passing each the shared event channel. The agents are started in no particular order.

type ApplicationConfigYamlReader

type ApplicationConfigYamlReader struct {
}

ApplicationConfigYamlReader reads a testharness application YAML config file

func NewApplicationConfigYamlReader

func NewApplicationConfigYamlReader() *ApplicationConfigYamlReader

NewApplicationConfigYamlReader creates a new, empty ApplicationConfigYamlReader

func (*ApplicationConfigYamlReader) ParseFile

func (reader *ApplicationConfigYamlReader) ParseFile(fileName string) ([]*ESME, []*SMSC, error)

ParseFile opens a file and treats its contents as a validly formatted testharness config YAML file

func (*ApplicationConfigYamlReader) ParseReader

func (reader *ApplicationConfigYamlReader) ParseReader(ioReader io.Reader) ([]*ESME, []*SMSC, error)

ParseReader reads from an io.Reader stream, treating the contents provided as a validly formatted testharness config YAML file

type DefaultPduFactory

type DefaultPduFactory struct {
	// contains filtered or unexported fields
}

DefaultPduFactory produces a standard set of PDUs

func NewDefaultPduFactory

func NewDefaultPduFactory() *DefaultPduFactory

NewDefaultPduFactory constructs a new DefaultPduFactory. The factory stores a monotonically incrementing sequence number, which is used in the production of requests messages. Methods that generate a response PDU are provided the triggering request PDU, and use the same sequence number for the Response as the one found in the Request.

func (factory *DefaultPduFactory) CreateEnquireLink() *smpp.PDU

CreateEnquireLink creates an enquire-link with no parameters

func (*DefaultPduFactory) CreateEnquireLinkRespFromRequest

func (factory *DefaultPduFactory) CreateEnquireLinkRespFromRequest(requestPDU *smpp.PDU) *smpp.PDU

CreateEnquireLinkRespFromRequest creates an enquire-link-resp with no parameters

func (*DefaultPduFactory) CreateSubmitSm

func (factory *DefaultPduFactory) CreateSubmitSm(parameters map[string]string) (*smpp.PDU, error)

CreateSubmitSm creates a submit-sm. The current supported parameter map keys that are supported are:

source_addr_npi - uint8 (default 0)
source_addr - string (default "")
dest_addr_npi - uint8 (default 0)
destination_address - string (default "")
short_message - string (default "This is a test short message")

If CreateSubmitSm cannot coerce the string value for a parameter into its proper type (e.g., uint8), and error will be returned.

func (*DefaultPduFactory) CreateSubmitSmRespFromRequest

func (factory *DefaultPduFactory) CreateSubmitSmRespFromRequest(requestPDU *smpp.PDU, messageID string) *smpp.PDU

CreateSubmitSmRespFromRequest creates a submit-sm-resp. The message-id will be set to the messageID value.

type ESME

type ESME struct {
	// contains filtered or unexported fields
}

ESME represents an SMPP 3.4 client, which initiates one or more transport connections and sends binds on those connections

func NewEsme

func NewEsme(esmeName string, esmeIP net.IP, esmePort uint16) *ESME

NewEsme creates an SMPP 3.4 client with the given name, and using the given IP and port for outgoing transport connections

func (*ESME) Name

func (esme *ESME) Name() string

Name returns the name of this ESME agent

func (*ESME) SendMessageToPeer

func (esme *ESME) SendMessageToPeer(message *MessageDescriptor) error

SendMessageToPeer instructs this ESME agent to send a message to the peer identified in the MessageDescriptor. No effort is made to validate that the MessageDescriptor SourceAgentName matches this agent's name.

func (*ESME) SetAgentEventChannel

func (esme *ESME) SetAgentEventChannel(agentEventChannel chan<- *AgentEvent)

SetAgentEventChannel sets a channel to which this ESME instance will write events

func (*ESME) StartEventLoop

func (esme *ESME) StartEventLoop()

StartEventLoop instructs this ESME agent to start listening for incoming transport connections, to respond to binds, to emit AgentEvents to the agentEventChannel, and accept messages for remote delivery via SendMessagesToPeer().

func (*ESME) UnbindAll

func (esme *ESME) UnbindAll()

UnbindAll instructs this ESME agent to both unbind all outstanding peer connections, and close their corresponding transports.

type MessageDescriptor

type MessageDescriptor struct {
	NameOfSendingPeer   string
	NameOfReceivingPeer string
	PDU                 *smpp.PDU
}

A MessageDescriptor is provided to smpp agents, indicating what PDU to send, the name of the source from which to send, and the name of the destination to which the PDU should be sent

type OutputGenerator

type OutputGenerator interface {
	SayThatAPduWasReceivedByAnAgent(sendingAgentName string, receivingPeerName string, receivedPDU *smpp.PDU) string
	SayThatAPduWasSentByAnAgent(sendingAgentName string, receivingPeerName string, sentPDU *smpp.PDU) string
	SayThatATransceiverBindWasCompletedByAnAgent(localAgentName string, remotePeerName string) string
	SayThatTheTransportForAPeerClosed(localAgentName string, remotePeerName string) string
	SayThatATransportErrorWasThrown(localAgentName string, remotePeerName string, err error) string
	SayThatAnApplicationErrorWasThrown(reportingAgentName string, err error) string
}

OutputGenerator is an inteface describing methods to generate standard responses to commands or events. It can be implemented to change the responses used by standard test harness application components

type PduFactory

type PduFactory interface {
	CreateEnquireLink() *smpp.PDU
	CreateEnquireLinkRespFromRequest(requestPDU *smpp.PDU) *smpp.PDU
	CreateSubmitSm(parameters map[string]string) (*smpp.PDU, error)
	CreateSubmitSmRespFromRequest(requestPDU *smpp.PDU, messageID string) *smpp.PDU
}

PduFactory instances produces smpp.PDU objects for various message types. Implementations can alter the default messages generated by various test harness application components

type SMSC

type SMSC struct {
	// contains filtered or unexported fields
}

SMSC represents an SMPP 3.4 server, which accepts one or more transport connections and responds to bind requests

func NewSMSC

func NewSMSC(smscName string, smscBindSystemID string, listeningIP net.IP, listeningPort uint16) *SMSC

NewSMSC creates a new SMSC agent.

func (*SMSC) Name

func (smsc *SMSC) Name() string

Name returns the name of this SMSC agent instance

func (*SMSC) SendMessageToPeer

func (smsc *SMSC) SendMessageToPeer(message *MessageDescriptor) error

SendMessageToPeer instructs this SMSC agent to send a message to the peer identified in the MessageDescriptor. No effort is made to validate that the MessageDescriptor SourceAgentName matches this agent's name.

func (*SMSC) SetAgentEventChannel

func (smsc *SMSC) SetAgentEventChannel(agentEventChannel chan<- *AgentEvent)

SetAgentEventChannel sets a channel to which this SMSC instance will write events

func (*SMSC) StartEventLoop

func (smsc *SMSC) StartEventLoop()

StartEventLoop instructs this SMSC agent to start listening for incoming transport connections, to respond to binds, to emit AgentEvents to the agentEventChannel, and accept messages for remote delivery via SendMessageToPeer().

func (*SMSC) StopAndUnbindAll

func (smsc *SMSC) StopAndUnbindAll()

StopAndUnbindAll instructs this SMSC agent to stop listening for incoming transport connections, and to both unbind all outstanding peer connections, and close their corresponding transports.

type SendPduDetails

type SendPduDetails struct {
	NameOfAgentThatWillSendPdu     string
	NameOfPeerThatShouldReceivePdu string
	TypeOfSmppPDU                  smpp.CommandIDType
	StringParametersMap            map[string]string
}

SendPduDetails provides a structured set of details for an Agent, instructing it to send an SMPP PDU to a particular destination. StringParameterMap depends on the TypeOfSmppPDU.

type StandardApplication

type StandardApplication struct {
	// contains filtered or unexported fields
}

StandardApplication provides a standard method for accepting user input commands (marshalled to UserCommand structs), generate smpp PDUs (if the command is 'SendPDU'), respond to known PDU types (e.g., send enquire-link-resp in response to an enquire-link), and produce standard text output to an io.Writer, based on a supplied OutputGenerator. By default, the application uses a StandardOutputGenerator and a DefaultPduFactory, but these can be overridden. Some of the output is based on events that arrive on a supplied AgentEvent channel. If the creator of the StandardApplication would also like to see the AgentEvent messages, a call to AttachEventChannel() returns a channel to which the AgentEvent messages are proxied.

Generally speaking, the application is used in this way:

app := NewStandardApplication().
          SetOutputGenerator(someOutputGenerator).
          SetEventOutputWriter(someIoWriter).
          SetPduFactory(somePduFactory).
          SetAgentGroup(someAgentGroup)
proxiedEventChannel := app.AttachEventChannel(underlyingEventChannel)
go app.Start()
  // ... some time later when user input arrives ... //
app.ReceiveNextCommand(someUserCommand)

func NewStandardApplication

func NewStandardApplication() *StandardApplication

NewStandardApplication creates a new StandardApplication

func (*StandardApplication) AttachEventChannel

func (app *StandardApplication) AttachEventChannel(channel <-chan *AgentEvent) (proxiedEventChannel <-chan *AgentEvent)

AttachEventChannel attaches a shared AgentEvent channel, generally the one used by the associated AgentGroup. An AgentEvent channel is returned. Any message that arrives on incoming AgentEvent channel is copied to the proxy channel. If DisableAgentEventProxying() is called, then nothing is written to the proxy channel. Otherwise, messages are written in a non-blocking way (but you shouldn't let them collect for too long).

func (*StandardApplication) DisableAgentEventProxying

func (app *StandardApplication) DisableAgentEventProxying() *StandardApplication

DisableAgentEventProxying instructs the StandardApplication to not (or stop) writing AgentEvents to the proxiedEventChannel returned by AttachEventChannel()

func (*StandardApplication) DisableAutomaticResponsesToRequestPdus

func (app *StandardApplication) DisableAutomaticResponsesToRequestPdus() *StandardApplication

DisableAutomaticResponsesToRequestPdus disables automatic responses to incoming PDUs. The PDUs can still be received by the creator of the StandardApplication by reading from the proxiedEventChannel (returned when AttachEventChannel is invoked).

func (*StandardApplication) DisableDebugMessages

func (app *StandardApplication) DisableDebugMessages()

DisableDebugMessages instructs the StandardApplication to stop sending any output for debugging messages embedded in the code.

func (*StandardApplication) EnableAgentEventProxying

func (app *StandardApplication) EnableAgentEventProxying() *StandardApplication

EnableAgentEventProxying instructs the StandardApplication to start writing AgentEvents to the proxiedEventChannel returned by AttachEventChannel() when events arrive on the attached event channel

func (*StandardApplication) EnableDebugMessages

func (app *StandardApplication) EnableDebugMessages(writer io.Writer)

EnableDebugMessages instructs the StandardApplication to output any debugging message embedded in the code. Messages are written to the provided writer.

func (*StandardApplication) OnQuit

func (app *StandardApplication) OnQuit(quitCommandCallback func()) *StandardApplication

OnQuit adds a callback when the user command is "quit"

func (*StandardApplication) ReceiveNextCommand

func (app *StandardApplication) ReceiveNextCommand(command *UserCommand)

ReceiveNextCommand sends a structured UserCommand to the StandardApplication. If the type is SendPDU, and the Details in the UserCommand are for a PDU type known to the StandardApplication, then the identified agent sends the message to the identified peer. If there is an error (e.g., if the identified sending agent is not under management by the associated AgentGroup), the error text is written to the EventOutputWriter.

func (*StandardApplication) SetAgentGroup

func (app *StandardApplication) SetAgentGroup(group *AgentGroup) *StandardApplication

SetAgentGroup adds a managed AgentGroup, which is used to direct send messages on a SendPDU command.

func (*StandardApplication) SetEventOutputWriter

func (app *StandardApplication) SetEventOutputWriter(writer io.Writer) *StandardApplication

SetEventOutputWriter sets the io.Writer to which output messages are written. If this option isn't applies, STDOUT is used.

func (*StandardApplication) SetOutputGenerator

func (app *StandardApplication) SetOutputGenerator(generator OutputGenerator) *StandardApplication

SetOutputGenerator adds something implementing the OutputGenerator interface, which is then used by the StandardApplication to generate output message (written to the EventOutputWriter). If this option isn't applied, the default is to use a StandardOutputGenerator.

func (*StandardApplication) SetPduFactory

func (app *StandardApplication) SetPduFactory(factory PduFactory) *StandardApplication

SetPduFactory adds something implementing the PduFactory interfaces, which is used to generate smpp PDUs based on SendPDU commands, or in response to received request PDUs.

func (*StandardApplication) Start

func (app *StandardApplication) Start()

Start begins the running application. This method never returns, so it may be appropriate to launch it as a go routine.

type StandardOutputGenerator

type StandardOutputGenerator struct {
}

StandardOutputGenerator implements OutputGenerator, providing generic text responses for commands and events

func NewStandardOutputGenerator

func NewStandardOutputGenerator() *StandardOutputGenerator

NewStandardOutputGenerator creates a new StandardOutputGenerator

func (*StandardOutputGenerator) SayThatAPduWasReceivedByAnAgent

func (generator *StandardOutputGenerator) SayThatAPduWasReceivedByAnAgent(sendingAgentName string, receivingPeerName string, receivedPDU *smpp.PDU) string

SayThatAPduWasReceivedByAnAgent produces output "$peer_name received $message_type from $agent_name"

func (*StandardOutputGenerator) SayThatAPduWasSentByAnAgent

func (generator *StandardOutputGenerator) SayThatAPduWasSentByAnAgent(sendingAgentName string, receivingPeerName string, sentPDU *smpp.PDU) string

SayThatAPduWasSentByAnAgent produces output "$sendingAgentName sent $message_type to $receivingPeerName"

func (*StandardOutputGenerator) SayThatATransceiverBindWasCompletedByAnAgent

func (generator *StandardOutputGenerator) SayThatATransceiverBindWasCompletedByAnAgent(localAgentName string, remotePeerName string) string

SayThatATransceiverBindWasCompletedByAnAgent produces output "$localAgentName completed a transceiver bind with $remotePeerName"

func (*StandardOutputGenerator) SayThatATransportErrorWasThrown

func (generator *StandardOutputGenerator) SayThatATransportErrorWasThrown(localAgentName string, remotePeerName string, err error) string

SayThatATransportErrorWasThrown produces output "$localAgentName received error on transport with $remotePeerName: $errString"

func (*StandardOutputGenerator) SayThatAnApplicationErrorWasThrown

func (generator *StandardOutputGenerator) SayThatAnApplicationErrorWasThrown(reportingAgentName string, err error) string

SayThatAnApplicationErrorWasThrown produces output "$reportingAgentName reports an application error: $errString"

func (*StandardOutputGenerator) SayThatTheTransportForAPeerClosed

func (generator *StandardOutputGenerator) SayThatTheTransportForAPeerClosed(localAgentName string, remotePeerName string) string

SayThatTheTransportForAPeerClosed produces output "$localAgentName peer connection closed from $remotePeerName"

type TextCommandProcessor

type TextCommandProcessor struct {
	// contains filtered or unexported fields
}

TextCommandProcessor accepts incoming text commands and, if they match the TextCommandProcessor syntax, then it emits a corresponding UserCommand structs. The syntax includes:

$agent_name: send enquire-link to $peer_name
$agent_name: send submit-sm to $peer_name [source_addr_ton=$sat] [source_address=$saddr] [dest_addr_ton=$dat] [destination_address=$daddr] [short_message=$msg]
help

func NewTextCommandProcessor

func NewTextCommandProcessor() *TextCommandProcessor

NewTextCommandProcessor creates a TextCommandProcessor.

func (*TextCommandProcessor) ConvertCommandLineStringToUserCommand

func (processor *TextCommandProcessor) ConvertCommandLineStringToUserCommand(commandLine string) (*UserCommand, error)

ConvertCommandLineStringToUserCommand accepts a string command line, and if it matches the TextCommandProcessor syntax, returns the matching UserCommand struct. It returns an error if some part of the command is not understood.

type UserCommand

type UserCommand struct {
	Type    UserCommandType
	Details interface{}
}

UserCommand represents a user instruction provided to an Agent in an AgentGroup. When Type is SendPDU, Details must be of type SendPduDetails. When Type is Help, Details must by nil.

type UserCommandType

type UserCommandType int

UserCommandType is the type of user command provided in a UserCommand struct

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL