📄 smsc_oisd.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. */ /* * smsc.oisd.c - Driver for Sema Group SMS Center G8.1 (OIS 5.8) * using direct TCP/IP access interface * * Dariusz Markowicz <dm@tenbit.pl> 2002-2004 * * This code is based on the CIMD2 module design. * * References: * * [1] Sema SMSC Version G8.1 Open Interface Specification * document version 5.8, 18 January 2001, Sema Telecoms. */#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 *host; long port; long keepalive; Octstr *my_number; long validityperiod; int no_dlr; int socket; unsigned long send_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 (10 * 1000000)#define RESULT_SUCCESS 0enum { INVOKE = 0, RESULT = 1};/* Textual names for the operation codes defined by the OISD spec. *//* If you make changes here, also change the operation table. */enum { SUBMIT_SM = 0, STATUS_REPORT = 4, DELIVER_SM = 9, RETRIEVE_REQUEST = 11, /* Not a request; add to any request to make it a response */ RESPONSE = 50};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[] = { { "Submit SM", SUBMIT_SM, 1, 0 }, { "Status Report", STATUS_REPORT, 0, 1 }, { "Deliver SM", DELIVER_SM, 0, 1 }, { "Retrieve Request", RETRIEVE_REQUEST, 1, 0 }, { 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); if (i >= 0) { Octstr *name = octstr_create(operations[i].name); octstr_append_cstr(name, " response"); return name; } } /* Put the operation number here when we have octstr_format */ return octstr_create("(unknown)");}/* Return true if a OISD client may send this operation */static const int operation_can_send(int operation){ int i = operation_find(operation); if (i >= 0) return operations[i].can_send; /* If we can receive the request, then we can send the response. */ if (operation >= RESPONSE) return operation_can_receive(operation - RESPONSE); return 0;}/* Return true if a OISD server may send this operation */static const int operation_can_receive(int operation){ int i = operation_find(operation); if (i >= 0) return operations[i].can_receive; /* If we can send the request, then we can receive the response. */ if (operation >= RESPONSE) return operation_can_send(operation - RESPONSE); return 0;}/*************************************************************************** * Packet encoding/decoding functions. They handle packets at the octet * * level, and know nothing of the network. * ***************************************************************************/struct packet{ unsigned long opref; /* operation reference */ int operation; Octstr *data; /* Encoded packet */};/* A reminder that packets are created without a valid sequence number */#define BOGUS_SEQUENCE 0static Msg *oisd_accept_delivery_report_message(struct packet *request, SMSCConn *conn);static void packet_parse_header(struct packet *packet){ packet->opref = (octstr_get_char(packet->data, 3) << 24) | (octstr_get_char(packet->data, 2) << 16) | (octstr_get_char(packet->data, 1) << 8) | (octstr_get_char(packet->data, 0)); packet->operation = octstr_get_char(packet->data, 5); if (octstr_get_char(packet->data, 4) == 1) packet->operation += RESPONSE;}/* * Accept an Octstr containing one packet, build a struct packet around * it, and return that struct. The Octstr is stored in the struct. * No error checking is done here yet. */static struct packet *packet_parse(Octstr *packet_data){ struct packet *packet; packet = gw_malloc(sizeof(*packet)); packet->data = packet_data; /* Fill in packet->operation and packet->opref */ packet_parse_header(packet); return packet;}/* Deallocate this packet */static void packet_destroy(struct packet *packet){ if (packet != NULL) { octstr_destroy(packet->data); gw_free(packet); }}/* * Find the first packet in "in", delete it from "in", and return it as * a struct. Return NULL if "in" contains no packet. Always delete * leading non-packet data from "in". */static struct packet *packet_extract(Octstr *in, SMSCConn *conn){ Octstr *packet; int size, i; static char s[4][4] = { { 0x01, 0x0b, 0x00, 0x00 }, { 0x01, 0x00, 0x00, 0x00 }, { 0x00, 0x04, 0x00, 0x00 }, { 0x00, 0x09, 0x00, 0x00 } }; /* msgtype, oper, 0, 0 */ char known_bytes[4]; if (octstr_len(in) < 10) return NULL; octstr_get_many_chars(known_bytes, in, 4, 4); /* Find s, and delete everything up to it. */ /* If packet starts with one of s, it should be good packet */ for (i = 0; i < 4; i++) { if (memcmp(s[i], known_bytes, 4) == 0) break; } if (i >= 4) { error(0, "OISD[%s]: wrong packet", octstr_get_cstr(conn->id)); octstr_dump(in, 0); return NULL; } /* Find end of packet */ size = (octstr_get_char(in, 9) << 8) | octstr_get_char(in, 8); if (size + 10 > octstr_len(in)) return NULL; packet = octstr_copy(in, 0, size + 10); octstr_delete(in, 0, size + 10); return packet_parse(packet);}static void packet_check_can_receive(struct packet *packet, SMSCConn *conn){ gw_assert(packet != NULL); if (!operation_can_receive(packet->operation)) { Octstr *name = operation_name(packet->operation); warning(0, "OISD[%s]: SMSC sent us %s request", octstr_get_cstr(conn->id), octstr_get_cstr(name)); octstr_destroy(name); }}static int oisd_expand_gsm7_to_bits(char *bits, Octstr *raw7){ int i, j, k; int len; char ch; len = octstr_len(raw7) * 7; /* number of bits in the gsm 7-bit msg */ for (j = i = 0; j < len; ++i) { ch = octstr_get_char(raw7, i); for (k = 0; k < 8; ++k) { bits[j++] = (char) (ch & 0x01); ch >>= 1; } } return j;}static char oisd_expand_gsm7_from_bits(const char *bits, int pos){ int i; char ch; pos *= 7; /* septet position in bits */ ch = '\0'; for (i = 6; i >= 0; --i) { ch <<= 1; ch |= bits[pos + i]; } return ch;}static Octstr *oisd_expand_gsm7(Octstr *raw7){ Octstr *raw8; int i, len; char *bits; raw8 = octstr_create(""); bits = gw_malloc(8 * octstr_len(raw7) + 1); oisd_expand_gsm7_to_bits(bits, raw7); len = octstr_len(raw7); for (i = 0; i < len; ++i) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -