Skip to content

Commit

Permalink
Issue8 (#9)
Browse files Browse the repository at this point in the history
`failed submits` mode implemented
  • Loading branch information
ukarim authored Sep 30, 2023
1 parent 70916ca commit 67dfdfc
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 25 deletions.
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@ docker build -t smscsim .
docker run -p 2775:2775 -p 12775:12775 smscsim
```

3) or use prebuild docker image (from hub.docker.com)
3) or build and run with docker-compose

```
docker-compose up
```

4) or use prebuild docker image (from hub.docker.com)

```
docker run -p 2775:2775 -p 12775:12775 ukarim/smscsim
Expand Down Expand Up @@ -55,4 +61,6 @@ delivered to the selected smpp session using a _deliver_sm_ PDU.

* SMSC_PORT - override default smpp port
* WEB_PORT - override default web port

* FAILED_SUBMITS - if this is set to true, submit_sm requests will fail
- for submit_sm with even sequence number smscsim will return submit_sm_resp with command_status set to 0x00000008 (System Error)
- for submit_sm with odd sequence number smscsim will return DLR with UNDELIVERABLE message state
3 changes: 2 additions & 1 deletion docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ version: '3'

services:
smscsim:
image: ukarim/smscsim
build: .
ports:
- '2775:2775'
- '12775:12775'
environment:
- TZ=Asia/Almaty
# - FAILED_SUBMITS=true

3 changes: 2 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ var wg sync.WaitGroup
func main() {
smscPort := getPort("SMSC_PORT", 2775)
webPort := getPort("WEB_PORT", 12775)
failedSubmits := "true" == os.Getenv("FAILED_SUBMITS")

wg.Add(2)

// start smpp server
smsc := NewSmsc()
smsc := NewSmsc(failedSubmits)
go smsc.Start(smscPort, wg)

// start web server
Expand Down
56 changes: 35 additions & 21 deletions smsc.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const (
STS_INVALID_CMD = 0x00000003
STS_INV_BIND_STS = 0x00000004
STS_ALREADY_BOUND = 0x00000005
STS_SYS_ERROR = 0x00000008
)

// data coding
Expand Down Expand Up @@ -66,12 +67,13 @@ type Tlv struct {
}

type Smsc struct {
Sessions map[int]Session
Sessions map[int]Session
FailedSubmits bool
}

func NewSmsc() Smsc {
func NewSmsc(failedSubmits bool) Smsc {
sessions := make(map[int]Session)
return Smsc{sessions}
return Smsc{sessions, failedSubmits}
}

func (smsc *Smsc) Start(port int, wg sync.WaitGroup) {
Expand Down Expand Up @@ -264,20 +266,25 @@ func handleSmppConnection(smsc *Smsc, conn net.Conn) {
// prepare submit_sm_resp
msgId := strconv.Itoa(rand.Int())

respBytes = stringBodyPDU(SUBMIT_SM_RESP, STS_OK, seqNum, msgId)

if registeredDlr != 0 {
go func() {
time.Sleep(2000 * time.Millisecond)
now := time.Now()
dlr := deliveryReceiptPDU(msgId, now, now)
if _, err := conn.Write(dlr); err != nil {
log.Printf("error sending delivery receipt to system_id[%s] due %v.", systemId, err)
return
} else {
log.Printf("delivery receipt for message [%s] was send to system_id[%s]", msgId, systemId)
}
}()
if smsc.FailedSubmits && seqNum%2 == 0 {
// return error response
respBytes = headerPDU(SUBMIT_SM_RESP, STS_SYS_ERROR, seqNum)
} else {
respBytes = stringBodyPDU(SUBMIT_SM_RESP, STS_OK, seqNum, msgId)
// send DLR if necessary
if registeredDlr != 0 {
go func() {
time.Sleep(2000 * time.Millisecond)
now := time.Now()
dlr := deliveryReceiptPDU(msgId, now, now, smsc.FailedSubmits)
if _, err := conn.Write(dlr); err != nil {
log.Printf("error sending delivery receipt to system_id[%s] due %v.", systemId, err)
return
} else {
log.Printf("delivery receipt for message [%s] was send to system_id[%s]", msgId, systemId)
}
}()
}
}
}
case DELIVER_SM_RESP: // deliver_sm_resp
Expand Down Expand Up @@ -334,12 +341,19 @@ func stringBodyPDU(cmdId, cmdSts, seqNum uint32, body string) []byte {
return buf
}

const DELIVERY_RECEIPT_FORMAT = "id:%s sub:001 dlvrd:001 submit date:%s done date:%s stat:DELIVRD err:000 Text:..."
const DLR_RECEIPT_FORMAT = "id:%s sub:001 dlvrd:001 submit date:%s done date:%s stat:DELIVRD err:000 Text:..."
const DLR_RECEIPT_FORMAT_FAILED = "id:%s sub:001 dlvrd:000 submit date:%s done date:%s stat:UNDELIV err:069 Text:..."

func deliveryReceiptPDU(msgId string, submitDate, doneDate time.Time) []byte {
func deliveryReceiptPDU(msgId string, submitDate, doneDate time.Time, failedDeliv bool) []byte {
sbtDateFrmt := submitDate.Format("0601021504")
doneDateFrmt := doneDate.Format("0601021504")
deliveryReceipt := fmt.Sprintf(DELIVERY_RECEIPT_FORMAT, msgId, sbtDateFrmt, doneDateFrmt)
dlrFmt := DLR_RECEIPT_FORMAT
msgState := []byte{2}
if failedDeliv {
dlrFmt = DLR_RECEIPT_FORMAT_FAILED
msgState = []byte{5}
}
deliveryReceipt := fmt.Sprintf(dlrFmt, msgId, sbtDateFrmt, doneDateFrmt)
var tlvs []Tlv

// receipted_msg_id TLV
Expand All @@ -350,7 +364,7 @@ func deliveryReceiptPDU(msgId string, submitDate, doneDate time.Time) []byte {
tlvs = append(tlvs, receiptMsgId)

// message_state TLV
msgStateTlv := Tlv{TLV_MESSAGE_STATE, 1, []byte{2}} // 2 - delivered
msgStateTlv := Tlv{TLV_MESSAGE_STATE, 1, msgState}
tlvs = append(tlvs, msgStateTlv)

return deliverSmPDU("", "", []byte(deliveryReceipt), CODING_DEFAULT, rand.Int(), tlvs)
Expand Down

0 comments on commit 67dfdfc

Please sign in to comment.