Skip to content

Commit

Permalink
added send submit multi
Browse files Browse the repository at this point in the history
  • Loading branch information
Phil Bayfield committed May 12, 2010
1 parent 044c86f commit 02d1588
Show file tree
Hide file tree
Showing 3 changed files with 276 additions and 2 deletions.
8 changes: 7 additions & 1 deletion smpp_param.go
Expand Up @@ -6,8 +6,14 @@ package smpp

// Default params
var (
// Bind defaults
defaultsBind = Params{"systemId": "", "password": "", "systemType": "", "addrTon": SMPPTypeOfNumber(TON_UNKNOWN), "addrNpi": SMPPNumericPlanIndicator(NPI_UNKNOWN), "addressRange": ""}
defaultsSubmitSM = Params{"serviceType": "", "sourceAddrTon": SMPPTypeOfNumber(TON_UNKNOWN), "sourceAddrNpi": SMPPNumericPlanIndicator(NPI_UNKNOWN), "sourceAddr": "", "destAddrTon": SMPPTypeOfNumber(TON_UNKNOWN), "destAddrNpi": SMPPNumericPlanIndicator(NPI_UNKNOWN), "esmClass": SMPPEsmClassESME(ESME_MSG_MODE_DEFAULT), "protocolId": uint8(0x00), "priorityFlag": SMPPPriority(PRIORITY_NORMAL), "schedDelTime": "", "validityPeriod": "", "regDelivery": SMPPDelivery(DELIVERY_NONE), "replaceFlag": uint8(0x00), "dataCoding": SMPPDataCoding(CODING_LATIN1), "smDefaultMsgId": uint8(0x00)}

// SubmitSM defaults
defaultsSubmitSM = Params{"serviceType": "", "sourceAddrTon": SMPPTypeOfNumber(TON_UNKNOWN), "sourceAddrNpi": SMPPNumericPlanIndicator(NPI_UNKNOWN), "sourceAddr": "", "destAddrTon": SMPPTypeOfNumber(TON_UNKNOWN), "destAddrNpi": SMPPNumericPlanIndicator(NPI_UNKNOWN), "esmClass": SMPPEsmClassESME(ESME_MSG_MODE_DEFAULT), "protocolId": uint8(0x00), "priorityFlag": SMPPPriority(PRIORITY_NORMAL), "schedDelTime": "", "validityPeriod": "", "regDelivery": SMPPDelivery(DELIVERY_NONE), "replaceFlag": uint8(0x00), "dataCoding": SMPPDataCoding(CODING_LATIN1), "smDefaultMsgId": uint8(0x00)}

// SubmitMulti defaults
defaultsSubmitMulti = Params{"serviceType": "", "sourceAddrTon": SMPPTypeOfNumber(TON_UNKNOWN), "sourceAddrNpi": SMPPNumericPlanIndicator(NPI_UNKNOWN), "sourceAddr": "", "destAddrTon": SMPPTypeOfNumber(TON_UNKNOWN), "destAddrNpi": SMPPNumericPlanIndicator(NPI_UNKNOWN), "esmClass": SMPPEsmClassESME(ESME_MSG_MODE_DEFAULT), "protocolId": uint8(0x00), "priorityFlag": SMPPPriority(PRIORITY_NORMAL), "schedDelTime": "", "validityPeriod": "", "regDelivery": SMPPDelivery(DELIVERY_NONE), "replaceFlag": uint8(0x00), "dataCoding": SMPPDataCoding(CODING_LATIN1), "smDefaultMsgId": uint8(0x00)}
)

// Params definitions
Expand Down
154 changes: 153 additions & 1 deletion smpp_pdu.go
Expand Up @@ -375,7 +375,7 @@ func (pdu *PDUSubmitSM) write(w *bufio.Writer) (err os.Error) {
return
}
// Create byte array the size of the PDU
p := make([]byte, pdu.Header.CmdLength - 16 - pdu.OptionalLen)
p := make([]byte, pdu.Header.CmdLength - pdu.OptionalLen - 16)
pos := 0
// Copy service type
if len(pdu.ServiceType) > 0 {
Expand Down Expand Up @@ -507,6 +507,158 @@ func (pdu *PDUSubmitSMResp) GetStruct() interface{} {
return *pdu
}

// SubmitMulti PDU
type PDUSubmitMulti struct {
PDUCommon
ServiceType string
SourceAddrTon SMPPTypeOfNumber
SourceAddrNpi SMPPNumericPlanIndicator
SourceAddr string
NumOfDests uint8
DestAddrTon SMPPTypeOfNumber
DestAddrNpi SMPPNumericPlanIndicator
DestAddrs []string
DestLists []string
EsmClass SMPPEsmClassESME
ProtocolId uint8
PriorityFlag SMPPPriority
SchedDelTime string
ValidityPeriod string
RegDelivery SMPPDelivery
ReplaceFlag uint8
DataCoding SMPPDataCoding
SmDefaultMsgId uint8
SmLength uint8
ShortMessage string
}

// Read SubmitMulti PDU
func (pdu *PDUSubmitMulti) read(r *bufio.Reader) (err os.Error) {
return
}

// Write SubmitMulti PDU
func (pdu *PDUSubmitMulti) write(w *bufio.Writer) (err os.Error) {
// Write Header
err = pdu.Header.write(w)
if err != nil {
err = os.NewError("SubmitMulti: Error writing Header")
return
}
// Create byte array the size of the PDU
p := make([]byte, pdu.Header.CmdLength - pdu.OptionalLen - 16)
pos := 0
// Copy service type
if len(pdu.ServiceType) > 0 {
copy(p[pos:len(pdu.ServiceType)], []byte(pdu.ServiceType))
pos += len(pdu.ServiceType)
}
pos ++ // Null terminator
// Source TON
p[pos] = byte(pdu.SourceAddrTon)
pos ++
// Source NPI
p[pos] = byte(pdu.SourceAddrNpi)
pos ++
// Source Address
if len(pdu.SourceAddr) > 0 {
copy(p[pos:pos + len(pdu.SourceAddr)], []byte(pdu.SourceAddr))
pos += len(pdu.SourceAddr)
}
pos ++ // Null terminator
// Number of destinations
p[pos] = byte(pdu.NumOfDests)
pos ++
// Send destination numbers
for _, destNum := range pdu.DestAddrs {
// Number indicator
p[pos] = byte(0x01)
pos ++
// Destination TON
p[pos] = byte(pdu.DestAddrTon)
pos ++
// Destination NPI
p[pos] = byte(pdu.DestAddrNpi)
pos ++
// Copy number
copy(p[pos:pos + len(destNum)], []byte(destNum))
pos += len(destNum) + 1
}
// Send destination lists
for _, destList := range pdu.DestLists {
// List indicator
p[pos] = byte(0x02)
pos ++
// Copy list name
copy(p[pos:pos + len(destList)], []byte(destList))
pos += len(destList) + 1
}
// ESM Class
p[pos] = byte(pdu.EsmClass)
pos ++
// Protocol Id
p[pos] = byte(pdu.ProtocolId)
pos ++
// Priority Flag
p[pos] = byte(pdu.PriorityFlag)
pos ++
// Sheduled Delivery Time
if len(pdu.SchedDelTime) > 0 {
copy(p[pos:pos + len(pdu.SchedDelTime)], []byte(pdu.SchedDelTime))
pos += len(pdu.SchedDelTime)
}
pos ++ // Null terminator
// Validity Period
if len(pdu.ValidityPeriod) > 0 {
copy(p[pos:pos + len(pdu.ValidityPeriod)], []byte(pdu.ValidityPeriod))
pos += len(pdu.ValidityPeriod)
}
pos ++ // Null terminator
// Registered Delivery
p[pos] = byte(pdu.RegDelivery)
pos ++
// Replace Flag
p[pos] = byte(pdu.ReplaceFlag)
pos ++
// Data Coding
p[pos] = byte(pdu.DataCoding)
pos ++
// Default Msg Id
p[pos] = byte(pdu.SmDefaultMsgId)
pos ++
// Msg Length
p[pos] = byte(pdu.SmLength)
pos ++
// Message
if len(pdu.ShortMessage) > 0 {
copy(p[pos:pos + len(pdu.ShortMessage)], []byte(pdu.ShortMessage))
pos += len(pdu.ShortMessage)
}
// Write to buffer
_, err = w.Write(p)
if err != nil {
err = os.NewError("SubmitMulti: Error writing to buffer")
return
}
// Flush write buffer
err = w.Flush()
if err != nil {
err = os.NewError("SubmitMulti: Error flushing write buffer")
return
}
// Optional params
err = pdu.writeOptional(w)
if err != nil {
err = os.NewError("SubmitMulti: Error writing optional params")
}
return
}

// Get Struct
func (pdu *PDUSubmitMulti) GetStruct() interface{} {
return *pdu
}

// PDU Header
type PDUHeader struct {
CmdLength uint32
Expand Down
116 changes: 116 additions & 0 deletions smpp_transmitter.go
Expand Up @@ -14,6 +14,7 @@ type Transmitter struct {
smpp
}

// Submit SM
func (tx *Transmitter) SubmitSM(dest, msg string, params Params, optional ...OptParams) (sequence uint32, msgId string, err os.Error) {
// Check connected and bound
if !tx.connected || !tx.bound {
Expand Down Expand Up @@ -119,3 +120,118 @@ func (tx *Transmitter) SubmitSM(dest, msg string, params Params, optional ...Opt
}
return
}

// Submit Multi
func (tx *Transmitter) SubmitMulti(destNum, destList []string, msg string, params Params, optional ...OptParams) (sequence uint32, unsuccess []string, err os.Error) {
// Check connected and bound
if !tx.connected || !tx.bound {
err = os.NewError("SubmitMulti: A bound connection is required to submit a message")
return
}
// Check destination number and message
if len(destNum) == 0 && len(destList) == 0 {
err = os.NewError("SubmitMulti: At least 1 destination number or list is required")
return
}
// Merge params with defaults
allParams := mergeParams(params, defaultsSubmitMulti)
// Increment sequence number
tx.sequence ++
// PDU header
hdr := new(PDUHeader)
hdr.CmdLength = 32
hdr.CmdId = CMD_SUBMIT_MULTI
hdr.CmdStatus = STATUS_ESME_ROK
hdr.Sequence = tx.sequence
// Mising params cause panic, this provides a clean error/exit
paramOK := false
defer func() {
if !paramOK && recover() != nil {
err = os.NewError("SubmitMulti: Panic, invalid params")
return
}
}()
// Create new PDU
pdu := new(PDUSubmitMulti)
// Populate params
pdu.ServiceType = allParams["serviceType"].(string)
pdu.SourceAddrTon = allParams["sourceAddrTon"].(SMPPTypeOfNumber)
pdu.SourceAddrNpi = allParams["sourceAddrNpi"].(SMPPNumericPlanIndicator)
pdu.SourceAddr = allParams["sourceAddr"].(string)
pdu.NumOfDests = uint8(len(destNum) + len(destList))
pdu.DestAddrTon = allParams["destAddrTon"].(SMPPTypeOfNumber)
pdu.DestAddrNpi = allParams["destAddrNpi"].(SMPPNumericPlanIndicator)
pdu.DestAddrs = destNum
pdu.DestLists = destList
pdu.EsmClass = allParams["esmClass"].(SMPPEsmClassESME)
pdu.ProtocolId = allParams["protocolId"].(uint8)
pdu.PriorityFlag = allParams["priorityFlag"].(SMPPPriority)
pdu.SchedDelTime = allParams["schedDelTime"].(string)
pdu.ValidityPeriod = allParams["validityPeriod"].(string)
pdu.RegDelivery = allParams["regDelivery"].(SMPPDelivery)
pdu.ReplaceFlag = allParams["replaceFlag"].(uint8)
pdu.DataCoding = allParams["dataCoding"].(SMPPDataCoding)
pdu.SmDefaultMsgId = allParams["smDefaultMsgId"].(uint8)
pdu.SmLength = uint8(len(msg))
pdu.ShortMessage = msg
// Add length of strings to pdu length
hdr.CmdLength += uint32(len(pdu.ServiceType))
hdr.CmdLength += uint32(len(pdu.SourceAddr))
hdr.CmdLength += uint32(len(pdu.SchedDelTime))
hdr.CmdLength += uint32(len(pdu.ValidityPeriod))
hdr.CmdLength += uint32(len(pdu.ShortMessage))
// Add length of any numbers to the pdu length
if len(destNum) > 0 {
for _, num := range destNum {
hdr.CmdLength += uint32(len(num)) + 4
}
}
// Add length of any list names to the pdu length
if len(destList) > 0 {
for _, list := range destList {
hdr.CmdLength += uint32(len(list)) + 2
}
}
// Calculate size of optional params
if len(optional) > 0 && len(optional[0]) > 0 {
pdu.Optional = optional[0]
for _, val := range optional[0] {
v := reflect.NewValue(val)
switch t := v.(type) {
default:
err = os.NewError("SubmitMulti: Invalid optional param format")
return
case *reflect.StringValue:
hdr.CmdLength += uint32(len(val.(string)))
pdu.OptionalLen += uint32(len(val.(string)))
case *reflect.Uint8Value:
hdr.CmdLength ++
pdu.OptionalLen ++
case *reflect.Uint16Value:
hdr.CmdLength += 2
pdu.OptionalLen += 2
case *reflect.Uint32Value:
hdr.CmdLength += 4
pdu.OptionalLen += 4
}
// Add 4 bytes for optional param header
hdr.CmdLength += 4
pdu.OptionalLen += 4
}
}
// Params were fine 'disable' the recover
paramOK = true
// Send PDU
pdu.setHeader(hdr)
err = pdu.write(tx.writer)
if err != nil {
return
}
// If not async get the response
if tx.async {
sequence = tx.sequence
} else {

}
return
}

0 comments on commit 02d1588

Please sign in to comment.