Permalink
Browse files

working towards async/sync usage and generic response method, still w…

…ork in progress
  • Loading branch information...
1 parent c40a317 commit 316a54f34ff32f8e37e39b67229240971a040db1 Phil Bayfield committed May 9, 2010
Showing with 406 additions and 457 deletions.
  1. +102 −65 smpp.go
  2. +1 −0 smpp_const.go
  3. +251 −324 smpp_pdu.go
  4. +52 −68 smpp_transmitter.go
View
167 smpp.go
@@ -19,6 +19,7 @@ type smpp struct {
writer *bufio.Writer
connected bool
bound bool
+ async bool
sequence uint32
}
@@ -43,18 +44,18 @@ func (smpp *smpp) close() (err os.Error) {
return
}
-// Send bind request
+// Send bind request (called via NewTransmitter/NewReceiver/NewTransceiver) always synchronous
func (smpp *smpp) bind(cmd, rcmd SMPPCommand, params Params) (err os.Error) {
// Sequence number starts at 1
smpp.sequence ++
// Create bind PDU
- pdu := new(pduBind)
+ pdu := new(PDUBind)
// PDU header
- pdu.header = new(pduHeader)
- pdu.header.cmdLength = 23 // Min length
- pdu.header.cmdId = cmd
- pdu.header.cmdStatus = STATUS_ESME_ROK
- pdu.header.sequence = smpp.sequence
+ pdu.Header = new(PDUHeader)
+ pdu.Header.CmdLength = 23 // Min length
+ pdu.Header.CmdId = cmd
+ pdu.Header.CmdStatus = STATUS_ESME_ROK
+ pdu.Header.Sequence = smpp.sequence
// Mising params cause panic, this provides a clean error/exit
paramOK := false
defer func() {
@@ -64,51 +65,37 @@ func (smpp *smpp) bind(cmd, rcmd SMPPCommand, params Params) (err os.Error) {
}
}()
// Populate params
- pdu.systemId = params["systemId"].(string)
- pdu.password = params["password"].(string)
- pdu.systemType = params["systemType"].(string)
- pdu.ifVersion = SMPP_INTERFACE_VER
- pdu.addrTon = params["addrTon"].(SMPPTypeOfNumber)
- pdu.addrNpi = params["addrNpi"].(SMPPNumericPlanIndicator)
- pdu.addressRange = params["addressRange"].(string)
+ pdu.SystemId = params["systemId"].(string)
+ pdu.Password = params["password"].(string)
+ pdu.SystemType = params["systemType"].(string)
+ pdu.IfVersion = SMPP_INTERFACE_VER
+ pdu.AddrTon = params["addrTon"].(SMPPTypeOfNumber)
+ pdu.AddrNpi = params["addrNpi"].(SMPPNumericPlanIndicator)
+ pdu.AddressRange = params["addressRange"].(string)
// Add length of strings to pdu length
- pdu.header.cmdLength += uint32(len(pdu.systemId))
- pdu.header.cmdLength += uint32(len(pdu.password))
- pdu.header.cmdLength += uint32(len(pdu.systemType))
- pdu.header.cmdLength += uint32(len(pdu.addressRange))
+ pdu.Header.CmdLength += uint32(len(pdu.SystemId))
+ pdu.Header.CmdLength += uint32(len(pdu.Password))
+ pdu.Header.CmdLength += uint32(len(pdu.SystemType))
+ pdu.Header.CmdLength += uint32(len(pdu.AddressRange))
// Params were fine 'disable' the recover
paramOK = true
// Send PDU
err = pdu.write(smpp.writer)
if err != nil {
return
}
- // Create bind response PDU
- rpdu := new(pduBindResp)
- // Read PDU data
- err = rpdu.read(smpp.reader)
- if err != nil {
- return
- }
- // Validate PDU data
- if rpdu.header.cmdId != rcmd {
- err = os.NewError("Bind Response: Invalid command")
- return
- }
- if rpdu.header.cmdStatus != STATUS_ESME_ROK {
- err = os.NewError("Bind Response: Error received from SMSC")
- return
- }
- if rpdu.header.sequence != smpp.sequence {
- err = os.NewError("Bind Response: Invalid sequence number")
- return
- }
- smpp.bound = true
+ // Get response
+ _, err = smpp.GetResp(rcmd, smpp.sequence)
return
}
+// Set async commands on/offer (trancsceiver is always async)
+func (smpp *smpp) Async(async bool) {
+ smpp.async = async
+}
+
// Send unbind request
-func (smpp *smpp) Unbind() (err os.Error) {
+func (smpp *smpp) Unbind() (sequence uint32, err os.Error) {
// Check connected and bound
if !smpp.connected || !smpp.bound {
err = os.NewError("Unbind: A bound connection is required to unbind")
@@ -117,41 +104,91 @@ func (smpp *smpp) Unbind() (err os.Error) {
// Increment sequence number
smpp.sequence ++
// Create bind PDU
- pdu := new(pduUnbind)
+ pdu := new(PDUUnbind)
// PDU header
- pdu.header = new(pduHeader)
- pdu.header.cmdLength = 16
- pdu.header.cmdId = CMD_UNBIND
- pdu.header.cmdStatus = STATUS_ESME_ROK
- pdu.header.sequence = smpp.sequence
+ pdu.Header = new(PDUHeader)
+ pdu.Header.CmdLength = 16
+ pdu.Header.CmdId = CMD_UNBIND
+ pdu.Header.CmdStatus = STATUS_ESME_ROK
+ pdu.Header.Sequence = smpp.sequence
// Send PDU
err = pdu.write(smpp.writer)
if err != nil {
return
}
- // Create unbind response PDU
- rpdu := new(pduUnbindResp)
- // Read PDU data
- err = rpdu.read(smpp.reader)
- if err != nil {
- return
+ // If not async get the response
+ if smpp.async {
+ sequence = smpp.sequence
+ } else {
+ _, err = smpp.GetResp(CMD_UNBIND_RESP, smpp.sequence)
}
- // Validate PDU data
- if rpdu.header.cmdId != CMD_UNBIND_RESP {
- err = os.NewError("Unbind Response: Invalid command")
- return
+ return
+}
+
+// Get response PDU
+func (smpp *smpp) GetResp(cmd SMPPCommand, sequence uint32) (rpdu PDU, err os.Error) {
+ // Has packet been read
+ pduRead := false
+ // Read the header
+ hdr := new(PDUHeader)
+ err = hdr.read(smpp.reader)
+ // Defer reading rest of packet from buffer on error
+ defer func() {
+ if err != nil && !pduRead && hdr.CmdLength > 16 {
+ p := make([]byte, hdr.CmdLength - 16)
+ smpp.reader.Read(p)
+ }
+ }()
+ // Check cmd and/or sequence if not 0
+ if cmd != CMD_NONE && hdr.CmdId != cmd {
+ err = os.NewError("Get Response: Invalid command")
+ return nil, err
}
- if rpdu.header.cmdStatus != STATUS_ESME_ROK {
- err = os.NewError("Unbind Response: Error received from SMSC")
- return
+ // Check sequence number if not 0
+ if sequence > 0 && hdr.Sequence != sequence {
+ err = os.NewError("Get Response: Invalid sequence number")
+ return nil, err
}
- if rpdu.header.sequence != smpp.sequence {
- err = os.NewError("Unbind Response: Invalid sequence number")
- return
+ // Check for error response
+ if hdr.CmdStatus != STATUS_ESME_ROK {
+ err = os.NewError("Get Response: PDU contains an error")
+ return nil, err
+ }
+ // Set PDU as read (to disable the deferred read)
+ pduRead = true
+ // Get response PDU
+ switch hdr.CmdId {
+ // Default unhandled PDU
+ default:
+ err = os.NewError("Get Response: Unknown or unhandled PDU received")
+ return nil, err
+ // Bind responses
+ case CMD_BIND_RECEIVER_RESP, CMD_BIND_TRANSMITTER_RESP, CMD_BIND_TRANSCEIVER_RESP:
+ rpdu = new(PDUBindResp)
+ err = rpdu.read(smpp.reader, hdr)
+ if err != nil {
+ return nil, err
+ }
+ // Set connection as bound
+ smpp.bound = true
+ // Unbind response
+ case CMD_UNBIND_RESP:
+ rpdu = new(PDUUnbindResp)
+ err = rpdu.read(smpp.reader, hdr)
+ if err != nil {
+ return nil, err
+ }
+ // Set connection as unbound and disconnect
+ smpp.bound = false
+ smpp.close()
+ // SubmitSM response
+ case CMD_SUBMIT_SM_RESP:
+ rpdu = new(PDUSubmitSMResp)
+ err = rpdu.read(smpp.reader, hdr)
+ if err != nil {
+ return nil, err
+ }
}
- // Disconnect
- smpp.bound = false
- smpp.close()
return
}
View
@@ -11,6 +11,7 @@ const (
type SMPPCommand uint32
const (
+ CMD_NONE = 0x00000000
CMD_GENERIC_NACK = 0x80000000
CMD_BIND_RECEIVER = 0x00000001
CMD_BIND_RECEIVER_RESP = 0x80000001
Oops, something went wrong.

0 comments on commit 316a54f

Please sign in to comment.