📄 smsc_emi_x25.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_emi.c - implement interface to the CMG SMS Center (UCP/EMI).* Mikael Gueck for WapIT Ltd.*//* This file implements two smsc interfaces: EMI_X25 */#include <errno.h>#include <string.h>#include <stdio.h>#include <unistd.h>#include <fcntl.h>#include <termios.h>#include <stdarg.h>#include <stdlib.h>#include <string.h>#include <strings.h>#include <sys/time.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/param.h>#include <sys/ioctl.h>#include "gwlib/gwlib.h"#include "smsc.h"#include "smsc_p.h"#include "alt_charsets.h"#include "sms.h"#ifndef CRTSCTS#define CRTSCTS 0#endif/******************************************************************************* Static functions*/static int get_data(SMSCenter *smsc, char *buff, int length);static int put_data(SMSCenter *smsc, char *buff, int length, int is_backup);static int memorybuffer_append_data(SMSCenter *smsc, char *buff, int length);static int memorybuffer_insert_data(SMSCenter *smsc, char *buff, int length);static int memorybuffer_has_rawmessage(SMSCenter *smsc, int type, char auth);static int memorybuffer_cut_rawmessage(SMSCenter *smsc, char *buff, int length);static int parse_rawmessage_to_msg(SMSCenter *smsc, Msg **msg, char *rawmessage, int length);static int parse_msg_to_rawmessage(SMSCenter *smsc, Msg *msg, char *rawmessage, int length);static int acknowledge_from_rawmessage(SMSCenter *smsc, char *rawmessage, int length);static int parse_emi_to_iso88591(char *from, char *to, int length, int alt_charset);static int parse_iso88591_to_emi(char *from, char *to, int length, int alt_charset);static int parse_binary_to_emi(char *from, char *to, int length);static int at_dial(char *device, char *phonenum, char *at_prefix, time_t how_long);static int guarantee_link(SMSCenter *smsc);static void generate_checksum(const unsigned char *buffer, unsigned char *checksum_out);static int wait_for_ack(SMSCenter *smsc, int op_type);static char char_iso_to_sms(unsigned char from, int alt_charset);static char char_sms_to_iso(unsigned char from, int alt_charset);/******************************************************************************* Open the connection and log in - handshake baby*/static int emi_open_connection(SMSCenter *smsc){ char tmpbuff[1024]; sprintf(tmpbuff, "/dev/%s", smsc->emi_serialdevice); smsc->emi_fd = at_dial(tmpbuff, smsc->emi_phonenum, "ATD", 30); if (smsc->emi_fd <= 0) return -1; return 0;}/* open EMI smscenter */SMSCenter *emi_open(char *phonenum, char *serialdevice, char *username, char *password){ SMSCenter *smsc; smsc = smscenter_construct(); if (smsc == NULL) goto error; smsc->type = SMSC_TYPE_EMI_X25; smsc->emi_phonenum = gw_strdup(phonenum); smsc->emi_serialdevice = gw_strdup(serialdevice); smsc->emi_username = gw_strdup(username); smsc->emi_password = gw_strdup(password); smsc->emi_current_msg_number = 0; if (emi_open_connection(smsc) < 0) goto error; sprintf(smsc->name, "EMI:%s:%s", smsc->emi_phonenum, smsc->emi_username); return smsc;error: error(0, "emi_open failed"); smscenter_destruct(smsc); return NULL;}int emi_reopen(SMSCenter *smsc){ emi_close(smsc); if (emi_open_connection(smsc) < 0) { error(0, "emi_reopen failed"); return -1; } return 0;}int emi_close(SMSCenter *smsc){ return emi_close_ip(smsc);}static int emi_fill_ucp60_login(char *buf, char *OAdC, char *passwd) { int max_ia5passwd_len; char *ia5passwd; max_ia5passwd_len = strlen(passwd) * 2 + 1; ia5passwd = gw_malloc(max_ia5passwd_len); if (parse_binary_to_emi(passwd, ia5passwd, strlen(passwd)) < 0) { error(0, "parse_binary_to_emi failed"); gw_free(ia5passwd); return -1; } sprintf(buf, "%s/%c/%c/%c/%s//%s/////", OAdC, /* OAdC: Address code originator */ '6', /* OTON: 6 = Abbreviated number (short number alias) */ '5', /* ONPI: 5 = Private (TCP/IP address/abbreviated number address) */ '1', /* STYP: 1 = open session */ ia5passwd, /* PWD: Current password encoded into IA5 characters */ "0100" /* VERS: Version number 0100 */ ); gw_free(ia5passwd); return 0;}static int emi_open_session(SMSCenter *smsc){ char message_whole [1024]; char message_body [1024]; char message_header [50]; char message_footer [10]; char my_buffer [1024]; int length; memset(message_whole, 0, sizeof(message_whole)); memset(message_body, 0, sizeof(message_body)); memset(message_header, 0, sizeof(message_header)); memset(message_footer, 0, sizeof(message_footer)); if (emi_fill_ucp60_login(message_body, smsc->emi_username, smsc->emi_password) < 0) { error(0, "emi_fill_ucp60_login failed"); return -1; } length = strlen(message_body); length += 13; /* header (fixed) */ length += 2; /* footer (fixed) */ length += 2; /* slashes between header, body, footer */ sprintf(message_header, "%02i/%05i/O/60", (smsc->emi_current_msg_number++ % 100), length); /* FOOTER */ sprintf(my_buffer, "%s/%s/", message_header, message_body); generate_checksum(my_buffer, message_footer); sprintf(message_whole, "\x02%s/%s/%s\x03", message_header, message_body, message_footer); debug("bb.sms.emi", 0, "final UCP60 msg: <%s>", message_whole); put_data(smsc, message_whole, strlen(message_whole), 0); if (!wait_for_ack(smsc, 60)) { info(0, "emi_open_session: wait for ack failed!"); return -1; } return 0;}/******************************************************* * the actual protocol open... quite simple here */static int emi_open_connection_ip(SMSCenter *smsc){ smsc->emi_fd = tcpip_connect_to_server_with_port(smsc->emi_hostname, smsc->emi_port, smsc->emi_our_port, NULL); /* XXX add interface_name if required */ if (smsc->emi_fd < 0) return -1; if (smsc->emi_username && smsc->emi_password) { return emi_open_session(smsc); } return 0;}int emi_reopen_ip(SMSCenter *smsc){ emi_close_ip(smsc); return emi_open_connection_ip(smsc);}int emi_close_ip(SMSCenter *smsc){ if (smsc->emi_fd == -1) { info(0, "Trying to close already closed EMI, ignoring"); return 0; } close(smsc->emi_fd); smsc->emi_fd = -1; return 0;}/******************************************************************************* Check if the buffers contain any messages*/int emi_pending_smsmessage(SMSCenter *smsc){ char *tmpbuff; int n = 0; /* time_t timenow; */ /* Block until we have a connection */ guarantee_link(smsc); /* If we have MO-message, then act (return 1) */ if (memorybuffer_has_rawmessage(smsc, 52, 'O') > 0 || memorybuffer_has_rawmessage(smsc, 1, 'O') > 0 ) return 1; tmpbuff = gw_malloc(10 * 1024); memset(tmpbuff, 0, 10*1024); /* check for data */ n = get_data(smsc, tmpbuff, 10 * 1024); if (n > 0) memorybuffer_insert_data(smsc, tmpbuff, n); /* delete all ACKs/NACKs/whatever */ while (memorybuffer_has_rawmessage(smsc, 51, 'R') > 0 || memorybuffer_has_rawmessage(smsc, 1, 'R') > 0) memorybuffer_cut_rawmessage(smsc, tmpbuff, 10*1024); gw_free(tmpbuff); /* If we have MO-message, then act (return 1) */ if (memorybuffer_has_rawmessage(smsc, 52, 'O') > 0 || memorybuffer_has_rawmessage(smsc, 1, 'O') > 0) return 1; /* time(&timenow); if( (smsc->emi_last_spoke + 60*20) < timenow) { time(&smsc->emi_last_spoke); } */ return 0;}/****************************************************************************** * Submit (send) a Mobile Terminated message to the EMI server */int emi_submit_msg(SMSCenter *smsc, Msg *omsg){ char *tmpbuff = NULL; if (smsc == NULL) goto error; if (omsg == NULL) goto error; tmpbuff = gw_malloc(10 * 1024); memset(tmpbuff, 0, 10*1024); if (parse_msg_to_rawmessage(smsc, omsg, tmpbuff, 10*1024) < 1) goto error; if (put_data(smsc, tmpbuff, strlen(tmpbuff), 0) < 0) { info(0, "put_data failed!"); goto error; } wait_for_ack(smsc, 51); /* smsc->emi_current_msg_number += 1; */ debug("bb.sms.emi", 0, "Submit Ok..."); gw_free(tmpbuff); return 0;error: debug("bb.sms.emi", 0, "Submit Error..."); gw_free(tmpbuff); return -1;}/******************************************************************************* Receive a Mobile Terminated message to the EMI server*/int emi_receive_msg(SMSCenter *smsc, Msg **tmsg){ char *tmpbuff; Msg *msg = NULL; *tmsg = NULL; tmpbuff = gw_malloc(10 * 1024); memset(tmpbuff, 0, 10*1024); /* get and delete message from buffer */ memorybuffer_cut_rawmessage(smsc, tmpbuff, 10*1024); parse_rawmessage_to_msg(smsc, &msg, tmpbuff, strlen(tmpbuff)); /* yeah yeah, I got the message... */ acknowledge_from_rawmessage(smsc, tmpbuff, strlen(tmpbuff)); /* return with the joyful news */ gw_free(tmpbuff); if (msg == NULL) goto error; *tmsg = msg; return 1;error: gw_free(tmpbuff); msg_destroy(msg); return -1;}/******************************************************************************* Internal functions*//******************************************************************************* Guarantee that we have a link*/static int guarantee_link(SMSCenter *smsc){ int need_to_connect = 0; /* If something is obviously wrong. */ if (strstr(smsc->buffer, "OK")) need_to_connect = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -