📄 smsc_cimd2.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. */ /* Driver for CIMD 2 SMS centres. * Copyright 2000 WapIT Oy Ltd. * Author: Richard Braakman * * Upgrade to SMSCConn API: 2002 Kalle Marjola / 2003 Angel Fradejas *//* TODO: Check checksums on incoming packets *//* TODO: Leading or trailing spaces are not allowed on parameters * "user identity" and "password". Check this. *//* TODO: Try to use the "More messages to send" flag *//* This code is based on the CIMD 2 spec, version 2-0 en. * All USSD-specific parts have been left out, since we only want to * communicate with SMSC's. * * I found one contradiction in the spec: * * - The definition of Integer parameters specifies decimal digits only, * but at least one Integer parameter (Validity Period Relative) can * be negative. I assume that this means a leading - is valid. */#include <ctype.h>#include <time.h>#include <errno.h>#include <limits.h>#include <string.h>#include <unistd.h>#include "gwlib/gwlib.h"#include "smscconn.h"#include "smscconn_p.h"#include "bb_smscconn_cb.h"#include "shared.h"#include "sms.h"#include "dlr.h"typedef struct privdata { Octstr *username; Octstr *password; Octstr *host; long port; long our_port; long keepalive; Octstr *my_number; int no_dlr; int socket; int send_seq; int receive_seq; Octstr *inbuffer; List *received; time_t next_ping; List *outgoing_queue; SMSCConn *conn; int io_thread; int quitting; List *stopped; /* list-trick for suspend/isolate */} PrivData;/* Microseconds before giving up on a request */#define RESPONSE_TIMEOUT (60 * 1000000)/* Textual names for the operation codes defined by the CIMD 2 spec. *//* If you make changes here, also change the operation table. */enum { /* Requests from client */ LOGIN = 1, LOGOUT = 2, SUBMIT_MESSAGE = 3, ENQUIRE_MESSAGE_STATUS = 4, DELIVERY_REQUEST = 5, CANCEL_MESSAGE = 6, SET_REQ = 8, GET_REQ = 9, /* Requests from server */ DELIVER_MESSAGE = 20, DELIVER_STATUS_REPORT = 23, /* Requests from either */ ALIVE = 40, /* Not a request; add to any request to make it a response */ RESPONSE = 50, /* Responses not related to requests */ GENERAL_ERROR_RESPONSE = 98, NACK = 99};/* Textual names for the parameters defined by the CIMD 2 spec. *//* If you make changes here, also change the parameter table. */enum { P_USER_IDENTITY = 10, P_PASSWORD = 11, P_DESTINATION_ADDRESS = 21, P_ORIGINATING_ADDRESS = 23, P_ORIGINATING_IMSI = 26, P_ALPHANUMERIC_ORIGINATING_ADDRESS = 27, P_ORIGINATED_VISITED_MSC = 28, P_DATA_CODING_SCHEME = 30, P_USER_DATA_HEADER = 32, P_USER_DATA = 33, P_USER_DATA_BINARY = 34, P_MORE_MESSAGES_TO_SEND = 44, P_VALIDITY_PERIOD_RELATIVE = 50, P_VALIDITY_PERIOD_ABSOLUTE = 51, P_PROTOCOL_IDENTIFIER = 52, P_FIRST_DELIVERY_TIME_RELATIVE = 53, P_FIRST_DELIVERY_TIME_ABSOLUTE = 54, P_REPLY_PATH = 55, P_STATUS_REPORT_REQUEST = 56, P_CANCEL_ENABLED = 58, P_CANCEL_MODE = 59, P_MC_TIMESTAMP = 60, P_STATUS_CODE = 61, P_STATUS_ERROR_CODE = 62, P_DISCHARGE_TIME = 63, P_TARIFF_CLASS = 64, P_SERVICE_DESCRIPTION = 65, P_MESSAGE_COUNT = 66, P_PRIORITY = 67, P_DELIVERY_REQUEST_MODE = 68, P_SERVICE_CENTER_ADDRESS = 69, P_GET_PARAMETER = 500, P_MC_TIME = 501, P_ERROR_CODE = 900, P_ERROR_TEXT = 901};/***************************************************************************//* Table of properties of the parameters defined by CIMD 2, and some *//* functions to look up fields. *//***************************************************************************//* Parameter types, internal. CIMD 2 spec considers P_TIME to be "Integer" * and P_SMS to be "User Data". */enum { P_INT, P_STRING, P_ADDRESS, P_TIME, P_HEX, P_SMS };/* Information about the parameters defined by the CIMD 2 spec. * Used for warning about invalid incoming messages, and for validating * outgoing messages. */static const struct{ unsigned char *name; int number; int maxlen; int type; /* P_ values */ int minval, maxval; /* For P_INT */}parameters[] = { { "user identity", P_USER_IDENTITY, 32, P_STRING }, { "password", P_PASSWORD, 32, P_STRING }, { "destination address", P_DESTINATION_ADDRESS, 20, P_ADDRESS }, { "originating address", P_ORIGINATING_ADDRESS, 20, P_ADDRESS }, /* IMSI is International Mobile Subscriber Identity number */ { "originating IMSI", P_ORIGINATING_IMSI, 20, P_ADDRESS }, { "alphanumeric originating address", P_ALPHANUMERIC_ORIGINATING_ADDRESS, 11, P_STRING }, { "originated visited MSC", P_ORIGINATED_VISITED_MSC, 20, P_ADDRESS }, { "data coding scheme", P_DATA_CODING_SCHEME, 3, P_INT, 0, 255 }, { "user data header", P_USER_DATA_HEADER, 280, P_HEX }, { "user data", P_USER_DATA, 480, P_SMS }, { "user data binary", P_USER_DATA_BINARY, 280, P_HEX }, { "more messages to send", P_MORE_MESSAGES_TO_SEND, 1, P_INT, 0, 1 }, { "validity period relative", P_VALIDITY_PERIOD_RELATIVE, 3, P_INT, -1, 255 }, { "validity period absolute", P_VALIDITY_PERIOD_ABSOLUTE, 12, P_TIME }, { "protocol identifier", P_PROTOCOL_IDENTIFIER, 3, P_INT, 0, 255 }, { "first delivery time relative", P_FIRST_DELIVERY_TIME_RELATIVE, 3, P_INT, -1, 255 }, { "first delivery time absolute", P_FIRST_DELIVERY_TIME_ABSOLUTE, 12, P_TIME }, { "reply path", P_REPLY_PATH, 1, P_INT, 0, 1 }, { "status report request", P_STATUS_REPORT_REQUEST, 2, P_INT, 0, 63 }, { "cancel enabled", P_CANCEL_ENABLED, 1, P_INT, 0, 1 }, { "cancel mode", P_CANCEL_MODE, 1, P_INT, 0, 2 }, { "service centre timestamp", P_MC_TIMESTAMP, 12, P_TIME }, { "status code", P_STATUS_CODE, 2, P_INT, 0, 9 }, { "status error code", P_STATUS_ERROR_CODE, 3, P_INT, 0, 999 }, { "discharge time", P_DISCHARGE_TIME, 12, P_TIME }, { "tariff class", P_TARIFF_CLASS, 2, P_INT, 0, 99 }, { "service description", P_SERVICE_DESCRIPTION, 2, P_INT, 0, 9 }, { "message count", P_MESSAGE_COUNT, 3, P_INT, 0, 999 }, { "priority", P_PRIORITY, 1, P_INT, 1, 9 }, { "delivery request mode", P_DELIVERY_REQUEST_MODE, 1, P_INT, 0, 2 }, { "service center address", P_SERVICE_CENTER_ADDRESS, 20, P_ADDRESS }, { "get parameter", P_GET_PARAMETER, 3, P_INT, 501, 999 }, { "MC time", P_MC_TIME, 12, P_TIME }, { "error code", P_ERROR_CODE, 3, P_INT, 0, 999 }, { "error text", P_ERROR_TEXT, 64, P_STRING }, { NULL }};/* Return the index in the parameters array for this parameter id. * Return -1 if it is not found. */static const int parm_index(int parmno){ int i; for (i = 0; parameters[i].name != NULL; i++) { if (parameters[i].number == parmno) return i; } return -1;}#ifndef NO_GWASSERT/* Return the type of this parameter id. Return -1 if the id is unknown. */static const int parm_type(int parmno){ int i = parm_index(parmno); if (i < 0) return -1; return parameters[i].type;}#endif/* Return the max length for this parameter id. * Return -1 if the id is unknown. */static const int parm_maxlen(int parmno){ int i = parm_index(parmno); if (i < 0) return -1; return parameters[i].maxlen;}static const char *parm_name(int parmno){ int i = parm_index(parmno); if (i < 0) return NULL; return parameters[i].name;}#ifndef NO_GWASSERT/* Return 1 if the value for this (Integer) parameter is in range. * Return 0 otherwise. Return -1 if the parameter was not found. */static const int parm_in_range(int parmno, long value){ int i; i = parm_index(parmno); if (i < 0) return -1; return (value >= parameters[i].minval && value <= parameters[i].maxval);}#endif/* Helper function to check P_ADDRESS type */static int isphonedigit(int c){ return isdigit(c) || c == '+' || c == '-';}static const int parm_valid_address(Octstr *value){ return octstr_check_range(value, 0, octstr_len(value), isphonedigit);}/***************************************************************************//* Some functions to look up information about operation codes *//***************************************************************************/static int operation_find(int operation);static Octstr *operation_name(int operation);static const int operation_can_send(int operation);static const int operation_can_receive(int operation);static const struct{ unsigned char *name; int code; int can_send; int can_receive;}operations[] = { { "Login", LOGIN, 1, 0 }, { "Logout", LOGOUT, 1, 0 }, { "Submit message", SUBMIT_MESSAGE, 1, 0 }, { "Enquire message status", ENQUIRE_MESSAGE_STATUS, 1, 0 }, { "Delivery request", DELIVERY_REQUEST, 1, 0 }, { "Cancel message", CANCEL_MESSAGE, 1, 0 }, { "Set parameter", SET_REQ, 1, 0 }, { "Get parameter", GET_REQ, 1, 0 }, { "Deliver message", DELIVER_MESSAGE, 0, 1 }, { "Deliver status report", DELIVER_STATUS_REPORT, 0, 1 }, { "Alive", ALIVE, 1, 1 }, { "NACK", NACK, 1, 1 }, { "General error response", GENERAL_ERROR_RESPONSE, 0, 1 }, { NULL, 0, 0, 0 }};static int operation_find(int operation){ int i; for (i = 0; operations[i].name != NULL; i++) { if (operations[i].code == operation) return i; } return -1;}/* Return a human-readable representation of this operation code */static Octstr *operation_name(int operation){ int i; i = operation_find(operation); if (i >= 0) return octstr_create(operations[i].name); if (operation >= RESPONSE) { i = operation_find(operation - RESPONSE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -