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
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 #include <unistd.h>
00112 #include <ctype.h>
00113 #include <errno.h>
00114 #include <string.h>
00115 #include <sys/time.h>
00116 #include <sys/types.h>
00117 #include <sys/timeb.h>
00118 #include <sys/socket.h>
00119 #include <netinet/in.h>
00120 #include <arpa/inet.h>
00121
00122 #include "smsc.h"
00123 #include "smsc_p.h"
00124 #include "gwlib/gwlib.h"
00125 #include "sms.h"
00126
00127
00128 enum dcs_body_type {
00129 DCS_GSM_TEXT = 0,
00130 DCS_OCTET_DATA = 4
00131 };
00132
00133
00134
00135
00136 int ois_debug_level = 0;
00137
00138
00139
00140
00141 #define SAY(d,s) { if (d<=ois_debug_level) debug("bb.sms.ois",0,s); }
00142 #define SAY2(d,s,t) { if (d<=ois_debug_level) debug("bb.sms.ois",0,s,t); }
00143 #define SAY3(d,s,t,u) { if (d<=ois_debug_level) debug("bb.sms.ois",0,s,t,u); }
00144 #define IOTRACE(x,s,l) SAY3(1,"%s [%s]",x,ois_debug_str(s,l))
00145
00146
00147 #define BUFLEN (511)
00148 #define OIS_OPEN_WAITTIME (15)
00149 #define OIS_MESSAGE_WAITTIME (30)
00150 #define OIS_WAITTIME (999999)
00151 #define OIS_NOWAIT (0)
00152 #define MAXCOUNTER (10000)
00153 #define EOL ('\r')
00154
00155 typedef struct ois_listentry {
00156 struct ois_listentry *next;
00157 Msg *msg;
00158 } ois_listentry;
00159
00160 #define OIS_FLAG_DEBUG (0x000f)
00161 #define OIS_FLAG_ERROR (0x0100)
00162 #define OIS_FLAG_NOBANNER (0x0200)
00163 #define OIS_FLAG_MULTIPLE_CALL (0x0400)
00164 #define OIS_FLAG_CLOSED (0x0800)
00165
00166 static int ois_counter = 0;
00167 static int ois_open_listener(SMSCenter *smsc);
00168 static int ois_open_sender(SMSCenter *smsc);
00169 static int ois_open_receiver(SMSCenter *smsc);
00170 static void ois_disconnect_all(SMSCenter *smsc);
00171 static void ois_disconnect(SMSCenter *smsc);
00172 static int ois_read_into_buffer(SMSCenter *smsc, long wait_usec);
00173 static int ois_check_input(SMSCenter *smsc, long wait_usec);
00174 static int ois_check_incoming(SMSCenter *smsc, long wait_usec);
00175 static void ois_append_to_list(ois_listentry **head, Msg *msg);
00176 static int ois_int_to_i4(char *raw, int nbr);
00177 static int ois_increment_counter(void);
00178 static int ois_submit_sm_invoke(SMSCenter *smsc, const Msg *msg);
00179 static int ois_encode_submit_sm_invoke(char *str, const Msg *msg);
00180 static int ois_append_msisdn(char *raw, const Msg *msg);
00181 static int ois_append_sme_reference_number(char *raw);
00182 static int ois_append_priority(char *raw);
00183 static int ois_append_originating_address(char *raw);
00184 static int ois_append_validity_period(char *raw);
00185 static int ois_append_data_coding_scheme(char *raw, const Msg *msg);
00186 static int ois_append_status_report_request(char *raw);
00187 static int ois_append_protocol_id(char *raw);
00188 static int ois_append_submission_options(char *raw, const Msg *msg);
00189 static int ois_append_sm_text(char *raw, const Msg *msg);
00190 static int ois_submit_sm_result(SMSCenter *smsc, const char *buffer);
00191 static int ois_decode_submit_sm_result(int *code, const char *str);
00192 static int ois_deliver_sm_invoke(SMSCenter *smsc, const char *buffer);
00193 static int ois_decode_deliver_sm_invoke(Msg *msg, const char *str);
00194 static int ois_check_deliver_sm_invoke(const char *str);
00195 static int ois_adjust_destination_address(Msg *msg, const char *raw);
00196 static int ois_ignore_smsc_reference_number(const char *raw);
00197 static int ois_adjust_originating_address(Msg *msg, const char *raw);
00198 static int ois_adjust_data_coding_scheme(Msg *msg, const char *raw);
00199 static int ois_ignore_protocol_id(const char *raw);
00200 static int ois_adjust_additional_information(Msg *msg, const char *raw);
00201 static int ois_adjust_sm_text(Msg *msg, const char *raw);
00202 static int ois_ignore_time(const char *raw);
00203 static int ois_deliver_sm_result(SMSCenter *smsc, int result, const char *str);
00204 static int ois_encode_deliver_sm_result(char *str, int result);
00205 static int ois_expand_gsm7(char *raw8, const char *raw7, int len);
00206 static int ois_expand_gsm7_to_bits(char *bits, const char *raw7, int len);
00207 static char ois_expand_gsm7_from_bits(const char *bits, int pos);
00208 static int ois_convert_to_ia5(char *str, const char *raw, int len);
00209 static int ois_convert_from_ia5(char *raw, const char *str);
00210 static int ois_convert_to_iso88591(char *raw, int len);
00211 static int ois_extract_msg_from_buffer(char *str, SMSCenter *smsc);
00212 static int ois_extract_line_from_buffer(char *str, SMSCenter *smsc);
00213 static void ois_swap_buffering(SMSCenter *smsc);
00214 static const char *ois_debug_str(const char *raw, int len);
00215
00216
00217
00218
00219
00220
00221
00222 SMSCenter *ois_open(int receiveport, const char *hostname, int port, int debug_level)
00223 {
00224 SMSCenter *smsc;
00225 int ret;
00226
00227 ois_debug_level = debug_level & OIS_FLAG_DEBUG;
00228 SAY(2, "ois_open");
00229
00230
00231
00232 smsc = smscenter_construct();
00233 if (smsc == NULL) {
00234 goto error;
00235 }
00236
00237 smsc->type = SMSC_TYPE_OIS;
00238 smsc->receive_port = receiveport;
00239 smsc->hostname = gw_strdup(hostname);
00240 smsc->port = port;
00241 smsc->ois_flags = ois_debug_level;
00242
00243 ret = ois_open_listener(smsc);
00244 if (ret < 0) {
00245 goto error;
00246 }
00247 sprintf(smsc->name, "OIS:TCP/X.25-Translator:localhost:%d:TCP:%.512s:%d",
00248 smsc->receive_port, smsc->hostname, smsc->port);
00249
00250 return smsc;
00251
00252 error:
00253 error(0, "ois_open: could not open");
00254 smscenter_destruct(smsc);
00255 return NULL;
00256 }
00257
00258
00259
00260
00261
00262
00263 int ois_close(SMSCenter *smsc)
00264 {
00265 ois_debug_level = smsc->ois_flags & OIS_FLAG_DEBUG;
00266 SAY(2, "ois_close");
00267
00268 if (smsc->type != SMSC_TYPE_OIS) {
00269 warning(0, "ois_close: closing a not-ois connection...");
00270 }
00271
00272 ois_swap_buffering(smsc);
00273 smscenter_remove_from_buffer(smsc, smsc->buflen);
00274 ois_swap_buffering(smsc);
00275 smscenter_remove_from_buffer(smsc, smsc->buflen);
00276 SAY(4, "ois_close: ois_disconnect_all");
00277 ois_disconnect_all(smsc);
00278
00279 return 0;
00280 }
00281
00282
00283
00284
00285
00286
00287 int ois_reopen(SMSCenter *smsc)
00288 {
00289 int ret;
00290
00291 ois_debug_level = smsc->ois_flags & OIS_FLAG_DEBUG;
00292 SAY(2, "ois_reopen");
00293
00294 ois_close(smsc);
00295
00296 if (smsc->type == SMSC_TYPE_OIS) {
00297 ret = ois_open_listener(smsc);
00298 if (ret < 0) {
00299 goto error;
00300 }
00301 } else {
00302 error(0, "ois_reopen: wrong smsc type");
00303 goto error;
00304 }
00305 return 0;
00306
00307 error:
00308 error(0, "ois_reopen: could not open");
00309 return -1;
00310 }
00311
00312
00313
00314
00315
00316
00317
00318 int ois_pending_smsmessage(SMSCenter *smsc)
00319 {
00320 int ret;
00321
00322 ois_debug_level = smsc->ois_flags & OIS_FLAG_DEBUG;
00323 SAY(8, "ois_pending_smsmessage");
00324
00325 ret = ois_check_incoming(smsc, OIS_NOWAIT);
00326 if (ret == 0 && smsc->socket != -1) {
00327 ret = ois_check_input(smsc, OIS_NOWAIT);
00328 }
00329 if (ret == 0 && smsc->ois_socket != -1) {
00330 ois_swap_buffering(smsc);
00331 ret = ois_check_input(smsc, OIS_NOWAIT);
00332 ois_swap_buffering(smsc);
00333 if (smsc->ois_socket == -1 && smsc->ois_ack_debt != 0) {
00334 warning(0, "ois_pending_smsmessage: missing %d ack(s)...",
00335 smsc->ois_ack_debt);
00336 }
00337 }
00338 return ret;
00339 }
00340
00341
00342
00343
00344
00345
00346 int ois_submit_msg(SMSCenter *smsc, const Msg *msg)
00347 {
00348 int ret;
00349
00350 ois_debug_level = smsc->ois_flags & OIS_FLAG_DEBUG;
00351 SAY(2, "ois_submit_msg");
00352 ois_swap_buffering(smsc);
00353
00354 if (msg_type((Msg *)msg) != sms) {
00355 error(0, "ois_submit_msg: can not handle message types other than smart_msg");
00356 goto error;
00357 }
00358
00359 if (smsc->socket == -1) {
00360 ret = ois_open_sender(smsc);
00361 if (ret < 0) {
00362 goto error;
00363 }
00364 }
00365
00366 ret = ois_submit_sm_invoke(smsc, msg);
00367 if (ret < 0) {
00368 goto error_close;
00369 }
00370
00371 ++smsc->ois_ack_debt;
00372 time(&smsc->ois_alive);
00373 ret = 0;
00374 goto out;
00375
00376 error_close:
00377 if (smsc->ois_ack_debt != 0) {
00378 warning(0, "ois_submit_msg: missing %d ack(s)...",
00379 smsc->ois_ack_debt);
00380 }
00381 SAY(4, "ois_submit_msg: ois_disconnect in error_close");
00382 ois_disconnect(smsc);
00383 error:
00384 SAY(2, "ois_submit_msg error");
00385 ret = -1;
00386 out:
00387 ois_swap_buffering(smsc);
00388 return ret;
00389 }
00390
00391
00392
00393
00394
00395
00396 int ois_receive_msg(SMSCenter *smsc, Msg **msg)
00397 {
00398 ois_listentry *item;
00399
00400 ois_debug_level = smsc->ois_flags & OIS_FLAG_DEBUG;
00401 SAY(2, "ois_receive_msg");
00402
00403 item = smsc->ois_received_mo;
00404 if (item == NULL) {
00405 if ((smsc->ois_flags & OIS_FLAG_ERROR) == 0) {
00406 return 0;
00407 } else {
00408 return -1;
00409 }
00410 } else {
00411 smsc->ois_received_mo = item->next;
00412 *msg = item->msg;
00413 gw_free(item);
00414 return 1;
00415 }
00416 }
00417
00418
00419
00420
00421
00422
00423 void ois_delete_queue(SMSCenter *smsc)
00424 {
00425 Msg *msg;
00426
00427 ois_debug_level = smsc->ois_flags & OIS_FLAG_DEBUG;
00428 SAY(2, "ois_delete_queue");
00429
00430 while (ois_receive_msg(smsc, &msg) > 0) {
00431 gw_free(msg);
00432 }
00433 return;
00434 }
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448 static int ois_open_listener(SMSCenter *smsc)
00449 {
00450 SAY(2, "ois_open_listener");
00451
00452 smsc->ois_listening_socket = make_server_socket(smsc->receive_port,
00453 NULL);
00454
00455 if (smsc->ois_listening_socket < 0) {
00456 goto error;
00457 }
00458 if (socket_set_blocking(smsc->ois_listening_socket, 0) < 0) {
00459 ois_close(smsc);
00460 goto error;
00461 }
00462 smsc->ois_flags &= ~OIS_FLAG_ERROR;
00463 smsc->ois_flags &= ~OIS_FLAG_NOBANNER;
00464 smsc->ois_alive2 = time(&smsc->ois_alive);
00465
00466 SAY2(2, "ois_open_listener fd=%d", smsc->ois_listening_socket);
00467 return 0;
00468
00469 error:
00470 error(0, "ois_open_listener: failed to open listening socket");
00471 return -1;
00472 }
00473
00474
00475 static int ois_open_sender(SMSCenter *smsc)
00476 {
00477 int ret;
00478 char buffer[BUFLEN+1];
00479 time_t now;
00480 time_t beginning;
00481
00482 SAY(2, "ois_open_sender");
00483 debug("bb.sms.ois", 0, "connecting to host %s port %d",
00484 smsc->hostname, smsc->port);
00485
00486 time(&beginning);
00487 smsc->socket = tcpip_connect_to_server(smsc->hostname, smsc->port,
00488 NULL);
00489
00490 if (smsc->socket < 0) {
00491 return -1;
00492 } else {
00493 smsc->buflen = 0;
00494 time(&smsc->ois_alive);
00495 smsc->ois_ack_debt = 0;
00496 }
00497
00498 SAY2(2, "ois_open_sender fd=%d", smsc->socket);
00499 if (smsc->ois_flags & OIS_FLAG_NOBANNER) {
00500 return 0;
00501 }
00502
00503 buffer[0] = '\0';
00504 for (time(&now); (now - beginning) < OIS_OPEN_WAITTIME; time(&now)) {
00505 ret = ois_read_into_buffer(smsc, OIS_WAITTIME);
00506 if (ret < 0) {
00507 goto error;
00508 }
00509
00510 if (smsc->buflen == 0) {
00511
00512
00513 smsc->ois_flags |= OIS_FLAG_NOBANNER;
00514 debug("bb.sms.ois", 0, "assuming that %s:%d is in the quiet mode",
00515 smsc->hostname, smsc->port);
00516 return 0;
00517 }
00518 ret = ois_extract_line_from_buffer(buffer, smsc);
00519 if (ret > 0) {
00520 if (strncmp(buffer, "Trying", 6) == 0 &&
00521 strstr(buffer, "...Open\r\n") != NULL) {
00522 time(&smsc->ois_alive);
00523 return 0;
00524 } else {
00525 break;
00526 }
00527 }
00528 }
00529
00530 error:
00531 SAY(4, "ois_open_sender: ois_disconnect in error");
00532 ois_disconnect(smsc);
00533 error(0, "ois_open_sender: failed to connect [%s%s]",
00534 buffer, ois_debug_str(smsc->buffer, smsc->buflen));
00535 return -1;
00536 }
00537
00538
00539 static int ois_open_receiver(SMSCenter *smsc)
00540 {
00541 struct sockaddr_in addr;
00542 int addrlen;
00543 Octstr *os;
00544
00545 SAY(2, "ois_open_receiver");
00546
00547
00548
00549 addrlen = sizeof(addr);
00550 smsc->socket = accept(smsc->ois_listening_socket,
00551 (struct sockaddr *)&addr, (socklen_t *)&addrlen);
00552 if (smsc->socket == -1) {
00553 if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
00554
00555 {
00556 return 0;
00557 } else {
00558 error(errno, "ois_open_receiver: accept failed");
00559 smsc->ois_flags |= OIS_FLAG_ERROR;
00560 return -1;
00561 }
00562 }
00563
00564 SAY2(2, "ois_open_receiver fd=%d", smsc->socket);
00565 os = gw_netaddr_to_octstr(AF_INET, &addr.sin_addr);
00566 debug("bb.sms.ois", 0, "connection from host %s port %hu",
00567 octstr_get_cstr(os), ntohs(addr.sin_port));
00568 octstr_destroy(os);
00569 time(&smsc->ois_alive);
00570 return 0;
00571 }
00572
00573
00574 static void ois_disconnect_all(SMSCenter *smsc)
00575 {
00576 SAY2(2, "ois_disconnect_all fd=%d", smsc->ois_listening_socket);
00577
00578 ois_swap_buffering(smsc);
00579 SAY(4, "ois_disconnect_all: ois_disconnect");
00580 ois_disconnect(smsc);
00581 ois_swap_buffering(smsc);
00582 SAY(4, "ois_disconnect_all: ois_disconnect");
00583 ois_disconnect(smsc);
00584
00585 if (smsc->ois_listening_socket != -1) {
00586 if (close(smsc->ois_listening_socket) == -1) {
00587 warning(errno, "ois_disconnect_all: close failed...");
00588 }
00589 smsc->ois_listening_socket = -1;
00590 }
00591 return;
00592 }
00593
00594
00595 static void ois_disconnect(SMSCenter *smsc)
00596 {
00597 SAY2(2, "ois_disconnect fd=%d", smsc->socket);
00598
00599 if (smsc->socket != -1) {
00600 if (close(smsc->socket) == -1) {
00601 warning(errno, "ois_disconnect: close failed...");
00602 }
00603 smsc->socket = -1;
00604 }
00605 return;
00606 }
00607
00608
00609 static int ois_read_into_buffer(SMSCenter *smsc, long wait_usec)
00610 {
00611 int ret;
00612
00613 SAY(8, "ois_read_into_buffer");
00614
00615 if (smsc->socket == -1) {
00616 if ((smsc->ois_flags & OIS_FLAG_CLOSED) == 0) {
00617 debug("bb.sms.ois", 0, "attempting to read from a closed socket");
00618 smsc->ois_flags |= OIS_FLAG_CLOSED;
00619 }
00620 return 0;
00621 } else {
00622 smsc->ois_flags &= ~OIS_FLAG_CLOSED;
00623 }
00624
00625 ret = read_available(smsc->socket, wait_usec);
00626 if (ret > 0) {
00627 time(&smsc->ois_alive);
00628 ret = smscenter_read_into_buffer(smsc);
00629 if (ret > 0 || (ret == 0 && smsc->buflen > 0)) {
00630 SAY(2, "ois_read_into_buffer got something");
00631 } else if (ret == 0) {
00632 if (smsc->buflen > 0) {
00633 SAY(2, "ois_read_into_buffer has something");
00634 ret = 1;
00635 }
00636 SAY(4, "ois_read_into_buffer: ois_disconnect");
00637 ois_disconnect(smsc);
00638 }
00639 }
00640 return ret;
00641 }
00642
00643
00644 static int ois_check_input(SMSCenter *smsc, long wait_usec)
00645 {
00646 char buffer[BUFLEN+1];
00647 time_t now;
00648 int ret;
00649
00650 SAY(8, "ois_check_input");
00651
00652 ret = ois_read_into_buffer(smsc, wait_usec);
00653 if (ret < 0) {
00654 goto error;
00655 }
00656
00657 ret = ois_extract_msg_from_buffer(buffer, smsc);
00658 if (ret > 0) {
00659 IOTRACE("received", buffer, ret);
00660 switch (buffer[0]) {
00661 case 's':
00662 ret = ois_submit_sm_result(smsc, buffer);
00663 if (ret > 0) {
00664 warning(0, "ois_check_input: submit sm result signals (%d)...", ret);
00665 } else if (ret < 0) {
00666 error(0, "ois_check_input: invalid submit sm result");
00667 goto error;
00668 }
00669 --smsc->ois_ack_debt;
00670 time(&smsc->ois_alive);
00671 break;
00672 case 'M':
00673 ret = ois_deliver_sm_invoke(smsc, buffer);
00674 if (ret >= 0) {
00675 ret = ois_deliver_sm_result(smsc, ret, buffer);
00676 if (ret < 0) {
00677 goto error;
00678 }
00679 } else {
00680 error(0, "ois_check_input: invalid deliver sm invoke");
00681 goto error;
00682 }
00683 time(&smsc->ois_alive);
00684 break;
00685 default:
00686 warning(0, "ois_check_input: unexpected message [%s]...",
00687 ois_debug_str(buffer, ret));
00688 break;
00689 }
00690 } else {
00691 if (smsc->socket != -1) {
00692 time(&now);
00693 if ((now - smsc->ois_alive) > OIS_MESSAGE_WAITTIME) {
00694 debug("bb.sms.ois", 0, "closing an idle connection");
00695 SAY(4, "ois_check_input: ois_disconnect");
00696 ois_disconnect(smsc);
00697 }
00698 }
00699 }
00700
00701 if (ret < 0) {
00702 error(0, "ois_check_input: malformatted message [%s]",
00703 ois_debug_str(buffer, -ret));
00704 goto error;
00705 }
00706
00707 if (smsc->ois_received_mo != NULL ||
00708 (smsc->ois_flags & OIS_FLAG_ERROR) != 0) {
00709 SAY(2, "ois_check_input has something");
00710 return 1;
00711 } else {
00712 return 0;
00713 }
00714
00715 error:
00716 smsc->ois_flags |= OIS_FLAG_ERROR;
00717 return 1;
00718 }
00719
00720
00721 static int ois_check_incoming(SMSCenter *smsc, long wait_usec)
00722 {
00723 fd_set read_fd;
00724 struct timeval tv;
00725 int ret;
00726
00727 SAY(8, "ois_check_incoming");
00728
00729 tv.tv_sec = 0;
00730 tv.tv_usec = wait_usec;
00731
00732 FD_ZERO(&read_fd);
00733 FD_SET(smsc->ois_listening_socket, &read_fd);
00734 ret = select(smsc->ois_listening_socket + 1, &read_fd, NULL, NULL, &tv);
00735 if (ret == -1) {
00736 if (errno == EINTR || errno == EAGAIN) {
00737 return 0;
00738 } else {
00739 error(errno, "ois_check_incoming: select failed");
00740 smsc->ois_flags |= OIS_FLAG_ERROR;
00741 return -1;
00742 }
00743 } else if (ret == 0) {
00744 return 0;
00745 }
00746
00747
00748
00749 if (smsc->socket != -1) {
00750 if ((smsc->ois_flags & OIS_FLAG_MULTIPLE_CALL) == 0) {
00751
00752
00753 debug("bb.sms.ois", 0, "letting an incoming call to wait until the old one disconnects");
00754 smsc->ois_flags |= OIS_FLAG_MULTIPLE_CALL;
00755 }
00756 return 0;
00757 }
00758
00759 smsc->ois_flags &= ~OIS_FLAG_MULTIPLE_CALL;
00760 return ois_open_receiver(smsc);
00761 }
00762
00763
00764 static void ois_append_to_list(ois_listentry **head, Msg *msg)
00765 {
00766 ois_listentry *item;
00767 ois_listentry *tail;
00768
00769 SAY(2, "ois_append_to_list");
00770
00771 item = gw_malloc(sizeof(ois_listentry));
00772 item->next = NULL;
00773 item->msg = msg;
00774
00775 if (*head == NULL) {
00776 *head = item;
00777 } else {
00778 for (tail = *head; tail->next != NULL; tail = tail->next) ;
00779 tail->next = item;
00780 }
00781 return;
00782 }
00783
00784
00785
00786 static int ois_int_to_i4(char *raw, int nbr)
00787 {
00788 int pos;
00789
00790 SAY(3, "ois_int_to_i4");
00791
00792 for (pos = 0; pos < 4; ++pos) {
00793 raw[pos] = (char)(nbr % 0x100);
00794 nbr /= 0x100;
00795 }
00796 return 4;
00797 }
00798
00799 static int ois_increment_counter(void)
00800 {
00801 SAY(3, "ois_increment_counter");
00802
00803 ois_counter = (ois_counter+1) % MAXCOUNTER;
00804 return ois_counter;
00805 }
00806
00807
00808 static int ois_submit_sm_invoke(SMSCenter *smsc, const Msg *msg)
00809 {
00810 char body[BUFLEN+1];
00811 char buffer[BUFLEN+1];
00812 int len;
00813 int count;
00814 int i;
00815 int ret;
00816
00817 SAY(2, "ois_submit_sm_invoke");
00818
00819
00820
00821 ois_increment_counter();
00822 len = ois_encode_submit_sm_invoke(body, msg);
00823
00824
00825
00826
00827 count = (len-1) / 121;
00828
00829
00830
00831 sprintf(buffer, "%c%c%04d%.121s%c",
00832 'S',
00833 (char)(0x50|count),
00834 ois_counter,
00835 &body[0],
00836 EOL);
00837 IOTRACE("sending", buffer, strlen(buffer));
00838 ret = write_to_socket(smsc->socket, buffer);
00839 if (ret < 0) {
00840 goto error;
00841 }
00842
00843
00844
00845 for (i = 1; i <= count; ++i) {
00846 sprintf(buffer, "%c%c%04d%.121s%c",
00847 'S',
00848 (char)(0x60|(count-i)),
00849 ois_counter,
00850 &body[i*121],
00851 EOL);
00852 IOTRACE("sending", buffer, strlen(buffer));
00853 ret = write_to_socket(smsc->socket, buffer);
00854 if (ret < 0) {
00855 goto error;
00856 }
00857 }
00858
00859 SAY(2, "ois_submit_sm_invoke ok");
00860 return 0;
00861
00862 error:
00863 SAY(2, "ois_submit_sm_invoke error");
00864 return -1;
00865 }
00866
00867
00868 static int ois_encode_submit_sm_invoke(char *str, const Msg *msg)
00869 {
00870 char raw[BUFLEN];
00871 int pos;
00872 int ret;
00873
00874 SAY(3, "ois_encode_submit_sm_invoke");
00875
00876
00877
00878 pos = 0;
00879 pos += ois_append_msisdn(&raw[pos], msg);
00880 pos += ois_append_sme_reference_number(&raw[pos]);
00881 pos += ois_append_priority(&raw[pos]);
00882 pos += ois_append_originating_address(&raw[pos]);
00883 pos += ois_append_validity_period(&raw[pos]);
00884 pos += ois_append_data_coding_scheme(&raw[pos], msg);
00885 pos += ois_append_status_report_request(&raw[pos]);
00886 pos += ois_append_protocol_id(&raw[pos]);
00887 pos += ois_append_submission_options(&raw[pos], msg);
00888 pos += ois_append_sm_text(&raw[pos], msg);
00889
00890 ret = ois_convert_to_ia5(str, raw, pos);
00891 return ret;
00892 }
00893
00894 static int ois_append_msisdn(char *raw, const Msg *msg)
00895 {
00896 int len;
00897
00898 SAY(3, "ois_append_msisdn");
00899
00900 len = octstr_len(msg->sms.receiver);
00901 raw[0] = (char) len;
00902 memcpy(&raw[1], octstr_get_cstr(msg->sms.receiver), len);
00903 return 1 + len;
00904 }
00905
00906 static int ois_append_sme_reference_number(char *raw)
00907 {
00908 SAY(3, "ois_append_sme_reference_number");
00909
00910
00911
00912 raw[0] = (char) 2;
00913 return 1 + ois_int_to_i4(&raw[1], ois_counter);
00914 }
00915
00916 static int ois_append_priority(char *raw)
00917 {
00918 SAY(3, "ois_append_priority");
00919
00920 raw[0] = (char) 1;
00921 return 1;
00922 }
00923
00924 static int ois_append_originating_address(char *raw)
00925 {
00926 SAY(3, "ois_append_originating_address");
00927
00928 raw[0] = (char) 2;
00929 raw[1] = 'A';
00930 raw[2] = '3';
00931
00932 return 3;
00933 }
00934
00935 static int ois_append_validity_period(char *raw)
00936 {
00937 SAY(3, "ois_append_validity_period");
00938
00939 raw[0] = (char) 2;
00940 raw[1] = (char) 1;
00941 return 2;
00942 }
00943
00944 static int ois_append_data_coding_scheme(char *raw, const Msg *msg)
00945 {
00946 SAY(3, "ois_append_data_coding_scheme");
00947
00948
00949
00950
00951
00952 raw[0] = (char) (msg->sms.coding == DC_8BIT ? DCS_OCTET_DATA : 0x0f);
00953 return 1;
00954 }
00955
00956 static int ois_append_status_report_request(char *raw)
00957 {
00958 SAY(3, "ois_append_status_report_request");
00959
00960 raw[0] = (char) 0x00;
00961 return 1;
00962 }
00963
00964 static int ois_append_protocol_id(char *raw)
00965 {
00966 SAY(3, "ois_append_protocol_id");
00967
00968 raw[0] = (char) 0;
00969 return 1;
00970 }
00971
00972 static int ois_append_submission_options(char *raw, const Msg *msg)
00973 {
00974 SAY(3, "ois_append_submission_options");
00975
00976
00977 raw[0] = (char) 0x00;
00978 if (octstr_len(msg->sms.udhdata)) {
00979 raw[0] |= (char) 0x02;
00980 }
00981 if (msg->sms.coding == DC_8BIT) {
00982 raw[0] |= (char) 0x10;
00983 }
00984 return 1;
00985 }
00986
00987
00988 static int ois_append_sm_text(char *raw, const Msg *msg)
00989 {
00990 int udhlen7, udhlen8;
00991 int msglen7, msglen8;
00992 int len;
00993
00994 SAY(3, "ois_append_sm_text");
00995
00996 if (msg->sms.coding == DC_7BIT || msg->sms.coding == DC_UNDEF) {
00997 charset_utf8_to_gsm(msg->sms.udhdata);
00998 charset_utf8_to_gsm(msg->sms.msgdata);
00999 }
01000
01001
01002
01003
01004 udhlen8 = octstr_len(msg->sms.udhdata);
01005 msglen8 = octstr_len(msg->sms.msgdata);
01006
01007 udhlen7 = udhlen8;
01008 msglen7 = msglen8;
01009 len = udhlen8 + msglen8;
01010
01011
01012
01013 raw[0] = (char) (len);
01014 raw[1] = (char) (udhlen7 + msglen7);
01015 memcpy(&raw[2], octstr_get_cstr(msg->sms.udhdata), udhlen8);
01016 memcpy(&raw[2+udhlen8], octstr_get_cstr(msg->sms.msgdata), msglen8);
01017
01018 IOTRACE("encoding", &raw[2], len);
01019
01020 return 2 + len;
01021 }
01022
01023
01024 static int ois_submit_sm_result(SMSCenter *smsc, const char *buffer)
01025 {
01026 int status;
01027 int ret;
01028
01029 SAY(2, "ois_submit_sm_result");
01030
01031 ret = ois_decode_submit_sm_result(&status, buffer);
01032 if (ret < 0) {
01033 goto error;
01034 }
01035
01036 return status;
01037
01038 error:
01039 return -1;
01040 }
01041
01042
01043 static int ois_decode_submit_sm_result(int *code, const char *str)
01044 {
01045 int buflen;
01046 char raw[BUFLEN];
01047 int len;
01048
01049 SAY(3, "ois_decode_submit_sm_result");
01050
01051 buflen = strlen(str) - 1;
01052 if (buflen < 7 || str[0] != 's' || str[1] != 0x50 || str[buflen] != EOL) {
01053 goto error;
01054 }
01055
01056 len = ois_convert_from_ia5(raw, &str[6]);
01057 if (len <= 0) {
01058 goto error;
01059 }
01060
01061 *code = raw[0];
01062 *code &= 0xff;
01063
01064
01065
01066 return 0;
01067
01068 error:
01069 return -1;
01070 }
01071
01072
01073 static int ois_deliver_sm_invoke(SMSCenter *smsc, const char *buffer)
01074 {
01075 Msg *msg;
01076 int ret;
01077 ois_listentry **mo;
01078
01079 SAY(2, "ois_deliver_sm_invoke");
01080
01081 msg = msg_create(sms);
01082
01083 ret = ois_decode_deliver_sm_invoke(msg, buffer);
01084 if (ret < 0) {
01085 goto error;
01086 }
01087
01088 mo = (ois_listentry **)&smsc->ois_received_mo;
01089 ois_append_to_list(mo, msg);
01090
01091 return 0;
01092
01093 error:
01094 msg_destroy(msg);
01095 return -1;
01096 }
01097
01098
01099 static int ois_decode_deliver_sm_invoke(Msg *msg, const char *str)
01100 {
01101 char body[BUFLEN+1];
01102 char raw[BUFLEN];
01103 int len;
01104 int i;
01105 int pos;
01106 int ret;
01107
01108 SAY(3, "ois_decode_deliver_sm_invoke");
01109
01110 ret = ois_check_deliver_sm_invoke(str);
01111 if (ret < 0) {
01112 goto error;
01113 }
01114
01115
01116
01117 len = strlen(str);
01118 for (pos = 0, i = 6; i < len; ++i) {
01119 if (str[i] != EOL) {
01120 body[pos++] = str[i];
01121 } else {
01122 i += 6;
01123 }
01124 }
01125 body[pos] = '\0';
01126 memset(raw, '\0', sizeof(raw));
01127 len = ois_convert_from_ia5(raw, body);
01128
01129
01130
01131 pos = 0;
01132 pos += ois_adjust_destination_address(msg, &raw[pos]);
01133 pos += ois_ignore_smsc_reference_number(&raw[pos]);
01134 pos += ois_adjust_originating_address(msg, &raw[pos]);
01135 pos += ois_adjust_data_coding_scheme(msg, &raw[pos]);
01136 pos += ois_ignore_protocol_id(&raw[pos]);
01137 pos += ois_adjust_additional_information(msg, &raw[pos]);
01138 pos += ois_adjust_sm_text(msg, &raw[pos]);
01139 pos += ois_ignore_time(&raw[pos]);
01140 pos += ois_ignore_time(&raw[pos]);
01141 if (pos != len) {
01142 error(0, "ois_decode_deliver_sm_invoke: message parsing error (%d!=%d)",
01143 pos, len);
01144 goto error;
01145 }
01146 return 0;
01147
01148 error:
01149 return -1;
01150 }
01151
01152
01153 static int ois_check_deliver_sm_invoke(const char *str)
01154 {
01155 int buflen;
01156 char buffer[BUFLEN+1];
01157 int count;
01158
01159 SAY(3, "ois_check_deliver_sm_invoke");
01160
01161
01162
01163 buflen = strlen(str) - 1;
01164 if (buflen < 7 || str[0] != 'M' || (str[1] & 0x50) != 0x50
01165 || str[buflen] != EOL) {
01166 goto error;
01167 }
01168
01169 count = str[1] & 0x0f;
01170 while (--count >= 0)
01171 {
01172
01173
01174 sprintf(buffer, "%c%c%c%.4s",
01175 EOL,
01176 'M',
01177 (char)(0x60|count),
01178 &str[2]);
01179 if (strstr(str, buffer) == NULL) {
01180 goto error;
01181 }
01182 }
01183
01184 return 0;
01185
01186 error:
01187 return -1;
01188 }
01189
01190
01191 static int ois_adjust_destination_address(Msg *msg, const char *raw)
01192 {
01193 int len;
01194
01195 SAY(3, "ois_adjust_destination_address");
01196
01197 len = raw[0] & 0xff;
01198 msg->sms.receiver = octstr_create_from_data(&raw[1+2], len-2);
01199
01200 return 1 + len;
01201 }
01202
01203 static int ois_ignore_smsc_reference_number(const char *raw)
01204 {
01205 int value;
01206
01207 SAY(3, "ois_ignore_smsc_reference_number");
01208
01209 value = raw[3] & 0xff;
01210 value <<= 8;
01211 value |= raw[2] & 0xff;
01212 value <<= 8;
01213 value |= raw[1] & 0xff;
01214 value <<= 8;
01215 value |= raw[0] & 0xff;
01216
01217 return 4;
01218 }
01219
01220 static int ois_adjust_originating_address(Msg *msg, const char *raw)
01221 {
01222 int len;
01223
01224 SAY(3, "ois_adjust_originating_address");
01225
01226 len = raw[0] & 0xff;
01227 msg->sms.sender = octstr_create_from_data(&raw[1+2], len-2);
01228
01229 return 1 + len;
01230 }
01231
01232 static int ois_adjust_data_coding_scheme(Msg *msg, const char *raw)
01233 {
01234 SAY(3, "ois_adjust_data_coding_scheme");
01235
01236
01237
01238
01239 msg->sms.coding = (raw[0] & 0xff) + 1;
01240
01241 return 1;
01242 }
01243
01244 static int ois_ignore_protocol_id(const char *raw)
01245 {
01246 int value;
01247
01248 SAY(3, "ois_ignore_protocol_id");
01249
01250 value = raw[0] & 0xff;
01251
01252 return 1;
01253 }
01254
01255 static int ois_adjust_additional_information(Msg *msg, const char *raw)
01256 {
01257 SAY(3, "ois_adjust_additional_information");
01258
01259
01260
01261 msg->sms.mclass = raw[0] & 0xff;
01262
01263 return 1;
01264 }
01265
01266 static int ois_adjust_sm_text(Msg *msg, const char *raw)
01267 {
01268 int msglen7, msglen8;
01269 char buffer[BUFLEN+1];
01270
01271 SAY(3, "ois_adjust_sm_text");
01272
01273
01274
01275 msglen7 = raw[0] & 0xff;
01276 msglen8 = raw[1] & 0xff;
01277
01278
01279
01280 switch ((msg->sms.coding - 1) & 0xff) {
01281 case 0x00:
01282 ois_expand_gsm7(buffer, &raw[2], msglen7);
01283 ois_convert_to_iso88591(buffer, msglen7);
01284 if (msg->sms.mclass & 0x02) {
01285 msg->sms.msgdata = octstr_create("");
01286 msg->sms.udhdata = octstr_create_from_data(buffer, msglen7);
01287 } else {
01288 msg->sms.msgdata = octstr_create_from_data(buffer, msglen7);
01289 msg->sms.udhdata = octstr_create("");
01290 }
01291 msg->sms.coding = DC_7BIT;
01292 break;
01293 case 0x0f:
01294 memcpy(buffer, &raw[2], msglen8);
01295 ois_convert_to_iso88591(buffer, msglen8);
01296 if (msg->sms.mclass & 0x02) {
01297 msg->sms.msgdata = octstr_create("");
01298 msg->sms.udhdata = octstr_create_from_data(buffer, msglen8);
01299 } else {
01300 msg->sms.msgdata = octstr_create_from_data(buffer, msglen8);
01301 msg->sms.udhdata = octstr_create("");
01302 }
01303 msg->sms.coding = DC_7BIT;
01304 break;
01305 default:
01306 if (msg->sms.mclass & 0x02) {
01307 msg->sms.msgdata = octstr_create("");
01308 msg->sms.udhdata = octstr_create_from_data(&raw[2], msglen8);
01309 } else {
01310 msg->sms.msgdata = octstr_create_from_data(&raw[2], msglen8);
01311 msg->sms.udhdata = octstr_create("");
01312 }
01313 msg->sms.coding = DC_8BIT;
01314 break;
01315 }
01316 msg->sms.mclass = MC_UNDEF;
01317
01318 if (octstr_len(msg->sms.udhdata)) {
01319 IOTRACE("decoded udh", octstr_get_cstr(msg->sms.udhdata),
01320 octstr_len(msg->sms.udhdata));
01321 } else {
01322 IOTRACE("decoded", octstr_get_cstr(msg->sms.msgdata),
01323 octstr_len(msg->sms.msgdata));
01324 }
01325
01326 return 2 + msglen8;
01327 }
01328
01329
01330 static int ois_ignore_time(const char *raw)
01331 {
01332 char str[15];
01333
01334 SAY(3, "ois_ignore_time");
01335
01336 strncpy(str, raw, 14); str[14] = '\0';
01337
01338 return 14;
01339 }
01340
01341
01342
01343 static int ois_deliver_sm_result(SMSCenter *smsc, int result, const char *str)
01344 {
01345 char body[BUFLEN+1];
01346 char buffer[BUFLEN+1];
01347 int len;
01348 int ret;
01349
01350 SAY(2, "ois_deliver_sm_result");
01351
01352
01353
01354 len = ois_encode_deliver_sm_result(body, result);
01355
01356
01357
01358 sprintf(buffer, "%c%c%.4s%.121s%c",
01359 'm',
01360 (char)(0x50),
01361 &str[2],
01362 &body[0],
01363 EOL);
01364
01365 IOTRACE("sending", buffer, strlen(buffer));
01366 ret = write_to_socket(smsc->socket, buffer);
01367 if (ret < 0) {
01368 goto error;
01369 }
01370
01371 return 0;
01372
01373 error:
01374 return -1;
01375 }
01376
01377
01378 static int ois_encode_deliver_sm_result(char *str, int result)
01379 {
01380 char raw[4];
01381
01382 SAY(3, "ois_encode_deliver_sm_result");
01383
01384
01385
01386 raw[0] = (char) result;
01387
01388 return ois_convert_to_ia5(str, raw, 1);
01389 }
01390
01391
01392 static int ois_expand_gsm7(char *raw8, const char *raw7, int len)
01393 {
01394 int i;
01395 char bits[8*(BUFLEN+1)];
01396
01397 SAY2(3, "ois_expand_gsm7 len=%d", len);
01398
01399
01400
01401
01402 ois_expand_gsm7_to_bits(bits, raw7, len);
01403 for (i = 0; i < len; ++i) {
01404 raw8[i] = ois_expand_gsm7_from_bits(bits, i);
01405 }
01406
01407 SAY2(5, "ois_expand_gsm7 gave [%s]", ois_debug_str(raw8, i));
01408 return i;
01409 }
01410
01411 static int ois_expand_gsm7_to_bits(char *bits, const char *raw7, int len)
01412 {
01413 int i, j, k;
01414 char ch;
01415
01416 SAY(3, "ois_expand_gsm7_to_bits");
01417
01418 len *= 7;
01419
01420 for (j = i = 0; j < len; ++i) {
01421 ch = raw7[i];
01422 for (k = 0; k < 8; ++k) {
01423 bits[j++] = (char) (ch & 0x01);
01424 ch >>= 1;
01425 }
01426 }
01427
01428 return j;
01429 }
01430
01431 static char ois_expand_gsm7_from_bits(const char *bits, int pos)
01432 {
01433 int i;
01434 char ch;
01435
01436 SAY2(8, "ois_expand_gsm7_from_bits pos=%d", pos);
01437
01438 pos *= 7;
01439 ch = '\0';
01440 for (i = 6; i >= 0; --i) {
01441 ch <<= 1;
01442 ch |= bits[pos+i];
01443 }
01444
01445 return ch;
01446 }
01447
01448
01449 static int ois_convert_to_ia5(char *str, const char *raw, int len)
01450 {
01451 int j;
01452 int i;
01453 int ch;
01454
01455 SAY2(3, "ois_convert_to_ia5 len=%d", len);
01456
01457 for (j = i = 0; i < len; ++i) {
01458 ch = raw[i] & 0xff;
01459 if (ch == 0x5c || ch == 0x5e || ch == 0x60 || ch == 0x7e) {
01460 str[j++] = (char) 0x5c;
01461 str[j++] = (char) ch;
01462 } else if (0x20 <= ch && ch < 0x7f) {
01463 str[j++] = (char) ch;
01464 } else if (0x00 <= ch && ch < 0x20) {
01465 str[j++] = (char) 0x5e;
01466 str[j++] = (char) ch + 0x40;
01467 } else if (0xa0 <= ch && ch < 0xff) {
01468 str[j++] = (char) 0x60;
01469 str[j++] = (char) ch - 0x80;
01470 } else if (0x80 <= ch && ch < 0xa0) {
01471 str[j++] = (char) 0x7e;
01472 str[j++] = (char) ch - 0x40;
01473 } else if (ch == 0x7f) {
01474 str[j++] = (char) 0x5e;
01475 str[j++] = (char) 0x7e;
01476 } else {
01477 str[j++] = (char) 0x7e;
01478 str[j++] = (char) 0x7e;
01479 }
01480 }
01481
01482 str[j] = '\0';
01483 SAY2(5, "ois_convert_to_ia5 gave [%s]", ois_debug_str(str, j));
01484 return j;
01485 }
01486
01487
01488 static int ois_convert_from_ia5(char *raw, const char *str)
01489 {
01490 int j;
01491 int i;
01492 int ch;
01493
01494 SAY(3, "ois_convert_from_ia5");
01495
01496 for (j = i = 0; ; ++i) {
01497 ch = str[i] & 0xff;
01498 if (ch < 0x20 || 0x7f <= ch) {
01499 break;
01500 } else if (ch == 0x5c) {
01501 ch = str[++i] & 0xff;
01502 if (ch == 0x5c || ch == 0x5e || ch == 0x60 || ch == 0x7e) {
01503 raw[j++] = (char) ch;
01504 } else {
01505 break;
01506 }
01507 } else if (ch == 0x5e) {
01508 ch = str[++i] & 0xff;
01509 if (0x40 <= ch && ch < 0x60) {
01510 raw[j++] = (char) ch - 0x40;
01511 } else if (ch == 0x7e) {
01512 raw[j++] = (char) 0x7f;
01513 } else {
01514 break;
01515 }
01516 } else if (ch == 0x60) {
01517 ch = str[++i] & 0xff;
01518 if (0x20 <= ch && ch < 0x7f) {
01519 raw[j++] = (char) ch + 0x80;
01520 } else {
01521 break;
01522 }
01523 } else if (ch == 0x7e) {
01524 ch = str[++i] & 0xff;
01525 if (0x40 <= ch && ch < 0x60) {
01526 raw[j++] = (char) ch + 0x40;
01527 } else if (ch == 0x7e) {
01528 raw[j++] = (char) 0xff;
01529 } else {
01530 break;
01531 }
01532 } else {
01533 raw[j++] = (char) ch;
01534 }
01535 }
01536
01537 SAY2(5, "ois_convert_from_ia5 gave [%s]", ois_debug_str(raw, j));
01538 return j;
01539 }
01540
01541
01542 static int ois_convert_to_iso88591(char *raw, int len)
01543 {
01544
01545
01546 static const char gsm_to_iso88591[] = {
01547 '@', 0xa3,'$', 0xa5,0xe8,0xe9,0xf9,0xec,
01548 0xf2,0xc7,'\n',0xd8,0xf8,'\r',0xc5,0xe5,
01549 'D', ' ', 'F', 'G', 'L', 'W', 'P', 'Y',
01550 'Y', 'S', 'X', ' ', 0xc6,0xe6,'b', 0xc9,
01551 ' ', '!', '"', '#', 0xa4, '%', '&', '\'',
01552 '(', ')', '*', '+', ',', '-', '.', '/',
01553 '0', '1', '2', '3', '4', '5', '6', '7',
01554 '8', '9', ':', ';', '<', '=', '>', '?',
01555 0xa1,'A', 'B', 'C', 'D', 'E', 'F', 'G',
01556 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
01557 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
01558 'X', 'Y', 'Z', 0xc4,0xd6,0xd1,0xdc,0xa7,
01559 0xbf,'a', 'b', 'c', 'd', 'e', 'f', 'g',
01560 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
01561 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
01562 'x', 'y', 'z', 0xe4,0xf6,0xf1,0xfc,0xe0
01563 };
01564
01565 int i;
01566
01567 SAY2(3, "ois_convert_to_iso88591 len=%d", len);
01568
01569 for (i = 0; i < len; ++i) {
01570 raw[i] = gsm_to_iso88591[raw[i] & 0x7f];
01571 }
01572
01573 SAY2(5, "ois_convert_to_iso88591 gave [%s]", ois_debug_str(raw, i));
01574 return i;
01575 }
01576
01577
01578
01579
01580
01581
01582 static int ois_extract_msg_from_buffer(char *str, SMSCenter *smsc)
01583 {
01584 int len;
01585 int count;
01586
01587 SAY2(8, "ois_extract_msg_from_buffer buflen=%ld", (long)smsc->buflen);
01588
01589 str[0] = '\0';
01590
01591 if (smsc->buflen < 7) {
01592 return 0;
01593 }
01594
01595 if (strchr("SRDATECQLMPOVsrdatecqlmpov", smsc->buffer[0]) == NULL
01596 || (smsc->buffer[1] & 0xf0) != 0x50) {
01597
01598 goto error;
01599 }
01600
01601
01602
01603 count = smsc->buffer[1] & 0x0f;
01604 for (len = 0; (size_t) len < smsc->buflen; ++len) {
01605 if (smsc->buffer[len] == EOL) {
01606 if (--count < 0) {
01607 ++len;
01608 break;
01609 }
01610 }
01611 }
01612
01613 if (count >= 0) {
01614 if (len < BUFLEN) {
01615 return 0;
01616 }
01617 goto error;
01618 }
01619
01620
01621
01622 memcpy(str, smsc->buffer, len);
01623 str[len] = '\0';
01624 smscenter_remove_from_buffer(smsc, len);
01625
01626 return len;
01627
01628 error:
01629 for (len = 0; (size_t) len < smsc->buflen && smsc->buffer[len] != EOL;
01630 ++len) ;
01631 if (len > BUFLEN) len = BUFLEN;
01632
01633 memcpy(str, smsc->buffer, len);
01634 str[len] = '\0';
01635 smscenter_remove_from_buffer(smsc, smsc->buflen);
01636
01637 return -len;
01638 }
01639
01640
01641
01642
01643
01644
01645
01646 static int ois_extract_line_from_buffer(char *str, SMSCenter *smsc)
01647 {
01648 int len;
01649
01650 SAY2(3, "ois_extract_line_from_buffer buflen=%ld", (long)smsc->buflen);
01651
01652 str[0] = '\0';
01653
01654 for (len = 0; (size_t) len < smsc->buflen && smsc->buffer[len] != '\n';
01655 ++len) ;
01656
01657 if ((size_t) len >= smsc->buflen) {
01658 return 0;
01659 } else {
01660 ++len;
01661 }
01662
01663
01664
01665 memcpy(str, smsc->buffer, len);
01666 str[len] = '\0';
01667 smscenter_remove_from_buffer(smsc, len);
01668
01669 return len;
01670 }
01671
01672
01673 static void ois_swap_buffering(SMSCenter *smsc)
01674 {
01675 time_t alive;
01676 int socket;
01677 char *buffer;
01678 size_t bufsize;
01679 size_t buflen;
01680
01681 SAY(8, "ois_swap_buffering");
01682
01683 if (smsc->ois_bufsize == 0) {
01684 smsc->ois_buflen = 0;
01685 smsc->ois_bufsize = smsc->bufsize;
01686 smsc->ois_buffer = gw_malloc(smsc->ois_bufsize);
01687 memset(smsc->ois_buffer, 0, smsc->ois_bufsize);
01688 }
01689
01690 alive = smsc->ois_alive;
01691 smsc->ois_alive = smsc->ois_alive2;
01692 smsc->ois_alive2 = alive;
01693
01694 socket = smsc->socket;
01695 smsc->socket = smsc->ois_socket;
01696 smsc->ois_socket = socket;
01697
01698 buffer = smsc->buffer;
01699 smsc->buffer = smsc->ois_buffer;
01700 smsc->ois_buffer = buffer;
01701
01702 buflen = smsc->buflen;
01703 smsc->buflen = smsc->ois_buflen;
01704 smsc->ois_buflen = buflen;
01705
01706 bufsize = smsc->bufsize;
01707 smsc->bufsize = smsc->ois_bufsize;
01708 smsc->ois_bufsize = bufsize;
01709
01710 return;
01711 }
01712
01713
01714 static const char *ois_debug_str(const char *raw, int len)
01715 {
01716 static const char hex[] = "0123456789abcdef";
01717 static char str[4*(BUFLEN+1)+1];
01718 int pos;
01719 int ch;
01720 int i;
01721
01722 pos = 0;
01723 for (i = 0; i < len; ++i) {
01724 ch = raw[i] & 0xff;
01725 if (0x20 <= ch && ch < 0x7f && ch != 0x5c) {
01726 str[pos++] = (char) ch;
01727 } else {
01728 str[pos++] = '\\';
01729 str[pos++] = 'x';
01730 str[pos++] = hex[ch/16];
01731 str[pos++] = hex[ch%16];
01732 }
01733 }
01734 str[pos] = '\0';
01735 return str;
01736 }
See file LICENSE for details about the license agreement for using,
modifying, copying or deriving work from this software.