static SMPP_PDU *handle_unbind(ESME *esme, SMPP_PDU *pdu) { SMPP_PDU *resp; resp = smpp_pdu_create(unbind_resp, pdu->u.unbind.sequence_number); return resp; }
static void send_smpp_thread(void *arg) { ESME *esme; Octstr *os; SMPP_PDU *pdu; unsigned long id; esme = arg; id = 0; while (!quitting && counter_value(num_to_esme) < max_to_esme) { id = counter_increase(num_to_esme) + 1; while (!quitting && counter_value(num_from_esme) + 500 < id) gwthread_sleep(1.0); if (quitting) break; pdu = smpp_pdu_create(deliver_sm, counter_increase(message_id_counter)); pdu->u.deliver_sm.source_addr = octstr_create("456"); pdu->u.deliver_sm.destination_addr = octstr_create("123"); pdu->u.deliver_sm.short_message = octstr_format("%ld", id); if (esme->version > 0x33) pdu->u.deliver_sm.receipted_message_id = octstr_create("receipted_message_id\0"); os = smpp_pdu_pack(NULL, pdu); conn_write(esme->conn, os); octstr_destroy(os); smpp_pdu_destroy(pdu); if (first_to_esme == (time_t) -1) time(&first_to_esme); debug("test.smpp", 0, "Delivered SMS %ld of %ld to bearerbox via SMPP.", id, max_to_esme); if ((id % enquire_interval) == 0) { pdu = smpp_pdu_create(enquire_link, counter_increase(message_id_counter)); os = smpp_pdu_pack(NULL, pdu); conn_write(esme->conn, os); octstr_destroy(os); smpp_pdu_destroy(pdu); debug("test.smpp", 0, "Sent enquire_link to bearerbox."); } } time(&last_to_esme); if (id == max_to_esme) info(0, "All messages sent to ESME."); debug("test.smpp", 0, "%s terminates.", __func__); }
static SMPP_PDU *handle_bind_receiver(ESME *esme, SMPP_PDU *pdu) { SMPP_PDU *resp; esme->receiver = 1; esme->version = pdu->u.bind_receiver.interface_version; resp = smpp_pdu_create(bind_receiver_resp, pdu->u.bind_receiver.sequence_number); #if 0 /* XXX system_id is not implemented in the PDU at the moment */ resp->u.bind_receiver_resp.system_id = octstr_duplicate(smsc_system_id); #endif return resp; }
static SMPP_PDU *handle_submit_sm(ESME *esme, SMPP_PDU *pdu) { SMPP_PDU *resp; unsigned long id; debug("test.smpp", 0, "submit_sm: short_message = <%s>", octstr_get_cstr(pdu->u.submit_sm.short_message)); id = counter_increase(num_from_esme) + 1; if (id == max_to_esme) info(0, "ESME has submitted all messages to SMSC."); time(&last_from_esme); resp = smpp_pdu_create(submit_sm_resp, pdu->u.submit_sm.sequence_number); #if 0 /* XXX message_id is not implemented in the PDU at the moment */ resp->u.submit_sm_resp.message_id = octstr_format("%ld", counter_increase(message_id_counter)); #endif return resp; }
SMPP_PDU *smpp_pdu_unpack(Octstr *data_without_len) { SMPP_PDU *pdu; unsigned long type; long len, pos; len = octstr_len(data_without_len); if (len < 4) { error(0, "SMPP: PDU was too short (%ld bytes).", octstr_len(data_without_len)); return NULL; } /* get the PDU type */ if ((type = decode_integer(data_without_len, 0, 4)) == -1) return NULL; /* create a coresponding representation structure */ pdu = smpp_pdu_create(type, 0); if (pdu == NULL) return NULL; pos = 0; switch (type) { #define OPTIONAL_BEGIN \ { /* Read optional parameters */ \ while (pos + 4 <= len) { \ 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); #define TLV_INTEGER(name, octets) \ if (SMPP_##name == opt_tag) { \ /* check length */ \ if (opt_len > octets) { \ error(0, "SMPP: Optional field (%s) with invalid length (%ld) dropped.", #name, opt_len); \ pos += opt_len; \ continue; \ } \ INTEGER(name, opt_len); \ } else #define TLV_NULTERMINATED(name, max_len) \ if (SMPP_##name == opt_tag) { \ /* check length */ \ if (opt_len > max_len || pos+opt_len > len) { \ error(0, "SMPP: Optional field (%s) with invalid length (%ld) dropped.", #name, opt_len); \ pos += opt_len; \ continue; \ } \ NULTERMINATED(name, opt_len); \ } else #define TLV_OCTETS(name, min_len, max_len) \ if (SMPP_##name == 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.", \ #name, opt_len, min_len, max_len); \ pos += opt_len; \ continue; \ } \ p->name = octstr_copy(data_without_len, pos, opt_len); \ pos += opt_len; \ } else #define OPTIONAL_END \ { \ Octstr *val = octstr_copy(data_without_len, pos, opt_len); \ if (val) octstr_binary_to_hex(val, 0); \ else val = octstr_create(""); \ error(0, "SMPP: Unknown TLV(0x%04lx,0x%04lx,%s) for PDU type (%s) received!", \ opt_tag, opt_len, octstr_get_cstr(val), pdu->type_name); \ pos += opt_len; \ octstr_destroy(val); \ } \ } \ } #define INTEGER(name, octets) \ p->name = decode_integer(data_without_len, pos, octets); \ pos += octets; #define NULTERMINATED(name, max_octets) \ p->name = copy_until_nul(data_without_len, &pos, max_octets); #define OCTETS(name, field_giving_octets) \ 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 'short_message', " \ "len is %ld but should have been %ld, dropping.", \ octstr_len(p->name), p->field_giving_octets); \ return NULL; \ } else { \ pos += p->field_giving_octets; \ } #define PDU(name, id, fields) \ case id: { struct name *p = &pdu->u.name; fields } break; #include "smpp_pdu.def" default: error(0, "Unknown SMPP_PDU type, internal error while unpacking."); } return pdu; }
static SMPP_PDU *handle_enquire_link(ESME *esme, SMPP_PDU *pdu) { return smpp_pdu_create(enquire_link_resp, pdu->u.enquire_link.sequence_number); }
SMPP_PDU *smpp_pdu_unpack(Octstr *smsc_id, Octstr *data_without_len) { SMPP_PDU *pdu; unsigned long type; long len, pos; len = octstr_len(data_without_len); if (len < 4) { error(0, "SMPP: PDU was too short (%ld bytes).", octstr_len(data_without_len)); return NULL; } /* get the PDU type */ if ((type = decode_integer(data_without_len, 0, 4)) == -1) return NULL; /* create a coresponding representation structure */ pdu = smpp_pdu_create(type, 0); if (pdu == NULL) return NULL; pos = 0; switch (type) { #define OPTIONAL_BEGIN \ { /* 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 TLV_INTEGER(mname, octets) \ 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 #define TLV_NULTERMINATED(mname, max_len) \ 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; \ } \ 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 #define TLV_OCTETS(mname, min_len, max_len) \ 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; \ } \ 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 #define OPTIONAL_END \ { \ Octstr *val = NULL; \ if (tlv != NULL) { \ /* found configured tlv */ \ /* check length */ \ if (opt_len > tlv->length) { \ error(0, "SMPP: Optional field (%s) with invalid length (%ld) (should be %ld) dropped.", \ octstr_get_cstr(tlv->name), opt_len, tlv->length); \ pos += opt_len; \ continue; \ } \ switch (tlv->type) { \ case SMPP_TLV_INTEGER: { \ long val_i; \ if ((val_i = decode_integer(data_without_len, pos, opt_len)) == -1) \ goto err; \ val = octstr_format("%ld", val_i); \ dict_put(p->tlv, tlv->name, val); \ pos += opt_len; \ break; \ } \ case SMPP_TLV_OCTETS: { \ val = octstr_copy(data_without_len, pos, opt_len); \ dict_put(p->tlv, tlv->name, val); \ pos += opt_len; \ break; \ } \ case SMPP_TLV_NULTERMINATED: { \ if (copy_until_nul(octstr_get_cstr(tlv->name), data_without_len, &pos, opt_len, &val) == 0) \ dict_put(p->tlv, tlv->name, val); \ break; \ } \ default: \ panic(0, "SMPP: Internal error, unknown configured TLV type %d.", tlv->type); \ break; \ } \ } else { \ val = octstr_copy(data_without_len, pos, opt_len); \ if (val) \ octstr_binary_to_hex(val, 0); \ else \ val = octstr_create(""); \ warning(0, "SMPP: Unknown TLV(0x%04lx,0x%04lx,%s) for PDU type (%s) received!", \ opt_tag, opt_len, octstr_get_cstr(val), pdu->type_name); \ octstr_destroy(val); \ pos += opt_len; \ } \ } \ } \ } #define INTEGER(name, octets) \ if ((p->name = decode_integer(data_without_len, pos, octets)) == -1) \ goto err; \ pos += octets; #define NULTERMINATED(name, max_octets) \ /* just warn about errors but not fail */ \ copy_until_nul(#name, data_without_len, &pos, max_octets, &p->name); #define OCTETS(name, field_giving_octets) \ 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 PDU(name, id, fields) \ case id: { struct name *p = &pdu->u.name; fields } break; #include "smpp_pdu.def" default: error(0, "Unknown SMPP_PDU type 0x%08lx, internal error while unpacking.", type); break; } return pdu; err: smpp_pdu_destroy(pdu); octstr_dump(data_without_len, 0); return NULL; }