/* -------------------------------------------------------------------- */ /* SMS Client, send messages to mobile phones and pagers */ /* */ /* tap.c */ /* */ /* Copyright (C) 1997,1998,1999 Angelo Masci */ /* */ /* This library is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU Library General Public */ /* License as published by the Free Software Foundation; either */ /* version 2 of the License, or (at your option) any later version. */ /* */ /* This library is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ /* Library General Public License for more details. */ /* */ /* You should have received a copy of the GNU Library General Public */ /* License along with this library; if not, write to the Free */ /* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* */ /* You can contact the author at this e-mail address: */ /* */ /* angelo@styx.demon.co.uk */ /* */ /* -------------------------------------------------------------------- */ /* $Id: tap.c,v 5.1 1998/02/01 07:10:39 root Exp root $ -------------------------------------------------------------------- */ #include #include #include #include #include "common/common.h" #include "logfile/logfile.h" #include "driver.h" #include "error.h" #include "comms/comms.h" #include "resource/resource.h" #include "ascii.h" /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ static struct tap_env { DRIVER_DEFAULT_ENV def; /* Place any extended driver */ /* variables here */ long max_tries, login_timeout, init_login_sleep, login_sleep; char *select, *response, *disconnect; } driver_env; /* -------------------------------------------------------------------- */ static RESOURCE resource_list[] = { { RESOURCE_STRING, "SMS_comms_params", 0, 1, NULL, 0, "8N1", 0, &(driver_env.def.comms_params) }, { RESOURCE_STRING, "SMS_centre_number", 0, 1, NULL, 0, NULL, 0, &(driver_env.def.centre_number) }, { RESOURCE_NUMERIC, "SMS_baud", 0, 1, NULL, 0, NULL, 9600, &(driver_env.def.baud) }, { RESOURCE_NUMERIC, "SMS_deliver_timeout", 0, 0, NULL, 0, NULL, 30, &(driver_env.def.deliver_timeout) }, { RESOURCE_NUMERIC, "SMS_timeout", 0, 0, NULL, 0, NULL, 10, &(driver_env.def.timeout) }, { RESOURCE_NUMERIC, "SMS_login_timeout", 0, 0, NULL, 0, NULL, 10, &(driver_env.login_timeout) }, { RESOURCE_NUMERIC, "SMS_login_sleep", 0, 0, NULL, 0, NULL, 2000000, &(driver_env.login_sleep) }, { RESOURCE_NUMERIC, "SMS_init_login_sleep", 0, 0, NULL, 0, NULL, 1500000, &(driver_env.init_login_sleep) }, { RESOURCE_NUMERIC, "SMS_write_timeout", 0, 0, NULL, 0, NULL, 10, &(driver_env.def.write_timeout) }, { RESOURCE_NUMERIC, "SMS_max_tries", 0, 0, NULL, 0, NULL, 5, &(driver_env.max_tries) }, { RESOURCE_NUMERIC, "SMS_max_deliver", 0, 0, NULL, 0, NULL, 0, &(driver_env.def.max_deliver) }, { RESOURCE_STRING, "SMS_tap_select", 0, 0, NULL, 0, "PG1", 0, &(driver_env.select) }, { RESOURCE_STRING, "SMS_tap_response", 0, 0, NULL, 0, "TRUE", 0, &(driver_env.response) }, { RESOURCE_STRING, "SMS_tap_disconnect", 0, 0, NULL, 0, "TRUE", 0, &(driver_env.disconnect) }, { RESOURCE_NULL, NULL, 0, 1, NULL, 0, NULL, 0, NULL } }; /* -------------------------------------------------------------------- */ #define DELIVERTIMEOUT (driver_env.def.deliver_timeout) #define TIMEOUT (driver_env.def.timeout) #define LOGINTIMEOUT (driver_env.login_timeout) #define LOGINSLEEP (driver_env.login_sleep) #define INITLOGINSLEEP (driver_env.init_login_sleep) #define WRITETIMEOUT (driver_env.def.write_timeout) #define TAP_SELECT (driver_env.select) #define TAP_RESPONSE (strcmp(driver_env.response, "TRUE") == 0) #define TAP_DISCONNECT (strcmp(driver_env.disconnect, "TRUE") == 0) /* -------------------------------------------------------------------- */ #define FD (driver_env.def.fd) /* -------------------------------------------------------------------- */ #define MAX_TRIES (driver_env.max_tries) #define MAX_TAPMESSAGE 150 #define MAX_ENVELOPE 64 #define MAX_NUMBER 20 #define MAX_MOBILENUM 20 #define MAX_MESSAGE 512 /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ static char TAP_charset[] = { 0x20 /* 0x00 */, 0x20 /* 0x01 */, 0x20 /* 0x02 */, 0x20 /* 0x03 */, 0x20 /* 0x04 */, 0x20 /* 0x05 */, 0x20 /* 0x06 */, 0x20 /* 0x07 */, 0x20 /* 0x08 */, 0x20 /* 0x09 */, 0x0A /* 0x0A LF */, 0x20 /* 0x0B */, 0x20 /* 0x0C */, 0x0A /* 0x0D LF */, 0x20 /* 0x0E */, 0x20 /* 0x0F */, 0x20 /* 0x10 */, 0x20 /* 0x11 */, 0x20 /* 0x12 */, 0x20 /* 0x13 */, 0x20 /* 0x14 */, 0x20 /* 0x15 */, 0x20 /* 0x16 */, 0x20 /* 0x17 */, 0x20 /* 0x18 */, 0x20 /* 0x19 */, 0x20 /* 0x1A */, 0x20 /* 0x1B */, 0x20 /* 0x1C */, 0x20 /* 0x1D */, 0x20 /* 0x1E */, 0x20 /* 0x1F */, 0x20 /* 0x20 */, 0x21 /* 0x21 ! */, 0x22 /* 0x22 " */, 0x23 /* 0x23 # */, 0x24 /* 0x24 $ */, 0x25 /* 0x25 % */, 0x26 /* 0x26 & */, 0x27 /* 0x27 ' */, 0x28 /* 0x28 ( */, 0x29 /* 0x29 ) */, 0x2A /* 0x2A * */, 0x2B /* 0x2B + */, 0x2C /* 0x2C , */, 0x2D /* 0x2D - */, 0x2E /* 0x2E . */, 0x2F /* 0x2F / */, 0x30 /* 0x30 0 */, 0x31 /* 0x31 1 */, 0x32 /* 0x32 2 */, 0x33 /* 0x33 3 */, 0x34 /* 0x34 4 */, 0x35 /* 0x35 5 */, 0x36 /* 0x36 6 */, 0x37 /* 0x37 7 */, 0x38 /* 0x38 8 */, 0x39 /* 0x39 9 */, 0x3A /* 0x3A : */, 0x3B /* 0x3B ; */, 0x3C /* 0x3C < */, 0x3D /* 0x3D = */, 0x3E /* 0x3E > */, 0x3F /* 0x3F ? */, 0x40 /* 0x40 @ */, 0x41 /* 0x41 A */, 0x42 /* 0x42 B */, 0x43 /* 0x43 C */, 0x44 /* 0x44 D */, 0x45 /* 0x45 E */, 0x46 /* 0x46 F */, 0x47 /* 0x47 G */, 0x48 /* 0x48 H */, 0x49 /* 0x49 I */, 0x4A /* 0x4A J */, 0x4B /* 0x4B K */, 0x4C /* 0x4C L */, 0x4D /* 0x4D M */, 0x4E /* 0x4E N */, 0x4F /* 0x4F O */, 0x50 /* 0x50 P */, 0x51 /* 0x51 Q */, 0x52 /* 0x52 R */, 0x53 /* 0x53 S */, 0x54 /* 0x54 T */, 0x55 /* 0x55 U */, 0x56 /* 0x56 V */, 0x57 /* 0x57 W */, 0x58 /* 0x58 X */, 0x59 /* 0x59 Y */, 0x5A /* 0x5A Z */, 0x20 /* 0x5B */, 0x20 /* 0x5C */, 0x20 /* 0x5D */, 0x20 /* 0x5E */, 0x20 /* 0x5F */, 0x20 /* 0x60 */, 0x61 /* 0x61 a */, 0x62 /* 0x62 b */, 0x63 /* 0x63 c */, 0x64 /* 0x64 d */, 0x65 /* 0x65 e */, 0x66 /* 0x66 f */, 0x67 /* 0x67 g */, 0x68 /* 0x68 h */, 0x69 /* 0x69 i */, 0x6A /* 0x6A j */, 0x6B /* 0x6B k */, 0x6C /* 0x6C l */, 0x6D /* 0x6D m */, 0x6E /* 0x6E n */, 0x6F /* 0x6F o */, 0x70 /* 0x70 p */, 0x71 /* 0x71 q */, 0x72 /* 0x72 r */, 0x73 /* 0x73 s */, 0x74 /* 0x74 t */, 0x75 /* 0x75 u */, 0x76 /* 0x76 v */, 0x77 /* 0x77 w */, 0x78 /* 0x78 x */, 0x79 /* 0x79 y */, 0x7A /* 0x7A z */, 0x20 /* 0x7B */, 0x20 /* 0x7C */, 0x20 /* 0x7D */, 0x20 /* 0x7E */, 0x20 /* 0x7F */, 0x20 /* 0x80 */, 0x20 /* 0x81 */, 0x20 /* 0x82 */, 0x20 /* 0x83 */, 0x20 /* 0x84 */, 0x20 /* 0x85 */, 0x20 /* 0x86 */, 0x20 /* 0x87 */, 0x20 /* 0x88 */, 0x20 /* 0x89 */, 0x20 /* 0x8A */, 0x20 /* 0x8B */, 0x20 /* 0x8C */, 0x20 /* 0x8D */, 0x20 /* 0x8E */, 0x20 /* 0x8F */, 0x20 /* 0x90 */, 0x20 /* 0x91 */, 0x20 /* 0x92 */, 0x20 /* 0x93 */, 0x20 /* 0x94 */, 0x20 /* 0x95 */, 0x20 /* 0x96 */, 0x20 /* 0x97 */, 0x20 /* 0x98 */, 0x20 /* 0x99 */, 0x20 /* 0x9A */, 0x20 /* 0x9B */, 0x20 /* 0x9C */, 0x20 /* 0x9D */, 0x20 /* 0x9E */, 0x20 /* 0x9F */, 0x20 /* 0xA0 */, 0x20 /* 0xA1 */, 0x20 /* 0xA2 */, 0x20 /* 0xA3 */, 0x20 /* 0xA4 */, 0x20 /* 0xA5 */, 0x20 /* 0xA6 */, 0x20 /* 0xA7 */, 0x20 /* 0xA8 */, 0x20 /* 0xA9 */, 0x20 /* 0xAA */, 0x20 /* 0xAB */, 0x20 /* 0xAC */, 0x20 /* 0xAD */, 0x20 /* 0xAE */, 0x20 /* 0xAF */, 0x20 /* 0xB0 */, 0x20 /* 0xB1 */, 0x20 /* 0xB2 */, 0x20 /* 0xB3 */, 0x20 /* 0xB4 */, 0x20 /* 0xB5 */, 0x20 /* 0xB6 */, 0x20 /* 0xB7 */, 0x20 /* 0xB8 */, 0x20 /* 0xB9 */, 0x20 /* 0xBA */, 0x20 /* 0xBB */, 0x20 /* 0xBC */, 0x20 /* 0xBD */, 0x20 /* 0xBE */, 0x20 /* 0xBF */, 0x20 /* 0xC0 */, 0x20 /* 0xC1 */, 0x20 /* 0xC2 */, 0x20 /* 0xC3 */, 0x5B /* 0xC4 */, 0x20 /* 0xC5 */, 0x20 /* 0xC6 */, 0x20 /* 0xC7 */, 0x20 /* 0xC8 */, 0x20 /* 0xC9 */, 0x20 /* 0xCA */, 0x20 /* 0xCB */, 0x20 /* 0xCC */, 0x20 /* 0xCD */, 0x20 /* 0xCE */, 0x20 /* 0xCF */, 0x20 /* 0xD0 */, 0x20 /* 0xD1 */, 0x20 /* 0xD2 */, 0x20 /* 0xD3 */, 0x20 /* 0xD4 */, 0x20 /* 0xD5 */, 0x5C /* 0xD6 */, 0x20 /* 0xD7 */, 0x20 /* 0xD8 */, 0x20 /* 0xD9 */, 0x20 /* 0xDA */, 0x20 /* 0xDB */, 0x5D /* 0xDC */, 0x20 /* 0xDD */, 0x20 /* 0xDE */, 0x20 /* 0xDF */, 0x7E /* 0xE0 */, 0x20 /* 0xE1 */, 0x20 /* 0xE2 */, 0x20 /* 0xE3 */, 0x7B /* 0xE4 */, 0x20 /* 0xE5 */, 0x20 /* 0xE6 */, 0x20 /* 0xE7 */, 0x20 /* 0xE8 */, 0x20 /* 0xE9 */, 0x20 /* 0xEA */, 0x20 /* 0xEB */, 0x20 /* 0xEC */, 0x20 /* 0xED */, 0x20 /* 0xEE */, 0x20 /* 0xEF */, 0x20 /* 0xF0 */, 0x20 /* 0xF1 */, 0x20 /* 0xF2 */, 0x20 /* 0xF3 */, 0x20 /* 0xF4 */, 0x20 /* 0xF5 */, 0x7C /* 0xF6 */, 0x20 /* 0xF7 */, 0x20 /* 0xF8 */, 0x20 /* 0xF9 */, 0x20 /* 0xFA */, 0x20 /* 0xFB */, 0x7D /* 0xFC */, 0x20 /* 0xFD */, 0x20 /* 0xFE */, 0x20 /* 0xFF */ }; /* -------------------------------------------------------------------- */ static char ACK1[] = { 'I', 'D', '=', '\0' }; static char ACK2[] = { S_ACK, S_CR, '\0' }; static char ACK3[] = { S_ESC, '[', 'p', S_CR, '\0' }; static char ACK4[] = { S_CR, '\0' }; static char ACK5[] = { S_ACK, S_CR, '\0' }; static char ACK6[] = { S_NAK, S_CR, '\0' }; static char ACK7[] = { S_RS, S_CR, '\0' }; static char ACK8[] = { S_ESC, S_EOT, S_CR, '\0' }; static char REQ1[] = { S_CR, '\0' }; static char REQ2a[] = { S_ESC, '\0' }; static char REQ2b[] = { S_CR, '\0' }; static char REQ3[] = { S_STX, '\0' }; static char REQ4[] = { S_CR, '\0' }; static char REQ5[] = { S_CR, S_ETX, '\0' }; static char REQ6[] = { S_CR, '\0' }; static char REQ7[] = { S_EOT, S_CR, '\0' }; /* -------------------------------------------------------------------- */ static char buf[MAX_RESPONSE_BUFSIZE]; /* -------------------------------------------------------------------- */ static void TAP_checksum(char *); static void TAP_hangup(void); static void TAP_buildmessage(char *, char *, char *); static int TAP_send_disconnect(void); static int TAP_login(void); static int TAP_sendmessage(char *, char *); /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ static void TAP_checksum(char *message) { int i, checksum; checksum = 0; for (i=0; i128 */ checksum += (unsigned char)message[i]; #endif } checksum = (checksum & 0x0FFF); /* Mask low 12Bits */ message[i] = (((checksum & 0x0F00) >> 8) | 0x30); message[i+1] = (((checksum & 0x00F0) >> 4) | 0x30); message[i+2] = (((checksum & 0x000F) ) | 0x30); message[i+3] = '\0'; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ static void TAP_hangup(void) { default_hangup((DRIVER_DEFAULT_ENV *)(&driver_env)); } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ static int TAP_send_disconnect(void) { lprintf(LOG_STANDARD, "Disconnect...\n"); if (TAP_DISCONNECT) { twrite(FD, REQ7, strlen(REQ7), WRITETIMEOUT); if (expstr(FD, buf, ACK8, MAX_RESPONSE_BUFSIZE, TIMEOUT) == 0) { lprintf(LOG_STANDARD, "Disconnected from SMSC\n"); } else { lprintf(LOG_STANDARD, "Failed to disconnect from SMSC\n"); TAP_hangup(); return ETAP_NODISCONNECT; } } return 0; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ static int TAP_login(void) { int i; lprintf(LOG_STANDARD, "Login...\n"); /* Resend the S_CR every 2 seconds */ /* until ID= received, only try */ /* 5 times then give up. */ libcommon_usleep(INITLOGINSLEEP); for (i=0; i < MAX_TRIES; i++) { twrite(FD, REQ1, strlen(REQ1), WRITETIMEOUT); if (expstr(FD, buf, ACK1, MAX_RESPONSE_BUFSIZE, LOGINTIMEOUT) == 0) { lprintf(LOG_STANDARD, "SMSC Acknowledgment received\n"); break; } lprintf(LOG_STANDARD, "SMSC Retry for Acknowledgment\n"); libcommon_usleep(LOGINSLEEP); } if (i == MAX_TRIES) { lprintf(LOG_STANDARD, "Failed Acknowledgment %ld retries attempted\n", MAX_TRIES); TAP_hangup(); return ETAP_NOACK; } /* Send S_ESC S_CR and get back */ /* the acknowledgement S_ACK S_CR */ twrite(FD, REQ2a, strlen(REQ2a), WRITETIMEOUT); twrite(FD, TAP_SELECT, strlen(TAP_SELECT), WRITETIMEOUT); twrite(FD, REQ2b, strlen(REQ2b), WRITETIMEOUT); if (expstr(FD, buf, ACK2, MAX_RESPONSE_BUFSIZE, TIMEOUT) == 0) { lprintf(LOG_STANDARD, "Login successful\n"); } else { lprintf(LOG_STANDARD, "Login failed\n"); TAP_hangup(); return ETAP_NOLOGIN; } if (expstr(FD, buf, ACK3, MAX_RESPONSE_BUFSIZE, TIMEOUT) == 0) { lprintf(LOG_STANDARD, "Ready to receive message\n"); } else { lprintf(LOG_STANDARD, "SMSC NOT Ready to receive message\n"); TAP_hangup(); return ETAP_NOREADY; } return 0; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ static void TAP_buildmessage(char *tap_message, char *msisdn, char *message) { int i; char *ptr; /* ---------------------------- */ tap_message[0] = '\0'; strcat(tap_message, REQ3); strcat(tap_message, msisdn); strcat(tap_message, REQ4); /* Convert message so that it contains */ /* only TAP valid characters */ /* any invalid characters will be */ /* mapped to a SPACE */ /* Add to tap_message */ ptr = tap_message; while(*ptr != '\0') { ptr++; } for (i=0; i