Skip to content

Commit

Permalink
New OnAllPDU seeting that lets users choose to handle all PDUs from S…
Browse files Browse the repository at this point in the history
…MSC (#110)

As propose in #96  and in  #107 

What:
This feature allows the ESME to control PDU response by using a new
setting that will handle all PDU. This proposed feature does not
interfere with current user behaviour.

Why:
Some ESME need to validate incoming PDUs, like DeliverSm and DataSM,
before returning a response.

How:
- new `OnAllPDU` setting that lets users choose how to handle PDUs from
SMSC
- If the user sets new setting, it will overide `OnPDU`
- Respond function added to Receivable and Transceivable, to allow
Respond/Submit for the response


Warning:
This setting, if set, overrides `OnPDU` and bypass all auto response
feature, Enquirelink and Unbind request must be handled by user.

Added a new example called `transcceiver_with_manual_response` to see
how it can be used, moved old example in
`transceiver_with_auto_response` .
  • Loading branch information
laduchesneau authored Sep 15, 2023
1 parent d095b83 commit 151b333
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 0 deletions.
134 changes: 134 additions & 0 deletions example/transcceiver_with_manual_response/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package main

import (
"fmt"
"log"
"sync"
"time"

"github.com/linxGnu/gosmpp"
"github.com/linxGnu/gosmpp/data"
"github.com/linxGnu/gosmpp/pdu"
)

func main() {
var wg sync.WaitGroup

wg.Add(1)
go sendingAndReceiveSMS(&wg)

wg.Wait()
}

func sendingAndReceiveSMS(wg *sync.WaitGroup) {
defer wg.Done()

auth := gosmpp.Auth{
SMSC: "localhost:2775",
SystemID: "169994",
Password: "EDXPJU",
SystemType: "",
}

sendResponse := make(chan pdu.PDU)
defer close(sendResponse)
trans, err := gosmpp.NewSession(
gosmpp.TRXConnector(gosmpp.NonTLSDialer, auth),
gosmpp.Settings{
EnquireLink: 5 * time.Second,

ReadTimeout: 10 * time.Second,

OnSubmitError: func(_ pdu.PDU, err error) {
log.Fatal("SubmitPDU error:", err)
},

OnReceivingError: func(err error) {
fmt.Println("Receiving PDU/Network error:", err)
},

OnRebindingError: func(err error) {
fmt.Println("Rebinding but error:", err)
},

OnAllPDU: handlePDU(),

OnClosed: func(state gosmpp.State) {
fmt.Println(state)
},
}, 5*time.Second)
if err != nil {
log.Fatal(err)
}
defer func() {
_ = trans.Close()
}()

// sending SMS(s)
for i := 0; i < 30; i++ {
if err = trans.Transceiver().Submit(newSubmitSM()); err != nil {
fmt.Println(err)
}
time.Sleep(time.Second)
}

}

func handlePDU() func(pdu.PDU) pdu.PDU {
return func(p pdu.PDU) pdu.PDU {
switch pd := p.(type) {
case *pdu.Unbind:
fmt.Println("Unbind Received")
return pd.GetResponse()

case *pdu.UnbindResp:
fmt.Println("UnbindResp Received")

case *pdu.SubmitSMResp:
fmt.Println("SubmitSMResp Received")

case *pdu.GenericNack:
fmt.Println("GenericNack Received")

case *pdu.EnquireLinkResp:
fmt.Println("EnquireLinkResp Received")

case *pdu.EnquireLink:
fmt.Println("EnquireLink Received")
return pd.GetResponse()

case *pdu.DataSM:
fmt.Println("DataSM receiver")
return pd.GetResponse()

case *pdu.DeliverSM:
fmt.Println("DeliverSM receiver")
return pd.GetResponse()
}
return nil
}
}

func newSubmitSM() *pdu.SubmitSM {
// build up submitSM
srcAddr := pdu.NewAddress()
srcAddr.SetTon(5)
srcAddr.SetNpi(0)
_ = srcAddr.SetAddress("00" + "522241")

destAddr := pdu.NewAddress()
destAddr.SetTon(1)
destAddr.SetNpi(1)
_ = destAddr.SetAddress("99" + "522241")

submitSM := pdu.NewSubmitSM().(*pdu.SubmitSM)
submitSM.SourceAddr = srcAddr
submitSM.DestAddr = destAddr
_ = submitSM.Message.SetMessageWithEncoding("Đừng buồn thế dù ngoài kia vẫn mưa nghiễng rợi tý tỵ", data.UCS2)
submitSM.ProtocolID = 0
submitSM.RegisteredDelivery = 1
submitSM.ReplaceIfPresentFlag = 0
submitSM.EsmClass = 0

return submitSM
}
File renamed without changes.
8 changes: 8 additions & 0 deletions pkg.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ type Settings struct {
//
// `Responded` flag indicates this pdu is responded automatically,
// no manual respond needed.
//
// Will be ignored if OnAllPDU is set
OnPDU PDUCallback

// OnReceivingError notifies happened error while reading PDU
Expand All @@ -64,5 +66,11 @@ type Settings struct {
// OnClosed notifies `closed` event due to State.
OnClosed ClosedCallback

// OnAllPDU handles all received PDU from SMSC.
//
// This pdu is NOT responded to automatically,
// manual response/handling is needed
OnAllPDU func(pdu pdu.PDU) pdu.PDU

response func(pdu.PDU)
}
7 changes: 7 additions & 0 deletions receivable.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,13 @@ func (t *receivable) loop() {

func (t *receivable) handleOrClose(p pdu.PDU) (closing bool) {
if p != nil {
if t.settings.OnAllPDU != nil {
r := t.settings.OnAllPDU(p)
if r != nil {
t.settings.response(r)
}
return
}
switch pp := p.(type) {
case *pdu.EnquireLink:
if t.settings.response != nil {
Expand Down
2 changes: 2 additions & 0 deletions transceivable.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ func newTransceivable(conn *Connection, settings Settings) *transceivable {

OnPDU: settings.OnPDU,

OnAllPDU: settings.OnAllPDU,

OnReceivingError: settings.OnReceivingError,

OnClosed: func(state State) {
Expand Down

0 comments on commit 151b333

Please sign in to comment.