📄 smpp_pdu.c
字号:
/* ==================================================================== * The Kannel Software License, Version 1.0 * * Copyright (c) 2001-2004 Kannel Group * Copyright (c) 1998-2001 WapIT Ltd. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Kannel Group (http://www.kannel.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Kannel" and "Kannel Group" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please * contact org@kannel.org. * * 5. Products derived from this software may not be called "Kannel", * nor may "Kannel" appear in their name, without prior written * permission of the Kannel Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Kannel Group. For more information on * the Kannel Group, please see <http://www.kannel.org/>. * * Portions of this software are based upon software originally written at * WapIT Ltd., Helsinki, Finland for the Kannel project. */ /* * smpp_pdu.c - parse and generate SMPP PDUs * * Lars Wirzenius * Alexander Malysh <a.malysh@centrium.de>: * Extended optional parameters implementation. */#include <string.h>#include "smpp_pdu.h"#define MIN_SMPP_PDU_LEN (4*4)/* old value was (1024). We need more because message_payload can be up to 64K octets*/#define MAX_SMPP_PDU_LEN (7424) static long decode_integer(Octstr *os, long pos, int octets){ unsigned long u; int i; if (octstr_len(os) < pos + octets) return -1; u = 0; for (i = 0; i < octets; ++i) u = (u << 8) | octstr_get_char(os, pos + i); return u;}static void append_encoded_integer(Octstr *os, unsigned long u, long octets){ long i; for (i = 0; i < octets; ++i) octstr_append_char(os, (u >> ((octets - i - 1) * 8)) & 0xFF);}static Octstr *copy_until_nul(Octstr *os, long *pos, long max_octets){ long nul; Octstr *data; nul = octstr_search_char(os, '\0', *pos); if (nul == -1) { warning(0, "SMPP: PDU NULL terminated string has no NULL."); return NULL; } if (*pos + max_octets < nul) { error(0, "SMPP: PDU NULL terminated string longer than allowed."); return NULL; } data = (nul - *pos > 0) ? octstr_copy(os, *pos, nul - *pos) : NULL; *pos = nul + 1; return data;}SMPP_PDU *smpp_pdu_create(unsigned long type, unsigned long seq_no){ SMPP_PDU *pdu; pdu = gw_malloc(sizeof(*pdu)); pdu->type = type; switch (type) { #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 #define INTEGER(name, octets) \ if (strcmp(#name, "command_id") == 0) p->name = type; \ else if (strcmp(#name, "sequence_number") == 0) p->name = seq_no; \ else 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) \ case id: { \ struct name *p = &pdu->u.name; \ pdu->type_name = #name; \ fields \ } break; #include "smpp_pdu.def" default: error(0, "Unknown SMPP_PDU type, internal error."); gw_free(pdu); return NULL; } return pdu;}void smpp_pdu_destroy(SMPP_PDU *pdu){ if (pdu == NULL) return; switch (pdu->type) { #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 #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; #include "smpp_pdu.def" default: error(0, "Unknown SMPP_PDU type, internal error while destroying."); } gw_free(pdu);}Octstr *smpp_pdu_pack(SMPP_PDU *pdu){ Octstr *os; Octstr *temp; os = octstr_create(""); gw_assert(pdu != NULL); /* * Fix lengths of octet string fields. */ switch (pdu->type) { #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; #include "smpp_pdu.def" default: error(0, "Unknown SMPP_PDU type, internal error while packing."); } switch (pdu->type) { #define TL(name, octets) \ append_encoded_integer(os, SMPP_##name, 2); \ append_encoded_integer(os, octets, 2); #define OPTIONAL_BEGIN #define TLV_INTEGER(name, octets) \ if (p->name != -1) { \ TL(name, octets); \ INTEGER(name, octets) \ } #define TLV_NULTERMINATED(name, max_len) \ if (p->name != NULL) { \ TL(name, (octstr_len(p->name) > max_len ? max_len : octstr_len(p->name))); \ NULTERMINATED(name, max_len) \ } #define TLV_OCTETS(name, min_len, max_len) \ 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); \ } \ } #define OPTIONAL_END #define INTEGER(name, octets) \ append_encoded_integer(os, p->name, octets); #define NULTERMINATED(name, max_octets) \ 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 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; #include "smpp_pdu.def"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -