00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 #include <errno.h>
00065 #include <string.h>
00066 #include <stdio.h>
00067 #include <unistd.h>
00068 #include <fcntl.h>
00069 #include <termios.h>
00070 #include <stdarg.h>
00071 #include <stdlib.h>
00072 #include <string.h>
00073 #include <strings.h>
00074
00075 #include <sys/time.h>
00076 #include <sys/types.h>
00077 #include <sys/socket.h>
00078 #include <sys/param.h>
00079 #include <sys/ioctl.h>
00080
00081 #include "gwlib/gwlib.h"
00082 #include "smsc.h"
00083 #include "smsc_p.h"
00084 #include "alt_charsets.h"
00085 #include "sms.h"
00086
00087 #ifndef CRTSCTS
00088 #define CRTSCTS 0
00089 #endif
00090
00091
00092
00093
00094 static int get_data(SMSCenter *smsc, char *buff, int length);
00095
00096 static int put_data(SMSCenter *smsc, char *buff, int length, int is_backup);
00097
00098 static int memorybuffer_append_data(SMSCenter *smsc, char *buff, int length);
00099
00100 static int memorybuffer_insert_data(SMSCenter *smsc, char *buff, int length);
00101
00102 static int memorybuffer_has_rawmessage(SMSCenter *smsc, int type, char auth);
00103
00104 static int memorybuffer_cut_rawmessage(SMSCenter *smsc, char *buff, int length);
00105
00106 static int parse_rawmessage_to_msg(SMSCenter *smsc, Msg **msg,
00107 char *rawmessage, int length);
00108
00109 static int parse_msg_to_rawmessage(SMSCenter *smsc, Msg *msg,
00110 char *rawmessage, int length);
00111
00112 static int acknowledge_from_rawmessage(SMSCenter *smsc,
00113 char *rawmessage, int length);
00114
00115 static int parse_emi_to_iso88591(char *from, char *to,
00116 int length, int alt_charset);
00117
00118 static int parse_iso88591_to_emi(char *from, char *to,
00119 int length, int alt_charset);
00120 static int parse_binary_to_emi(char *from, char *to, int length);
00121
00122 static int at_dial(char *device, char *phonenum,
00123 char *at_prefix, time_t how_long);
00124 static int guarantee_link(SMSCenter *smsc);
00125
00126
00127 static void generate_checksum(const unsigned char *buffer,
00128 unsigned char *checksum_out);
00129 static int wait_for_ack(SMSCenter *smsc, int op_type);
00130
00131
00132 static char char_iso_to_sms(unsigned char from, int alt_charset);
00133 static char char_sms_to_iso(unsigned char from, int alt_charset);
00134
00135
00136
00137
00138 static int emi_open_connection(SMSCenter *smsc)
00139 {
00140 char tmpbuff[1024];
00141
00142 sprintf(tmpbuff, "/dev/%s", smsc->emi_serialdevice);
00143 smsc->emi_fd = at_dial(tmpbuff, smsc->emi_phonenum, "ATD", 30);
00144
00145 if (smsc->emi_fd <= 0)
00146 return -1;
00147
00148 return 0;
00149 }
00150
00151
00152
00153 SMSCenter *emi_open(char *phonenum, char *serialdevice, char *username, char *password)
00154 {
00155 SMSCenter *smsc;
00156
00157 smsc = smscenter_construct();
00158 if (smsc == NULL)
00159 goto error;
00160
00161 smsc->type = SMSC_TYPE_EMI_X25;
00162
00163 smsc->emi_phonenum = gw_strdup(phonenum);
00164 smsc->emi_serialdevice = gw_strdup(serialdevice);
00165 smsc->emi_username = gw_strdup(username);
00166 smsc->emi_password = gw_strdup(password);
00167
00168 smsc->emi_current_msg_number = 0;
00169
00170 if (emi_open_connection(smsc) < 0)
00171 goto error;
00172
00173 sprintf(smsc->name, "EMI:%s:%s", smsc->emi_phonenum,
00174 smsc->emi_username);
00175 return smsc;
00176
00177 error:
00178 error(0, "emi_open failed");
00179 smscenter_destruct(smsc);
00180 return NULL;
00181 }
00182
00183 int emi_reopen(SMSCenter *smsc)
00184 {
00185 emi_close(smsc);
00186
00187 if (emi_open_connection(smsc) < 0) {
00188 error(0, "emi_reopen failed");
00189 return -1;
00190 }
00191 return 0;
00192 }
00193
00194 int emi_close(SMSCenter *smsc)
00195 {
00196 return emi_close_ip(smsc);
00197 }
00198
00199 static int emi_fill_ucp60_login(char *buf, char *OAdC, char *passwd) {
00200 int max_ia5passwd_len;
00201 char *ia5passwd;
00202
00203 max_ia5passwd_len = strlen(passwd) * 2 + 1;
00204 ia5passwd = gw_malloc(max_ia5passwd_len);
00205
00206 if (parse_binary_to_emi(passwd, ia5passwd, strlen(passwd)) < 0) {
00207 error(0, "parse_binary_to_emi failed");
00208 gw_free(ia5passwd);
00209 return -1;
00210 }
00211
00212 sprintf(buf, "%s/%c/%c/%c/%s//%s/////",
00213 OAdC,
00214 '6',
00215 '5',
00216 '1',
00217 ia5passwd,
00218 "0100"
00219 );
00220
00221 gw_free(ia5passwd);
00222 return 0;
00223 }
00224
00225 static int emi_open_session(SMSCenter *smsc)
00226 {
00227 char message_whole [1024];
00228 char message_body [1024];
00229 char message_header [50];
00230 char message_footer [10];
00231 char my_buffer [1024];
00232 int length;
00233
00234 memset(message_whole, 0, sizeof(message_whole));
00235 memset(message_body, 0, sizeof(message_body));
00236 memset(message_header, 0, sizeof(message_header));
00237 memset(message_footer, 0, sizeof(message_footer));
00238
00239 if (emi_fill_ucp60_login(message_body, smsc->emi_username, smsc->emi_password) < 0) {
00240 error(0, "emi_fill_ucp60_login failed");
00241 return -1;
00242 }
00243
00244 length = strlen(message_body);
00245 length += 13;
00246 length += 2;
00247 length += 2;
00248
00249 sprintf(message_header, "%02i/%05i/O/60",
00250 (smsc->emi_current_msg_number++ % 100), length);
00251
00252
00253
00254 sprintf(my_buffer, "%s/%s/", message_header, message_body);
00255 generate_checksum((unsigned char *)my_buffer, (unsigned char *)message_footer);
00256
00257 sprintf(message_whole, "\x02%s/%s/%s\x03", message_header,
00258 message_body, message_footer);
00259
00260 debug("bb.sms.emi", 0, "final UCP60 msg: <%s>", message_whole);
00261
00262 put_data(smsc, message_whole, strlen(message_whole), 0);
00263
00264 if (!wait_for_ack(smsc, 60)) {
00265 info(0, "emi_open_session: wait for ack failed!");
00266 return -1;
00267 }
00268
00269 return 0;
00270 }
00271
00272
00273
00274
00275
00276 static int emi_open_connection_ip(SMSCenter *smsc)
00277 {
00278 smsc->emi_fd =
00279 tcpip_connect_to_server_with_port(smsc->emi_hostname,
00280 smsc->emi_port, smsc->emi_our_port,
00281 NULL);
00282
00283 if (smsc->emi_fd < 0)
00284 return -1;
00285
00286 if (smsc->emi_username && smsc->emi_password) {
00287 return emi_open_session(smsc);
00288 }
00289
00290 return 0;
00291 }
00292
00293
00294 int emi_reopen_ip(SMSCenter *smsc)
00295 {
00296 emi_close_ip(smsc);
00297
00298 return emi_open_connection_ip(smsc);
00299 }
00300
00301
00302 int emi_close_ip(SMSCenter *smsc)
00303 {
00304
00305 if (smsc->emi_fd == -1) {
00306 info(0, "Trying to close already closed EMI, ignoring");
00307 return 0;
00308 }
00309 close(smsc->emi_fd);
00310 smsc->emi_fd = -1;
00311
00312 return 0;
00313 }
00314
00315
00316
00317
00318
00319 int emi_pending_smsmessage(SMSCenter *smsc)
00320 {
00321
00322 char *tmpbuff;
00323 int n = 0;
00324
00325
00326
00327 guarantee_link(smsc);
00328
00329
00330 if (memorybuffer_has_rawmessage(smsc, 52, 'O') > 0 ||
00331 memorybuffer_has_rawmessage(smsc, 1, 'O') > 0 )
00332 return 1;
00333
00334 tmpbuff = gw_malloc(10 * 1024);
00335 memset(tmpbuff, 0, 10*1024);
00336
00337
00338 n = get_data(smsc, tmpbuff, 10 * 1024);
00339 if (n > 0)
00340 memorybuffer_insert_data(smsc, tmpbuff, n);
00341
00342
00343 while (memorybuffer_has_rawmessage(smsc, 51, 'R') > 0 ||
00344 memorybuffer_has_rawmessage(smsc, 1, 'R') > 0)
00345 memorybuffer_cut_rawmessage(smsc, tmpbuff, 10*1024);
00346
00347 gw_free(tmpbuff);
00348
00349
00350
00351 if (memorybuffer_has_rawmessage(smsc, 52, 'O') > 0 ||
00352 memorybuffer_has_rawmessage(smsc, 1, 'O') > 0)
00353 return 1;
00354
00355
00356
00357
00358
00359
00360
00361
00362 return 0;
00363
00364 }
00365
00366
00367
00368
00369
00370
00371
00372 int emi_submit_msg(SMSCenter *smsc, Msg *omsg)
00373 {
00374 char *tmpbuff = NULL;
00375
00376 if (smsc == NULL) goto error;
00377 if (omsg == NULL) goto error;
00378
00379 tmpbuff = gw_malloc(10 * 1024);
00380 memset(tmpbuff, 0, 10*1024);
00381
00382 if (parse_msg_to_rawmessage(smsc, omsg, tmpbuff, 10*1024) < 1)
00383 goto error;
00384
00385 if (put_data(smsc, tmpbuff, strlen(tmpbuff), 0) < 0) {
00386 info(0, "put_data failed!");
00387 goto error;
00388 }
00389
00390 wait_for_ack(smsc, 51);
00391
00392
00393 debug("bb.sms.emi", 0, "Submit Ok...");
00394
00395 gw_free(tmpbuff);
00396 return 0;
00397
00398 error:
00399 debug("bb.sms.emi", 0, "Submit Error...");
00400
00401 gw_free(tmpbuff);
00402 return -1;
00403 }
00404
00405
00406
00407
00408 int emi_receive_msg(SMSCenter *smsc, Msg **tmsg)
00409 {
00410 char *tmpbuff;
00411 Msg *msg = NULL;
00412
00413 *tmsg = NULL;
00414
00415 tmpbuff = gw_malloc(10 * 1024);
00416 memset(tmpbuff, 0, 10*1024);
00417
00418
00419 memorybuffer_cut_rawmessage(smsc, tmpbuff, 10*1024);
00420 parse_rawmessage_to_msg(smsc, &msg, tmpbuff, strlen(tmpbuff));
00421
00422
00423 acknowledge_from_rawmessage(smsc, tmpbuff, strlen(tmpbuff));
00424
00425
00426 gw_free(tmpbuff);
00427
00428 if (msg == NULL) goto error;
00429
00430 *tmsg = msg;
00431
00432 return 1;
00433
00434 error:
00435 gw_free(tmpbuff);
00436 msg_destroy(msg);
00437 return -1;
00438 }
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449 static int guarantee_link(SMSCenter *smsc)
00450 {
00451 int need_to_connect = 0;
00452
00453
00454 if (strstr(smsc->buffer, "OK")) need_to_connect = 1;
00455 if (strstr(smsc->buffer, "NO CARRIER")) need_to_connect = 1;
00456 if (strstr(smsc->buffer, "NO DIALTONE")) need_to_connect = 1;
00457
00458
00459 while (need_to_connect) {
00460
00461 need_to_connect = emi_open_connection(smsc) < 0;
00462
00463
00464
00465 smsc->buflen = 0;
00466 memset(smsc->buffer, 0, smsc->bufsize);
00467 }
00468
00469 return 0;
00470 }
00471
00472 static int at_dial(char *device, char *phonenum, char *at_prefix, time_t how_long)
00473 {
00474 char tmpbuff[1024];
00475 int howmanyread = 0;
00476 int thistime = 0;
00477 int redial;
00478 int fd = -1;
00479 int ret;
00480 time_t timestart;
00481 struct termios tios;
00482
00483
00484
00485
00486 time(×tart);
00487
00488
00489
00490 fd = open(device, O_RDWR | O_NONBLOCK | O_NOCTTY);
00491 if (fd == -1) {
00492 error(errno, "at_dial: error opening character device <%s>", device);
00493 goto error;
00494 }
00495 tcflush(fd, TCIOFLUSH);
00496
00497
00498 tcgetattr(fd, &tios);
00499 #if defined(B115200)
00500 cfsetospeed(&tios, B115200);
00501 cfsetispeed(&tios, B115200);
00502 #elif defined(B76800)
00503 cfsetospeed(&tios, B76800);
00504 cfsetispeed(&tios, B76800);
00505 #elif defined(B57600)
00506 cfsetospeed(&tios, B57600);
00507 cfsetispeed(&tios, B57600);
00508 #elif defined(B38400)
00509 cfsetospeed(&tios, B38400);
00510 cfsetispeed(&tios, B38400);
00511 #elif defined(B19200)
00512 cfsetospeed(&tios, B19200);
00513 cfsetispeed(&tios, B19200);
00514 #elif defined(B9600)
00515 cfsetospeed(&tios, B9600);
00516 cfsetispeed(&tios, B9600);
00517 #endif
00518 kannel_cfmakeraw(&tios);
00519 tios.c_cflag |= (HUPCL | CREAD | CRTSCTS);
00520 ret = tcsetattr(fd, TCSANOW, &tios);
00521 if (ret == -1) {
00522 error(errno, "EMI[X25]: at_dial: fail to set termios attribute");
00523 }
00524
00525
00526 for (redial = 1; redial; ) {
00527 info(0, "at_dial: dialing <%s> on <%s> for <%i> seconds",
00528 phonenum, device,
00529 (int)(how_long - (time(NULL) - timestart)));
00530
00531
00532 howmanyread = 0;
00533 sprintf(tmpbuff, "%s%s\r\n", at_prefix, phonenum);
00534 ret = write(fd, tmpbuff, strlen(tmpbuff));
00535 memset(&tmpbuff, 0, sizeof(tmpbuff));
00536
00537
00538 for (; ; ) {
00539
00540 if (how_long != 0 && time(NULL) > timestart + how_long)
00541 goto timeout;
00542
00543
00544 if (howmanyread >= (int) sizeof(tmpbuff))
00545 goto error;
00546
00547
00548
00549
00550 thistime = read(fd, &tmpbuff[howmanyread], 1);
00551 if (thistime == -1) {
00552 if (errno == EAGAIN) continue;
00553 if (errno == EINTR) continue;
00554 goto error;
00555 } else {
00556 howmanyread += thistime;
00557 }
00558
00559
00560 if (tmpbuff[howmanyread - 1] == '\r'
00561 || tmpbuff[howmanyread - 1] == '\n') {
00562
00563
00564
00565 if (strstr(tmpbuff, "CONNECT") != NULL) {
00566 debug("bb.sms.emi", 0, "at_dial: CONNECT");
00567 redial = 0;
00568 break;
00569
00570 } else if (strstr(tmpbuff, "NO CARRIER") != NULL) {
00571 debug("bb.sms.emi", 0, "at_dial: NO CARRIER");
00572 redial = 1;
00573 break;
00574
00575 } else if (strstr(tmpbuff, "BUSY") != NULL) {
00576 debug("bb.sms.emi", 0, "at_dial: BUSY");
00577 redial = 1;
00578 break;
00579
00580 } else if (strstr(tmpbuff, "NO DIALTONE") != NULL) {
00581 debug("bb.sms.emi", 0, "at_dial: NO DIALTONE");
00582 redial = 1;
00583 break;
00584
00585 }
00586
00587 }
00588
00589
00590
00591
00592
00593 usleep(1000);
00594
00595 }
00596
00597
00598 sleep(1);
00599
00600 }
00601
00602 debug("bb.sms.emi", 0, "at_dial: done with dialing");
00603 return fd;
00604
00605 timeout:
00606 error(0, "at_dial timed out");
00607 close(fd);
00608 return -1;
00609
00610 error:
00611 error(0, "at_dial failed");
00612 close(fd);
00613 return -1;
00614 }
00615
00616
00617
00618
00619
00620
00621 static int wait_for_ack(SMSCenter *smsc, int op_type)
00622 {
00623 char *tmpbuff;
00624 int found = 0;
00625 int n;
00626 time_t start;
00627
00628 tmpbuff = gw_malloc(10 * 1024);
00629 memset(tmpbuff, 0, 10*1024);
00630 start = time(NULL);
00631 do {
00632
00633 n = get_data(smsc, tmpbuff, 1024 * 10);
00634
00635
00636
00637
00638
00639 if (n > 0)
00640 memorybuffer_append_data(smsc, tmpbuff, n);
00641
00642
00643 if (memorybuffer_has_rawmessage(smsc, op_type, 'R') > 0) {
00644 memorybuffer_cut_rawmessage(smsc, tmpbuff, 10*1024);
00645 debug("bb.sms.emi", 0, "Found ACK/NACK: <%s>", tmpbuff);
00646 found = 1;
00647 }
00648 } while (!found && ((time(NULL) - start) < 5));
00649
00650 gw_free(tmpbuff);
00651 return found;
00652 }
00653
00654
00655
00656
00657
00658
00659
00660 static int get_data(SMSCenter *smsc, char *buff, int length)
00661 {
00662 int n = 0;
00663
00664 struct sockaddr_in client_addr;
00665 socklen_t client_addr_len;
00666
00667 fd_set rf;
00668 struct timeval to;
00669 int ret;
00670
00671 memset(buff, 0, length);
00672
00673 if (smsc->type == SMSC_TYPE_EMI_X25) {
00674 tcdrain(smsc->emi_fd);
00675 n = read(smsc->emi_fd, buff, length);
00676 return n;
00677 }
00678
00679 FD_ZERO(&rf);
00680 if (smsc->emi_fd >= 0) FD_SET(smsc->emi_fd, &rf);
00681 if (smsc->emi_secondary_fd >= 0) FD_SET(smsc->emi_secondary_fd, &rf);
00682 if (smsc->emi_backup_fd > 0) FD_SET(smsc->emi_backup_fd, &rf);
00683
00684 FD_SET(0, &rf);
00685 to.tv_sec = 0;
00686 to.tv_usec = 100;
00687
00688 ret = select(FD_SETSIZE, &rf, NULL, NULL, &to);
00689
00690 if (ret > 0) {
00691 if (smsc->emi_secondary_fd >= 0 && FD_ISSET(smsc->emi_secondary_fd, &rf)) {
00692 n = read(smsc->emi_secondary_fd, buff, length - 1);
00693
00694 if (n == -1) {
00695 error(errno, "Error - Secondary socket closed");
00696 close(smsc->emi_secondary_fd);
00697 smsc->emi_secondary_fd = -1;
00698 } else if (n == 0) {
00699 info(0, "Secondary socket closed by SMSC");
00700 close(smsc->emi_secondary_fd);
00701 smsc->emi_secondary_fd = -1;
00702 } else {
00703 buff[n] = 'X';
00704 n++;
00705 }
00706 } else if (smsc->emi_fd >= 0 && FD_ISSET(smsc->emi_fd, &rf)) {
00707 n = read(smsc->emi_fd, buff, length);
00708 if (n == 0) {
00709 close(smsc->emi_fd);
00710 info(0, "Main EMI socket closed by SMSC");
00711 smsc->emi_fd = -1;
00712 }
00713 }
00714 if ((smsc->emi_backup_fd > 0) && FD_ISSET(smsc->emi_backup_fd, &rf)) {
00715 if (smsc->emi_secondary_fd == -1) {
00716 Octstr *ip, *allow;
00717
00718 smsc->emi_secondary_fd = accept(smsc->emi_backup_fd,
00719 (struct sockaddr *)&client_addr, &client_addr_len);
00720
00721 ip = host_ip(client_addr);
00722 if (smsc->emi_backup_allow_ip == NULL)
00723 allow = NULL;
00724 else
00725 allow = octstr_create(smsc->emi_backup_allow_ip);
00726 if (is_allowed_ip(allow, octstr_imm("*.*.*.*"), ip) == 0) {
00727 info(0, "SMSC secondary connection tried from <%s>, "
00728 "disconnected",
00729 octstr_get_cstr(ip));
00730 octstr_destroy(ip);
00731 octstr_destroy(allow);
00732 close(smsc->emi_secondary_fd);
00733 smsc->emi_secondary_fd = -1;
00734 return 0;
00735 }
00736 info(0, "Secondary socket opened by SMSC from <%s>",
00737 octstr_get_cstr(ip));
00738 octstr_destroy(ip);
00739 octstr_destroy(allow);
00740 } else
00741 info(0, "New connection request while old secondary is open!");
00742 }
00743 }
00744 if (n > 0) {
00745 debug("bb.sms.emi", 0, "get_data:Read %d bytes: <%.*s>", n, n, buff);
00746 debug("bb.sms.emi", 0, "get_data:smsc->buffer == <%s>", smsc->buffer);
00747 }
00748 return n;
00749
00750 }
00751
00752
00753
00754
00755 static int put_data(SMSCenter *smsc, char *buff, int length, int is_backup)
00756 {
00757 size_t len = length;
00758 int ret;
00759 int fd = -1;
00760
00761 fd = smsc->emi_fd;
00762 tcdrain(smsc->emi_fd);
00763
00764
00765 while (len > 0) {
00766 ret = write(fd, buff, len);
00767 if (ret == -1) {
00768 if (errno == EINTR) continue;
00769 if (errno == EAGAIN) continue;
00770 error(errno, "Writing to fd failed");
00771 return -1;
00772 }
00773
00774
00775 len -= ret;
00776 buff += ret;
00777 }
00778
00779 if (smsc->type == SMSC_TYPE_EMI_X25) {
00780
00781
00782
00783
00784 tcdrain(smsc->emi_fd);
00785 usleep(1000);
00786 }
00787
00788 return 0;
00789 }
00790
00791
00792
00793
00794 static int memorybuffer_append_data(SMSCenter *smsc, char *buff, int length)
00795 {
00796 while (smsc->bufsize < (smsc->buflen + length)) {
00797 char *p = gw_realloc(smsc->buffer, smsc->bufsize * 2);
00798 smsc->buffer = p;
00799 smsc->bufsize *= 2;
00800 }
00801
00802 memcpy(smsc->buffer + smsc->buflen, buff, length);
00803 smsc->buflen += length;
00804 return 0;
00805
00806 }
00807
00808
00809
00810
00811 static int memorybuffer_insert_data(SMSCenter *smsc, char *buff, int length)
00812 {
00813 while (smsc->bufsize < (smsc->buflen + length)) {
00814 char *p = gw_realloc(smsc->buffer, smsc->bufsize * 2);
00815 smsc->buffer = p;
00816 smsc->bufsize *= 2;
00817 }
00818 memmove(smsc->buffer + length, smsc->buffer, smsc->buflen);
00819 memcpy(smsc->buffer, buff, length);
00820 smsc->buflen += length;
00821 return 0;
00822
00823 }
00824
00825
00826
00827
00828 static int memorybuffer_has_rawmessage(SMSCenter *smsc, int type, char auth)
00829 {
00830 char tmpbuff[1024], tmpbuff2[1024];
00831 char *stx, *etx;
00832
00833 stx = memchr(smsc->buffer, '\2', smsc->buflen);
00834 etx = memchr(smsc->buffer, '\3', smsc->buflen);
00835
00836 if (stx && etx && stx < etx) {
00837 strncpy(tmpbuff, stx, etx - stx + 1);
00838 tmpbuff[etx - stx + 1] = '\0';
00839 if (auth)
00840 sprintf(tmpbuff2, "/%c/%02i/", auth, type);
00841 else
00842 sprintf(tmpbuff2, "/%02i/", type);
00843
00844 if (strstr(tmpbuff, tmpbuff2) != NULL) {
00845 debug("bb.sms.emi", 0, "found message <%c/%02i>...msg <%s>", auth, type, tmpbuff);
00846 return 1;
00847 }
00848 }
00849 return 0;
00850
00851 }
00852
00853
00854
00855
00856
00857 static int memorybuffer_cut_rawmessage(SMSCenter *smsc, char *buff, int length)
00858 {
00859
00860 char *stx, *etx;
00861 int size_of_cut_piece;
00862 int size_of_the_rest;
00863
00864
00865
00866
00867 stx = memchr(smsc->buffer, '\2', smsc->buflen);
00868 etx = memchr(smsc->buffer, '\3', smsc->buflen);
00869
00870 if (*(etx + 1) == 'X')
00871 etx++;
00872
00873 size_of_cut_piece = (etx - stx) + 1;
00874 size_of_the_rest = (smsc->buflen - size_of_cut_piece);
00875
00876 if (length < size_of_cut_piece) {
00877 error(0, "the buffer you provided for cutting was too small");
00878 return -1;
00879 }
00880
00881
00882 memcpy(buff, stx, size_of_cut_piece);
00883 buff[size_of_cut_piece] = '\0';
00884
00885
00886 memmove(stx, etx + 1, (smsc->buffer + smsc->bufsize) - stx );
00887
00888 smsc->buflen -= size_of_cut_piece;
00889
00890 return 0;
00891
00892 }
00893
00894
00895
00896
00897 static int parse_rawmessage_to_msg(SMSCenter *smsc, Msg **msg,
00898 char *rawmessage, int length)
00899 {
00900
00901 char emivars[128][1024];
00902 char *leftslash, *rightslash;
00903 char isotext[2048];
00904 int msgnbr;
00905 int tmpint;
00906
00907 msgnbr = -1;
00908
00909 memset(isotext, 0, sizeof(isotext));
00910
00911 strncpy(isotext, rawmessage, length);
00912 leftslash = isotext;
00913
00914 for (tmpint = 0; leftslash != NULL; tmpint++) {
00915 rightslash = strchr(leftslash + 1, '/');
00916
00917 if (rightslash == NULL)
00918 rightslash = strchr(leftslash + 1, '\3');
00919
00920 if (rightslash == NULL)
00921 break;
00922
00923 *rightslash = '\0';
00924 strcpy(emivars[tmpint], leftslash + 1);
00925 leftslash = rightslash;
00926 }
00927
00928 if (strcmp(emivars[3], "01") == 0) {
00929 if (strcmp(emivars[7], "2") == 0) {
00930 strcpy(isotext, emivars[8]);
00931 } else if (strcmp(emivars[7], "3") == 0) {
00932 parse_emi_to_iso88591(emivars[8], isotext, sizeof(isotext),
00933 smsc->alt_charset);
00934 } else {
00935 error(0, "Unknown 01-type EMI SMS (%s)", emivars[7]);
00936 strcpy(isotext, "");
00937 }
00938 } else if (strcmp(emivars[3], "51") == 0) {
00939 parse_emi_to_iso88591(emivars[24], isotext, sizeof(isotext),
00940 smsc->alt_charset);
00941 } else if (strcmp(emivars[3], "52") == 0) {
00942 parse_emi_to_iso88591(emivars[24], isotext, sizeof(isotext),
00943 smsc->alt_charset);
00944 } else {
00945 error(0, "HEY WE SHOULD NOT BE HERE!! Type = %s", emivars[3]);
00946 strcpy(isotext, "");
00947 }
00948
00949 *msg = msg_create(sms);
00950 if (*msg == NULL) goto error;
00951
00952 (*msg)->sms.sender = octstr_create(emivars[5]);
00953 (*msg)->sms.receiver = octstr_create(emivars[4]);
00954 (*msg)->sms.msgdata = octstr_create(isotext);
00955 (*msg)->sms.udhdata = NULL;
00956
00957 return msgnbr;
00958
00959 error:
00960 return -1;
00961 }
00962
00963
00964
00965
00966 static int acknowledge_from_rawmessage(SMSCenter *smsc,
00967 char *rawmessage, int length)
00968 {
00969
00970 char emivars[128][1024];
00971 char timestamp[2048], sender[2048], receiver[2048];
00972 char emitext[2048], isotext[2048];
00973 char *leftslash, *rightslash;
00974 int msgnbr;
00975 int tmpint;
00976 int is_backup = 0;
00977
00978 msgnbr = -1;
00979 memset(&sender, 0, sizeof(sender));
00980 memset(&receiver, 0, sizeof(receiver));
00981 memset(&emitext, 0, sizeof(emitext));
00982 memset(&isotext, 0, sizeof(isotext));
00983 memset(×tamp, 0, sizeof(timestamp));
00984
00985 strncpy(isotext, rawmessage, length);
00986 leftslash = isotext;
00987
00988 if (isotext[length - 1] == 'X')
00989 is_backup = 1;
00990
00991 for (tmpint = 0; leftslash != NULL; tmpint++) {
00992 rightslash = strchr(leftslash + 1, '/');
00993
00994 if (rightslash == NULL)
00995 rightslash = strchr(leftslash + 1, '\3');
00996
00997 if (rightslash == NULL)
00998 break;
00999
01000 *rightslash = '\0';
01001 strcpy(emivars[tmpint], leftslash + 1);
01002 leftslash = rightslash;
01003 }
01004
01005
01006 sprintf(isotext, "A//%s:%s", emivars[4], emivars[18]);
01007 sprintf(isotext, "A//%s:", emivars[5]);
01008 is_backup = 0;
01009
01010
01011
01012 debug("bb.sms.emi", 0, "acknowledge: type = '%s'", emivars[3]);
01013
01014 sprintf(emitext, "%s/%05i/%s/%s", emivars[0], (int) strlen(isotext) + 17,
01015 "R", emivars[3]);
01016
01017 smsc->emi_current_msg_number = atoi(emivars[0]) + 1;
01018
01019
01020 sprintf(timestamp, "%s/%s/", emitext, isotext);
01021 generate_checksum((unsigned char *)timestamp, (unsigned char *)receiver);
01022
01023 sprintf(sender, "%c%s/%s/%s%c", 0x02, emitext, isotext, receiver, 0x03);
01024 put_data(smsc, sender, strlen(sender), is_backup);
01025
01026 return msgnbr;
01027
01028 }
01029
01030
01031
01032
01033
01034 static int parse_msg_to_rawmessage(SMSCenter *smsc, Msg *msg, char *rawmessage, int rawmessage_length)
01035 {
01036 char message_whole[10*1024];
01037 char message_body[10*1024];
01038 char message_header[1024];
01039 char message_footer[1024];
01040
01041 char my_buffer[10*1024];
01042 char my_buffer2[10*1024];
01043 char msgtext[1024];
01044 int length;
01045 char mt;
01046 char mcl[20];
01047 char snumbits[20];
01048 char xser[1024];
01049 int udh_len;
01050
01051 memset(&message_whole, 0, sizeof(message_whole));
01052 memset(&message_body, 0, sizeof(message_body));
01053 memset(&message_header, 0, sizeof(message_header));
01054 memset(&message_footer, 0, sizeof(message_footer));
01055 memset(&my_buffer, 0, sizeof(my_buffer));
01056 memset(&my_buffer2, 0, sizeof(my_buffer2));
01057 mt = '3';
01058 memset(&snumbits, 0, sizeof(snumbits));
01059 memset(&xser, 0, sizeof(xser));
01060
01061
01062
01063
01064 if (octstr_len(msg->sms.udhdata)) {
01065 char xserbuf[258];
01066
01067
01068
01069 udh_len = octstr_get_char(msg->sms.udhdata, 0) + 1;
01070 xserbuf[0] = 1;
01071 xserbuf[1] = udh_len;
01072 octstr_get_many_chars(&xserbuf[2], msg->sms.udhdata, 0, udh_len);
01073 parse_binary_to_emi(xserbuf, xser, udh_len + 2);
01074 } else {
01075 udh_len = 0;
01076 }
01077
01078 if (msg->sms.coding == DC_7BIT || msg->sms.coding == DC_UNDEF) {
01079 octstr_get_many_chars(msgtext, msg->sms.msgdata, 0, octstr_len(msg->sms.msgdata));
01080 msgtext[octstr_len(msg->sms.msgdata)] = '\0';
01081 parse_iso88591_to_emi(msgtext, my_buffer2,
01082 octstr_len(msg->sms.msgdata),
01083 smsc->alt_charset);
01084
01085 strcpy(snumbits, "");
01086 mt = '3';
01087 strcpy(mcl, "");
01088 } else {
01089 octstr_get_many_chars(msgtext, msg->sms.msgdata, 0, octstr_len(msg->sms.msgdata));
01090
01091 parse_binary_to_emi(msgtext, my_buffer2, octstr_len(msg->sms.msgdata));
01092
01093 sprintf(snumbits, "%04ld", octstr_len(msg->sms.msgdata)*8);
01094 mt = '4';
01095 strcpy(mcl, "1");
01096 }
01097
01098
01099
01100
01101
01102 sprintf(message_body,
01103 "%s/%s/%s/%s/%s//%s////////////%c/%s/%s////%s//////%s//",
01104 octstr_get_cstr(msg->sms.receiver),
01105 msg->sms.sender ? octstr_get_cstr(msg->sms.sender) : "",
01106 "",
01107 "",
01108 "",
01109 "0100",
01110 mt,
01111 snumbits,
01112 my_buffer2,
01113 mcl,
01114 xser);
01115
01116
01117
01118 length = strlen(message_body);
01119 length += 13;
01120 length += 2;
01121 length += 2;
01122
01123 sprintf(message_header, "%02i/%05i/%s/%s", (smsc->emi_current_msg_number++ % 100), length, "O", "51");
01124
01125
01126
01127 sprintf(my_buffer, "%s/%s/", message_header, message_body);
01128 generate_checksum((unsigned char *)my_buffer, (unsigned char *)message_footer);
01129
01130 sprintf(message_whole, "%c%s/%s/%s%c", 0x02, message_header, message_body, message_footer, 0x03);
01131
01132 strncpy(rawmessage, message_whole, rawmessage_length);
01133
01134 if (smsc->type == SMSC_TYPE_EMI_X25) {
01135
01136 strcat(rawmessage, "\r");
01137 }
01138 debug("bb.sms.emi", 0, "emi %d message %s",
01139 smsc->emi_current_msg_number, rawmessage);
01140 return strlen(rawmessage);
01141 }
01142
01143
01144
01145
01146 static int parse_emi_to_iso88591(char *from, char *to, int length,
01147 int alt_charset)
01148 {
01149 int hmtg = 0;
01150 unsigned int mychar;
01151 char tmpbuff[128];
01152
01153 for (hmtg = 0; hmtg <= (int)strlen(from); hmtg += 2) {
01154 strncpy(tmpbuff, from + hmtg, 2);
01155 sscanf(tmpbuff, "%x", &mychar);
01156 to[hmtg / 2] = char_sms_to_iso(mychar, alt_charset);
01157 }
01158
01159 to[(hmtg / 2)-1] = '\0';
01160
01161 return 0;
01162
01163 }
01164
01165
01166
01167
01168 static int parse_iso88591_to_emi(char *from, char *to,
01169 int length, int alt_charset)
01170 {
01171 char buf[10];
01172 unsigned char tmpchar;
01173 char *ptr;
01174
01175 if (!from || !to || length <= 0)
01176 return -1;
01177
01178 *to = '\0';
01179
01180 debug("bb.sms.emi", 0, "emi parsing <%s> to emi, length %d", from, length);
01181
01182 for (ptr = from; length > 0; ptr++, length--) {
01183 tmpchar = char_iso_to_sms(*ptr, alt_charset);
01184 sprintf(buf, "%02X", tmpchar);
01185 strncat(to, buf, 2);
01186 }
01187 return 0;
01188 }
01189
01190
01191
01192
01193 static int parse_binary_to_emi(char *from, char *to, int length)
01194 {
01195 char buf[10];
01196 char *ptr;
01197
01198 if (!from || !to || length <= 0)
01199 return -1;
01200
01201 *to = '\0';
01202
01203 for (ptr = from; length > 0; ptr++, length--) {
01204 sprintf(buf, "%02X", (unsigned char)*ptr);
01205 strncat(to, buf, 2);
01206 }
01207
01208 return 0;
01209 }
01210
01211
01212
01213
01214
01215 static void generate_checksum(const unsigned char *buf, unsigned char *out)
01216 {
01217 const unsigned char *p;
01218 int j;
01219
01220 j = 0;
01221 for (p = buf; *p != '\0'; p++) {
01222 j += *p;
01223
01224 if (j >= 256)
01225 j -= 256;
01226 }
01227
01228 sprintf((char *)out, "%02X", j);
01229 }
01230
01231
01232
01233
01234
01235
01236
01237 static char char_iso_to_sms(unsigned char from, int alt_charset)
01238 {
01239
01240 switch ((char)from) {
01241
01242 case 'A':
01243 return 0x41;
01244 case 'B':
01245 return 0x42;
01246 case 'C':
01247 return 0x43;
01248 case 'D':
01249 return 0x44;
01250 case 'E':
01251 return 0x45;
01252 case 'F':
01253 return 0x46;
01254 case 'G':
01255 return 0x47;
01256 case 'H':
01257 return 0x48;
01258 case 'I':
01259 return 0x49;
01260 case 'J':
01261 return 0x4A;
01262 case 'K':
01263 return 0x4B;
01264 case 'L':
01265 return 0x4C;
01266 case 'M':
01267 return 0x4D;
01268 case 'N':
01269 return 0x4E;
01270 case 'O':
01271 return 0x4F;
01272 case 'P':
01273 return 0x50;
01274 case 'Q':
01275 return 0x51;
01276 case 'R':
01277 return 0x52;
01278 case 'S':
01279 return 0x53;
01280 case 'T':
01281 return 0x54;
01282 case 'U':
01283 return 0x55;
01284 case 'V':
01285 return 0x56;
01286 case 'W':
01287 return 0x57;
01288 case 'X':
01289 return 0x58;
01290 case 'Y':
01291 return 0x59;
01292 case 'Z':
01293 return 0x5A;
01294
01295 case 'a':
01296 return 0x61;
01297 case 'b':
01298 return 0x62;
01299 case 'c':
01300 return 0x63;
01301 case 'd':
01302 return 0x64;
01303 case 'e':
01304 return 0x65;
01305 case 'f':
01306 return 0x66;
01307 case 'g':
01308 return 0x67;
01309 case 'h':
01310 return 0x68;
01311 case 'i':
01312 return 0x69;
01313 case 'j':
01314 return 0x6A;
01315 case 'k':
01316 return 0x6B;
01317 case 'l':
01318 return 0x6C;
01319 case 'm':
01320 return 0x6D;
01321 case 'n':
01322 return 0x6E;
01323 case 'o':
01324 return 0x6F;
01325 case 'p':
01326 return 0x70;
01327 case 'q':
01328 return 0x71;
01329 case 'r':
01330 return 0x72;
01331 case 's':
01332 return 0x73;
01333 case 't':
01334 return 0x74;
01335 case 'u':
01336 return 0x75;
01337 case 'v':
01338 return 0x76;
01339 case 'w':
01340 return 0x77;
01341 case 'x':
01342 return 0x78;
01343 case 'y':
01344 return 0x79;
01345 case 'z':
01346 return 0x7A;
01347
01348 case '0':
01349 return 0x30;
01350 case '1':
01351 return 0x31;
01352 case '2':
01353 return 0x32;
01354 case '3':
01355 return 0x33;
01356 case '4':
01357 return 0x34;
01358 case '5':
01359 return 0x35;
01360 case '6':
01361 return 0x36;
01362 case '7':
01363 return 0x37;
01364 case '8':
01365 return 0x38;
01366 case '9':
01367 return 0x39;
01368 case ':':
01369 return 0x3A;
01370 case ';':
01371 return 0x3B;
01372 case '<':
01373 return 0x3C;
01374 case '=':
01375 return 0x3D;
01376 case '>':
01377 return 0x3E;
01378 case '?':
01379 return 0x3F;
01380
01381 case 'Ä':
01382 return '[';
01383 case 'Ö':
01384 return '\\';
01385 case 'Å':
01386 return 0x0E;
01387 case 'Ü':
01388 return ']';
01389 case 'ä':
01390 return '{';
01391 case 'ö':
01392 return '|';
01393 case 'å':
01394 return 0x0F;
01395 case 'ü':
01396 return '}';
01397 case 'ß':
01398 return '~';
01399 case '§':
01400 return '^';
01401 case 'Ñ':
01402 return 0x5F;
01403 case 'ø':
01404 return 0x0C;
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417 case ' ':
01418 return 0x20;
01419 case '@':
01420 if (alt_charset == EMI_SWAPPED_CHARS)
01421 return 0x00;
01422 else
01423 return 0x40;
01424 case '£':
01425 return 0x01;
01426 case '$':
01427 return 0x24;
01428 case '¥':
01429 return 0x03;
01430 case 'è':
01431 return 0x04;
01432 case 'é':
01433 return 0x05;
01434 case 'ù':
01435 return 0x06;
01436 case 'ì':
01437 return 0x07;
01438 case 'ò':
01439 return 0x08;
01440 case 'Ç':
01441 return 0x09;
01442 case '\r':
01443 return 0x0A;
01444 case 'Ø':
01445 return 0x0B;
01446 case '\n':
01447 return 0x0D;
01448 case 'Æ':
01449 return 0x1C;
01450 case 'æ':
01451 return 0x1D;
01452 case 'É':
01453 return 0x1F;
01454
01455 case '!':
01456 return 0x21;
01457 case '"':
01458 return 0x22;
01459 case '#':
01460 return 0x23;
01461 case '¤':
01462 return 0x02;
01463 case '%':
01464 return 0x25;
01465
01466 case '&':
01467 return 0x26;
01468 case '\'':
01469 return 0x27;
01470 case '(':
01471 return 0x28;
01472 case ')':
01473 return 0x29;
01474 case '*':
01475 return 0x2A;
01476
01477 case '+':
01478 return 0x2B;
01479 case ',':
01480 return 0x2C;
01481 case '-':
01482 return 0x2D;
01483 case '.':
01484 return 0x2E;
01485 case '/':
01486 return 0x2F;
01487
01488 case '¿':
01489 return 0x60;
01490 case 'ñ':
01491 return 0x1E;
01492 case 'à':
01493 return 0x7F;
01494 case '¡':
01495 if (alt_charset == EMI_SWAPPED_CHARS)
01496 return 0x40;
01497 else
01498 return 0x00;
01499 case '_':
01500 return 0x11;
01501
01502 default:
01503 return 0x20;
01504
01505 }
01506 }
01507
01508
01509
01510
01511
01512
01513 static char char_sms_to_iso(unsigned char from, int alt_charset)
01514 {
01515
01516 switch ((int)from) {
01517
01518 case 0x41:
01519 return 'A';
01520 case 0x42:
01521 return 'B';
01522 case 0x43:
01523 return 'C';
01524 case 0x44:
01525 return 'D';
01526 case 0x45:
01527 return 'E';
01528 case 0x46:
01529 return 'F';
01530 case 0x47:
01531 return 'G';
01532 case 0x48:
01533 return 'H';
01534 case 0x49:
01535 return 'I';
01536 case 0x4A:
01537 return 'J';
01538 case 0x4B:
01539 return 'K';
01540 case 0x4C:
01541 return 'L';
01542 case 0x4D:
01543 return 'M';
01544 case 0x4E:
01545 return 'N';
01546 case 0x4F:
01547 return 'O';
01548 case 0x50:
01549 return 'P';
01550 case 0x51:
01551 return 'Q';
01552 case 0x52:
01553 return 'R';
01554 case 0x53:
01555 return 'S';
01556 case 0x54:
01557 return 'T';
01558 case 0x55:
01559 return 'U';
01560 case 0x56:
01561 return 'V';
01562 case 0x57:
01563 return 'W';
01564 case 0x58:
01565 return 'X';
01566 case 0x59:
01567 return 'Y';
01568 case 0x5A:
01569 return 'Z';
01570
01571 case 0x61:
01572 return 'a';
01573 case 0x62:
01574 return 'b';
01575 case 0x63:
01576 return 'c';
01577 case 0x64:
01578 return 'd';
01579 case 0x65:
01580 return 'e';
01581 case 0x66:
01582 return 'f';
01583 case 0x67:
01584 return 'g';
01585 case 0x68:
01586 return 'h';
01587 case 0x69:
01588 return 'i';
01589 case 0x6A:
01590 return 'j';
01591 case 0x6B:
01592 return 'k';
01593 case 0x6C:
01594 return 'l';
01595 case 0x6D:
01596 return 'm';
01597 case 0x6E:
01598 return 'n';
01599 case 0x6F:
01600 return 'o';
01601 case 0x70:
01602 return 'p';
01603 case 0x71:
01604 return 'q';
01605 case 0x72:
01606 return 'r';
01607 case 0x73:
01608 return 's';
01609 case 0x74:
01610 return 't';
01611 case 0x75:
01612 return 'u';
01613 case 0x76:
01614 return 'v';
01615 case 0x77:
01616 return 'w';
01617 case 0x78:
01618 return 'x';
01619 case 0x79:
01620 return 'y';
01621 case 0x7A:
01622 return 'z';
01623
01624 case 0x30:
01625 return '0';
01626 case 0x31:
01627 return '1';
01628 case 0x32:
01629 return '2';
01630 case 0x33:
01631 return '3';
01632 case 0x34:
01633 return '4';
01634 case 0x35:
01635 return '5';
01636 case 0x36:
01637 return '6';
01638 case 0x37:
01639 return '7';
01640 case 0x38:
01641 return '8';
01642 case 0x39:
01643 return '9';
01644 case 0x3A:
01645 return ':';
01646 case 0x3B:
01647 return ';';
01648 case 0x3C:
01649 return '<';
01650 case 0x3D:
01651 return '=';
01652 case 0x3E:
01653 return '>';
01654 case 0x3F:
01655 return '?';
01656
01657 case '[':
01658 return 'Ä';
01659 case '\\':
01660 return 'Ö';
01661 case '\xC5':
01662 return 'Å';
01663 case ']':
01664 return 'Ü';
01665 case '{':
01666 return 'ä';
01667 case '|':
01668 return 'ö';
01669 case 0xE5:
01670 return 'å';
01671 case '}':
01672 return 'ü';
01673 case '~':
01674 return 'ß';
01675 case 0xA7:
01676 return '§';
01677 case 0xD1:
01678 return 'Ñ';
01679 case 0xF8:
01680 return 'ø';
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693 case 0x20:
01694 return ' ';
01695 case 0x40:
01696 return '@';
01697 case 0xA3:
01698 return '£';
01699 case 0x24:
01700 return '$';
01701 case 0xA5:
01702 return '¥';
01703 case 0xE8:
01704 return 'è';
01705 case 0xE9:
01706 return 'é';
01707 case 0xF9:
01708 return 'ù';
01709 case 0xEC:
01710 return 'ì';
01711 case 0xF2:
01712 return 'ò';
01713 case 0xC7:
01714 return 'Ç';
01715 case 0x0A:
01716 return '\r';
01717 case 0xD8:
01718 return 'Ø';
01719 case 0x0D:
01720 return '\n';
01721 case 0xC6:
01722 return 'Æ';
01723 case 0xE6:
01724 return 'æ';
01725 case 0x1F:
01726 return 'É';
01727
01728 case 0x21:
01729 return '!';
01730 case 0x22:
01731 return '"';
01732 case 0x23:
01733 return '#';
01734 case 0xA4:
01735 return '¤';
01736 case 0x25:
01737 return '%';
01738
01739 case 0x26:
01740 return '&';
01741 case 0x27:
01742 return '\'';
01743 case 0x28:
01744 return '(';
01745 case 0x29:
01746 return ')';
01747 case 0x2A:
01748 return '*';
01749
01750 case 0x2B:
01751 return '+';
01752 case 0x2C:
01753 return ',';
01754 case 0x2D:
01755 return '-';
01756 case 0x2E:
01757 return '.';
01758 case 0x2F:
01759 return '/';
01760
01761 case 0xBF:
01762 return '¿';
01763 case 0xF1:
01764 return 'ñ';
01765 case 0xE0:
01766 return 'à';
01767 case 0xA1:
01768 return '¡';
01769 case 0x5F:
01770 return '_';
01771
01772 default:
01773 return ' ';
01774
01775 }
01776 }
See file LICENSE for details about the license agreement for using,
modifying, copying or deriving work from this software.