Kannel: Open Source WAP and SMS gateway  svn-r5262
smpp_pdu.c File Reference
#include <string.h>
#include "smpp_pdu.h"
#include "smpp_pdu.def"

Go to the source code of this file.

Data Structures

struct  smpp_tlv
 

Macros

#define MIN_SMPP_PDU_LEN   (4*4)
 
#define MAX_SMPP_PDU_LEN   (7424)
 
#define DEFAULT_SMSC_ID   "def;ault"
 
#define OPTIONAL_BEGIN
 
#define TLV_INTEGER(name, octets)   OCTETS(name, octets)
 
#define TLV_NULTERMINATED(name, max_len)   OCTETS(name, max_len)
 
#define TLV_OCTETS(name, min_len, max_len)   OCTETS(name, min_len)
 
#define OPTIONAL_END
 
#define INTEGER(name, octets)   OCTETS(name, octets)
 
#define NULTERMINATED(name, max_octets)   OCTETS(name, max_octets)
 
#define OCTETS(name, field_giving_octetst)
 
#define PDU(name, id, fields)
 
#define OPTIONAL_BEGIN
 
#define TLV_INTEGER(name, octets)   p->name = -1;
 
#define TLV_NULTERMINATED(name, max_len)   p->name = NULL;
 
#define TLV_OCTETS(name, min_len, max_len)   p->name = NULL;
 
#define OPTIONAL_END   p->tlv = dict_create(1024, octstr_destroy_item);
 
#define INTEGER(name, octets)   p->name = 0;
 
#define NULTERMINATED(name, max_octets)   p->name = NULL;
 
#define OCTETS(name, field_giving_octetst)   p->name = NULL;
 
#define PDU(name, id, fields)
 
#define OPTIONAL_BEGIN
 
#define TLV_INTEGER(name, octets)   p->name = -1;
 
#define TLV_NULTERMINATED(name, max_octets)   octstr_destroy(p->name);
 
#define TLV_OCTETS(name, min_len, max_len)   octstr_destroy(p->name);
 
#define OPTIONAL_END   dict_destroy(p->tlv);
 
#define INTEGER(name, octets)   p->name = 0; /* Make sure "p" is used */
 
#define NULTERMINATED(name, max_octets)   octstr_destroy(p->name);
 
#define OCTETS(name, field_giving_octets)   octstr_destroy(p->name);
 
#define PDU(name, id, fields)   case id: { struct name *p = &pdu->u.name; fields } break;
 
#define OPTIONAL_BEGIN
 
#define TLV_INTEGER(name, octets)
 
#define TLV_NULTERMINATED(name, max_len)
 
#define TLV_OCTETS(name, min_len, max_len)
 
#define OPTIONAL_END
 
#define INTEGER(name, octets)   p = *(&p);
 
#define NULTERMINATED(name, max_octets)   p = *(&p);
 
#define OCTETS(name, field_giving_octets)   p->field_giving_octets = octstr_len(p->name);
 
#define PDU(name, id, fields)   case id: { struct name *p = &pdu->u.name; fields } break;
 
#define TL(name, octets)
 
#define OPTIONAL_BEGIN
 
#define TLV_INTEGER(name, octets)
 
#define TLV_NULTERMINATED(name, max_len)
 
#define TLV_OCTETS(name, min_len, max_len)
 
#define OPTIONAL_END
 
#define INTEGER(name, octets)   append_encoded_integer(os, p->name, octets);
 
#define NULTERMINATED(name, max_octets)
 
#define OCTETS(name, field_giving_octets)   if (p->name) octstr_append(os, p->name);
 
#define PDU(name, id, fields)   case id: { struct name *p = &pdu->u.name; fields } break;
 
#define OPTIONAL_BEGIN
 
#define TLV_INTEGER(mname, octets)
 
#define TLV_NULTERMINATED(mname, max_len)
 
#define TLV_OCTETS(mname, min_len, max_len)
 
#define OPTIONAL_END
 
#define INTEGER(name, octets)
 
#define NULTERMINATED(name, max_octets)
 
#define OCTETS(name, field_giving_octets)
 
#define PDU(name, id, fields)   case id: { struct name *p = &pdu->u.name; fields } break;
 
#define OPTIONAL_BEGIN
 
#define TLV_INTEGER(name, max_len)
 
#define TLV_NULTERMINATED(name, max_len)
 
#define TLV_OCTETS(name, min_len, max_len)
 
#define OPTIONAL_END
 
#define INTEGER(name, octets)   debug("sms.smpp", 0, " %s: %lu = 0x%08lx", #name, p->name, p->name);
 
#define NULTERMINATED(name, max_octets)   octstr_dump_short(p->name, 2, #name);
 
#define OCTETS(name, field_giving_octets)   octstr_dump_short(p->name, 2, #name);
 
#define PDU(name, id, fields)   case id: { struct name *p = &pdu->u.name; fields } break;
 
#define OPTIONAL_BEGIN
 
#define TLV_INTEGER(name, max_len)
 
#define TLV_NULTERMINATED(name, max_len)
 
#define TLV_OCTETS(name, min_len, max_len)
 
#define OPTIONAL_END
 
#define INTEGER(name, octets)   octstr_format_append(str, " [%s:0:0x%08lx]", #name, p->name);
 
#define NULTERMINATED(name, max_octets)   octstr_format_append(str, " [%s:%d:%E]", #name, octstr_len(p->name), (p->name != NULL ? p->name : octstr_imm("NULL")));
 
#define OCTETS(name, field_giving_octets)   octstr_format_append(str, " [%s:%d:%E]", #name, octstr_len(p->name), (p->name != NULL ? p->name : octstr_imm("NULL")));
 
#define PDU(name, id, fields)   case id: { struct name *p = &pdu->u.name; fields } break;
 

Functions

static void smpp_tlv_destroy (struct smpp_tlv *tlv)
 
void smpp_tlv_add_constant (Octstr *smsc_id, Dict **tlvs)
 
static struct smpp_tlvsmpp_tlv_get_by_name (Octstr *smsc_id, Octstr *name)
 
static struct smpp_tlvsmpp_tlv_get_by_tag (Octstr *smsc_id, long tag)
 
int smpp_pdu_init (Cfg *cfg)
 
int smpp_pdu_shutdown (void)
 
static long decode_integer (Octstr *os, long pos, int octets)
 
static void append_encoded_integer (Octstr *os, unsigned long u, long octets)
 
static int copy_until_nul (const char *field_name, Octstr *os, long *pos, long max_octets, Octstr **data)
 
static int is_defined_field (long type, const char *field_name)
 
SMPP_PDUsmpp_pdu_create (unsigned long type, unsigned long seq_no)
 
void smpp_pdu_destroy (SMPP_PDU *pdu)
 
Octstrsmpp_pdu_pack (Octstr *smsc_id, SMPP_PDU *pdu)
 
SMPP_PDUsmpp_pdu_unpack (Octstr *smsc_id, Octstr *data_without_len)
 
void smpp_pdu_dump (Octstr *smsc_id, SMPP_PDU *pdu)
 
void smpp_pdu_dump_line (Octstr *smsc_id, SMPP_PDU *pdu)
 
long smpp_pdu_read_len (Connection *conn)
 
Octstrsmpp_pdu_read_data (Connection *conn, long len)
 
const char * smpp_error_to_string (enum SMPP_ERROR_MESSAGES error)
 

Variables

static Dicttlvs_by_tag
 
static Dicttlvs_by_name
 
static Dicttlvs_by_const
 
static Listtlvs
 
static int initialized
 

Macro Definition Documentation

◆ DEFAULT_SMSC_ID

#define DEFAULT_SMSC_ID   "def;ault"

Definition at line 73 of file smpp_pdu.c.

Referenced by smpp_pdu_init(), smpp_tlv_get_by_name(), and smpp_tlv_get_by_tag().

◆ INTEGER [1/8]

#define INTEGER (   name,
  octets 
)    OCTETS(name, octets)

◆ INTEGER [2/8]

#define INTEGER (   name,
  octets 
)    p->name = 0;

◆ INTEGER [3/8]

#define INTEGER (   name,
  octets 
)    p->name = 0; /* Make sure "p" is used */

◆ INTEGER [4/8]

#define INTEGER (   name,
  octets 
)    p = *(&p);

◆ INTEGER [5/8]

#define INTEGER (   name,
  octets 
)    append_encoded_integer(os, p->name, octets);

◆ INTEGER [6/8]

#define INTEGER (   name,
  octets 
)
Value:
if ((p->name = decode_integer(data_without_len, pos, octets)) == -1) \
goto err; \
pos += octets;
static long decode_integer(Octstr *os, long pos, int octets)
Definition: smpp_pdu.c:330

◆ INTEGER [7/8]

#define INTEGER (   name,
  octets 
)    debug("sms.smpp", 0, " %s: %lu = 0x%08lx", #name, p->name, p->name);

◆ INTEGER [8/8]

#define INTEGER (   name,
  octets 
)    octstr_format_append(str, " [%s:0:0x%08lx]", #name, p->name);

◆ MAX_SMPP_PDU_LEN

#define MAX_SMPP_PDU_LEN   (7424)

Definition at line 71 of file smpp_pdu.c.

Referenced by smpp_pdu_read_len().

◆ MIN_SMPP_PDU_LEN

#define MIN_SMPP_PDU_LEN   (4*4)

Definition at line 69 of file smpp_pdu.c.

Referenced by smpp_pdu_read_len().

◆ NULTERMINATED [1/8]

#define NULTERMINATED (   name,
  max_octets 
)    OCTETS(name, max_octets)

◆ NULTERMINATED [2/8]

#define NULTERMINATED (   name,
  max_octets 
)    p->name = NULL;

◆ NULTERMINATED [3/8]

#define NULTERMINATED (   name,
  max_octets 
)    octstr_destroy(p->name);

◆ NULTERMINATED [4/8]

#define NULTERMINATED (   name,
  max_octets 
)    p = *(&p);

◆ NULTERMINATED [5/8]

#define NULTERMINATED (   name,
  max_octets 
)
Value:
if (p->name != NULL) { \
if (octstr_len(p->name) >= max_octets) { \
warning(0, "SMPP: PDU element <%s> too long " \
"(length is %ld, should be %d)", \
#name, octstr_len(p->name), max_octets-1); \
temp = octstr_copy(p->name, 0, max_octets-1); \
} else \
temp = octstr_duplicate(p->name); \
octstr_append(os, temp); \
octstr_destroy(temp); \
} \
octstr_append_char(os, '\0');
#define octstr_copy(ostr, from, len)
Definition: octstr.h:178
#define octstr_duplicate(ostr)
Definition: octstr.h:187
char * name
Definition: smsc_cimd2.c:212
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340

◆ NULTERMINATED [6/8]

#define NULTERMINATED (   name,
  max_octets 
)
Value:
/* just warn about errors but not fail */ \
copy_until_nul(#name, data_without_len, &pos, max_octets, &p->name);
char * name
Definition: smsc_cimd2.c:212

◆ NULTERMINATED [7/8]

#define NULTERMINATED (   name,
  max_octets 
)    octstr_dump_short(p->name, 2, #name);

◆ NULTERMINATED [8/8]

#define NULTERMINATED (   name,
  max_octets 
)    octstr_format_append(str, " [%s:%d:%E]", #name, octstr_len(p->name), (p->name != NULL ? p->name : octstr_imm("NULL")));

◆ OCTETS [1/8]

#define OCTETS (   name,
  field_giving_octetst 
)
Value:
if (strncmp(#name, field_name, sizeof(#name) - 1) == 0) \
return 1;
char * name
Definition: smsc_cimd2.c:212

◆ OCTETS [2/8]

#define OCTETS (   name,
  field_giving_octetst 
)    p->name = NULL;

◆ OCTETS [3/8]

#define OCTETS (   name,
  field_giving_octets 
)    octstr_destroy(p->name);

◆ OCTETS [4/8]

#define OCTETS (   name,
  field_giving_octets 
)    p->field_giving_octets = octstr_len(p->name);

◆ OCTETS [5/8]

#define OCTETS (   name,
  field_giving_octets 
)    if (p->name) octstr_append(os, p->name);

◆ OCTETS [6/8]

#define OCTETS (   name,
  field_giving_octets 
)
Value:
p->name = octstr_copy(data_without_len, pos, \
p->field_giving_octets); \
if (p->field_giving_octets != (unsigned long) octstr_len(p->name)) { \
error(0, "smpp_pdu: error while unpacking '" #name "', " \
"len is %ld but should have been %ld, dropping.", \
octstr_len(p->name), p->field_giving_octets); \
goto err; \
} else { \
pos += p->field_giving_octets; \
}
#define octstr_copy(ostr, from, len)
Definition: octstr.h:178
char * name
Definition: smsc_cimd2.c:212
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340

◆ OCTETS [7/8]

#define OCTETS (   name,
  field_giving_octets 
)    octstr_dump_short(p->name, 2, #name);

◆ OCTETS [8/8]

#define OCTETS (   name,
  field_giving_octets 
)    octstr_format_append(str, " [%s:%d:%E]", #name, octstr_len(p->name), (p->name != NULL ? p->name : octstr_imm("NULL")));

◆ OPTIONAL_BEGIN [1/8]

#define OPTIONAL_BEGIN

◆ OPTIONAL_BEGIN [2/8]

#define OPTIONAL_BEGIN

◆ OPTIONAL_BEGIN [3/8]

#define OPTIONAL_BEGIN

◆ OPTIONAL_BEGIN [4/8]

#define OPTIONAL_BEGIN

◆ OPTIONAL_BEGIN [5/8]

#define OPTIONAL_BEGIN

◆ OPTIONAL_BEGIN [6/8]

#define OPTIONAL_BEGIN
Value:
{ /* Read optional parameters */ \
while (pos + 4 <= len) { \
struct smpp_tlv *tlv; \
unsigned long opt_tag, opt_len; \
opt_tag = decode_integer(data_without_len, pos, 2); pos += 2; \
debug("sms.smpp", 0, "Optional parameter tag (0x%04lx)", opt_tag); \
opt_len = decode_integer(data_without_len, pos, 2); pos += 2; \
debug("sms.smpp", 0, "Optional parameter length read as %ld", opt_len); \
/* check configured TLVs */ \
tlv = smpp_tlv_get_by_tag(smsc_id, opt_tag); \
if (tlv != NULL) debug("sms.smpp", 0, "Found configured optional parameter `%s'", octstr_get_cstr(tlv->name));
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
static Octstr * smsc_id
Definition: mtbatch.c:98
static struct smpp_tlv * smpp_tlv_get_by_tag(Octstr *smsc_id, long tag)
Definition: smpp_pdu.c:155
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
static long decode_integer(Octstr *os, long pos, int octets)
Definition: smpp_pdu.c:330

◆ OPTIONAL_BEGIN [7/8]

#define OPTIONAL_BEGIN

◆ OPTIONAL_BEGIN [8/8]

#define OPTIONAL_BEGIN

◆ OPTIONAL_END [1/8]

#define OPTIONAL_END

◆ OPTIONAL_END [2/8]

#define OPTIONAL_END   p->tlv = dict_create(1024, octstr_destroy_item);

◆ OPTIONAL_END [3/8]

#define OPTIONAL_END   dict_destroy(p->tlv);

◆ OPTIONAL_END [4/8]

#define OPTIONAL_END

◆ OPTIONAL_END [5/8]

#define OPTIONAL_END

◆ OPTIONAL_END [6/8]

#define OPTIONAL_END

◆ OPTIONAL_END [7/8]

#define OPTIONAL_END
Value:
if (p->tlv != NULL) { \
List *keys; \
Octstr *key; \
struct smpp_tlv *tlv; \
keys = dict_keys(p->tlv); \
while(keys != NULL && (key = gwlist_extract_first(keys)) != NULL) { \
if (tlv != NULL) { \
octstr_dump_short(dict_get(p->tlv, key), 2, octstr_get_cstr(key)); \
} \
octstr_destroy(key); \
} \
gwlist_destroy(keys, octstr_destroy_item); \
}
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
void * gwlist_extract_first(List *list)
Definition: list.c:305
void * dict_get(Dict *dict, Octstr *key)
Definition: dict.c:286
static Octstr * smsc_id
Definition: mtbatch.c:98
void octstr_destroy_item(void *os)
Definition: octstr.c:334
static struct smpp_tlv * smpp_tlv_get_by_name(Octstr *smsc_id, Octstr *name)
Definition: smpp_pdu.c:132
List * dict_keys(Dict *dict)
Definition: dict.c:347

◆ OPTIONAL_END [8/8]

#define OPTIONAL_END
Value:
if (p->tlv != NULL) { \
List *keys; \
Octstr *key; \
struct smpp_tlv *tlv; \
keys = dict_keys(p->tlv); \
while(keys != NULL && (key = gwlist_extract_first(keys)) != NULL) { \
if (tlv != NULL) { \
Octstr *val = dict_get(p->tlv, key); \
octstr_format_append(str, " [%E:%d:%E]", key, octstr_len(val), val); \
} \
octstr_destroy(key); \
} \
gwlist_destroy(keys, octstr_destroy_item); \
}
void * gwlist_extract_first(List *list)
Definition: list.c:305
void * dict_get(Dict *dict, Octstr *key)
Definition: dict.c:286
static Octstr * smsc_id
Definition: mtbatch.c:98
void octstr_destroy_item(void *os)
Definition: octstr.c:334
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
static struct smpp_tlv * smpp_tlv_get_by_name(Octstr *smsc_id, Octstr *name)
Definition: smpp_pdu.c:132
List * dict_keys(Dict *dict)
Definition: dict.c:347

◆ PDU [1/8]

#define PDU (   name,
  id,
  fields 
)
Value:
case id: { \
fields \
} break;

◆ PDU [2/8]

#define PDU (   name,
  id,
  fields 
)
Value:
case id: { \
struct name *p = &pdu->u.name; \
pdu->type_name = #name; \
fields \
p->command_id = type; \
p->sequence_number = seq_no; \
} break;
int type
Definition: smsc_cimd2.c:215
char * name
Definition: smsc_cimd2.c:212

◆ PDU [3/8]

#define PDU (   name,
  id,
  fields 
)    case id: { struct name *p = &pdu->u.name; fields } break;

◆ PDU [4/8]

#define PDU (   name,
  id,
  fields 
)    case id: { struct name *p = &pdu->u.name; fields } break;

◆ PDU [5/8]

#define PDU (   name,
  id,
  fields 
)    case id: { struct name *p = &pdu->u.name; fields } break;

◆ PDU [6/8]

#define PDU (   name,
  id,
  fields 
)    case id: { struct name *p = &pdu->u.name; fields } break;

◆ PDU [7/8]

#define PDU (   name,
  id,
  fields 
)    case id: { struct name *p = &pdu->u.name; fields } break;

◆ PDU [8/8]

#define PDU (   name,
  id,
  fields 
)    case id: { struct name *p = &pdu->u.name; fields } break;

◆ TL

#define TL (   name,
  octets 
)
Value:
append_encoded_integer(os, SMPP_##name, 2); \
append_encoded_integer(os, octets, 2);
char * name
Definition: smsc_cimd2.c:212
static void append_encoded_integer(Octstr *os, unsigned long u, long octets)
Definition: smpp_pdu.c:346

◆ TLV_INTEGER [1/8]

#define TLV_INTEGER (   name,
  octets 
)    OCTETS(name, octets)

◆ TLV_INTEGER [2/8]

#define TLV_INTEGER (   name,
  octets 
)    p->name = -1;

◆ TLV_INTEGER [3/8]

#define TLV_INTEGER (   name,
  octets 
)    p->name = -1;

◆ TLV_INTEGER [4/8]

#define TLV_INTEGER (   name,
  octets 
)

◆ TLV_INTEGER [5/8]

#define TLV_INTEGER (   name,
  octets 
)
Value:
if (p->name >= 0) { \
TL(name, octets); \
INTEGER(name, octets) \
}
char * name
Definition: smsc_cimd2.c:212

◆ TLV_INTEGER [6/8]

#define TLV_INTEGER (   mname,
  octets 
)
Value:
if (SMPP_##mname == opt_tag) { \
/* check length */ \
if (opt_len > octets) { \
error(0, "SMPP: Optional field (%s) with invalid length (%ld) dropped.", #mname, opt_len); \
pos += opt_len; \
continue; \
} \
INTEGER(mname, opt_len); \
if (tlv != NULL) dict_put(p->tlv, tlv->name, octstr_format("%ld", p->mname)); \
} else
void dict_put(Dict *dict, Octstr *key, void *value)
Definition: dict.c:240
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2462

◆ TLV_INTEGER [7/8]

#define TLV_INTEGER (   name,
  max_len 
)
Value:
if (p->name != -1) { \
INTEGER(name, max_len) \
}
char * name
Definition: smsc_cimd2.c:212

◆ TLV_INTEGER [8/8]

#define TLV_INTEGER (   name,
  max_len 
)
Value:
if (p->name != -1) { \
INTEGER(name, max_len) \
}
char * name
Definition: smsc_cimd2.c:212

◆ TLV_NULTERMINATED [1/8]

#define TLV_NULTERMINATED (   name,
  max_len 
)    OCTETS(name, max_len)

◆ TLV_NULTERMINATED [2/8]

#define TLV_NULTERMINATED (   name,
  max_len 
)    p->name = NULL;

◆ TLV_NULTERMINATED [3/8]

#define TLV_NULTERMINATED (   name,
  max_octets 
)    octstr_destroy(p->name);

◆ TLV_NULTERMINATED [4/8]

#define TLV_NULTERMINATED (   name,
  max_len 
)

◆ TLV_NULTERMINATED [5/8]

#define TLV_NULTERMINATED (   name,
  max_len 
)
Value:
if (p->name != NULL) { \
TL(name, (octstr_len(p->name) > max_len ? max_len : octstr_len(p->name) + 1)); \
NULTERMINATED(name, max_len) \
}
char * name
Definition: smsc_cimd2.c:212
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340

◆ TLV_NULTERMINATED [6/8]

#define TLV_NULTERMINATED (   mname,
  max_len 
)
Value:
if (SMPP_##mname == opt_tag) { \
/* check length */ \
if (opt_len > max_len || pos+opt_len > len) { \
error(0, "SMPP: Optional field (%s) with invalid length (%ld) dropped.", #mname, opt_len); \
pos += opt_len; \
continue; \
} \
if(p->mname != NULL) { \
warning(0, "SMPP: Optional field (%s) was sent more than once, overwriting", #mname); \
octstr_destroy(p->mname); \
p->mname = NULL; \
} \
copy_until_nul(#mname, data_without_len, &pos, opt_len, &p->mname); \
if (tlv != NULL) dict_put(p->tlv, tlv->name, octstr_duplicate(p->mname)); \
} else
void dict_put(Dict *dict, Octstr *key, void *value)
Definition: dict.c:240
#define octstr_duplicate(ostr)
Definition: octstr.h:187

◆ TLV_NULTERMINATED [7/8]

#define TLV_NULTERMINATED (   name,
  max_len 
)
Value:
if (p->name != NULL) { \
NULTERMINATED(name, max_len) \
}
char * name
Definition: smsc_cimd2.c:212

◆ TLV_NULTERMINATED [8/8]

#define TLV_NULTERMINATED (   name,
  max_len 
)
Value:
if (p->name != NULL) { \
NULTERMINATED(name, max_len) \
}
char * name
Definition: smsc_cimd2.c:212

◆ TLV_OCTETS [1/8]

#define TLV_OCTETS (   name,
  min_len,
  max_len 
)    OCTETS(name, min_len)

◆ TLV_OCTETS [2/8]

#define TLV_OCTETS (   name,
  min_len,
  max_len 
)    p->name = NULL;

◆ TLV_OCTETS [3/8]

#define TLV_OCTETS (   name,
  min_len,
  max_len 
)    octstr_destroy(p->name);

◆ TLV_OCTETS [4/8]

#define TLV_OCTETS (   name,
  min_len,
  max_len 
)

◆ TLV_OCTETS [5/8]

#define TLV_OCTETS (   name,
  min_len,
  max_len 
)
Value:
if (p->name != NULL) { \
unsigned long len = octstr_len(p->name); \
if (len > max_len || len < min_len) { \
error(0, "SMPP: Optional field (%s) with invalid length (%ld) (should be %d - %d) dropped.", \
#name, len, min_len, max_len);\
} else { \
TL(name, len); \
octstr_append(os, p->name); \
} \
}
char * name
Definition: smsc_cimd2.c:212
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340

◆ TLV_OCTETS [6/8]

#define TLV_OCTETS (   mname,
  min_len,
  max_len 
)
Value:
if (SMPP_##mname == opt_tag) { \
/* check length */ \
if (opt_len < min_len || opt_len > max_len || pos + opt_len > len) { \
error(0, "SMPP: Optional field (%s) with invalid length (%ld) (should be %d - %d) dropped.", \
#mname, opt_len, min_len, max_len); \
pos += opt_len; \
continue; \
} \
if(p->mname != NULL) { \
warning(0, "SMPP: Optional field (%s) was sent more than once, overwriting", #mname); \
octstr_destroy(p->mname); \
p->mname = NULL; \
} \
p->mname = octstr_copy(data_without_len, pos, opt_len); \
pos += opt_len; \
if (tlv != NULL) dict_put(p->tlv, tlv->name, octstr_duplicate(p->mname)); \
} else
void dict_put(Dict *dict, Octstr *key, void *value)
Definition: dict.c:240
#define octstr_copy(ostr, from, len)
Definition: octstr.h:178
#define octstr_duplicate(ostr)
Definition: octstr.h:187

◆ TLV_OCTETS [7/8]

#define TLV_OCTETS (   name,
  min_len,
  max_len 
)
Value:
if (p->name != NULL) { \
OCTETS(name, max_len) \
}
char * name
Definition: smsc_cimd2.c:212

◆ TLV_OCTETS [8/8]

#define TLV_OCTETS (   name,
  min_len,
  max_len 
)
Value:
if (p->name != NULL) { \
OCTETS(name, max_len) \
}
char * name
Definition: smsc_cimd2.c:212

Function Documentation

◆ append_encoded_integer()

static void append_encoded_integer ( Octstr os,
unsigned long  u,
long  octets 
)
static

Definition at line 346 of file smpp_pdu.c.

References octstr_append_char().

Referenced by smpp_pdu_pack().

347 {
348  long i;
349 
350  for (i = 0; i < octets; ++i)
351  octstr_append_char(os, (u >> ((octets - i - 1) * 8)) & 0xFF);
352 }
void octstr_append_char(Octstr *ostr, int ch)
Definition: octstr.c:1515

◆ copy_until_nul()

static int copy_until_nul ( const char *  field_name,
Octstr os,
long *  pos,
long  max_octets,
Octstr **  data 
)
static

Definition at line 355 of file smpp_pdu.c.

References error(), octstr_copy, octstr_search_char(), and warning().

356 {
357  long nul;
358 
359  *data = NULL;
360 
361  nul = octstr_search_char(os, '\0', *pos);
362  if (nul == -1) {
363  warning(0, "SMPP: PDU NULL terminated string (%s) has no NULL.", field_name);
364  return -1;
365  }
366  if (*pos + max_octets < nul) {
367  error(0, "SMPP: PDU NULL terminated string (%s) longer than allowed.", field_name);
368  return -1;
369  }
370  *data = (nul - *pos > 0) ? octstr_copy(os, *pos, nul - *pos) : NULL;
371  *pos = nul + 1;
372  return 0;
373 }
void error(int err, const char *fmt,...)
Definition: log.c:648
#define octstr_copy(ostr, from, len)
Definition: octstr.h:178
long octstr_search_char(const Octstr *ostr, int ch, long pos)
Definition: octstr.c:1010
void warning(int err, const char *fmt,...)
Definition: log.c:660

◆ decode_integer()

static long decode_integer ( Octstr os,
long  pos,
int  octets 
)
static

Definition at line 330 of file smpp_pdu.c.

References octstr_get_char(), and octstr_len().

Referenced by smpp_pdu_unpack().

331 {
332  unsigned long u;
333  int i;
334 
335  if (octstr_len(os) < pos + octets)
336  return -1;
337 
338  u = 0;
339  for (i = 0; i < octets; ++i)
340  u = (u << 8) | octstr_get_char(os, pos + i);
341 
342  return u;
343 }
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:404

◆ is_defined_field()

static int is_defined_field ( long  type,
const char *  field_name 
)
static

Definition at line 375 of file smpp_pdu.c.

376 {
377  switch (type) {
378  #define OPTIONAL_BEGIN
379  #define TLV_INTEGER(name, octets) OCTETS(name, octets)
380  #define TLV_NULTERMINATED(name, max_len) OCTETS(name, max_len)
381  #define TLV_OCTETS(name, min_len, max_len) OCTETS(name, min_len)
382  #define OPTIONAL_END
383  #define INTEGER(name, octets) OCTETS(name, octets)
384  #define NULTERMINATED(name, max_octets) OCTETS(name, max_octets)
385  #define OCTETS(name, field_giving_octetst) \
386  if (strncmp(#name, field_name, sizeof(#name) - 1) == 0) \
387  return 1;
388  #define PDU(name, id, fields) \
389  case id: { \
390  fields \
391  } break;
392  #include "smpp_pdu.def"
393  default:
394  break;
395  }
396 
397  return 0;
398 }
int type
Definition: smsc_cimd2.c:215

◆ smpp_error_to_string()

const char* smpp_error_to_string ( enum SMPP_ERROR_MESSAGES  error)

Definition at line 911 of file smpp_pdu.c.

References SMPP_ESME_RALYBND, SMPP_ESME_RBCASTCANCELFAIL, SMPP_ESME_RBCASTFAIL, SMPP_ESME_RBCASTQUERYFAIL, SMPP_ESME_RBINDFAIL, SMPP_ESME_RCANCELFAIL, SMPP_ESME_RCNTSUBDL, SMPP_ESME_RDELIVERYFAILURE, SMPP_ESME_RINVBCAST_REP, SMPP_ESME_RINVBCASTALIAS_NAME, SMPP_ESME_RINVBCASTAREAFMT, SMPP_ESME_RINVBCASTCHANIND, SMPP_ESME_RINVBCASTCNTTYPE, SMPP_ESME_RINVBCASTFREQINT, SMPP_ESME_RINVBCASTMSGCLASS, SMPP_ESME_RINVBCASTSRVGRP, SMPP_ESME_RINVBNDSTS, SMPP_ESME_RINVCMDID, SMPP_ESME_RINVCMDLEN, SMPP_ESME_RINVDCS, SMPP_ESME_RINVDESTFLAG, SMPP_ESME_RINVDFTMSGID, SMPP_ESME_RINVDLNAME, SMPP_ESME_RINVDSTADDRSUBUNIT, SMPP_ESME_RINVDSTADR, SMPP_ESME_RINVDSTNPI, SMPP_ESME_RINVDSTTON, SMPP_ESME_RINVESMCLASS, SMPP_ESME_RINVEXPIRY, SMPP_ESME_RINVMSGLEN, SMPP_ESME_RINVNUMBCAST_AREAS, SMPP_ESME_RINVNUMDESTS, SMPP_ESME_RINVNUMMSGS, SMPP_ESME_RINVPASWD, SMPP_ESME_RINVPRTFLG, SMPP_ESME_RINVREGDLVFLG, SMPP_ESME_RINVREPFLAG, SMPP_ESME_RINVSCHED, SMPP_ESME_RINVSERTYP, SMPP_ESME_RINVSRCADDRSUBUNIT, SMPP_ESME_RINVSRCADR, SMPP_ESME_RINVSRCNPI, SMPP_ESME_RINVSRCTON, SMPP_ESME_RINVSUBREP, SMPP_ESME_RINVSYSID, SMPP_ESME_RINVSYSTYP, SMPP_ESME_RINVTLVLEN, SMPP_ESME_RINVTLVSTREAM, SMPP_ESME_RINVTLVVAL, SMPP_ESME_RMISSINGTLV, SMPP_ESME_RMSGQFUL, SMPP_ESME_ROK, SMPP_ESME_RPROHIBITED, SMPP_ESME_RQUERYFAIL, SMPP_ESME_RREPLACEFAIL, SMPP_ESME_RSERTYPDENIED, SMPP_ESME_RSERTYPUNAUTH, SMPP_ESME_RSERTYPUNAVAIL, SMPP_ESME_RSUBMITFAIL, SMPP_ESME_RSYSERR, SMPP_ESME_RTHROTTLED, SMPP_ESME_RTLVNOTALLWD, SMPP_ESME_RUNKNOWNERR, SMPP_ESME_RX_P_APPN, SMPP_ESME_RX_R_APPN, and SMPP_ESME_RX_T_APPN.

Referenced by handle_pdu().

912 {
913  switch (error) {
914  case SMPP_ESME_ROK:
915  return "OK";
917  return "Message Length is invalid";
919  return "Command Length is invalid";
920  case SMPP_ESME_RINVCMDID:
921  return "Invalid Command ID";
923  return "Incorrect BIND Status for given command";
924  case SMPP_ESME_RALYBND:
925  return "ESME Already in Bound State";
927  return "Invalid Priority Flag";
929  return "Invalid Registered Delivery Flag";
930  case SMPP_ESME_RSYSERR:
931  return "System Error";
933  return "Invalid Source Address";
935  return "Invalid Destination Address";
936  case SMPP_ESME_RBINDFAIL:
937  return "Bind Failed";
938  case SMPP_ESME_RINVPASWD:
939  return "Invalid Password";
940  case SMPP_ESME_RINVSYSID:
941  return "Invalid System ID";
943  return "Cancel SM Failed";
945  return "Replace SM Failed";
946  case SMPP_ESME_RMSGQFUL:
947  return "Message Queue Full";
949  return "Invalid Service Type";
951  return "Invalid number of destinations";
953  return "Invalid Distribution List Name";
955  return "Destination flag is invalid";
957  return "Submit w/replace not supported/allowed";
959  return "Invalid esm_class field data";
960  case SMPP_ESME_RCNTSUBDL:
961  return "Cannot Submit to Distribution List";
963  return "Submit failed";
965  return "Invalid Source address TON";
967  return "Invalid Source address NPI";
969  return "Invalid Destination address TON";
971  return "Invalid Destination address NPI";
973  return "Invalid system_type field";
975  return "Invalid replace_if_present flag";
977  return "Invalid number of messages";
979  return "Throttling error";
980  case SMPP_ESME_RINVSCHED:
981  return "Invalid Scheduled Delivery Time";
983  return "Invalid message validity period";
985  return "Predefined Message ID is Invalid or specific predefined message was not found";
986  case SMPP_ESME_RX_T_APPN:
987  return "ESME Receiver Temporary App Error Code";
988  case SMPP_ESME_RX_P_APPN:
989  return "ESME Receiver Permanent App Error Code";
990  case SMPP_ESME_RX_R_APPN:
991  return "ESME Receiver Reject Message Error Code";
993  return "query_sm request failed";
995  return "Error in optional part of the PDU Body";
997  return "TLV not allowed";
999  return "Invalid Parameter Length";
1000  case SMPP_ESME_RMISSINGTLV:
1001  return "Expected TLV missing";
1002  case SMPP_ESME_RINVTLVVAL:
1003  return "Invalid TLV value";
1005  return "Transaction Delivery Failure";
1006  case SMPP_ESME_RUNKNOWNERR:
1007  return "Unknown Error";
1009  return "ESME Not authorized to use specified service_type";
1010  case SMPP_ESME_RPROHIBITED:
1011  return "ESME Prohibited from using specified operation";
1013  return "Specified service_type is unavailable";
1015  return "Specified service_type is denied";
1016  case SMPP_ESME_RINVDCS:
1017  return "Invalid Data Coding Scheme";
1019  return "Source Address Sub unit is invalid";
1021  return "Destination Address Sub unit is invalid";
1023  return "Broadcast Frequency Interval is invalid";
1025  return "Broadcast Alias Name is invalid";
1027  return "Broadcast Area Format is invalid";
1029  return "Number of Broadcast Areas is invalid";
1031  return "Broadcast Content Type is invalid";
1033  return "Broadcast Message Class is invalid";
1034  case SMPP_ESME_RBCASTFAIL:
1035  return "broadcast_sm operation failed";
1037  return "broadcast_query_sm operation failed";
1039  return "broadcast_cancel_sm operation failed";
1041  return "Number of Repeated Broadcasts is invalid";
1043  return "Broadcast Service Group is invalid";
1045  return "Broadcast Channel Indicator is invalid";
1046 
1047  default:
1048  /* tell the user that we have a vendor-specific beast here */
1049  if (error >= 0x0400 && error <= 0x04FF)
1050  return "Vendor-specific error, please refer to your SMPP provider";
1051  else
1052  return "Unknown/Reserved";
1053  }
1054 }
void error(int err, const char *fmt,...)
Definition: log.c:648

◆ smpp_pdu_create()

SMPP_PDU* smpp_pdu_create ( unsigned long  type,
unsigned long  seq_no 
)

Definition at line 400 of file smpp_pdu.c.

References error(), smpp_tlv::type, and SMPP_PDU::type.

Referenced by handle_bind_receiver(), handle_bind_transmitter(), handle_enquire_link(), handle_pdu(), handle_submit_sm(), handle_unbind(), msg_to_pdu(), open_receiver(), open_transceiver(), open_transmitter(), send_enquire_link(), send_gnack(), send_smpp_thread(), send_unbind(), smpp_emu_handle_pdu(), smpp_emu_writer(), smpp_pdu_unpack(), and smsc_emu_submit_ack().

401 {
402  SMPP_PDU *pdu;
403 
404  pdu = gw_malloc(sizeof(*pdu));
405  pdu->type = type;
406 
407  switch (type) {
408  #define OPTIONAL_BEGIN
409  #define TLV_INTEGER(name, octets) p->name = -1;
410  #define TLV_NULTERMINATED(name, max_len) p->name = NULL;
411  #define TLV_OCTETS(name, min_len, max_len) p->name = NULL;
412  #define OPTIONAL_END p->tlv = dict_create(1024, octstr_destroy_item);
413  #define INTEGER(name, octets) p->name = 0;
414  #define NULTERMINATED(name, max_octets) p->name = NULL;
415  #define OCTETS(name, field_giving_octetst) p->name = NULL;
416  #define PDU(name, id, fields) \
417  case id: { \
418  struct name *p = &pdu->u.name; \
419  pdu->type_name = #name; \
420  fields \
421  p->command_id = type; \
422  p->sequence_number = seq_no; \
423  } break;
424  #include "smpp_pdu.def"
425  default:
426  error(0, "Unknown SMPP_PDU type, internal error.");
427  gw_free(pdu);
428  return NULL;
429  }
430 
431  return pdu;
432 }
void error(int err, const char *fmt,...)
Definition: log.c:648
int type
Definition: smsc_cimd2.c:215
unsigned long type
Definition: smpp_pdu.h:91

◆ smpp_pdu_destroy()

void smpp_pdu_destroy ( SMPP_PDU pdu)

Definition at line 434 of file smpp_pdu.c.

References error(), and SMPP_PDU::type.

Referenced by bearerbox_to_smpp(), handle_pdu(), io_thread(), msg_to_pdu(), open_receiver(), open_transceiver(), open_transmitter(), receive_smpp_thread(), send_enquire_link(), send_gnack(), send_messages(), send_smpp_thread(), send_unbind(), smpp_emu_handle_pdu(), smpp_emu_reader(), smpp_emu_writer(), smpp_pdu_destroy_item(), smpp_pdu_unpack(), and smsc_emu_submit_ack().

435 {
436  if (pdu == NULL)
437  return;
438 
439  switch (pdu->type) {
440  #define OPTIONAL_BEGIN
441  #define TLV_INTEGER(name, octets) p->name = -1;
442  #define TLV_NULTERMINATED(name, max_octets) octstr_destroy(p->name);
443  #define TLV_OCTETS(name, min_len, max_len) octstr_destroy(p->name);
444  #define OPTIONAL_END dict_destroy(p->tlv);
445  #define INTEGER(name, octets) p->name = 0; /* Make sure "p" is used */
446  #define NULTERMINATED(name, max_octets) octstr_destroy(p->name);
447  #define OCTETS(name, field_giving_octets) octstr_destroy(p->name);
448  #define PDU(name, id, fields) \
449  case id: { struct name *p = &pdu->u.name; fields } break;
450  #include "smpp_pdu.def"
451  default:
452  error(0, "Unknown SMPP_PDU type, internal error while destroying.");
453  }
454  gw_free(pdu);
455 }
void error(int err, const char *fmt,...)
Definition: log.c:648
unsigned long type
Definition: smpp_pdu.h:91

◆ smpp_pdu_dump()

void smpp_pdu_dump ( Octstr smsc_id,
SMPP_PDU pdu 
)

Definition at line 766 of file smpp_pdu.c.

References debug(), and error().

Referenced by handle_pdu().

767 {
768  debug("sms.smpp", 0, "SMPP PDU %p dump:", (void *) pdu);
769  debug("sms.smpp", 0, " type_name: %s", pdu->type_name);
770  switch (pdu->type) {
771  #define OPTIONAL_BEGIN
772  #define TLV_INTEGER(name, max_len) \
773  if (p->name != -1) { \
774  INTEGER(name, max_len) \
775  }
776  #define TLV_NULTERMINATED(name, max_len) \
777  if (p->name != NULL) { \
778  NULTERMINATED(name, max_len) \
779  }
780  #define TLV_OCTETS(name, min_len, max_len) \
781  if (p->name != NULL) { \
782  OCTETS(name, max_len) \
783  }
784  #define OPTIONAL_END \
785  if (p->tlv != NULL) { \
786  List *keys; \
787  Octstr *key; \
788  struct smpp_tlv *tlv; \
789  keys = dict_keys(p->tlv); \
790  while(keys != NULL && (key = gwlist_extract_first(keys)) != NULL) { \
791  tlv = smpp_tlv_get_by_name(smsc_id, key); \
792  if (tlv != NULL) { \
793  octstr_dump_short(dict_get(p->tlv, key), 2, octstr_get_cstr(key)); \
794  } \
795  octstr_destroy(key); \
796  } \
797  gwlist_destroy(keys, octstr_destroy_item); \
798  }
799  #define INTEGER(name, octets) \
800  debug("sms.smpp", 0, " %s: %lu = 0x%08lx", #name, p->name, p->name);
801  #define NULTERMINATED(name, max_octets) \
802  octstr_dump_short(p->name, 2, #name);
803  #define OCTETS(name, field_giving_octets) \
804  octstr_dump_short(p->name, 2, #name);
805  #define PDU(name, id, fields) \
806  case id: { struct name *p = &pdu->u.name; fields } break;
807  #include "smpp_pdu.def"
808  default:
809  error(0, "Unknown SMPP_PDU type, internal error.");
810  break;
811  }
812  debug("sms.smpp", 0, "SMPP PDU dump ends.");
813 }
void error(int err, const char *fmt,...)
Definition: log.c:648
const char * type_name
Definition: smpp_pdu.h:92
unsigned long type
Definition: smpp_pdu.h:91
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726

◆ smpp_pdu_dump_line()

void smpp_pdu_dump_line ( Octstr smsc_id,
SMPP_PDU pdu 
)

Definition at line 816 of file smpp_pdu.c.

References debug(), error(), octstr_create, octstr_destroy(), octstr_format_append(), octstr_get_cstr, and SMPP_PDU::type_name.

817 {
818  Octstr *str = octstr_create("");
819 
820  octstr_format_append(str, "SMPP PDU %p dump: [type_name:%d:%s]", (void *) pdu, strlen(pdu->type_name), pdu->type_name);
821  switch (pdu->type) {
822  #define OPTIONAL_BEGIN
823  #define TLV_INTEGER(name, max_len) \
824  if (p->name != -1) { \
825  INTEGER(name, max_len) \
826  }
827  #define TLV_NULTERMINATED(name, max_len) \
828  if (p->name != NULL) { \
829  NULTERMINATED(name, max_len) \
830  }
831  #define TLV_OCTETS(name, min_len, max_len) \
832  if (p->name != NULL) { \
833  OCTETS(name, max_len) \
834  }
835  #define OPTIONAL_END \
836  if (p->tlv != NULL) { \
837  List *keys; \
838  Octstr *key; \
839  struct smpp_tlv *tlv; \
840  keys = dict_keys(p->tlv); \
841  while(keys != NULL && (key = gwlist_extract_first(keys)) != NULL) { \
842  tlv = smpp_tlv_get_by_name(smsc_id, key); \
843  if (tlv != NULL) { \
844  Octstr *val = dict_get(p->tlv, key); \
845  octstr_format_append(str, " [%E:%d:%E]", key, octstr_len(val), val); \
846  } \
847  octstr_destroy(key); \
848  } \
849  gwlist_destroy(keys, octstr_destroy_item); \
850  }
851  #define INTEGER(name, octets) \
852  octstr_format_append(str, " [%s:0:0x%08lx]", #name, p->name);
853  #define NULTERMINATED(name, max_octets) \
854  octstr_format_append(str, " [%s:%d:%E]", #name, octstr_len(p->name), (p->name != NULL ? p->name : octstr_imm("NULL")));
855  #define OCTETS(name, field_giving_octets) \
856  octstr_format_append(str, " [%s:%d:%E]", #name, octstr_len(p->name), (p->name != NULL ? p->name : octstr_imm("NULL")));
857  #define PDU(name, id, fields) \
858  case id: { struct name *p = &pdu->u.name; fields } break;
859  #include "smpp_pdu.def"
860  default:
861  error(0, "Unknown SMPP_PDU type, internal error.");
862  break;
863  }
864  debug("sms.smpp", 0, "%s", octstr_get_cstr(str));
865  octstr_destroy(str);
866 }
void error(int err, const char *fmt,...)
Definition: log.c:648
const char * type_name
Definition: smpp_pdu.h:92
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
#define octstr_create(cstr)
Definition: octstr.h:125
Definition: octstr.c:118
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
void octstr_format_append(Octstr *os, const char *fmt,...)
Definition: octstr.c:2505

◆ smpp_pdu_init()

int smpp_pdu_init ( Cfg cfg)

Definition at line 184 of file smpp_pdu.c.

References cfg_get, cfg_get_integer(), cfg_get_multi_group(), smpp_tlv::constant, debug(), DEFAULT_SMSC_ID, dict_create(), dict_destroy(), dict_get(), dict_put(), dict_put_once(), error(), gwlist_create, gwlist_destroy(), gwlist_extract_first(), gwlist_produce(), initialized, smpp_tlv::length, smpp_tlv::name, octstr_create, octstr_destroy(), octstr_destroy_item(), octstr_format(), octstr_get_cstr, octstr_imm(), octstr_split(), octstr_str_case_compare(), smpp_tlv_destroy(), smpp_tlv::SMPP_TLV_INTEGER, smpp_tlv::SMPP_TLV_NULTERMINATED, smpp_tlv::SMPP_TLV_OCTETS, smsc_id, smpp_tlv::tag, and smpp_tlv::type.

Referenced by init_smppbox(), main(), and smsc2_start().

185 {
186  CfgGroup *grp;
187  List *l;
188 
189  if (initialized)
190  return 0;
191 
192  l = cfg_get_multi_group(cfg, octstr_imm("smpp-tlv"));
193  tlvs = gwlist_create();
194  tlvs_by_tag = dict_create(1024, (void(*)(void*))dict_destroy);
195  tlvs_by_name = dict_create(1024, (void(*)(void*))dict_destroy);
196  tlvs_by_const = dict_create(1024, (void(*)(void*))dict_destroy);
197  while (l != NULL && (grp = gwlist_extract_first(l)) != NULL) {
198  struct smpp_tlv *tlv;
199  Octstr *tmp, *smsc_id;
200  List *l2;
201 
202  tlv = gw_malloc(sizeof(*tlv));
203  if ((tlv->name = cfg_get(grp, octstr_imm("name"))) == NULL) {
204  error(0, "SMPP: Unable to get name for smpp-tlv.");
205  smpp_tlv_destroy(tlv);
206  goto failed;
207  }
208  tlv->constant = cfg_get(grp, octstr_imm("const"));
209  if (cfg_get_integer(&tlv->tag, grp, octstr_imm("tag")) == -1) {
210  error(0, "SMPP: Unable to get tag for smpp-tlv.");
211  smpp_tlv_destroy(tlv);
212  goto failed;
213  }
214  if (cfg_get_integer(&tlv->length, grp, octstr_imm("length")) == -1) {
215  error(0, "SMPP: Unable to get length for smpp-tlv.");
216  smpp_tlv_destroy(tlv);
217  goto failed;
218  }
219  if ((tmp = cfg_get(grp, octstr_imm("type"))) == NULL) {
220  error(0, "SMPP: Unable to get type for smpp-tlv.");
221  smpp_tlv_destroy(tlv);
222  goto failed;
223  }
224  if (octstr_str_case_compare(tmp, "octetstring") == 0)
225  tlv->type = SMPP_TLV_OCTETS;
226  else if (octstr_str_case_compare(tmp, "nulterminated") == 0)
228  else if (octstr_str_case_compare(tmp, "integer") == 0)
229  tlv->type = SMPP_TLV_INTEGER;
230  else {
231  error(0, "SMPP: Unknown type for smpp-tlv: `%s'", octstr_get_cstr(tmp));
232  octstr_destroy(tmp);
233  smpp_tlv_destroy(tlv);
234  goto failed;
235  }
236  octstr_destroy(tmp);
237 
238  /* put to all TLVs */
239  gwlist_produce(tlvs, tlv);
240 
241  smsc_id = cfg_get(grp, octstr_imm("smsc-id"));
242  if (smsc_id != NULL) {
243  l2 = octstr_split(smsc_id, octstr_imm(";"));
244  octstr_destroy(smsc_id);
245  } else {
246  l2 = gwlist_create();
248  }
249  while(l2 != NULL && (smsc_id = gwlist_extract_first(l2)) != NULL) {
250  Dict *tmp_dict;
251 
252  debug("sms.smpp", 0, "adding smpp-tlv for smsc-id=%s", octstr_get_cstr(smsc_id));
253 
254  /* name */
255  tmp_dict = dict_get(tlvs_by_name, smsc_id);
256  if (tmp_dict == NULL) {
257  tmp_dict = dict_create(1024, NULL);
258  dict_put(tlvs_by_name, smsc_id, tmp_dict);
259  }
260  /* put into dict */
261  if (!dict_put_once(tmp_dict, tlv->name, tlv)) {
262  error(0, "SMPP: Double TLV name %s found.", octstr_get_cstr(tlv->name));
263  octstr_destroy(smsc_id);
264  goto failed;
265  }
266 
267  /* tag */
268  tmp_dict = dict_get(tlvs_by_tag, smsc_id);
269  if (tmp_dict == NULL) {
270  tmp_dict = dict_create(1024, NULL);
271  dict_put(tlvs_by_tag, smsc_id, tmp_dict);
272  }
273  tmp = octstr_format("%ld", tlv->tag);
274  if (!dict_put_once(tmp_dict, tmp, tlv)) {
275  error(0, "SMPP: Double TLV tag %s found.", octstr_get_cstr(tmp));
277  octstr_destroy(tmp);
278  octstr_destroy(smsc_id);
279  goto failed;
280  }
281 
282  /* const */
283  if (tlv->constant != NULL) {
284  tmp_dict = dict_get(tlvs_by_const, smsc_id);
285  if (tmp_dict == NULL) {
286  tmp_dict = dict_create(1024, NULL);
287  dict_put(tlvs_by_const, smsc_id, tmp_dict);
288  }
289  if (!dict_put_once(tmp_dict, tlv->name, tlv)) {
290  error(0, "SMPP: Double TLV name %s found.", octstr_get_cstr(tlv->name));
291  octstr_destroy(smsc_id);
292  goto failed;
293  }
294  }
295 
296  octstr_destroy(tmp);
297  octstr_destroy(smsc_id);
298  }
300  }
301  gwlist_destroy(l, NULL);
302 
303  initialized = 1;
304  return 0;
305 
306 failed:
307  gwlist_destroy(tlvs, (void(*)(void*))smpp_tlv_destroy);
310  return -1;
311 }
Dict * dict_create(long size_hint, void(*destroy_value)(void *))
Definition: dict.c:192
void error(int err, const char *fmt,...)
Definition: log.c:648
Octstr * constant
Definition: smpp_pdu.c:79
int octstr_str_case_compare(const Octstr *ostr, const char *str)
Definition: octstr.c:984
static int initialized
Definition: smpp_pdu.c:89
void dict_put(Dict *dict, Octstr *key, void *value)
Definition: dict.c:240
enum smpp_tlv::@13 type
void gwlist_produce(List *list, void *item)
Definition: list.c:411
#define cfg_get(grp, varname)
Definition: cfg.h:86
static Dict * tlvs_by_name
Definition: smpp_pdu.c:86
static void smpp_tlv_destroy(struct smpp_tlv *tlv)
Definition: smpp_pdu.c:92
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
static Dict * tlvs_by_tag
Definition: smpp_pdu.c:84
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:281
void * gwlist_extract_first(List *list)
Definition: list.c:305
void * dict_get(Dict *dict, Octstr *key)
Definition: dict.c:286
long tag
Definition: smpp_pdu.c:77
Definition: dict.c:116
static Octstr * smsc_id
Definition: mtbatch.c:98
List * cfg_get_multi_group(Cfg *cfg, Octstr *name)
Definition: cfg.c:642
#define DEFAULT_SMSC_ID
Definition: smpp_pdu.c:73
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2462
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
#define octstr_create(cstr)
Definition: octstr.h:125
void octstr_destroy_item(void *os)
Definition: octstr.c:334
void dict_destroy(Dict *dict)
Definition: dict.c:215
long length
Definition: smpp_pdu.c:78
Definition: octstr.c:118
static Dict * tlvs_by_const
Definition: smpp_pdu.c:87
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
int cfg_get_integer(long *n, CfgGroup *grp, Octstr *varname)
Definition: cfg.c:739
Definition: cfg.c:73
#define gwlist_create()
Definition: list.h:136
int dict_put_once(Dict *dict, Octstr *key, void *value)
Definition: dict.c:271
Octstr * name
Definition: smpp_pdu.c:76
List * octstr_split(const Octstr *os, const Octstr *sep)
Definition: octstr.c:1638
Definition: list.c:102
static List * tlvs
Definition: smpp_pdu.c:88
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145

◆ smpp_pdu_pack()

Octstr* smpp_pdu_pack ( Octstr smsc_id,
SMPP_PDU pdu 
)

Definition at line 458 of file smpp_pdu.c.

References append_encoded_integer(), error(), gw_assert(), octstr_create, octstr_destroy(), octstr_insert(), octstr_len(), and SMPP_PDU::type.

Referenced by handle_pdu(), send_enquire_link(), send_gnack(), send_pdu(), send_smpp_thread(), send_unbind(), smpp_emu_handle_pdu(), smpp_emu_writer(), and smsc_emu_submit_ack().

459 {
460  Octstr *os;
461  Octstr *temp;
462 
463  os = octstr_create("");
464 
465  gw_assert(pdu != NULL);
466 
467  /*
468  * Fix lengths of octet string fields.
469  */
470  switch (pdu->type) {
471  #define OPTIONAL_BEGIN
472  #define TLV_INTEGER(name, octets)
473  #define TLV_NULTERMINATED(name, max_len)
474  #define TLV_OCTETS(name, min_len, max_len)
475  #define OPTIONAL_END
476  #define INTEGER(name, octets) p = *(&p);
477  #define NULTERMINATED(name, max_octets) p = *(&p);
478  #define OCTETS(name, field_giving_octets) \
479  p->field_giving_octets = octstr_len(p->name);
480  #define PDU(name, id, fields) \
481  case id: { struct name *p = &pdu->u.name; fields } break;
482  #include "smpp_pdu.def"
483  default:
484  error(0, "Unknown SMPP_PDU type, internal error while packing.");
485  }
486 
487  switch (pdu->type) {
488  #define TL(name, octets) \
489  append_encoded_integer(os, SMPP_##name, 2); \
490  append_encoded_integer(os, octets, 2);
491  #define OPTIONAL_BEGIN
492  #define TLV_INTEGER(name, octets) \
493  if (p->name >= 0) { \
494  TL(name, octets); \
495  INTEGER(name, octets) \
496  }
497  #define TLV_NULTERMINATED(name, max_len) \
498  if (p->name != NULL) { \
499  TL(name, (octstr_len(p->name) > max_len ? max_len : octstr_len(p->name) + 1)); \
500  NULTERMINATED(name, max_len) \
501  }
502  #define TLV_OCTETS(name, min_len, max_len) \
503  if (p->name != NULL) { \
504  unsigned long len = octstr_len(p->name); \
505  if (len > max_len || len < min_len) { \
506  error(0, "SMPP: Optional field (%s) with invalid length (%ld) (should be %d - %d) dropped.", \
507  #name, len, min_len, max_len);\
508  } else { \
509  TL(name, len); \
510  octstr_append(os, p->name); \
511  } \
512  }
513  #define OPTIONAL_END \
514  if (p->tlv != NULL) { \
515  Octstr *key; \
516  List *keys; \
517  struct smpp_tlv *tlv; \
518  keys = dict_keys(p->tlv); \
519  while(keys != NULL && (key = gwlist_extract_first(keys)) != NULL) { \
520  tlv = smpp_tlv_get_by_name(smsc_id, key); \
521  if (tlv == NULL) { \
522  if (!is_defined_field(pdu->type, octstr_get_cstr(key))) \
523  error(0, "SMPP: Unknown TLV `%s', don't send.", octstr_get_cstr(key)); \
524  octstr_destroy(key); \
525  continue; \
526  } \
527  switch(tlv->type) { \
528  case SMPP_TLV_INTEGER: { \
529  long val = atol(octstr_get_cstr(dict_get(p->tlv, key))); \
530  append_encoded_integer(os, tlv->tag, 2); \
531  append_encoded_integer(os, tlv->length, 2); \
532  append_encoded_integer(os, val, tlv->length); \
533  break; \
534  } \
535  case SMPP_TLV_OCTETS: \
536  case SMPP_TLV_NULTERMINATED: { \
537  Octstr *val = dict_get(p->tlv, key); \
538  unsigned long len = octstr_len(val); \
539  if (len > tlv->length) { \
540  error(0, "SMPP: Optional field (%s) with invalid length (%ld) (should be %ld) dropped.", \
541  octstr_get_cstr(key), len, tlv->length);\
542  octstr_destroy(key); \
543  continue; \
544  } \
545  append_encoded_integer(os, tlv->tag, 2); \
546  if (tlv->type == SMPP_TLV_NULTERMINATED) \
547  append_encoded_integer(os, len + 1, 2); \
548  else \
549  append_encoded_integer(os, len, 2); \
550  octstr_append(os, val); \
551  if (tlv->type == SMPP_TLV_NULTERMINATED) \
552  octstr_append_char(os, '\0'); \
553  break; \
554  } \
555  default: \
556  panic(0, "SMPP: Internal error, unknown configured TLV type %d.", tlv->type); \
557  break; \
558  } \
559  octstr_destroy(key); \
560  } \
561  gwlist_destroy(keys, octstr_destroy_item); \
562  }
563  #define INTEGER(name, octets) \
564  append_encoded_integer(os, p->name, octets);
565  #define NULTERMINATED(name, max_octets) \
566  if (p->name != NULL) { \
567  if (octstr_len(p->name) >= max_octets) { \
568  warning(0, "SMPP: PDU element <%s> too long " \
569  "(length is %ld, should be %d)", \
570  #name, octstr_len(p->name), max_octets-1); \
571  temp = octstr_copy(p->name, 0, max_octets-1); \
572  } else \
573  temp = octstr_duplicate(p->name); \
574  octstr_append(os, temp); \
575  octstr_destroy(temp); \
576  } \
577  octstr_append_char(os, '\0');
578  #define OCTETS(name, field_giving_octets) \
579  if (p->name) octstr_append(os, p->name);
580  #define PDU(name, id, fields) \
581  case id: { struct name *p = &pdu->u.name; fields } break;
582  #include "smpp_pdu.def"
583  default:
584  error(0, "Unknown SMPP_PDU type 0x%08lx, internal error while packing.", pdu->type);
585  break;
586  }
587 
588  temp = octstr_create("");
589  append_encoded_integer(temp, octstr_len(os) + 4, 4);
590  octstr_insert(os, temp, 0);
591  octstr_destroy(temp);
592 
593  return os;
594 }
void error(int err, const char *fmt,...)
Definition: log.c:648
gw_assert(wtls_machine->packet_to_send !=NULL)
unsigned long type
Definition: smpp_pdu.h:91
void octstr_insert(Octstr *ostr1, const Octstr *ostr2, long pos)
Definition: octstr.c:1301
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
#define octstr_create(cstr)
Definition: octstr.h:125
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
Definition: octstr.c:118
static void append_encoded_integer(Octstr *os, unsigned long u, long octets)
Definition: smpp_pdu.c:346

◆ smpp_pdu_read_data()

Octstr* smpp_pdu_read_data ( Connection conn,
long  len 
)

Definition at line 895 of file smpp_pdu.c.

References conn_read_fixed().

Referenced by read_pdu(), receive_smpp_thread(), and smpp_emu_reader().

896 {
897  Octstr *os;
898 
899  os = conn_read_fixed(conn, len - 4); /* `len' includes itself. */
900  return os;
901 }
Definition: octstr.c:118
Octstr * conn_read_fixed(Connection *conn, long length)
Definition: conn.c:1104

◆ smpp_pdu_read_len()

long smpp_pdu_read_len ( Connection conn)

Definition at line 869 of file smpp_pdu.c.

References conn_read_fixed(), decode_network_long(), error(), MAX_SMPP_PDU_LEN, MIN_SMPP_PDU_LEN, octstr_destroy(), and octstr_get_many_chars().

Referenced by read_pdu(), receive_smpp_thread(), and smpp_emu_reader().

870 {
871  Octstr *os;
872  unsigned char buf[4]; /* The length is 4 octets. */
873  long len;
874 
875  os = conn_read_fixed(conn, sizeof(buf));
876  if (os == NULL)
877  return 0;
878  octstr_get_many_chars((char*) buf, os, 0, sizeof(buf));
879  octstr_destroy(os);
880  len = decode_network_long(buf);
881  if (len < MIN_SMPP_PDU_LEN) {
882  error(0, "SMPP: PDU length was too small (%ld, minimum is %ld).",
883  len, (long) MIN_SMPP_PDU_LEN);
884  return -1;
885  }
886  if (len > MAX_SMPP_PDU_LEN) {
887  error(0, "SMPP: PDU length was too large (%ld, maximum is %ld).",
888  len, (long) MAX_SMPP_PDU_LEN);
889  return -1;
890  }
891  return len;
892 }
void error(int err, const char *fmt,...)
Definition: log.c:648
#define MAX_SMPP_PDU_LEN
Definition: smpp_pdu.c:71
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
long decode_network_long(unsigned char *data)
Definition: utils.c:935
Definition: octstr.c:118
Octstr * conn_read_fixed(Connection *conn, long length)
Definition: conn.c:1104
#define MIN_SMPP_PDU_LEN
Definition: smpp_pdu.c:69
void octstr_get_many_chars(char *buf, Octstr *ostr, long pos, long len)
Definition: octstr.c:423

◆ smpp_pdu_shutdown()

int smpp_pdu_shutdown ( void  )

Definition at line 314 of file smpp_pdu.c.

References dict_destroy(), gwlist_destroy(), initialized, and smpp_tlv_destroy().

Referenced by smsc2_shutdown().

315 {
316  if (initialized == 0)
317  return 0;
318 
319  initialized = 0;
320  gwlist_destroy(tlvs, (void(*)(void*))smpp_tlv_destroy);
321  tlvs = NULL;
324  tlvs_by_tag = tlvs_by_name = NULL;
325 
326  return 0;
327 }
static int initialized
Definition: smpp_pdu.c:89
static Dict * tlvs_by_name
Definition: smpp_pdu.c:86
static void smpp_tlv_destroy(struct smpp_tlv *tlv)
Definition: smpp_pdu.c:92
static Dict * tlvs_by_tag
Definition: smpp_pdu.c:84
void dict_destroy(Dict *dict)
Definition: dict.c:215
static List * tlvs
Definition: smpp_pdu.c:88
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145

◆ smpp_pdu_unpack()

SMPP_PDU* smpp_pdu_unpack ( Octstr smsc_id,
Octstr data_without_len 
)

Definition at line 597 of file smpp_pdu.c.

References decode_integer(), error(), octstr_dump, octstr_len(), smpp_pdu_create(), smpp_pdu_destroy(), and smpp_tlv::type.

Referenced by read_pdu(), receive_smpp_thread(), and smpp_emu_reader().

598 {
599  SMPP_PDU *pdu;
600  unsigned long type;
601  long len, pos;
602 
603  len = octstr_len(data_without_len);
604 
605  if (len < 4) {
606  error(0, "SMPP: PDU was too short (%ld bytes).",
607  octstr_len(data_without_len));
608  return NULL;
609  }
610 
611  /* get the PDU type */
612  if ((type = decode_integer(data_without_len, 0, 4)) == -1)
613  return NULL;
614 
615  /* create a coresponding representation structure */
616  pdu = smpp_pdu_create(type, 0);
617  if (pdu == NULL)
618  return NULL;
619 
620  pos = 0;
621 
622  switch (type) {
623  #define OPTIONAL_BEGIN \
624  { /* Read optional parameters */ \
625  while (pos + 4 <= len) { \
626  struct smpp_tlv *tlv; \
627  unsigned long opt_tag, opt_len; \
628  opt_tag = decode_integer(data_without_len, pos, 2); pos += 2; \
629  debug("sms.smpp", 0, "Optional parameter tag (0x%04lx)", opt_tag); \
630  opt_len = decode_integer(data_without_len, pos, 2); pos += 2; \
631  debug("sms.smpp", 0, "Optional parameter length read as %ld", opt_len); \
632  /* check configured TLVs */ \
633  tlv = smpp_tlv_get_by_tag(smsc_id, opt_tag); \
634  if (tlv != NULL) debug("sms.smpp", 0, "Found configured optional parameter `%s'", octstr_get_cstr(tlv->name));
635  #define TLV_INTEGER(mname, octets) \
636  if (SMPP_##mname == opt_tag) { \
637  /* check length */ \
638  if (opt_len > octets) { \
639  error(0, "SMPP: Optional field (%s) with invalid length (%ld) dropped.", #mname, opt_len); \
640  pos += opt_len; \
641  continue; \
642  } \
643  INTEGER(mname, opt_len); \
644  if (tlv != NULL) dict_put(p->tlv, tlv->name, octstr_format("%ld", p->mname)); \
645  } else
646  #define TLV_NULTERMINATED(mname, max_len) \
647  if (SMPP_##mname == opt_tag) { \
648  /* check length */ \
649  if (opt_len > max_len || pos+opt_len > len) { \
650  error(0, "SMPP: Optional field (%s) with invalid length (%ld) dropped.", #mname, opt_len); \
651  pos += opt_len; \
652  continue; \
653  } \
654  if(p->mname != NULL) { \
655  warning(0, "SMPP: Optional field (%s) was sent more than once, overwriting", #mname); \
656  octstr_destroy(p->mname); \
657  p->mname = NULL; \
658  } \
659  copy_until_nul(#mname, data_without_len, &pos, opt_len, &p->mname); \
660  if (tlv != NULL) dict_put(p->tlv, tlv->name, octstr_duplicate(p->mname)); \
661  } else
662  #define TLV_OCTETS(mname, min_len, max_len) \
663  if (SMPP_##mname == opt_tag) { \
664  /* check length */ \
665  if (opt_len < min_len || opt_len > max_len || pos + opt_len > len) { \
666  error(0, "SMPP: Optional field (%s) with invalid length (%ld) (should be %d - %d) dropped.", \
667  #mname, opt_len, min_len, max_len); \
668  pos += opt_len; \
669  continue; \
670  } \
671  if(p->mname != NULL) { \
672  warning(0, "SMPP: Optional field (%s) was sent more than once, overwriting", #mname); \
673  octstr_destroy(p->mname); \
674  p->mname = NULL; \
675  } \
676  p->mname = octstr_copy(data_without_len, pos, opt_len); \
677  pos += opt_len; \
678  if (tlv != NULL) dict_put(p->tlv, tlv->name, octstr_duplicate(p->mname)); \
679  } else
680  #define OPTIONAL_END \
681  { \
682  Octstr *val = NULL; \
683  if (tlv != NULL) { \
684  /* found configured tlv */ \
685  /* check length */ \
686  if (opt_len > tlv->length) { \
687  error(0, "SMPP: Optional field (%s) with invalid length (%ld) (should be %ld) dropped.", \
688  octstr_get_cstr(tlv->name), opt_len, tlv->length); \
689  pos += opt_len; \
690  continue; \
691  } \
692  switch (tlv->type) { \
693  case SMPP_TLV_INTEGER: { \
694  long val_i; \
695  if ((val_i = decode_integer(data_without_len, pos, opt_len)) == -1) \
696  goto err; \
697  val = octstr_format("%ld", val_i); \
698  dict_put(p->tlv, tlv->name, val); \
699  pos += opt_len; \
700  break; \
701  } \
702  case SMPP_TLV_OCTETS: { \
703  val = octstr_copy(data_without_len, pos, opt_len); \
704  dict_put(p->tlv, tlv->name, val); \
705  pos += opt_len; \
706  break; \
707  } \
708  case SMPP_TLV_NULTERMINATED: { \
709  if (copy_until_nul(octstr_get_cstr(tlv->name), data_without_len, &pos, opt_len, &val) == 0) \
710  dict_put(p->tlv, tlv->name, val); \
711  break; \
712  } \
713  default: \
714  panic(0, "SMPP: Internal error, unknown configured TLV type %d.", tlv->type); \
715  break; \
716  } \
717  } else { \
718  val = octstr_copy(data_without_len, pos, opt_len); \
719  if (val) \
720  octstr_binary_to_hex(val, 0); \
721  else \
722  val = octstr_create(""); \
723  warning(0, "SMPP: Unknown TLV(0x%04lx,0x%04lx,%s) for PDU type (%s) received!", \
724  opt_tag, opt_len, octstr_get_cstr(val), pdu->type_name); \
725  octstr_destroy(val); \
726  pos += opt_len; \
727  } \
728  } \
729  } \
730  }
731  #define INTEGER(name, octets) \
732  if ((p->name = decode_integer(data_without_len, pos, octets)) == -1) \
733  goto err; \
734  pos += octets;
735  #define NULTERMINATED(name, max_octets) \
736  /* just warn about errors but not fail */ \
737  copy_until_nul(#name, data_without_len, &pos, max_octets, &p->name);
738  #define OCTETS(name, field_giving_octets) \
739  p->name = octstr_copy(data_without_len, pos, \
740  p->field_giving_octets); \
741  if (p->field_giving_octets != (unsigned long) octstr_len(p->name)) { \
742  error(0, "smpp_pdu: error while unpacking '" #name "', " \
743  "len is %ld but should have been %ld, dropping.", \
744  octstr_len(p->name), p->field_giving_octets); \
745  goto err; \
746  } else { \
747  pos += p->field_giving_octets; \
748  }
749  #define PDU(name, id, fields) \
750  case id: { struct name *p = &pdu->u.name; fields } break;
751  #include "smpp_pdu.def"
752  default:
753  error(0, "Unknown SMPP_PDU type 0x%08lx, internal error while unpacking.", type);
754  break;
755  }
756 
757  return pdu;
758 
759 err:
760  smpp_pdu_destroy(pdu);
761  octstr_dump(data_without_len, 0);
762  return NULL;
763 }
void smpp_pdu_destroy(SMPP_PDU *pdu)
Definition: smpp_pdu.c:434
void error(int err, const char *fmt,...)
Definition: log.c:648
int type
Definition: smsc_cimd2.c:215
#define octstr_dump(ostr, level,...)
Definition: octstr.h:564
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
SMPP_PDU * smpp_pdu_create(unsigned long type, unsigned long seq_no)
Definition: smpp_pdu.c:400
static long decode_integer(Octstr *os, long pos, int octets)
Definition: smpp_pdu.c:330

◆ smpp_tlv_add_constant()

void smpp_tlv_add_constant ( Octstr smsc_id,
Dict **  tlvs 
)

Definition at line 102 of file smpp_pdu.c.

References smpp_tlv::constant, dict_create(), dict_get(), dict_keys(), dict_put(), gwlist_destroy(), gwlist_extract_first(), octstr_destroy(), octstr_destroy_item(), and octstr_duplicate.

Referenced by msg_to_pdu().

103 {
104  Dict *constant;
105  List *keys;
106  Octstr *key;
107  struct smpp_tlv *tlv;
108 
109  constant = dict_get(tlvs_by_const, smsc_id);
110  if (constant == NULL)
111  return;
112 
113  keys = dict_keys(constant);
114  while ((key = gwlist_extract_first(keys)) != NULL) {
115  /* only add if not available already */
116  tlv = dict_get(constant, key);
117  if (tlv && tlv->constant) {
118  if (*tlvs) {
119  if (dict_get(*tlvs, key) == NULL)
120  dict_put(*tlvs, key, octstr_duplicate(tlv->constant));
121  } else {
122  *tlvs = dict_create(1024, octstr_destroy_item);
123  dict_put(*tlvs, key, octstr_duplicate(tlv->constant));
124  }
125  }
126  octstr_destroy(key);
127  }
128  gwlist_destroy(keys, NULL);
129 }
Dict * dict_create(long size_hint, void(*destroy_value)(void *))
Definition: dict.c:192
Octstr * constant
Definition: smpp_pdu.c:79
void dict_put(Dict *dict, Octstr *key, void *value)
Definition: dict.c:240
void * gwlist_extract_first(List *list)
Definition: list.c:305
void * dict_get(Dict *dict, Octstr *key)
Definition: dict.c:286
Definition: dict.c:116
#define octstr_duplicate(ostr)
Definition: octstr.h:187
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
void octstr_destroy_item(void *os)
Definition: octstr.c:334
Definition: octstr.c:118
static Dict * tlvs_by_const
Definition: smpp_pdu.c:87
List * dict_keys(Dict *dict)
Definition: dict.c:347
Definition: list.c:102
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145

◆ smpp_tlv_destroy()

static void smpp_tlv_destroy ( struct smpp_tlv tlv)
static

Definition at line 92 of file smpp_pdu.c.

References smpp_tlv::constant, smpp_tlv::name, and octstr_destroy().

Referenced by smpp_pdu_init(), and smpp_pdu_shutdown().

93 {
94  if (tlv == NULL)
95  return;
96  octstr_destroy(tlv->name);
98  gw_free(tlv);
99 }
Octstr * constant
Definition: smpp_pdu.c:79
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
Octstr * name
Definition: smpp_pdu.c:76

◆ smpp_tlv_get_by_name()

static struct smpp_tlv* smpp_tlv_get_by_name ( Octstr smsc_id,
Octstr name 
)
static

Definition at line 132 of file smpp_pdu.c.

References DEFAULT_SMSC_ID, dict_get(), and octstr_imm().

133 {
134  struct smpp_tlv *res = NULL;
135  Dict *tmp_dict;
136 
137  if (tlvs_by_name == NULL || name == NULL)
138  return NULL;
139 
140  if (smsc_id != NULL) {
141  tmp_dict = dict_get(tlvs_by_name, smsc_id);
142  if (tmp_dict != NULL)
143  res = dict_get(tmp_dict, name);
144  }
145  if (res == NULL) {
146  /* try default smsc_id */
147  smsc_id = octstr_imm(DEFAULT_SMSC_ID);
148  tmp_dict = dict_get(tlvs_by_name, smsc_id);
149  if (tmp_dict != NULL)
150  res = dict_get(tmp_dict, name);
151  }
152  return res;
153 }
static Dict * tlvs_by_name
Definition: smpp_pdu.c:86
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:281
void * dict_get(Dict *dict, Octstr *key)
Definition: dict.c:286
Definition: dict.c:116
#define DEFAULT_SMSC_ID
Definition: smpp_pdu.c:73

◆ smpp_tlv_get_by_tag()

static struct smpp_tlv* smpp_tlv_get_by_tag ( Octstr smsc_id,
long  tag 
)
static

Definition at line 155 of file smpp_pdu.c.

References DEFAULT_SMSC_ID, dict_get(), octstr_destroy(), octstr_format(), and octstr_imm().

156 {
157  struct smpp_tlv *res = NULL;
158  Dict *tmp_dict;
159  Octstr *tmp;
160 
161  if (tlvs_by_tag == NULL)
162  return NULL;
163 
164  tmp = octstr_format("%ld", tag);
165 
166  if (smsc_id != NULL) {
167  tmp_dict = dict_get(tlvs_by_tag, smsc_id);
168  if (tmp_dict != NULL)
169  res = dict_get(tmp_dict, tmp);
170  }
171  if (res == NULL) {
172  /* try default smsc_id */
173  smsc_id = octstr_imm(DEFAULT_SMSC_ID);
174  tmp_dict = dict_get(tlvs_by_tag, smsc_id);
175  if (tmp_dict != NULL)
176  res = dict_get(tmp_dict, tmp);
177  }
178 
179  octstr_destroy(tmp);
180 
181  return res;
182 }
static Dict * tlvs_by_tag
Definition: smpp_pdu.c:84
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:281
void * dict_get(Dict *dict, Octstr *key)
Definition: dict.c:286
long tag
Definition: smpp_pdu.c:77
Definition: dict.c:116
#define DEFAULT_SMSC_ID
Definition: smpp_pdu.c:73
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2462
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
Definition: octstr.c:118

Variable Documentation

◆ initialized

int initialized
static

Definition at line 89 of file smpp_pdu.c.

Referenced by smpp_pdu_init(), and smpp_pdu_shutdown().

◆ tlvs

List* tlvs
static

Definition at line 88 of file smpp_pdu.c.

◆ tlvs_by_const

Dict* tlvs_by_const
static

Definition at line 87 of file smpp_pdu.c.

◆ tlvs_by_name

Dict* tlvs_by_name
static

Definition at line 86 of file smpp_pdu.c.

◆ tlvs_by_tag

Dict* tlvs_by_tag
static

Definition at line 84 of file smpp_pdu.c.

See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.