#include <errno.h>#include <stdarg.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <fcntl.h>#include <ctype.h>#include <termios.h>#include <sys/time.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <netdb.h>#include <sys/ioctl.h>#include <time.h>#include <math.h>#include "gwlib/gwlib.h"#include "gwlib/charset.h"#include "smscconn.h"#include "smscconn_p.h"#include "bb_smscconn_cb.h"#include "msg.h"#include "sms.h"#include "dlr.h"#include "smsc_at.h"Include dependency graph for smsc_at.c:

Go to the source code of this file.
|
||||||||||||
|
Definition at line 1452 of file smsc_at.c. References smscconn::data, PrivAT2data::device_thread, gw_prioqueue_produce, gwthread_wakeup(), msg_duplicate(), PrivAT2data::outgoing_queue, sms, and SMSCConn. 01453 {
01454 PrivAT2data *privdata = conn->data;
01455 Msg *copy;
01456
01457 copy = msg_duplicate(sms);
01458 gw_prioqueue_produce(privdata->outgoing_queue, copy);
01459 gwthread_wakeup(privdata->device_thread);
01460 return 0;
01461 }
|
Here is the call graph for this function:

|
|
Definition at line 1100 of file smsc_at.c. References at2_send_modem_command(), debug(), PrivAT2data::lines, PrivAT2data::name, O_DESTROY, octstr_create, octstr_get_cstr, octstr_imm(), octstr_len(), octstr_parse_long(), octstr_search(), PrivAT2data::sms_memory_capacity, and PrivAT2data::sms_memory_usage. 01101 {
01102 long values[4]; /* array to put response data in */
01103 int pos; /* position of parser in data stream */
01104 int ret;
01105 Octstr *search_cpms = NULL;
01106
01107 /* select memory type and get report */
01108 if ((ret = at2_send_modem_command(privdata, "AT+CPMS?", 0, 0)) != 0) {
01109 debug("bb.smsc.at2.memory_check", 0, "failed to send mem select command to modem %d", ret);
01110 return -1;
01111 }
01112
01113 search_cpms = octstr_create("+CPMS:");
01114
01115 if ((pos = octstr_search(privdata->lines, search_cpms, 0)) != -1) {
01116 /* got back a +CPMS response */
01117 int index = 0; /* index in values array */
01118 pos += 6; /* position of parser in the stream - start after header */
01119
01120 /* skip memory indication */
01121 pos = octstr_search(privdata->lines, octstr_imm(","), pos) + 1;
01122
01123 /* find all the values */
01124 while (index < 4 && pos < octstr_len(privdata->lines) &&
01125 (pos = octstr_parse_long(&values[index], privdata->lines, pos, 10)) != -1) {
01126 ++pos; /* skip number seperator */
01127 ++index; /* increment array index */
01128 if (index == 2)
01129 /* skip second memory indication */
01130 pos = octstr_search(privdata->lines, octstr_imm(","), pos) + 1;
01131 }
01132
01133 if (index < 4) {
01134 /* didn't get all memory data - I don't why, so I'll bail */
01135 debug("bb.smsc.at2", 0, "AT2[%s]: couldn't parse all memory locations : %d:'%s'.",
01136 octstr_get_cstr(privdata->name), index,
01137 &(octstr_get_cstr(privdata->lines)[pos]));
01138 O_DESTROY(search_cpms);
01139 return -1;
01140 }
01141
01142 privdata->sms_memory_usage = values[0];
01143 privdata->sms_memory_capacity = values[1];
01144 /*
01145 privdata->output_mem_sms_used = values[2];
01146 privdata->output_mem_sms_capacity = values[3];
01147 */
01148
01149 /* everything's cool */
01150 ret = 0;
01151
01152 /* clear the buffer */
01153 O_DESTROY(privdata->lines);
01154
01155 } else {
01156 debug("bb.smsc.at2", 0, "AT2[%s]: no correct header for CPMS response.",
01157 octstr_get_cstr(privdata->name));
01158
01159 /* didn't get a +CPMS response - this is clearly an error */
01160 ret = -1;
01161 }
01162
01163 O_DESTROY(search_cpms);
01164 return ret;
01165 }
|
Here is the call graph for this function:

|
|
Definition at line 278 of file smsc_at.c. References PrivAT2data::fd, PrivAT2data::ilb, info(), PrivAT2data::name, octstr_create, octstr_destroy(), octstr_get_cstr, PrivAT2data::phase2plus, and PrivAT2data::pin_ready. 00279 {
00280 info(0, "AT2[%s]: Closing device", octstr_get_cstr(privdata->name));
00281 close(privdata->fd);
00282 privdata->fd = -1;
00283 privdata->pin_ready = 0;
00284 privdata->phase2plus = 0;
00285 if (privdata->ilb != NULL)
00286 octstr_destroy(privdata->ilb);
00287 privdata->ilb = octstr_create("");
00288 }
|
Here is the call graph for this function:

|
|
Definition at line 2088 of file smsc_at.c. References at2_hexchar(), octstr_append_char(), octstr_create, octstr_get_char(), octstr_len(), and pdu. 02089 {
02090 Octstr *pdu;
02091 int i;
02092 int len = octstr_len(pdutext);
02093
02094 pdu = octstr_create("");
02095 for (i = 0; i < len; i += 2) {
02096 octstr_append_char(pdu, at2_hexchar(octstr_get_char(pdutext, i)) * 16
02097 + at2_hexchar(octstr_get_char(pdutext, i + 1)));
02098 }
02099 return pdu;
02100 }
|
Here is the call graph for this function:

|
||||||||||||||||||||
|
Definition at line 2106 of file smsc_at.c. References at2_lmask, at2_rmask, charset_gsm_to_utf8(), octstr_append_char(), octstr_get_char(), octstr_get_cstr, and octstr_len(). 02107 {
02108 unsigned char septet, octet, prevoctet;
02109 int i;
02110 int r = 1;
02111 int c = 7;
02112 int pos = 0;
02113
02114 /* Shift the buffer offset bits to the left */
02115 if (offset > 0) {
02116 unsigned char *ip;
02117 for (i = 0, ip = (unsigned char *)octstr_get_cstr(input); i < octstr_len(input); i++) {
02118 if (i == octstr_len(input) - 1)
02119 *ip = *ip >> offset;
02120 else
02121 *ip = (*ip >> offset) | (*(ip + 1) << (8 - offset));
02122 ip++;
02123 }
02124 }
02125 octet = octstr_get_char(input, pos);
02126 prevoctet = 0;
02127 for (i = 0; i < len; i++) {
02128 septet = ((octet & at2_rmask[c]) << (r - 1)) + prevoctet;
02129 octstr_append_char(decoded, septet);
02130
02131 prevoctet = (octet & at2_lmask[r]) >> c;
02132
02133 /* When r=7 we have a full character in prevoctet */
02134 if ((r == 7) && (i < len - 1)) {
02135 i++;
02136 octstr_append_char(decoded, prevoctet);
02137 prevoctet = 0;
02138 }
02139
02140 r = (r > 6) ? 1 : r + 1;
02141 c = (c < 2) ? 7 : c - 1;
02142
02143 pos++;
02144 octet = octstr_get_char(input, pos);
02145 }
02146 charset_gsm_to_utf8(decoded);
02147 }
|
Here is the call graph for this function:

|
|
Definition at line 2765 of file smsc_at.c. References ModemDef::detect_string, ModemDef::detect_string2, ModemDef::enable_hwhs, ModemDef::id, ModemDef::init_string, ModemDef::keepalive_cmd, ModemDef::message_storage, ModemDef::name, O_DESTROY, and ModemDef::reset_string. 02766 {
02767 if (modem != NULL) {
02768 O_DESTROY(modem->id);
02769 O_DESTROY(modem->name);
02770 O_DESTROY(modem->detect_string);
02771 O_DESTROY(modem->detect_string2);
02772 O_DESTROY(modem->init_string);
02773 O_DESTROY(modem->enable_hwhs);
02774 O_DESTROY(modem->keepalive_cmd);
02775 O_DESTROY(modem->message_storage);
02776 O_DESTROY(modem->reset_string);
02777 gw_free(modem);
02778 }
02779 }
|
|
|
Definition at line 2540 of file smsc_at.c. References at2_close_device(), at2_destroy_modem(), at2_flush_buffer(), at2_open_device(), at2_read_modems(), at2_send_modem_command(), at2_set_speed(), PrivAT2data::configfile, debug(), ModemDef::detect_string, ModemDef::detect_string2, gwlist_destroy(), gwlist_search(), info(), PrivAT2data::lines, PrivAT2data::modem, ModemDef::name, PrivAT2data::name, octstr_delete(), octstr_destroy(), octstr_destroy_item(), octstr_get_cstr, octstr_imm(), octstr_item_match(), octstr_len(), octstr_search(), octstr_search_char(), octstr_split(), octstr_truncate(), panic, PrivAT2data::phase2plus, res, and PrivAT2data::speed. 02541 {
02542 int res;
02543 ModemDef *modem;
02544 int i;
02545
02546 debug("bb.smsc.at2", 0, "AT2[%s]: detecting modem type", octstr_get_cstr(privdata->name));
02547
02548 if (at2_open_device(privdata) == -1)
02549 return -1;
02550
02551 at2_set_speed(privdata, privdata->speed);
02552 /* send a return so the modem can detect the speed */
02553 res = at2_send_modem_command(privdata, "", 1, 0);
02554 res = at2_send_modem_command(privdata, "AT", 0, 0);
02555
02556 if (at2_send_modem_command(privdata, "AT&F", 0, 0) == -1)
02557 return -1;
02558 if (at2_send_modem_command(privdata, "ATE0", 0, 0) == -1)
02559 return -1;
02560
02561 at2_flush_buffer(privdata);
02562
02563 if (at2_send_modem_command(privdata, "ATI", 0, 0) == -1)
02564 return -1;
02565
02566 /* we try to detect the modem automatically */
02567 i = 1;
02568 while ((modem = at2_read_modems(privdata, privdata->configfile, NULL, i++)) != NULL) {
02569
02570 if (octstr_len(modem->detect_string) == 0) {
02571 at2_destroy_modem(modem);
02572 continue;
02573 }
02574
02575 /*
02576 debug("bb.smsc.at2",0,"AT2[%s]: searching for %s", octstr_get_cstr(privdata->name),
02577 octstr_get_cstr(modem->name));
02578 */
02579
02580 if (octstr_search(privdata->lines, modem->detect_string, 0) != -1) {
02581 if (octstr_len(modem->detect_string2) == 0) {
02582 debug("bb.smsc.at2", 0, "AT2[%s]: found string <%s>, using modem definition <%s>",
02583 octstr_get_cstr(privdata->name), octstr_get_cstr(modem->detect_string),
02584 octstr_get_cstr(modem->name));
02585 privdata->modem = modem;
02586 break;
02587 } else {
02588 if (octstr_search(privdata->lines, modem->detect_string2, 0) != -1) {
02589 debug("bb.smsc.at2", 0, "AT2[%s]: found string <%s> plus <%s>, using modem "
02590 "definition <%s>", octstr_get_cstr(privdata->name),
02591 octstr_get_cstr(modem->detect_string),
02592 octstr_get_cstr(modem->detect_string2),
02593 octstr_get_cstr(modem->name));
02594 privdata->modem = modem;
02595 break;
02596 }
02597 }
02598 } else {
02599 /* Destroy modem */
02600 at2_destroy_modem(modem);
02601 }
02602 }
02603
02604 if (privdata->modem == NULL) {
02605 debug("bb.smsc.at2", 0, "AT2[%s]: Cannot detect modem, using generic",
02606 octstr_get_cstr(privdata->name));
02607 if ((modem = at2_read_modems(privdata, privdata->configfile, octstr_imm("generic"), 0)) == NULL) {
02608 panic(0, "AT2[%s]: Cannot detect modem and generic not found",
02609 octstr_get_cstr(privdata->name));
02610 } else {
02611 privdata->modem = modem;
02612 }
02613 }
02614
02615 /* lets see if it supports GSM SMS 2+ mode */
02616 res = at2_send_modem_command(privdata, "AT+CSMS=?", 0, 0);
02617 if (res != 0)
02618 /* if it doesnt even understand the command, I'm sure it won't support it */
02619 privdata->phase2plus = 0;
02620 else {
02621 /* we have to take a part a string like +CSMS: (0,1,128) */
02622 Octstr *ts;
02623 int i;
02624 List *vals;
02625
02626 ts = privdata->lines;
02627 privdata->lines = NULL;
02628
02629 i = octstr_search_char(ts, '(', 0);
02630 if (i > 0) {
02631 octstr_delete(ts, 0, i + 1);
02632 }
02633 i = octstr_search_char(ts, ')', 0);
02634 if (i > 0) {
02635 octstr_truncate(ts, i);
02636 }
02637 vals = octstr_split(ts, octstr_imm(","));
02638 octstr_destroy(ts);
02639 ts = gwlist_search(vals, octstr_imm("1"), (void*) octstr_item_match);
02640 if (ts)
02641 privdata->phase2plus = 1;
02642 gwlist_destroy(vals, octstr_destroy_item);
02643 }
02644 if (privdata->phase2plus)
02645 info(0, "AT2[%s]: Phase 2+ is supported", octstr_get_cstr(privdata->name));
02646 at2_close_device(privdata);
02647 return 0;
02648 }
|
Here is the call graph for this function:

|
|
Definition at line 2486 of file smsc_at.c. References at2_test_speed(), debug(), info(), PrivAT2data::name, octstr_get_cstr, and PrivAT2data::speed. 02487 {
02488 int i;
02489 int autospeeds[] = {
02490 #ifdef B115200
02491 115200,
02492 #endif
02493 #ifdef B57600
02494 57600,
02495 #endif
02496 38400, 19200, 9600 };
02497
02498 debug("bb.smsc.at2", 0, "AT2[%s]: detecting modem speed. ",
02499 octstr_get_cstr(privdata->name));
02500
02501 for (i = 0; i < (sizeof(autospeeds) / sizeof(int)); i++) {
02502 if(at2_test_speed(privdata, autospeeds[i]) == 0) {
02503 privdata->speed = autospeeds[i];
02504 break;
02505 }
02506 }
02507 if (privdata->speed == 0) {
02508 info(0, "AT2[%s]: cannot detect speed", octstr_get_cstr(privdata->name));
02509 return -1;
02510 }
02511 info(0, "AT2[%s]: detect speed is %ld", octstr_get_cstr(privdata->name), privdata->speed);
02512 return 0;
02513 }
|
Here is the call graph for this function:

|
|
Definition at line 1228 of file smsc_at.c. References at2_close_device(), at2_destroy_modem(), at2_detect_modem_type(), at2_detect_speed(), at2_init_device(), at2_login_device(), at2_open_device(), at2_read_pending_incoming_messages(), at2_read_sms_memory(), at2_send_messages(), at2_send_modem_command(), at2_test_speed(), at2_wait_modem_command(), bb_smscconn_connected(), bb_smscconn_killed(), PrivAT2data::configfile, smscconn::connect_time, smscconn::data, PrivAT2data::device, error(), PrivAT2data::fd, smscconn::flow_mutex, gw_prioqueue_destroy(), gw_prioqueue_len(), gwlist_destroy(), gwlist_len(), gwthread_sleep(), PrivAT2data::ilb, info(), PrivAT2data::keepalive, ModemDef::keepalive_cmd, PrivAT2data::lines, smscconn::log_idx, log_thread_to(), PrivAT2data::max_error_count, PrivAT2data::modem, mutex_lock, mutex_unlock, PrivAT2data::my_number, PrivAT2data::name, octstr_destroy(), octstr_destroy_item(), octstr_get_cstr, PrivAT2data::outgoing_queue, PrivAT2data::pending_incoming_messages, PrivAT2data::pin, smscconn::reconnect_delay, ModemDef::reset_string, PrivAT2data::shutdown, PrivAT2data::sms_center, PrivAT2data::sms_memory_poll_interval, SMSCConn, ModemDef::speed, PrivAT2data::speed, smscconn::status, PrivAT2data::validityperiod, and smscconn::why_killed. Referenced by smsc_at2_create(). 01229 {
01230 SMSCConn *conn = arg;
01231 PrivAT2data *privdata = conn->data;
01232 int reconnecting = 0, error_count = 0;
01233 long idle_timeout, memory_poll_timeout = 0;
01234
01235 conn->status = SMSCCONN_CONNECTING;
01236
01237 /* Make sure we log into our own log-file if defined */
01238 log_thread_to(conn->log_idx);
01239
01240 reconnect:
01241
01242 do {
01243 if (reconnecting) {
01244 if (conn->status == SMSCCONN_ACTIVE) {
01245 mutex_lock(conn->flow_mutex);
01246 conn->status = SMSCCONN_RECONNECTING;
01247 mutex_unlock(conn->flow_mutex);
01248 }
01249 error(0, "AT2[%s]: Couldn't connect (retrying in %ld seconds).",
01250 octstr_get_cstr(privdata->name), conn->reconnect_delay);
01251 gwthread_sleep(conn->reconnect_delay);
01252 reconnecting = 0;
01253 }
01254
01255 /* If modems->speed is defined, try to use it, else autodetect */
01256 if (privdata->speed == 0 && privdata->modem != NULL && privdata->modem->speed != 0) {
01257
01258 info(0, "AT2[%s]: trying to use speed <%ld> from modem definition",
01259 octstr_get_cstr(privdata->name), privdata->modem->speed);
01260 if (at2_test_speed(privdata, privdata->modem->speed) == 0) {
01261 privdata->speed = privdata->modem->speed;
01262 info(0, "AT2[%s]: speed is %ld",
01263 octstr_get_cstr(privdata->name), privdata->speed);
01264 } else {
01265 info(0, "AT2[%s]: speed in modem definition don't work, will autodetect",
01266 octstr_get_cstr(privdata->name));
01267 }
01268 }
01269
01270 if (privdata->speed == 0 && at2_detect_speed(privdata) == -1) {
01271 reconnecting = 1;
01272 continue;
01273 }
01274
01275 if (privdata->modem == NULL && at2_detect_modem_type(privdata) == -1) {
01276 reconnecting = 1;
01277 continue;
01278 }
01279
01280 if (at2_open_device(privdata)) {
01281 error(errno, "AT2[%s]: at2_device_thread: open_at2_device failed.",
01282 octstr_get_cstr(privdata->name));
01283 reconnecting = 1;
01284 continue;
01285 }
01286
01287 if (at2_login_device(privdata)) {
01288 error(errno, "AT2[%s]: at2_device_thread: at2_login_device failed.",
01289 octstr_get_cstr(privdata->name));
01290 reconnecting = 1;
01291 continue;
01292 }
01293
01294 if (privdata->max_error_count > 0 && error_count > privdata->max_error_count
01295 && privdata->modem != NULL && privdata->modem->reset_string != NULL) {
01296 error_count = 0;
01297 if (at2_send_modem_command(privdata,
01298 octstr_get_cstr(privdata->modem->reset_string), 0, 0) != 0) {
01299 error(0, "AT2[%s]: Reset of modem failed.", octstr_get_cstr(privdata->name));
01300 at2_close_device(privdata);
01301 reconnecting = 1;
01302 continue;
01303 } else {
01304 info(0, "AT2[%s]: Modem reseted.", octstr_get_cstr(privdata->name));
01305 }
01306 }
01307
01308 if (at2_init_device(privdata) != 0) {
01309 error(0, "AT2[%s]: Initialization of device failed.", octstr_get_cstr(privdata->name));
01310 at2_close_device(privdata);
01311 error_count++;
01312 reconnecting = 1;
01313 continue;
01314 } else
01315 error_count = 0;
01316
01317 /* If we got here, then the device is opened */
01318 break;
01319 } while (!privdata->shutdown);
01320
01321 mutex_lock(conn->flow_mutex);
01322 conn->status = SMSCCONN_ACTIVE;
01323 conn->connect_time = time(NULL);
01324 mutex_unlock(conn->flow_mutex);
01325 bb_smscconn_connected(conn);
01326
01327 idle_timeout = 0;
01328 while (!privdata->shutdown) {
01329 at2_wait_modem_command(privdata, 1, 0, NULL);
01330
01331 /* read error, so re-connect */
01332 if (privdata->fd == -1) {
01333 reconnecting = 1;
01334 goto reconnect;
01335 }
01336
01337 while (gwlist_len(privdata->pending_incoming_messages) > 0) {
01338 at2_read_pending_incoming_messages(privdata);
01339 }
01340
01341 if (privdata->keepalive &&
01342 idle_timeout + privdata->keepalive < time(NULL)) {
01343 if (at2_send_modem_command(privdata,
01344 octstr_get_cstr(privdata->modem->keepalive_cmd), 5, 0) < 0) {
01345 at2_close_device(privdata);
01346 reconnecting = 1;
01347 goto reconnect;
01348 }
01349 idle_timeout = time(NULL);
01350 }
01351
01352 if (privdata->sms_memory_poll_interval &&
01353 memory_poll_timeout + privdata->sms_memory_poll_interval < time(NULL)) {
01354 if (at2_read_sms_memory(privdata) == -1) {
01355 at2_close_device(privdata);
01356 reconnecting = 1;
01357 goto reconnect;
01358 }
01359 memory_poll_timeout = time(NULL);
01360 }
01361
01362 if (gw_prioqueue_len(privdata->outgoing_queue) > 0) {
01363 at2_send_messages(privdata);
01364 idle_timeout = time(NULL);
01365 }
01366 }
01367 at2_close_device(privdata);
01368 mutex_lock(conn->flow_mutex);
01369 conn->status = SMSCCONN_DISCONNECTED;
01370 mutex_unlock(conn->flow_mutex);
01371 /* maybe some cleanup here? */
01372 at2_destroy_modem(privdata->modem);
01373 octstr_destroy(privdata->device);
01374 octstr_destroy(privdata->ilb);
01375 octstr_destroy(privdata->lines);
01376 octstr_destroy(privdata->pin);
01377 octstr_destroy(privdata->validityperiod);
01378 octstr_destroy(privdata->my_number);
01379 octstr_destroy(privdata->sms_center);
01380 octstr_destroy(privdata->name);
01381 octstr_destroy(privdata->configfile);
01382 gw_prioqueue_destroy(privdata->outgoing_queue, NULL);
01383 gwlist_destroy(privdata->pending_incoming_messages, octstr_destroy_item);
01384 gw_free(conn->data);
01385 conn->data = NULL;
01386 mutex_lock(conn->flow_mutex);
01387 conn->why_killed = SMSCCONN_KILLED_SHUTDOWN;
01388 conn->status = SMSCCONN_DEAD;
01389 mutex_unlock(conn->flow_mutex);
01390 bb_smscconn_killed();
01391 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 2425 of file smsc_at.c. References octstr_append_char(), octstr_create, octstr_get_char(), and octstr_len(). 02426 {
02427 int LSBmask[8] = { 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F };
02428 int MSBmask[8] = { 0x00, 0x40, 0x60, 0x70, 0x78, 0x7C, 0x7E, 0x7F };
02429 int destRemain = (int)ceil ((octstr_len(source) * 7.0) / 8.0);
02430 int i = (offset?8-offset:7), iStore = offset;
02431 int posT, posS;
02432 Octstr *target = octstr_create("");
02433 int target_chr = 0, source_chr;
02434
02435 /* start packing the septet stream into an octet stream */
02436 for (posS = 0, posT = 0; (source_chr = octstr_get_char(source, posS++)) != -1;) {
02437 /* grab least significant bits from current septet and
02438 * store them packed to the right */
02439 target_chr |= (source_chr & LSBmask[i]) << iStore;
02440 /* store current byte if last command filled it */
02441 if (iStore != 0) {
02442 destRemain--;
02443 octstr_append_char(target, target_chr);
02444 target_chr = 0;
02445 }
02446 /* grab most significant bits from current septet and
02447 * store them packed to the left */
02448 target_chr |= (source_chr & MSBmask[7 - i]) >> (8 - iStore) % 8;
02449 /* advance target bit index by 7 (modulo 8 addition ) */
02450 iStore = (--iStore < 0 ? 7 : iStore);
02451 /* if just finished packing 8 septets (into 7 octets) don't advance mask index */
02452 if (iStore != 0)
02453 i = (++i > 7 ? 1 : i);
02454 }
02455
02456 /* don't forget to pack the leftovers ;-) */
02457 if (destRemain > 0)
02458 octstr_append_char(target, target_chr);
02459
02460 return target;
02461 }
|
Here is the call graph for this function:

|
|
Definition at line 2464 of file smsc_at.c. References at2_numtext(), octstr_append_char(), octstr_create, octstr_get_char(), and octstr_len(). 02465 {
02466 int len, i;
02467 Octstr *out = octstr_create("");
02468
02469 len = octstr_len(input);
02470
02471 for (i = 0; i < len; i++) {
02472 /* each character is encoded in its hex representation (2 chars) */
02473 octstr_append_char(out, at2_numtext( (octstr_get_char(input, i) & 0xF0) >> 4));
02474 octstr_append_char(out, at2_numtext( (octstr_get_char(input, i) & 0x0F)));
02475 }
02476 return out;
02477 }
|
Here is the call graph for this function:

|
|
Definition at line 2856 of file smsc_at.c. Referenced by at2_wait_modem_command(). 02857 {
02858 switch (code) {
02859 case 8:
02860 return "Operator determined barring";
02861 case 10:
02862 return "Call barred";
02863 case 21:
02864 return "Short message transfer rejected";
02865 case 27:
02866 return "Destination out of service";
02867 case 28:
02868 return "Unidentified subscriber";
02869 case 29:
02870 return "Facility rejected";
02871 case 30:
02872 return "Unknown subscriber";
02873 case 38:
02874 return "Network out of order";
02875 case 41:
02876 return "Temporary failure";
02877 case 42:
02878 return "Congestion";
02879 case 47:
02880 return "Resources unavailable, unspecified";
02881 case 50:
02882 return "Requested facility not subscribed";
02883 case 69:
02884 return "Requested facility not implemented";
02885 case 81:
02886 return "Invalid short message transfer reference value";
02887 case 95:
02888 return "Invalid message, unspecified";
02889 case 96:
02890 return "Invalid mandatory information";
02891 case 97:
02892 return "Message type non-existent or not implemented";
02893 case 98:
02894 return "Message not compatible with short message protocol state";
02895 case 99:
02896 return "Information element non-existent or not implemented";
02897 case 111:
02898 return "Protocol error, unspecified";
02899 case 127:
02900 return "Interworking, unspecified";
02901 case 128:
02902 return "Telematic interworking not supported";
02903 case 129:
02904 return "Short message Type 0 not supported";
02905 case 130:
02906 return "Cannot replace short message";
02907 case 143:
02908 return "Unspecified TP-PID error";
02909 case 144:
02910 return "Data coding scheme (alphabet not supported";
02911 case 145:
02912 return "Message class not supported";
02913 case 159:
02914 return "Unspecified TP-DCS error";
02915 case 160:
02916 return "Command cannot be actioned";
02917 case 161:
02918 return "Command unsupported";
02919 case 175:
02920 return "Unspecified TP-Command error";
02921 case 176:
02922 return "TPDU not supported";
02923 case 192:
02924 return "SC busy";
02925 case 193:
02926 return "No SC subscription";
02927 case 194:
02928 return "SC system failure";
02929 case 195:
02930 return "Invalid SME address";
02931 case 196:
02932 return "Destination SME barred";
02933 case 197:
02934 return "SM Rejected-Duplicate SM";
02935 case 198:
02936 return "TP-VPF not supported";
02937 case 199:
02938 return "TP-VP not supported";
02939 case 208:
02940 return "D0 SIM SMS storage full";
02941 case 209:
02942 return "No SMS storage capability in SIM";
02943 case 210:
02944 return "Error in MS";
02945 case 211:
02946 return "D0 SIM SMS storage full";
02947 case 212:
02948 return "SIM Application Toolkit Busy";
02949 case 213:
02950 return "SIM data download error";
02951 case 255:
02952 return "Unspecified error cause";
02953 case 300:
02954 return "ME failure";
02955 case 301:
02956 return "SMS service of ME reserved";
02957 case 302:
02958 return "Operation not allowed";
02959 case 303:
02960 return "Operation not supported";
02961 case 304:
02962 return "Invalid PDU mode parameter";
02963 case 305:
02964 return "Invalid text mode parameter";
02965 case 310:
02966 return "SIM not inserted";
02967 case 311:
02968 return "SIM PIN required";
02969 case 312:
02970 return "PH-SIM PIN required";
02971 case 313:
02972 return "SIM failure";
02973 case 314:
02974 return "SIM busy";
02975 case 315:
02976 return "SIM wrong";
02977 case 316:
02978 return "SIM PUK required";
02979 case 317:
02980 return "SIM PIN2 required";
02981 case 318:
02982 return "SIM PUK2 required";
02983 case 320:
02984 return "Memory failure";
02985 case 321:
02986 return "Invalid memory index -> don't worry, just memory fragmentation.";
02987 case 322:
02988 return "Memory full";
02989 case 330:
02990 return "SMSC address unknown";
02991 case 331:
02992 return "No network service";
02993 case 332:
02994 return "Network timeout";
02995 case 340:
02996 return "NO +CNMA ACK EXPECTED";
02997 case 500:
02998 return "Unknown error. -> maybe Sim storage is full? I'll have a look at it.";
02999 case 512:
03000 return "User abort";
03001 default:
03002 return "Error number unknown. Ask google and add it.";
03003 }
03004 }
|
|
|
Definition at line 548 of file smsc_at.c. References at2_read_buffer(), PrivAT2data::ilb, octstr_create, and octstr_destroy(). 00549 {
00550 at2_read_buffer(privdata);
00551 octstr_destroy(privdata->ilb);
00552 privdata->ilb = octstr_create("");
00553 }
|
Here is the call graph for this function:

|
|
Definition at line 2788 of file smsc_at.c. References O_DESTROY, octstr_append_char(), octstr_create, octstr_delete(), octstr_duplicate, octstr_get_char(), octstr_get_cstr, octstr_len(), octstr_strip_blanks(), and PNT_INTER. 02789 {
02790 int ntype = PNT_UNKNOWN;
02791 Octstr *out = octstr_create("");
02792 Octstr *temp = octstr_duplicate(msisdn);
02793
02794 octstr_strip_blanks(temp);
02795 /*
02796 * Check for international numbers
02797 * number starting with '+' or '00' are international,
02798 * others are national.
02799 */
02800 if (strncmp(octstr_get_cstr(msisdn), "+", 1) == 0) {
02801 octstr_delete(temp, 0, 1);
02802 ntype = PNT_INTER; /* international */
02803 } else if (strncmp(octstr_get_cstr(msisdn), "00", 2) == 0) {
02804 octstr_delete(temp, 0, 2);
02805 ntype = PNT_INTER; /* international */
02806 }
02807
02808 /* address length */
02809 octstr_append_char(out, octstr_len(temp));
02810
02811 /* Type of address : bit mapped values */
02812 octstr_append_char(out, 0x80 /* Type-of-address prefix */ |
02813 0x01 /* Numbering-plan: MSISDN */ |
02814 (ntype == PNT_INTER ? 0x10 : 0x00) /* Type-of-number: International or National */
02815 );
02816
02817 /* grab the digits from the MSISDN and encode as swapped semi-octets */
02818 while (out != NULL && octstr_len(temp) > 0) {
02819 int digit1, digit2;
02820 /* get the first two digit */
02821 digit1 = octstr_get_char(temp,0) - 48;
02822 digit2 = octstr_get_char(temp,1) - '0';
02823 if (digit2 < 0)
02824 digit2 = 0x0F;
02825 if(digit1 >= 0 && digit1 < 16 && digit2 < 16) {
02826 octstr_append_char(out, (digit2 << 4) | digit1);
02827 }
02828 else {
02829 O_DESTROY(out);
02830 out = NULL;
02831 }
02832 octstr_delete(temp, 0, 2);
02833 }
02834
02835 O_DESTROY(temp);
02836 return out;
02837 }
|
Here is the call graph for this function:

|
|
Definition at line 1757 of file smsc_at.c. 01758 {
01759 hexc = toupper(hexc) - 48;
01760 return (hexc > 9) ? hexc - 7 : hexc;
01761 }
|
|
|
Definition at line 556 of file smsc_at.c. References at2_flush_buffer(), at2_send_modem_command(), at2_set_message_storage(), at2_set_speed(), at2_wait_modem_command(), ModemDef::enable_hwhs, error(), gwlist_destroy(), gwlist_search(), gwthread_sleep(), info(), ModemDef::init_string, PrivAT2data::lines, ModemDef::message_storage, PrivAT2data::modem, PrivAT2data::name, ModemDef::no_pin, octstr_append(), octstr_append_char(), octstr_create, octstr_delete(), octstr_destroy(), octstr_destroy_item(), octstr_format(), octstr_get_cstr, octstr_imm(), octstr_item_match(), octstr_len(), octstr_search_char(), octstr_split(), octstr_truncate(), PrivAT2data::phase2plus, PrivAT2data::pin, PrivAT2data::pin_ready, PrivAT2data::sms_center, PrivAT2data::sms_memory_poll_interval, and PrivAT2data::speed. 00557 {
00558 int ret;
00559 Octstr *setpin;
00560
00561 info(0, "AT2[%s]: init device", octstr_get_cstr(privdata->name));
00562
00563 at2_set_speed(privdata, privdata->speed);
00564 /* sleep 10 ms in order to get device some time to accept speed */
00565 gwthread_sleep(0.10);
00566
00567 /* reset the modem */
00568 if (at2_send_modem_command(privdata, "ATZ", 0, 0) == -1) {
00569 error(0, "AT2[%s]: Wrong or no answer to ATZ, ignoring",
00570 octstr_get_cstr(privdata->name));
00571 }
00572
00573 /* check if the modem responded */
00574 if (at2_send_modem_command(privdata, "AT", 0, 0) == -1) {
00575 error(0, "AT2[%s]: Wrong or no answer to AT. Trying again",
00576 octstr_get_cstr(privdata->name));
00577 if (at2_send_modem_command(privdata, "AT", 0, 0) == -1) {
00578 error(0, "AT2[%s]: Second attempt to send AT failed",
00579 octstr_get_cstr(privdata->name));
00580 return -1;
00581 }
00582 }
00583
00584 at2_flush_buffer(privdata);
00585
00586 if (at2_send_modem_command(privdata, "AT&F", 7, 0) == -1) {
00587 error(0, "AT2[%s]: No answer to AT&F. Trying again",
00588 octstr_get_cstr(privdata->name));
00589 if (at2_send_modem_command(privdata, "AT&F", 7, 0) == -1) {
00590 return -1;
00591 }
00592 }
00593
00594 at2_flush_buffer(privdata);
00595
00596 /* check if the modem responded */
00597 if (at2_send_modem_command(privdata, "ATE0", 0, 0) == -1) {
00598 error(0, "AT2[%s]: Wrong or no answer to ATE0. Trying again",
00599 octstr_get_cstr(privdata->name));
00600 if (at2_send_modem_command(privdata, "ATE0", 0, 0) == -1) {
00601 error(0, "AT2[%s]: Second attempt to send ATE0 failed",
00602 octstr_get_cstr(privdata->name));
00603 return -1;
00604 }
00605 }
00606
00607 at2_flush_buffer(privdata);
00608
00609
00610 /* enable hardware handshake */
00611 if (octstr_len(privdata->modem->enable_hwhs)) {
00612 if (at2_send_modem_command(privdata,
00613 octstr_get_cstr(privdata->modem->enable_hwhs), 0, 0) == -1)
00614 info(0, "AT2[%s]: cannot enable hardware handshake",
00615 octstr_get_cstr(privdata->name));
00616 }
00617
00618 /*
00619 * Check does the modem require a PIN and, if so, send it.
00620 * This is not supported by the Nokia Premicell
00621 */
00622 if (!privdata->modem->no_pin) {
00623 ret = at2_send_modem_command(privdata, "AT+CPIN?", 10, 0);
00624
00625 if (!privdata->pin_ready) {
00626 if (ret == 2) {
00627 if (privdata->pin == NULL)
00628 return -1;
00629 setpin = octstr_format("AT+CPIN=\"%s\"", octstr_get_cstr(privdata->pin));
00630 ret = at2_send_modem_command(privdata, octstr_get_cstr(setpin), 0, 0);
00631 octstr_destroy(setpin);
00632 if (ret != 0 )
00633 return -1;
00634 } else if (ret == -1)
00635 return -1;
00636 }
00637
00638 /*
00639 * we have to wait until +CPIN: READY appears before issuing
00640 * the next command. 10 sec should be suficient
00641 */
00642 if (!privdata->pin_ready) {
00643 at2_wait_modem_command(privdata, 10, 0, NULL);
00644 if (!privdata->pin_ready) {
00645 at2_send_modem_command(privdata, "AT+CPIN?", 10, 0);
00646 if (!privdata->pin_ready) {
00647 return -1; /* give up */
00648 }
00649 }
00650 }
00651 }
00652 /*
00653 * Set the GSM SMS message center address if supplied
00654 */
00655 if (octstr_len(privdata->sms_center)) {
00656 Octstr *temp;
00657 temp = octstr_create("AT+CSCA=");
00658 octstr_append_char(temp, 34);
00659 octstr_append(temp, privdata->sms_center);
00660 octstr_append_char(temp, 34);
00661 /*
00662 * XXX If some modem don't process the +, remove it and add ",145"
00663 * and ",129" to national numbers
00664 */
00665 ret = at2_send_modem_command(privdata, octstr_get_cstr(temp), 0, 0);
00666 octstr_destroy(temp);
00667 if (ret == -1)
00668 return -1;
00669 if (ret > 0) {
00670 info(0, "AT2[%s]: Cannot set SMS message center, continuing",
00671 octstr_get_cstr(privdata->name));
00672 }
00673 }
00674
00675 /* Set the modem to PDU mode and autodisplay of new messages */
00676 ret = at2_send_modem_command(privdata, "AT+CMGF=0", 0, 0);
00677 if (ret != 0 )
00678 return -1;
00679
00680 /* lets see if it supports GSM SMS 2+ mode */
00681 ret = at2_send_modem_command(privdata, "AT+CSMS=?", 0, 0);
00682 if (ret != 0) {
00683 /* if it doesnt even understand the command, I'm sure it wont support it */
00684 privdata->phase2plus = 0;
00685 } else {
00686 /* we have to take a part a string like +CSMS: (0,1,128) */
00687 Octstr *ts;
00688 int i;
00689 List *vals;
00690
00691 ts = privdata->lines;
00692 privdata->lines = NULL;
00693
00694 i = octstr_search_char(ts, '(', 0);
00695 if (i > 0) {
00696 octstr_delete(ts, 0, i + 1);
00697 }
00698 i = octstr_search_char(ts, ')', 0);
00699 if (i > 0) {
00700 octstr_truncate(ts, i);
00701 }
00702 vals = octstr_split(ts, octstr_imm(","));
00703 octstr_destroy(ts);
00704 ts = gwlist_search(vals, octstr_imm("1"), (void*) octstr_item_match);
00705 if (ts)
00706 privdata->phase2plus = 1;
00707 gwlist_destroy(vals, octstr_destroy_item);
00708 }
00709 if (privdata->phase2plus) {
00710 info(0, "AT2[%s]: Phase 2+ is supported", octstr_get_cstr(privdata->name));
00711 ret = at2_send_modem_command(privdata, "AT+CSMS=1", 0, 0);
00712 if (ret != 0)
00713 return -1;
00714 }
00715
00716 /* send init string */
00717 ret = at2_send_modem_command(privdata, octstr_get_cstr(privdata->modem->init_string), 0, 0);
00718 if (ret != 0)
00719 return -1;
00720
00721 if (privdata->sms_memory_poll_interval && privdata->modem->message_storage) {
00722 /* set message storage location for "SIM buffering" using the CPMS command */
00723 if (at2_set_message_storage(privdata, privdata->modem->message_storage) != 0)
00724 return -1;
00725 }
00726
00727 info(0, "AT2[%s]: AT SMSC successfully opened.", octstr_get_cstr(privdata->name));
00728 return 0;
00729 }
|
Here is the call graph for this function:

|
|
Definition at line 201 of file smsc_at.c. References at2_read_buffer(), at2_send_modem_command(), at2_wait_modem_command(), gwthread_sleep(), info(), PrivAT2data::name, octstr_get_cstr, octstr_len(), PrivAT2data::password, and PrivAT2data::username. Referenced by at2_device_thread(). 00202 {
00203 info(0, "AT2[%s]: Logging in", octstr_get_cstr(privdata->name));
00204
00205 at2_read_buffer(privdata);
00206 gwthread_sleep(0.5);
00207 at2_read_buffer(privdata);
00208
00209 if((octstr_len(privdata->username) == 0 ) && (octstr_len(privdata->password)> 0)) {
00210 at2_wait_modem_command(privdata, 10, 3, NULL); /* wait for Password: prompt */
00211 at2_send_modem_command(privdata, octstr_get_cstr(privdata->password), 2,0); /* wait for OK: */
00212 at2_send_modem_command(privdata, "AT", 2,0); /* wait for OK: */
00213 }
00214 else if((octstr_len(privdata->username) > 0 ) && (octstr_len(privdata->password)> 0)) {
00215 at2_wait_modem_command(privdata, 10, 2, NULL); /* wait for Login: prompt */
00216 at2_send_modem_command(privdata, octstr_get_cstr(privdata->username), 10,3); /* wait fo Password: */
00217 at2_send_modem_command(privdata, octstr_get_cstr(privdata->password), 2,0); /* wait for OK: */
00218 at2_send_modem_command(privdata, "AT", 2,0); /* wait for OK: */
00219 }
00220
00221 return 0;
00222 }
|
Here is the call graph for this function:

|
|
Definition at line 2480 of file smsc_at.c. 02481 {
02482 return (num > 9) ? (num + 55) : (num + 48);
02483 }
|
|
|
Definition at line 225 of file smsc_at.c. References at2_open_device1(), debug(), error(), PrivAT2data::fd, PrivAT2data::is_serial, kannel_cfmakeraw(), PrivAT2data::modem, PrivAT2data::name, ModemDef::need_sleep, and octstr_get_cstr. 00226 {
00227 struct termios tios;
00228 int ret;
00229
00230 if ((ret = at2_open_device1(privdata)) != 0)
00231 return ret;
00232
00233 if (!privdata->is_serial)
00234 return 0;
00235
00236 tcgetattr(privdata->fd, &tios);
00237
00238 kannel_cfmakeraw(&tios);
00239
00240 tios.c_iflag |= IGNBRK; /* ignore break & parity errors */
00241 tios.c_iflag &= ~INPCK; /* INPCK: disable parity check */
00242 tios.c_cflag |= HUPCL; /* hangup on close */
00243 tios.c_cflag |= CREAD; /* enable receiver */
00244 tios.c_cflag |= CLOCAL; /* Ignore modem control lines */
00245 tios.c_cflag &= ~CSIZE; /* set to 8 bit */
00246 tios.c_cflag |= CS8;
00247 tios.c_oflag &= ~ONLCR; /* no NL to CR-NL mapping outgoing */
00248 tios.c_iflag |= IGNPAR; /* ignore parity */
00249 tios.c_iflag &= ~INPCK;
00250 #if defined(CRTSCTS)
00251 tios.c_cflag |= CRTSCTS; /* enable hardware flow control */
00252 #endif
00253 tios.c_cc[VSUSP] = 0; /* otherwhise we can not send CTRL Z */
00254
00255 /*
00256 if ( ModemTypes[privdata->modemid].enable_parity )
00257 tios.c_cflag ^= PARODD;
00258 */
00259
00260 ret = tcsetattr(privdata->fd, TCSANOW, &tios); /* apply changes now */
00261 if (ret == -1) {
00262 error(errno, "AT2[%s]: at_data_link: fail to set termios attribute",
00263 octstr_get_cstr(privdata->name));
00264 }
00265 tcflush(privdata->fd, TCIOFLUSH);
00266
00267 /*
00268 * Nokia 7110 and 6210 need some time between opening
00269 * the connection and sending the first AT commands
00270 */
00271 if (privdata->modem == NULL || privdata->modem->need_sleep)
00272 sleep(1);
00273 debug("bb.smsc.at2", 0, "AT2[%s]: device opened", octstr_get_cstr(privdata->name));
00274 return 0;
00275 }
|
Here is the call graph for this function:

|
|
Definition at line 163 of file smsc_at.c. References at2_close_device(), debug(), PrivAT2data::device, error(), PrivAT2data::fd, gw_assert, info(), PrivAT2data::is_serial, PrivAT2data::name, octstr_get_cstr, octstr_str_compare(), PrivAT2data::rawtcp_host, PrivAT2data::rawtcp_port, tcpip_connect_to_server(), PrivAT2data::use_telnet, and warning(). Referenced by at2_open_device(). 00164 {
00165 info(0, "AT2[%s]: opening device", octstr_get_cstr(privdata->name));
00166 if (privdata->fd > 0) {
00167 warning(0, "AT2[%s]: trying to open device with not closed device!!! Please report!!!",
00168 octstr_get_cstr(privdata->name));
00169 at2_close_device(privdata);
00170 }
00171 if (privdata->is_serial) {
00172 privdata->fd = open(octstr_get_cstr(privdata->device),
00173 O_RDWR | O_NONBLOCK | O_NOCTTY);
00174 privdata->use_telnet = 0;
00175 } else {
00176 if (octstr_str_compare(privdata->device, "rawtcp") == 0) {
00177 privdata->use_telnet = 0;
00178 privdata->fd = tcpip_connect_to_server(octstr_get_cstr(privdata->rawtcp_host),
00179 privdata->rawtcp_port, NULL);
00180 }
00181 else if (octstr_str_compare(privdata->device, "telnet") == 0) {
00182 privdata->use_telnet = 1;
00183 privdata->fd = tcpip_connect_to_server(octstr_get_cstr(privdata->rawtcp_host),
00184 privdata->rawtcp_port, NULL);
00185
00186 } else {
00187 gw_assert(0);
00188 }
00189 }
00190 if (privdata->fd == -1) {
00191 error(errno, "AT2[%s]: open failed! ERRNO=%d", octstr_get_cstr(privdata->name), errno);
00192 privdata->fd = -1;
00193 return -1;
00194 }
00195 debug("bb.smsc.at2", 0, "AT2[%s]: device opened. Telnet mode = %d", octstr_get_cstr(privdata->name),privdata->use_telnet);
00196
00197 return 0;
00198 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 1764 of file smsc_at.c. References at2_pdu_decode_deliver_sm(), at2_pdu_decode_report_sm(), AT_DELIVER_SM, AT_STATUS_REPORT_SM, data, octstr_get_char(), and type. 01765 {
01766 int type;
01767 Msg *msg = NULL;
01768
01769 /* Get the PDU type */
01770 type = octstr_get_char(data, 1) & 3;
01771
01772 switch (type) {
01773
01774 case AT_DELIVER_SM:
01775 msg = at2_pdu_decode_deliver_sm(data, privdata);
01776 break;
01777 case AT_STATUS_REPORT_SM:
01778 msg = at2_pdu_decode_report_sm(data, privdata);
01779 break;
01780
01781 /* Add other message types here: */
01782 }
01783
01784 return msg;
01785 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 1788 of file smsc_at.c. References at2_convertpdu(), at2_decode7bituncompressed(), data, date_convert_universal(), universaltime::day, DC_8BIT, dcs_to_fields(), debug(), error(), universaltime::hour, message, universaltime::minute, universaltime::month, msg_create, PrivAT2data::my_number, PrivAT2data::name, O_DESTROY, octstr_append_char(), octstr_copy, octstr_create, octstr_create_from_data, octstr_destroy(), octstr_duplicate, octstr_get_char(), octstr_get_cstr, octstr_len(), pdu, universaltime::second, sms, swap_nibbles(), text, and universaltime::year. 01789 {
01790 int len, pos, i, ntype;
01791 int udhi, dcs, udhlen, pid;
01792 Octstr *origin = NULL;
01793 Octstr *udh = NULL;
01794 Octstr *text = NULL, *tmpstr;
01795 Octstr *pdu = NULL;
01796 Msg *message = NULL;
01797 struct universaltime mtime; /* time structure */
01798 long stime; /* time in seconds */
01799 int timezone; /* timezone in 15 minutes jumps from GMT */
01800
01801 /*
01802 * Note: some parts of the PDU are not decoded because they are
01803 * not needed for the Msg type.
01804 */
01805
01806 /* convert the pdu to binary format for ease of processing */
01807 pdu = at2_convertpdu(data);
01808
01809 /* UDH Indicator */
01810 udhi = (octstr_get_char(pdu, 0) & 64) >> 6;
01811
01812 /* originating address */
01813 len = octstr_get_char(pdu, 1);
01814 if (len > 20) /* maximum valid number of semi-octets in Address-Value field */
01815 goto msg_error;
01816 ntype = octstr_get_char(pdu, 2);
01817
01818 pos = 3;
01819 if ((ntype & 0xD0) == 0xD0) {
01820 /* Alphanumeric sender */
01821 origin = octstr_create("");
01822 tmpstr = octstr_copy(pdu, 3, len);
01823 at2_decode7bituncompressed(tmpstr, (((len - 1) * 4 - 3) / 7) + 1, origin, 0);
01824 octstr_destroy(tmpstr);
01825 debug("bb.smsc.at2", 0, "AT2[%s]: Alphanumeric sender <%s>",
01826 octstr_get_cstr(privdata->name), octstr_get_cstr(origin));
01827 pos += (len + 1) / 2;
01828 } else {
01829 origin = octstr_create("");
01830 if ((ntype & 0x90) == 0x90) {
01831 /* International number */
01832 octstr_append_char(origin, '+');
01833 }
01834 for (i = 0; i < len; i += 2, pos++) {
01835 octstr_append_char(origin, (octstr_get_char(pdu, pos) & 15) + 48);
01836 if (i + 1 < len)
01837 octstr_append_char(origin, (octstr_get_char(pdu, pos) >> 4) + 48);
01838 }
01839 debug("bb.smsc.at2", 0, "AT2[%s]: Numeric sender %s <%s>",
01840 octstr_get_cstr(privdata->name), ((ntype & 0x90) == 0x90 ? "(international)" : ""),
01841 octstr_get_cstr(origin));
01842 }
01843
01844 if (pos > octstr_len(pdu))
01845 goto msg_error;
01846
01847 /* PID */
01848 pid = octstr_get_char(pdu, pos);
01849 pos++;
01850
01851 /* DCS */
01852 dcs = octstr_get_char(pdu, pos);
01853 pos++;
01854
01855 /* get the timestamp */
01856 mtime.year = swap_nibbles(octstr_get_char(pdu, pos));
01857 pos++;
01858 mtime.year += (mtime.year < 70 ? 2000 : 1900);
01859 mtime.month = swap_nibbles(octstr_get_char(pdu, pos));
01860 mtime.month--;
01861 pos++;
01862 mtime.day = swap_nibbles(octstr_get_char(pdu, pos));
01863 pos++;
01864 mtime.hour = swap_nibbles(octstr_get_char(pdu, pos));
01865 pos++;
01866 mtime.minute = swap_nibbles(octstr_get_char(pdu, pos));
01867 pos++;
01868 mtime.second = swap_nibbles(octstr_get_char(pdu, pos));
01869 pos++;
01870
01871 /*
01872 * time zone:
01873 *
01874 * time zone is "swapped nibble", with the MSB as the sign (1 is negative).
01875 */
01876 timezone = swap_nibbles(octstr_get_char(pdu, pos));
01877 pos++;
01878 timezone = ((timezone >> 7) ? -1 : 1) * (timezone & 127);
01879 /*
01880 * Ok, that was the time zone as read from the PDU. Now how to interpert it?
01881 * All the handsets I tested send the timestamp of their local time and the
01882 * timezone as GMT+0. I assume that the timestamp is the handset's local time,
01883 * so we need to apply the timezone in reverse to get GM time:
01884 */
01885
01886 /*
01887 * time in PDU is handset's local time and timezone is handset's time zone
01888 * difference from GMT
01889 */
01890 mtime.hour -= timezone / 4;
01891 mtime.minute -= 15 * (timezone % 4);
01892
01893 stime = date_convert_universal(&mtime);
01894
01895 /* get data length
01896 * XXX: Is it allowed to have length = 0 ??? (alex)
01897 */
01898 len = octstr_get_char(pdu, pos);
01899 pos++;
01900
01901 debug("bb.smsc.at2", 0, "AT2[%s]: User data length read as (%d)",
01902 octstr_get_cstr(privdata->name), len);
01903
01904 /* if there is a UDH */
01905 udhlen = 0;
01906 if (udhi && len > 0) {
01907 udhlen = octstr_get_char(pdu, pos);
01908 pos++;
01909 if (udhlen + 1 > len)
01910 goto msg_error;
01911 udh = octstr_copy(pdu, pos-1, udhlen+1);
01912 pos += udhlen;
01913 len -= udhlen + 1;
01914 } else if (len <= 0) /* len < 0 is impossible, but sure is sure */
01915 udhi = 0;
01916
01917 debug("bb.smsc.at2", 0, "AT2[%s]: Udh decoding done len=%d udhi=%d udhlen=%d udh='%s'",
01918 octstr_get_cstr(privdata->name), len, udhi, udhlen, (udh ? octstr_get_cstr(udh) : ""));
01919
01920 if (pos > octstr_len(pdu) || len < 0)
01921 goto msg_error;
01922
01923 /* build the message */
01924 message = msg_create(sms);
01925 if (!dcs_to_fields(&message, dcs)) {
01926 /* XXX Should reject this message? */
01927 debug("bb.smsc.at2", 0, "AT2[%s]: Invalid DCS", octstr_get_cstr(privdata->name));
01928 dcs_to_fields(&message, 0);
01929 }
01930
01931 message->sms.pid = pid;
01932
01933 /* deal with the user data -- 7 or 8 bit encoded */
01934 tmpstr = octstr_copy(pdu, pos, len);
01935 if (message->sms.coding == DC_8BIT || message->sms.coding == DC_UCS2) {
01936 text = octstr_duplicate(tmpstr);
01937 } else {
01938 int offset = 0;
01939 text = octstr_create("");
01940 if (udhi && message->sms.coding == DC_7BIT) {
01941 int nbits;
01942 nbits = (udhlen + 1) * 8;
01943 /* fill bits for UDH to septet boundary */
01944 offset = (((nbits / 7) + 1) * 7 - nbits) % 7;
01945 }
01946 at2_decode7bituncompressed(tmpstr, len, text, offset);
01947 }
01948
01949 message->sms.sender = origin;
01950 if (octstr_len(privdata->my_number)) {
01951 message->sms.receiver = octstr_duplicate(privdata->my_number);
01952 } else {
01953 /* Put a dummy address in the receiver for now (SMSC requires one) */
01954 message->sms.receiver = octstr_create_from_data("1234", 4);
01955 }
01956 if (udhi) {
01957 message->sms.udhdata = udh;
01958 }
01959 message->sms.msgdata = text;
01960 message->sms.time = stime;
01961
01962 /* cleanup */
01963 octstr_destroy(pdu);
01964 octstr_destroy(tmpstr);
01965
01966 return message;
01967
01968 msg_error:
01969 error(1, "AT2[%s]: Invalid DELIVER-SMS pdu!", octstr_get_cstr(privdata->name));
01970 O_DESTROY(udh);
01971 O_DESTROY(origin);
01972 O_DESTROY(text);
01973 O_DESTROY(pdu);
01974 return NULL;
01975 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 1978 of file smsc_at.c. References at2_convertpdu(), at2_decode7bituncompressed(), PrivAT2data::conn, data, debug(), dlr_find(), error(), smscconn::id, PrivAT2data::name, O_DESTROY, octstr_append_char(), octstr_copy, octstr_create, octstr_destroy(), octstr_duplicate, octstr_format(), octstr_get_char(), octstr_get_cstr, pdu, and type. 01979 {
01980 Msg *dlrmsg = NULL;
01981 Octstr *pdu, *msg_id, *tmpstr = NULL, *receiver = NULL;
01982 int type, tp_mr, len, ntype, pos;
01983
01984 /*
01985 * parse the PDU.
01986 */
01987
01988 /* convert the pdu to binary format for ease of processing */
01989 pdu = at2_convertpdu(data);
01990
01991 /* Message reference */
01992 tp_mr = octstr_get_char(pdu, 1);
01993 msg_id = octstr_format("%d", tp_mr);
01994 debug("bb.smsc.at2", 0, "AT2[%s]: got STATUS-REPORT for message <%d>:",
01995 octstr_get_cstr(privdata->name), tp_mr);
01996
01997 /* reciver address */
01998 len = octstr_get_char(pdu, 2);
01999 ntype = octstr_get_char(pdu, 3);
02000
02001 pos = 4;
02002 if ((ntype & 0xD0) == 0xD0) {
02003 /* Alphanumeric sender */
02004 receiver = octstr_create("");
02005 tmpstr = octstr_copy(pdu, pos, (len + 1) / 2);
02006 at2_decode7bituncompressed(tmpstr, (((len - 1) * 4 - 3) / 7) + 1, receiver, 0);
02007 octstr_destroy(tmpstr);
02008 debug("bb.smsc.at2", 0, "AT2[%s]: Alphanumeric receiver <%s>",
02009 octstr_get_cstr(privdata->name), octstr_get_cstr(receiver));
02010 pos += (len + 1) / 2;
02011 } else {
02012 int i;
02013 receiver = octstr_create("");
02014 if ((ntype & 0x90) == 0x90) {
02015 /* International number */
02016 octstr_append_char(receiver, '+');
02017 }
02018 for (i = 0; i < len; i += 2, pos++) {
02019 octstr_append_char(receiver, (octstr_get_char(pdu, pos) & 15) + 48);
02020 if (i + 1 < len)
02021 octstr_append_char(receiver, (octstr_get_char(pdu, pos) >> 4) + 48);
02022 }
02023 debug("bb.smsc.at2", 0, "AT2[%s]: Numeric receiver %s <%s>",
02024 octstr_get_cstr(privdata->name), ((ntype & 0x90) == 0x90 ? "(international)" : ""),
02025 octstr_get_cstr(receiver));
02026 }
02027
02028 pos += 14; /* skip time stamps for now */
02029
02030 if ((type = octstr_get_char(pdu, pos)) == -1 ) {
02031 error(1, "AT2[%s]: STATUS-REPORT pdu too short to have TP-Status field !",
02032 octstr_get_cstr(privdata->name));
02033 goto error;
02034 }
02035
02036 /* Check DLR type:
02037 * 3GPP TS 23.040 defines this a bit mapped field with lots of options
02038 * most of which are not really intersting to us, as we are only interested
02039 * in one of three conditions : failed, held in SC for delivery later, or delivered successfuly
02040 * and here's how I suggest to test it (read the 3GPP reference for further detailes) -
02041 * we'll test the 6th and 5th bits (7th bit when set making all other values 'reseved' so I want to test it).
02042 */
02043 type = type & 0xE0; /* filter out everything but the 7th, 6th and 5th bits */
02044 switch (type) {
02045 case 0x00:
02046 /* 0 0 : success class */
02047 type = DLR_SUCCESS;
02048 tmpstr = octstr_create("Success");
02049 break;
02050 case 0x20:
02051 /* 0 1 : buffered class (temporary error) */
02052 type = DLR_BUFFERED;
02053 tmpstr = octstr_create("Buffered");
02054 break;
02055 case 0x40:
02056 case 0x60:
02057 default:
02058 /* 1 0 : failed class */
02059 /* 1 1 : failed class (actually, temporary error but timed out) */
02060 /* and any other value (can't think of any) is considered failure */
02061 type = DLR_FAIL;
02062 tmpstr = octstr_create("Failed");
02063 break;
02064 }
02065 /* Actually, the above implementation is not correct, as the reference
02066 * says that implementations should consider any "reserved" values to be
02067 * "failure", but most reserved values fall into one of the three
02068 * categories. It will catch "reserved" values where the first 3 MSBits
02069 * are not set as "Success" which may not be correct. */
02070
02071 if ((dlrmsg = dlr_find(privdata->conn->id, msg_id, receiver, type)) == NULL) {
02072 debug("bb.smsc.at2", 1, "AT2[%s]: Received delivery notification but can't find that ID in the DLR storage",
02073 octstr_get_cstr(privdata->name));
02074 goto error;
02075 }
02076
02077 /* Beware DLR URL is now in msg->sms.dlr_url given by dlr_find() */
02078 dlrmsg->sms.msgdata = octstr_duplicate(tmpstr);
02079
02080 error:
02081 O_DESTROY(tmpstr);
02082 O_DESTROY(pdu);
02083 O_DESTROY(receiver);
02084 O_DESTROY(msg_id);
02085 return dlrmsg;
02086 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 2281 of file smsc_at.c. References smscconn::alt_dcs, at2_encode7bituncompressed(), at2_encode8bituncompressed(), at2_format_address_field(), charset_utf8_to_gsm(), PrivAT2data::conn, DC_8BIT, debug(), DLR_IS_ENABLED_DEVICE, error(), fields_to_dcs(), PrivAT2data::name, O_DESTROY, octstr_append(), octstr_append_char(), octstr_create, octstr_delete(), octstr_get_cstr, octstr_len(), pdu, SMS_7BIT_MAX_LEN, SMS_8BIT_MAX_LEN, sms_msgdata_len(), and PrivAT2data::validityperiod. 02282 {
02283 /*
02284 * Message coding is done as a binary octet string,
02285 * as per 3GPP TS 23.040 specification (GSM 03.40),
02286 */
02287 Octstr *pdu = NULL, *temp = NULL, *buffer = octstr_create("");
02288 int len, setvalidity = 0;
02289
02290 /*
02291 * message type SUBMIT , bit mapped :
02292 * bit7 .. bit0
02293 * TP-RP , TP-UDHI, TP-SRR, TP-VPF(4), TP-VPF(3), TP-RD, TP-MTI(1), TP-MTI(0)
02294 */
02295 octstr_append_char(buffer,
02296 ((msg->sms.rpi > 0 ? 1 : 0) << 7) /* TP-RP */
02297 | ((octstr_len(msg->sms.udhdata) ? 1 : 0) << 6) /* TP-UDHI */
02298 | ((DLR_IS_ENABLED_DEVICE(msg->sms.dlr_mask) ? 1 : 0) << 5) /* TP-SRR */
02299 | 16 /* TP-VP(Rel)*/
02300 | 1 /* TP-MTI: SUBMIT_SM */
02301 );
02302
02303 /* message reference (0 for now) */
02304 octstr_append_char(buffer, 0);
02305
02306 /* destination address */
02307 if ((temp = at2_format_address_field(msg->sms.receiver)) == NULL)
02308 goto error;
02309 octstr_append(buffer, temp);
02310 O_DESTROY(temp);
02311
02312 octstr_append_char(buffer, (msg->sms.pid == -1 ? 0 : msg->sms.pid) ); /* protocol identifier */
02313 octstr_append_char(buffer, fields_to_dcs(msg, /* data coding scheme */
02314 (msg->sms.alt_dcs != -1 ? msg->sms.alt_dcs : privdata->conn->alt_dcs)));
02315
02316 /*
02317 * Validity-Period (TP-VP)
02318 * see GSM 03.40 section 9.2.3.12
02319 * defaults to 24 hours = 167 if not set
02320 */
02321 if (msg->sms.validity >= 0) {
02322 if (msg->sms.validity > 635040)
02323 setvalidity = 255;
02324 if (msg->sms.validity >= 50400 && msg->sms.validity <= 635040)
02325 setvalidity = (msg->sms.validity - 1) / 7 / 24 / 60 + 192 + 1;
02326 if (msg->sms.validity > 43200 && msg->sms.validity < 50400)
02327 setvalidity = 197;
02328 if (msg->sms.validity >= 2880 && msg->sms.validity <= 43200)
02329 setvalidity = (msg->sms.validity - 1) / 24 / 60 + 166 + 1;
02330 if (msg->sms.validity > 1440 && msg->sms.validity < 2880)
02331 setvalidity = 168;
02332 if (msg->sms.validity >= 750 && msg->sms.validity <= 1440)
02333 setvalidity = (msg->sms.validity - 720 - 1) / 30 + 143 + 1;
02334 if (msg->sms.validity > 720 && msg->sms.validity < 750)
02335 setvalidity = 144;
02336 if (msg->sms.validity >= 5 && msg->sms.validity <= 720)
02337 setvalidity = (msg->sms.validity - 1) / 5 - 1 + 1;
02338 if (msg->sms.validity < 5)
02339 setvalidity = 0;
02340 } else
02341 setvalidity = (privdata->validityperiod != NULL ?
02342 atoi(octstr_get_cstr(privdata->validityperiod)) : 167);
02343
02344 if (setvalidity >= 0 && setvalidity <= 143)
02345 debug("bb.smsc.at2", 0, "AT2[%s]: TP-Validity-Period: %d minutes",
02346 octstr_get_cstr(privdata->name), (setvalidity + 1)*5);
02347 else if (setvalidity >= 144 && setvalidity <= 167)
02348 debug("bb.smsc.at2", 0, "AT2[%s]: TP-Validity-Period: %3.1f hours",
02349 octstr_get_cstr(privdata->name), ((float)(setvalidity - 143) / 2) + 12);
02350 else if (setvalidity >= 168 && setvalidity <= 196)
02351 debug("bb.smsc.at2", 0, "AT2[%s]: TP-Validity-Period: %d days",
02352 octstr_get_cstr(privdata->name), (setvalidity - 166));
02353 else
02354 debug("bb.smsc.at2", 0, "AT2[%s]: TP-Validity-Period: %d weeks",
02355 octstr_get_cstr(privdata->name), (setvalidity - 192));
02356 octstr_append_char(buffer, setvalidity);
02357
02358 /* user data length - include length of UDH if it exists */
02359 len = sms_msgdata_len(msg);
02360
02361 if (octstr_len(msg->sms.udhdata)) {
02362 if (msg->sms.coding == DC_8BIT || msg->sms.coding == DC_UCS2) {
02363 len += octstr_len(msg->sms.udhdata);
02364 if (len > SMS_8BIT_MAX_LEN) { /* truncate user data to allow UDH to fit */
02365 octstr_delete(msg->sms.msgdata, SMS_8BIT_MAX_LEN - octstr_len(msg->sms.udhdata), 9999);
02366 len = SMS_8BIT_MAX_LEN;
02367 }
02368 } else {
02369 /*
02370 * The reason we branch here is because UDH data length is determined
02371 * in septets if we are in GSM coding, otherwise it's in octets. Adding 6
02372 * will ensure that for an octet length of 0, we get septet length 0,
02373 * and for octet length 1 we get septet length 2.
02374 */
02375 int temp_len;
02376 len += (temp_len = (((8 * octstr_len(msg->sms.udhdata)) + 6) / 7));
02377 if (len > SMS_7BIT_MAX_LEN) { /* truncate user data to allow UDH to fit */
02378 octstr_delete(msg->sms.msgdata, SMS_7BIT_MAX_LEN - temp_len, 9999);
02379 len = SMS_7BIT_MAX_LEN;
02380 }
02381 }
02382 }
02383
02384 octstr_append_char(buffer,len);
02385
02386 if (octstr_len(msg->sms.udhdata)) /* udh */
02387 octstr_append(buffer, msg->sms.udhdata);
02388
02389 /* user data */
02390 if (msg->sms.coding == DC_8BIT || msg->sms.coding == DC_UCS2) {
02391 octstr_append(buffer, msg->sms.msgdata);
02392 } else {
02393 int offset = 0;
02394
02395 /*
02396 * calculate the number of fill bits needed to align
02397 * the 7bit encoded user data on septet boundry
02398 */
02399 if (octstr_len(msg->sms.udhdata)) { /* Have UDH */
02400 int nbits = octstr_len(msg->sms.udhdata) * 8; /* Includes UDH length byte */
02401 offset = (((nbits / 7) + 1) * 7 - nbits) % 7; /* Fill bits */
02402 }
02403
02404 charset_utf8_to_gsm(msg->sms.msgdata);
02405
02406 if ((temp = at2_encode7bituncompressed(msg->sms.msgdata, offset)) != NULL)
02407 octstr_append(buffer, temp);
02408 O_DESTROY(temp);
02409 }
02410
02411 /* convert PDU to HEX representation suitable for the AT2 command set */
02412 pdu = at2_encode8bituncompressed(buffer);
02413 O_DESTROY(buffer);
02414
02415 return pdu;
02416
02417 error:
02418 O_DESTROY(temp);
02419 O_DESTROY(buffer);
02420 O_DESTROY(pdu);
02421 return NULL;
02422 }
|
Here is the call graph for this function:

|
||||||||||||||||||||
|
Definition at line 1614 of file smsc_at.c. References at2_hexchar(), ModemDef::broken, debug(), gsm2number(), PrivAT2data::modem, PrivAT2data::name, ModemDef::no_smsc, octstr_append(), octstr_copy, octstr_create_from_data, octstr_destroy(), octstr_duplicate, octstr_get_char(), octstr_get_cstr, octstr_hex_to_binary(), octstr_imm(), octstr_len(), octstr_parse_long(), octstr_search(), octstr_truncate(), and pdu. 01615 {
01616 Octstr *buffer;
01617 long len = 0;
01618 int pos = 0;
01619 int tmp;
01620 Octstr *numtmp;
01621 Octstr *tmp2;
01622
01623 buffer = octstr_duplicate(line);
01624 /* find the beginning of a message from the modem*/
01625
01626 if ((pos = octstr_search(buffer, octstr_imm("+CDS:"), 0)) != -1)
01627 pos += 5;
01628 else {
01629 if ((pos = octstr_search(buffer, octstr_imm("+CMT:"), 0)) != -1)
01630 pos += 5;
01631 else if ((pos = octstr_search(buffer, octstr_imm("+CMGR:"), 0)) != -1) {
01632 /* skip status field in +CMGR response */
01633 if ((pos = octstr_search(buffer, octstr_imm(","), pos + 6)) != -1)
01634 pos++;
01635 else
01636 goto nomsg;
01637 } else
01638 goto nomsg;
01639
01640 /* skip the next comma in CMGR and CMT responses */
01641 tmp = octstr_search(buffer, octstr_imm(","), pos);
01642 if (!privdata->modem->broken && tmp == -1)
01643 goto nomsg;
01644 if (tmp != -1)
01645 pos = tmp + 1;
01646 }
01647
01648 /* read the message length */
01649 pos = octstr_parse_long(&len, buffer, pos, 10);
01650 if (pos == -1)
01651 goto nomsg;
01652
01653 /* skip the spaces and line return */
01654 while (isspace(octstr_get_char(buffer, pos)))
01655 pos++;
01656
01657 octstr_truncate(smsc_number,0);
01658
01659 /* skip the SMSC address on some modem types */
01660 if (!privdata->modem->no_smsc) {
01661 tmp = at2_hexchar(octstr_get_char(buffer, pos)) * 16
01662 + at2_hexchar(octstr_get_char(buffer, pos + 1));
01663 if (tmp < 0)
01664 goto nomsg;
01665
01666 numtmp = octstr_create_from_data(octstr_get_cstr(buffer)+pos+2,tmp * 2); /* we now have the hexchars of the SMSC in GSM encoding */
01667 octstr_hex_to_binary(numtmp);
01668 tmp2 = gsm2number(numtmp);
01669 debug("bb.smsc.at2", 0, "AT2[%s]: received message from SMSC: %s", octstr_get_cstr(privdata->name), octstr_get_cstr(tmp2));
01670 octstr_destroy(numtmp);
01671 octstr_append(smsc_number,tmp2);
01672 octstr_destroy(tmp2);
01673 pos += 2 + tmp * 2;
01674 }
01675
01676 /* check if the buffer is long enough to contain the full message */
01677 if (!privdata->modem->broken && octstr_len(buffer) < len * 2 + pos)
01678 goto nomsg;
01679
01680 if (privdata->modem->broken && octstr_len(buffer) < len * 2)
01681 goto nomsg;
01682
01683 /* copy the PDU then remove it from the input buffer*/
01684 *pdu = octstr_copy(buffer, pos, len * 2);
01685
01686 octstr_destroy(buffer);
01687 return 1;
01688
01689 nomsg:
01690 octstr_destroy(buffer);
01691 return 0;
01692 }
|
Here is the call graph for this function:

|
|
Definition at line 1424 of file smsc_at.c. References smscconn::data, gw_prioqueue_len(), smscconn::load, PrivAT2data::outgoing_queue, SMSCConn, and smscconn::status. 01425 {
01426 long ret;
01427 PrivAT2data *privdata = conn->data;
01428
01429 if (conn->status == SMSCCONN_DEAD) /* I'm dead, why would you care ? */
01430 return -1;
01431
01432 ret = gw_prioqueue_len(privdata->outgoing_queue);
01433
01434 /* use internal queue as load, maybe something else later */
01435 conn->load = ret;
01436 return ret;
01437 }
|
Here is the call graph for this function:

|
|
Definition at line 291 of file smsc_at.c. References at2_close_device(), at2_scan_for_telnet_escapes(), error(), PrivAT2data::fd, PrivAT2data::ilb, MAX_READ, PrivAT2data::name, octstr_append_data(), octstr_get_cstr, and PrivAT2data::use_telnet. 00292 {
00293 char buf[MAX_READ + 1];
00294 int ret;
00295 size_t count;
00296 signed int s;
00297 fd_set read_fd;
00298 struct timeval tv;
00299
00300 if (privdata->fd == -1) {
00301 error(errno, "AT2[%s]: at2_read_buffer: fd = -1. Can not read",
00302 octstr_get_cstr(privdata->name));
00303 return;
00304 }
00305 count = MAX_READ;
00306
00307 #ifdef SSIZE_MAX
00308 if (count > SSIZE_MAX)
00309 count = SSIZE_MAX;
00310 #endif
00311
00312 tv.tv_sec = 0;
00313 tv.tv_usec = 1000;
00314
00315 FD_ZERO(&read_fd);
00316 FD_SET(privdata->fd, &read_fd);
00317 ret = select(privdata->fd + 1, &read_fd, NULL, NULL, &tv);
00318 if (ret == -1) {
00319 if (!(errno == EINTR || errno == EAGAIN))
00320 error(errno, "AT2[%s]: error on select", octstr_get_cstr(privdata->name));
00321 return;
00322 }
00323
00324 if (ret == 0)
00325 return;
00326
00327 s = read(privdata->fd, buf, count);
00328 if (s < 0) {
00329 error(errno, "AT2[%s]: at2_read_buffer: Error during read",
00330 octstr_get_cstr(privdata->name));
00331 at2_close_device(privdata);
00332 } else {
00333 octstr_append_data(privdata->ilb, buf, s);
00334 if(privdata->use_telnet)
00335 at2_scan_for_telnet_escapes(privdata);
00336 }
00337 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 910 of file smsc_at.c. References at2_send_modem_command(), at2_wait_modem_command(), at2_write_line(), debug(), error(), PrivAT2data::name, and octstr_get_cstr. 00911 {
00912 char cmd[20];
00913 int message_count = 0;
00914
00915 sprintf(cmd, "AT+CMGR=%d", message_number);
00916 /* read one message from memory */
00917 at2_write_line(privdata, cmd);
00918 if (at2_wait_modem_command(privdata, 0, 0, &message_count) != 0) {
00919 debug("bb.smsc.at2", 0, "AT2[%s]: failed to get message %d.",
00920 octstr_get_cstr(privdata->name), message_number);
00921 return 0; /* failed to read the message - skip to next message */
00922 }
00923
00924 /* no need to delete if no message collected */
00925 if (!message_count) {
00926 debug("bb.smsc.at2", 0, "AT2[%s]: not deleted.",
00927 octstr_get_cstr(privdata->name));
00928 return 0;
00929 }
00930
00931 sprintf(cmd, "AT+CMGD=%d", message_number); /* delete the message we just read */
00932 /*
00933 * 3 seconds (default timeout of send_modem_command()) is not enough with some
00934 * modems if the message is large, so we'll give it 7 seconds
00935 */
00936 if (at2_send_modem_command(privdata, cmd, 7, 0) != 0) {
00937 /*
00938 * failed to delete the message, we'll just ignore it for now,
00939 * this is bad, since if the message really didn't get deleted
00940 * we'll see it next time around.
00941 */
00942 error(2, "AT2[%s]: failed to delete message %d.",
00943 octstr_get_cstr(privdata->name), message_number);
00944 }
00945
00946 return 1;
00947 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 362 of file smsc_at.c. References at2_read_buffer(), at2_scan_for_telnet_escapes(), debug(), PrivAT2data::ilb, PrivAT2data::login_prompt, PrivAT2data::name, octstr_append_cstr(), octstr_copy, octstr_destroy(), octstr_get_char(), octstr_get_cstr, octstr_imm(), octstr_len(), octstr_search(), octstr_search_char(), octstr_set_char(), octstr_strip_blanks(), PrivAT2data::password, PrivAT2data::password_prompt, and PrivAT2data::username. 00363 {
00364 int eol;
00365 int gtloc;
00366 int len;
00367 Octstr *line;
00368 Octstr *buf2;
00369 int i;
00370
00371 at2_read_buffer(privdata);
00372 at2_scan_for_telnet_escapes(privdata);
00373 len = octstr_len(privdata->ilb);
00374 if (len == 0)
00375 return NULL;
00376
00377 if (gt_flag==1) {
00378 /* looking for > if needed */
00379 gtloc = octstr_search_char(privdata->ilb, '>', 0);
00380 }
00381 else if((gt_flag == 2) && (privdata->username)) { /* looking for "Login" */
00382 gtloc = -1;
00383 if(privdata->login_prompt) {
00384 gtloc = octstr_search(privdata->ilb,privdata->login_prompt,0);
00385 }
00386 if(gtloc == -1) {
00387 gtloc = octstr_search(privdata->ilb,octstr_imm("Login:"),0);
00388 }
00389 if(gtloc == -1) {
00390 gtloc = octstr_search(privdata->ilb,octstr_imm("Username:"),0);
00391 }
00392 }
00393 else if ((gt_flag == 3) && (privdata->password)) {/* looking for Password */
00394 gtloc = -1;
00395 if(privdata->password_prompt) {
00396 gtloc = octstr_search(privdata->ilb,privdata->password_prompt,0);
00397 }
00398 if(gtloc == -1) {
00399 gtloc = octstr_search(privdata->ilb,octstr_imm("Password:"),0);
00400 }
00401 }
00402 else
00403 gtloc = -1;
00404
00405 /*
00406 if (gt_flag && (gtloc != -1))
00407 debug("bb.smsc.at2", 0, "in at2_read_line with gt_flag=1, gtloc=%d, ilb=%s",
00408 gtloc, octstr_get_cstr(privdata->ilb));
00409 */
00410
00411 eol = octstr_search_char(privdata->ilb, '\r', 0); /* looking for CR */
00412
00413 if ((gtloc != -1) && ((eol == -1) || (eol > gtloc)))
00414 eol = gtloc;
00415
00416 if (eol == -1)
00417 return NULL;
00418
00419 line = octstr_copy(privdata->ilb, 0, eol);
00420 buf2 = octstr_copy(privdata->ilb, eol + 1, len);
00421 octstr_destroy(privdata->ilb);
00422 privdata->ilb = buf2;
00423
00424 /* remove any non printable chars (including linefeed for example) */
00425 for (i = 0; i < octstr_len(line); i++) {
00426 if (octstr_get_char(line, i) < 32)
00427 octstr_set_char(line, i, ' ');
00428 }
00429 octstr_strip_blanks(line);
00430
00431 /* empty line, skipping */
00432 if ((strcmp(octstr_get_cstr(line), "") == 0) && ( gt_flag == 0))
00433 {
00434 octstr_destroy(line);
00435 return NULL;
00436 }
00437 if ((gt_flag) && (gtloc != -1)) {
00438 /* got to re-add it again as the parser needs to see it */
00439 octstr_append_cstr(line, ">");
00440 }
00441 debug("bb.smsc.at2", 0, "AT2[%s]: <-- %s", octstr_get_cstr(privdata->name),
00442 octstr_get_cstr(line));
00443 return line;
00444 }
|
Here is the call graph for this function:

|
||||||||||||||||||||
|
Definition at line 2651 of file smsc_at.c. References ModemDef::broken, cfg_create(), cfg_destroy(), cfg_get, cfg_get_bool(), cfg_get_integer(), cfg_get_multi_group(), cfg_read(), debug(), ModemDef::detect_string, ModemDef::detect_string2, ModemDef::enable_hwhs, ModemDef::enable_mms, file, gwlist_destroy(), gwlist_extract_first(), gwlist_len(), ModemDef::id, info(), ModemDef::init_string, ModemDef::keepalive_cmd, ModemDef::message_storage, ModemDef::name, PrivAT2data::name, ModemDef::need_sleep, ModemDef::no_pin, ModemDef::no_smsc, O_DESTROY, octstr_compare(), octstr_create, octstr_duplicate, octstr_get_cstr, octstr_imm(), octstr_len(), panic, ModemDef::reset_string, ModemDef::sendline_sleep, and ModemDef::speed. 02652 {
02653 Cfg *cfg;
02654 List *grplist;
02655 CfgGroup *grp;
02656 Octstr *p;
02657 ModemDef *modem;
02658 int i = 1;
02659
02660 /*
02661 * Use id and idnumber=0 or id=NULL and idnumber > 0
02662 */
02663 if (octstr_len(id) == 0 && idnumber == 0)
02664 return NULL;
02665
02666 if (idnumber == 0)
02667 debug("bb.smsc.at2", 0, "AT2[%s]: Reading modem definitions from <%s>",
02668 octstr_get_cstr(privdata->name), octstr_get_cstr(file));
02669 cfg = cfg_create(file);
02670
02671 if (cfg_read(cfg) == -1)
02672 panic(0, "Cannot read modem definition file");
02673
02674 grplist = cfg_get_multi_group(cfg, octstr_imm("modems"));
02675 if (idnumber == 0)
02676 debug("bb.smsc.at2", 0, "AT2[%s]: Found <%ld> modems in config",
02677 octstr_get_cstr(privdata->name), gwlist_len(grplist));
02678
02679 if (grplist == NULL)
02680 panic(0, "Where are the modem definitions ?!?!");
02681
02682 grp = NULL;
02683 while (grplist && (grp = gwlist_extract_first(grplist)) != NULL) {
02684 p = cfg_get(grp, octstr_imm("id"));
02685 if (p == NULL) {
02686 info(0, "Modems group without id, bad");
02687 continue;
02688 }
02689 /* Check by id */
02690 if (octstr_len(id) != 0 && octstr_compare(p, id) == 0) {
02691 O_DESTROY(p);
02692 break;
02693 }
02694 /* Check by idnumber */
02695 if (octstr_len(id) == 0 && idnumber == i) {
02696 O_DESTROY(p);
02697 break;
02698 }
02699 O_DESTROY(p);
02700 i++;
02701 grp = NULL;
02702 }
02703 if (grplist != NULL)
02704 gwlist_destroy(grplist, NULL);
02705
02706 if (grp != NULL) {
02707 modem = gw_malloc(sizeof(ModemDef));
02708
02709 modem->id = cfg_get(grp, octstr_imm("id"));
02710
02711 modem->name = cfg_get(grp, octstr_imm("name"));
02712 if (modem->name == NULL)
02713 modem->name = octstr_duplicate(modem->id);
02714
02715 modem->detect_string = cfg_get(grp, octstr_imm("detect-string"));
02716 modem->detect_string2 = cfg_get(grp, octstr_imm("detect-string2"));
02717
02718 modem->init_string = cfg_get(grp, octstr_imm("init-string"));
02719 if (modem->init_string == NULL)
02720 modem->init_string = octstr_create("AT+CNMI=1,2,0,1,0");
02721
02722 modem->reset_string = cfg_get(grp, octstr_imm("reset-string"));
02723
02724 modem->speed = 9600;
02725 cfg_get_integer(&modem->speed, grp, octstr_imm("speed"));
02726
02727 cfg_get_bool(&modem->need_sleep, grp, octstr_imm("need-sleep"));
02728
02729 modem->enable_hwhs = cfg_get(grp, octstr_imm("enable-hwhs"));
02730 if (modem->enable_hwhs == NULL)
02731 modem->enable_hwhs = octstr_create("AT+IFC=2,2");
02732
02733 cfg_get_bool(&modem->no_pin, grp, octstr_imm("no-pin"));
02734
02735 cfg_get_bool(&modem->no_smsc, grp, octstr_imm("no-smsc"));
02736
02737 modem->sendline_sleep = 100;
02738 cfg_get_integer(&modem->sendline_sleep, grp, octstr_imm("sendline-sleep"));
02739
02740 modem->keepalive_cmd = cfg_get(grp, octstr_imm("keepalive-cmd"));
02741 if (modem->keepalive_cmd == NULL)
02742 modem->keepalive_cmd = octstr_create("AT");
02743
02744 modem->message_storage = cfg_get(grp, octstr_imm("message-storage"));
02745
02746 cfg_get_bool(&modem->enable_mms, grp, octstr_imm("enable-mms"));
02747
02748 /*
02749 if (modem->message_storage == NULL)
02750 modem->message_storage = octstr_create("SM");
02751 */
02752
02753 cfg_get_bool(&modem->broken, grp, octstr_imm("broken"));
02754
02755 cfg_destroy(cfg);
02756 return modem;
02757
02758 } else {
02759 cfg_destroy(cfg);
02760 return NULL;
02761 }
02762 }
|
Here is the call graph for this function:

|
|
Definition at line 956 of file smsc_at.c. References at2_read_delete_message(), at2_set_message_storage(), error(), gwlist_extract_first(), gwlist_len(), info(), location, ModemDef::message_storage, PrivAT2data::modem, PrivAT2data::name, O_DESTROY, octstr_compare(), octstr_copy, octstr_destroy(), octstr_duplicate, octstr_get_cstr, octstr_parse_long(), octstr_search_char(), and PrivAT2data::pending_incoming_messages. 00957 {
00958 Octstr *current_storage = NULL;
00959
00960 if (privdata->modem->message_storage) {
00961 current_storage = octstr_duplicate(privdata->modem->message_storage);
00962 }
00963 while (gwlist_len(privdata->pending_incoming_messages) > 0) {
00964 int pos;
00965 long location;
00966 Octstr *cmti_storage = NULL, *line = NULL;
00967
00968 line = gwlist_extract_first(privdata->pending_incoming_messages);
00969 /* message memory starts after the first quote in the string */
00970 if ((pos = octstr_search_char(line, '"', 0)) != -1) {
00971 /* grab memory storage name */
00972 int next_quote = octstr_search_char(line, '"', ++pos);
00973 if (next_quote == -1) { /* no second qoute - this line must be broken somehow */
00974 O_DESTROY(line);
00975 continue;
00976 }
00977
00978 /* store notification storage location for reference */
00979 cmti_storage = octstr_copy(line, pos, next_quote - pos);
00980 } else
00981 /* reset pos for the next lookup which would start from the beginning if no memory
00982 * location was found */
00983 pos = 0;
00984
00985 /* if no message storage is set in configuration - set now */
00986 if (!privdata->modem->message_storage && cmti_storage) {
00987 info(2, "AT2[%s]: CMTI received, but no message-storage is set in confiuration."
00988 "setting now to <%s>", octstr_get_cstr(privdata->name), octstr_get_cstr(cmti_storage));
00989 privdata->modem->message_storage = octstr_duplicate(cmti_storage);
00990 current_storage = octstr_duplicate(cmti_storage);
00991 at2_set_message_storage(privdata, cmti_storage);
00992 }
00993
00994 /* find the message id from the line, which should appear after the first comma */
00995 if ((pos = octstr_search_char(line, ',', pos)) == -1) { /* this CMTI notification is probably broken */
00996 error(2, "AT2[%s]: failed to find memory location in CMTI notification",
00997 octstr_get_cstr(privdata->name));
00998 O_DESTROY(line);
00999 octstr_destroy(cmti_storage);
01000 continue;
01001 }
01002
01003 if ((pos = octstr_parse_long(&location, line, ++pos, 10)) == -1) {
01004 /* there was an error parsing the message id. next! */
01005 error(2, "AT2[%s]: error parsing memory location in CMTI notification",
01006 octstr_get_cstr(privdata->name));
01007 O_DESTROY(line);
01008 octstr_destroy(cmti_storage);
01009 continue;
01010 }
01011
01012 /* check if we need to change storage location before issuing the read command */
01013 if (!current_storage || (octstr_compare(current_storage, cmti_storage) != 0)) {
01014 octstr_destroy(current_storage);
01015 current_storage = octstr_duplicate(cmti_storage);
01016 at2_set_message_storage(privdata, cmti_storage);
01017 }
01018
01019 if (!at2_read_delete_message(privdata, location)) {
01020 error(1, "AT2[%s]: CMTI notification received, but no message found in memory!",
01021 octstr_get_cstr(privdata->name));
01022 }
01023
01024 octstr_destroy(line);
01025 octstr_destroy(cmti_storage);
01026 }
01027
01028 /* set prefered message storage back to what configured */
01029 if (current_storage && privdata->modem->message_storage
01030 && (octstr_compare(privdata->modem->message_storage, current_storage) != 0))
01031 at2_set_message_storage(privdata, privdata->modem->message_storage);
01032
01033 octstr_destroy(current_storage);
01034 }
|
Here is the call graph for this function:

|
|
Definition at line 1037 of file smsc_at.c. References at2_check_sms_memory(), at2_read_delete_message(), at2_read_pending_incoming_messages(), debug(), gwlist_len(), PrivAT2data::name, octstr_get_cstr, PrivAT2data::pending_incoming_messages, PrivAT2data::sms_memory_capacity, and PrivAT2data::sms_memory_usage. 01038 {
01039 /* get memory status */
01040 if (at2_check_sms_memory(privdata) == -1) {
01041 debug("bb.smsc.at2", 0, "AT2[%s]: memory check error", octstr_get_cstr(privdata->name));
01042 return -1;
01043 }
01044
01045 if (privdata->sms_memory_usage) {
01046 /*
01047 * that is - greater then 0, meaning there are some messages to fetch
01048 * now - I used to just loop over the first input_mem_sms_used locations,
01049 * but it doesn't hold, since under load, messages may be received while
01050 * we're in the loop, and get stored in locations towards the end of the list,
01051 * thus creating 'holes' in the memory.
01052 *
01053 * There are two ways we can fix this :
01054 * (a) Just read the last message location, delete it and return.
01055 * It's not a complete solution since holes can still be created if messages
01056 * are received between the memory check and the delete command,
01057 * and anyway - it will slow us down and won't hold well under pressure
01058 * (b) Just scan the entire memory each call, bottom to top.
01059 * This will be slow too, but it'll be reliable.
01060 *
01061 * We can massivly improve performance by stopping after input_mem_sms_used messages
01062 * have been read, but send_modem_command returns 0 for no message as well as for a
01063 * message read, and the only other way to implement it is by doing memory_check
01064 * after each read and stoping when input_mem_sms_used get to 0. This is slow
01065 * (modem commands take time) so we improve speed only if there are less then 10
01066 * messages in memory.
01067 *
01068 * I implemented the alternative - changed at2_wait_modem_command to return the
01069 * number of messages it collected.
01070 */
01071 int i;
01072 int message_count = 0; /* cound number of messages collected */
01073
01074 debug("bb.smsc.at2", 0, "AT2[%s]: %d messages waiting in memory",
01075 octstr_get_cstr(privdata->name), privdata->sms_memory_usage);
01076
01077 /*
01078 * loop till end of memory or collected enouch messages
01079 */
01080 for (i = 1; i <= privdata->sms_memory_capacity &&
01081 message_count < privdata->sms_memory_usage; ++i) {
01082
01083 /* if (meanwhile) there are pending CMTI notifications, process these first
01084 * to not let CMTI and sim buffering sit in each others way */
01085 while (gwlist_len(privdata->pending_incoming_messages) > 0) {
01086 at2_read_pending_incoming_messages(privdata);
01087 }
01088 /* read the message and delete it */
01089 message_count += at2_read_delete_message(privdata, i);
01090 }
01091 }
01092
01093 /*
01094 at2_send_modem_command(privdata, ModemTypes[privdata->modemid].init1, 0, 0);
01095 */
01096 return 0;
01097 }
|
Here is the call graph for this function:

|
|
Definition at line 102 of file smsc_at.c. References PrivAT2data::fd, PrivAT2data::ilb, octstr_binary_to_hex(), octstr_delete(), octstr_destroy(), octstr_duplicate, octstr_get_char(), octstr_len(), and octstr_search_char(). Referenced by at2_read_buffer(), and at2_read_line(). 00103 {
00104 int len;
00105 int pos;
00106 int start;
00107 int a;
00108 int b;
00109 int i;
00110 Octstr *hex;
00111
00112 char answer[5];
00113
00114
00115 if(!privdata->ilb)
00116 return;
00117 start = 0;
00118 len = octstr_len(privdata->ilb);
00119 hex = octstr_duplicate(privdata->ilb);
00120 octstr_binary_to_hex(hex,1);
00121
00122 octstr_destroy(hex);
00123
00124 while(start < len)
00125 {
00126 pos = octstr_search_char(privdata->ilb, 0xFF, start);
00127 if(pos < 0)
00128 return;
00129 if((len - pos )<3)
00130 return;
00131 a = octstr_get_char(privdata->ilb,pos+1);
00132 b = octstr_get_char(privdata->ilb,pos+2);
00133 switch(a)
00134 {
00135 case 0xFD: /* do! */
00136 answer[0] = 0xFF; /* escape */
00137 answer[1] = 0xFC; /* wont do any option*/
00138 answer[2] = b;
00139 i = write(privdata->fd,&answer,3);
00140 octstr_delete(privdata->ilb,pos,3);
00141 len -=3;
00142 break;
00143 break;
00144 case 0xFA: /* do you support option b ? */
00145 octstr_delete(privdata->ilb,pos,3);
00146 len -=3;
00147 break;
00148 break;
00149 case 0xFB: /* will */
00150 octstr_delete(privdata->ilb,pos,3);
00151 len -=3;
00152 break;
00153 case 0xFC: /* wont */
00154 octstr_delete(privdata->ilb,pos,3);
00155 len -=3;
00156 break;
00157 }
00158 start = pos;
00159 }
00160
00161 }
|
Here is the call graph for this function:

|
|
Definition at line 2150 of file smsc_at.c. References at2_send_modem_command(), at2_send_one_message(), ModemDef::enable_mms, gw_prioqueue_len(), gw_prioqueue_remove(), PrivAT2data::modem, and PrivAT2data::outgoing_queue. 02151 {
02152 Msg *msg;
02153
02154 if (privdata->modem->enable_mms &&
02155 gw_prioqueue_len(privdata->outgoing_queue) > 1)
02156 at2_send_modem_command(privdata, "AT+CMMS=2", 0, 0);
02157
02158 if ((msg = gw_prioqueue_remove(privdata->outgoing_queue)))
02159 at2_send_one_message(privdata, msg);
02160 }
|
Here is the call graph for this function:

|
||||||||||||||||||||
|
Definition at line 732 of file smsc_at.c. References at2_wait_modem_command(), and at2_write_line(). 00733 {
00734 at2_write_line(privdata, cmd);
00735 return at2_wait_modem_command(privdata, timeout, gt_flag, NULL);
00736 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 2163 of file smsc_at.c. References at2_pdu_encode(), at2_send_modem_command(), at2_wait_modem_command(), at2_write(), at2_write_ctrlz(), bb_smscconn_send_failed(), bb_smscconn_sent(), PrivAT2data::conn, debug(), dlr_add(), DLR_IS_ENABLED_DEVICE, error(), gwthread_sleep(), smscconn::id, ModemDef::id, PrivAT2data::modem, msg_type, PrivAT2data::my_number, PrivAT2data::name, ModemDef::no_smsc, O_DESTROY, octstr_compare(), octstr_create, octstr_destroy(), octstr_duplicate, octstr_format(), octstr_get_cstr, octstr_imm(), octstr_len(), pdu, and SMSCCONN_FAILED_TEMPORARILY. 02164 {
02165 char command[500];
02166 int ret = -1;
02167 char sc[3];
02168
02169 if (octstr_len(privdata->my_number)) {
02170 octstr_destroy(msg->sms.sender);
02171 msg->sms.sender = octstr_duplicate(privdata->my_number);
02172 }
02173
02174 /*
02175 * The standard says you should be prepending the PDU with 00 to indicate
02176 * to use the default SC. Some older modems dont expect this so it can be
02177 * disabled
02178 * NB: This extra padding is not counted in the CMGS byte count
02179 */
02180 sc[0] = '\0';
02181
02182 if (!privdata->modem->no_smsc)
02183 strcpy(sc, "00");
02184
02185 if (msg_type(msg) == sms) {
02186 Octstr *pdu;
02187
02188 if ((pdu = at2_pdu_encode(msg, privdata)) == NULL) {
02189 error(2, "AT2[%s]: Error encoding PDU!",octstr_get_cstr(privdata->name));
02190 return;
02191 }
02192
02193 int msg_id = -1;
02194 /*
02195 * send the initial command and then wait for >
02196 */
02197 sprintf(command, "AT+CMGS=%ld", octstr_len(pdu) / 2);
02198
02199 ret = at2_send_modem_command(privdata, command, 5, 1);
02200 debug("bb.smsc.at2", 0, "AT2[%s]: send command status: %d",
02201 octstr_get_cstr(privdata->name), ret);
02202
02203 if (ret == 1) {/* > only! */
02204
02205 /*
02206 * Ok the > has been see now so we can send the PDU now and a
02207 * control Z but no CR or LF
02208 *
02209 * We will handle the 'nokiaphone' types a bit differently, since
02210 * they have a generic error in accepting PDUs that are "too big".
02211 * Which means, PDU that are longer then 18 bytes get truncated by
02212 * the phone modems. We'll buffer the PDU output in a loop.
02213 * All other types will get handled as used to be.
02214 */
02215
02216 if (octstr_compare(privdata->modem->id, octstr_imm("nokiaphone")) != 0) {
02217
02218 sprintf(command, "%s%s", sc, octstr_get_cstr(pdu));
02219 at2_write(privdata, command);
02220 at2_write_ctrlz(privdata);
02221
02222 } else {
02223
02224 /* include the CTRL-Z in the PDU string */
02225 sprintf(command, "%s%s%c", sc, octstr_get_cstr(pdu), 0x1A);
02226
02227 /* chop PDU into 18-byte-at-a-time pieces to prevent choking
02228 * of certain GSM Phones (e.g. Nokia 6310, 6230 etc.) */
02229 if (strlen(command) > 18) {
02230 char chop[20];
02231 int len = strlen(command);
02232 int pos = 0;
02233 int ret = 18;
02234
02235 while (pos < len) {
02236 if (pos + ret > len)
02237 ret = len - pos;
02238 memcpy(chop, command + pos, ret);
02239 pos += ret;
02240 chop[ret] = '\0';
02241 at2_write(privdata, chop);
02242 gwthread_sleep((double) 10/1000);
02243 }
02244 } else {
02245 at2_write(privdata, command);
02246 }
02247 }
02248
02249 /* wait 20 secs for modem command */
02250 ret = at2_wait_modem_command(privdata, 20, 0, &msg_id);
02251 debug("bb.smsc.at2", 0, "AT2[%s]: send command status: %d",
02252 octstr_get_cstr(privdata->name), ret);
02253
02254 if (ret != 0) {
02255 bb_smscconn_send_failed(privdata->conn, msg,
02256 SMSCCONN_FAILED_TEMPORARILY, octstr_create("ERROR"));
02257 }else{
02258 /* store DLR message if needed for SMSC generated delivery reports */
02259 if (DLR_IS_ENABLED_DEVICE(msg->sms.dlr_mask)) {
02260 if (msg_id == -1)
02261 error(0,"AT2[%s]: delivery notification requested, but I have no message ID!",
02262 octstr_get_cstr(privdata->name));
02263 else {
02264 Octstr *dlrmsgid = octstr_format("%d", msg_id);
02265
02266 dlr_add(privdata->conn->id, dlrmsgid, msg);
02267
02268 O_DESTROY(dlrmsgid);
02269
02270 }
02271 }
02272
02273 bb_smscconn_sent(privdata->conn, msg, NULL);
02274 }
02275 }
02276 O_DESTROY(pdu);
02277 }
02278 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 2840 of file smsc_at.c. References at2_send_modem_command(), octstr_destroy(), octstr_format(), and octstr_get_cstr. 02841 {
02842 Octstr *temp;
02843 int ret;
02844
02845 if (!memory_name || !privdata)
02846 return -1;
02847
02848 temp = octstr_format("AT+CPMS=\"%S\"", memory_name);
02849 ret = at2_send_modem_command(privdata, octstr_get_cstr(temp), 0, 0);
02850 octstr_destroy(temp);
02851
02852 return !ret ? 0 : -1;
02853 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 1168 of file smsc_at.c. References error(), PrivAT2data::fd, info(), PrivAT2data::is_serial, PrivAT2data::name, and octstr_get_cstr. 01169 {
01170 struct termios tios;
01171 int ret;
01172 int speed;
01173
01174 if (!privdata->is_serial)
01175 return;
01176
01177 tcgetattr(privdata->fd, &tios);
01178
01179 switch (bps) {
01180 case 300:
01181 speed = B300;
01182 break;
01183 case 1200:
01184 speed = B1200;
01185 break;
01186 case 2400:
01187 speed = B2400;
01188 break;
01189 case 4800:
01190 speed = B4800;
01191 break;
01192 case 9600:
01193 speed = B9600;
01194 break;
01195 case 19200:
01196 speed = B19200;
01197 break;
01198 case 38400:
01199 speed = B38400;
01200 break;
01201 #ifdef B57600
01202 case 57600:
01203 speed = B57600;
01204 break;
01205 #endif
01206 #ifdef B115200
01207 case 115200:
01208 speed = B115200;
01209 break;
01210 #endif
01211 default:
01212 speed = B9600;
01213 }
01214
01215 cfsetospeed(&tios, speed);
01216 cfsetispeed(&tios, speed);
01217 ret = tcsetattr(privdata->fd, TCSANOW, &tios); /* apply changes now */
01218 if (ret == -1) {
01219 error(errno, "AT2[%s]: at_data_link: fail to set termios attribute",
01220 octstr_get_cstr(privdata->name));
01221 }
01222 tcflush(privdata->fd, TCIOFLUSH);
01223
01224 info(0, "AT2[%s]: speed set to %d", octstr_get_cstr(privdata->name), bps);
01225 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 1394 of file smsc_at.c. References bb_smscconn_send_failed(), smscconn::data, debug(), PrivAT2data::device_thread, gw_prioqueue_remove(), gwthread_wakeup(), PrivAT2data::name, octstr_get_cstr, PrivAT2data::outgoing_queue, PrivAT2data::shutdown, SMSCConn, SMSCCONN_FAILED_SHUTDOWN, and smscconn::why_killed. 01395 {
01396 PrivAT2data *privdata = conn->data;
01397
01398 debug("bb.sms", 0, "AT2[%s]: Shutting down SMSCConn, %s",
01399 octstr_get_cstr(privdata->name),
01400 finish_sending ? "slow" : "instant");
01401
01402 /*
01403 * Documentation claims this would have been done by smscconn.c,
01404 * but isn't when this code is being written.
01405 */
01406 conn->why_killed = SMSCCONN_KILLED_SHUTDOWN;
01407 privdata->shutdown = 1;
01408 /*
01409 * Separate from why_killed to avoid locking, as
01410 * why_killed may be changed from outside?
01411 */
01412 if (finish_sending == 0) {
01413 Msg *msg;
01414 while ((msg = gw_prioqueue_remove(privdata->outgoing_queue)) != NULL) {
01415 bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_SHUTDOWN, NULL);
01416 }
01417 }
01418 gwthread_wakeup(privdata->device_thread);
01419 return 0;
01420
01421 }
|
Here is the call graph for this function:

|
|
Definition at line 1440 of file smsc_at.c. References smscconn::data, debug(), PrivAT2data::device_thread, gwthread_wakeup(), PrivAT2data::name, octstr_get_cstr, SMSCConn, and smscconn::status. 01441 {
01442 PrivAT2data *privdata = conn->data;
01443
01444 if (conn->status == SMSCCONN_DISCONNECTED)
01445 conn->status = SMSCCONN_ACTIVE;
01446
01447 /* in case there are messages in the buffer already */
01448 gwthread_wakeup(privdata->device_thread);
01449 debug("smsc.at2", 0, "AT2[%s]: start called", octstr_get_cstr(privdata->name));
01450 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 2516 of file smsc_at.c. References at2_close_device(), at2_open_device(), at2_read_buffer(), at2_send_modem_command(), at2_set_speed(), and res. 02517 {
02518 int res;
02519
02520 if (at2_open_device(privdata) == -1)
02521 return -1;
02522
02523 at2_read_buffer(privdata); /* give telnet escape sequences a chance */
02524 at2_set_speed(privdata, speed);
02525 /* send a return so the modem can detect the speed */
02526 res = at2_send_modem_command(privdata, "", 1, 0);
02527 res = at2_send_modem_command(privdata, "AT", 0, 0);
02528
02529 if (res != 0)
02530 res = at2_send_modem_command(privdata, "AT", 0, 0);
02531 if (res != 0)
02532 res = at2_send_modem_command(privdata, "AT", 0, 0);
02533
02534 at2_close_device(privdata);
02535
02536 return res;
02537 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 340 of file smsc_at.c. References at2_read_line(), end_time, PrivAT2data::lines, octstr_create, and octstr_destroy(). 00341 {
00342 Octstr *line;
00343 time_t end_time;
00344 time_t cur_time;
00345
00346 time(&end_time);
00347 if (timeout == 0)
00348 timeout = 3;
00349 end_time += timeout;
00350
00351 if (privdata->lines != NULL)
00352 octstr_destroy(privdata->lines);
00353 privdata->lines = octstr_create("");
00354 while (time(&cur_time) <= end_time) {
00355 line = at2_read_line(privdata, gt_flag);
00356 if (line)
00357 return line;
00358 }
00359 return NULL;
00360 }
|
Here is the call graph for this function:

|
||||||||||||||||||||
|
Definition at line 739 of file smsc_at.c. References at2_error_string(), at2_pdu_decode(), at2_pdu_extract(), at2_read_line(), at2_wait_line(), at2_write_line(), bb_smscconn_receive(), PrivAT2data::conn, debug(), end_time, error(), PrivAT2data::fd, gwlist_append(), smscconn::id, PrivAT2data::ilb, PrivAT2data::lines, PrivAT2data::name, O_DESTROY, octstr_append(), octstr_append_cstr(), octstr_create, octstr_destroy(), octstr_duplicate, octstr_get_cstr, octstr_imm(), octstr_len(), octstr_parse_long(), octstr_search(), pdu, PrivAT2data::pending_incoming_messages, PrivAT2data::phase2plus, and PrivAT2data::pin_ready. 00741 {
00742 Octstr *line = NULL;
00743 Octstr *line2 = NULL;
00744 Octstr *pdu = NULL;
00745 Octstr *smsc_number = NULL;
00746 int ret;
00747 time_t end_time;
00748 time_t cur_time;
00749 Msg *msg;
00750 int len;
00751 int cmgr_flag = 0;
00752 int expect_extra_ok = 0;
00753
00754 time(&end_time);
00755 if (timeout == 0)
00756 timeout = 3;
00757 end_time += timeout;
00758
00759 if (privdata->lines != NULL)
00760 octstr_destroy(privdata->lines);
00761 privdata->lines = octstr_create("");
00762
00763 smsc_number = octstr_create("");
00764 while (privdata->fd != -1 && time(&cur_time) <= end_time) {
00765 O_DESTROY(line);
00766 if ((line = at2_read_line(privdata, gt_flag))) {
00767 octstr_append(privdata->lines, line);
00768 octstr_append_cstr(privdata->lines, "\n");
00769
00770 if (octstr_search(line, octstr_imm("SIM PIN"), 0) != -1) {
00771 ret = 2;
00772 goto end;
00773 }
00774 if (octstr_search(line, octstr_imm("OK"), 0) != -1) {
00775 if (!expect_extra_ok) {
00776 ret = 0;
00777 goto end;
00778 } else {
00779 --expect_extra_ok;
00780 }
00781 }
00782 if ((gt_flag ) && (octstr_search(line, octstr_imm(">"), 0) != -1)) {
00783 ret = 1;
00784 goto end;
00785 }
00786 if (octstr_search(line, octstr_imm("RING"), 0) != -1) {
00787 at2_write_line(privdata, "ATH0");
00788 continue;
00789 }
00790 if (octstr_search(line, octstr_imm("+CPIN: READY"), 0) != -1) {
00791 privdata->pin_ready = 1;
00792 continue;
00793 }
00794 if (octstr_search(line, octstr_imm("+CMS ERROR"), 0) != -1) {
00795 int errcode;
00796 error(0, "AT2[%s]: CMS ERROR: %s", octstr_get_cstr(privdata->name),
00797 octstr_get_cstr(line));
00798 if (sscanf(octstr_get_cstr(line), "+CMS ERROR: %d", &errcode) == 1)
00799 error(0, "AT2[%s]: CMS ERROR: %s (%d)", octstr_get_cstr(privdata->name),
00800 at2_error_string(errcode), errcode);
00801 ret = 1;
00802 goto end;
00803 }
00804 if (octstr_search(line, octstr_imm("+CMTI:"), 0) != -1 ||
00805 octstr_search(line, octstr_imm("+CDSI:"), 0) != -1) {
00806 /*
00807 * we received an incoming message indication
00808 * put it in the pending_incoming_messages queue for later retrieval
00809 */
00810 debug("bb.smsc.at2", 0, "AT2[%s]: +CMTI incoming SMS indication: %s",
00811 octstr_get_cstr(privdata->name), octstr_get_cstr(line));
00812 gwlist_append(privdata->pending_incoming_messages, line);
00813 line = NULL;
00814 continue;
00815 }
00816 if (octstr_search(line, octstr_imm("+CMT:"), 0) != -1 ||
00817 octstr_search(line, octstr_imm("+CDS:"), 0) != -1 ||
00818 ((octstr_search(line, octstr_imm("+CMGR:"), 0) != -1) && (cmgr_flag = 1)) ) {
00819 line2 = at2_wait_line(privdata, 1, 0);
00820
00821 if (line2 == NULL) {
00822 error(0, "AT2[%s]: got +CMT but waiting for next line timed out",
00823 octstr_get_cstr(privdata->name));
00824 } else {
00825 octstr_append_cstr(line, "\n");
00826 octstr_append(line, line2);
00827 O_DESTROY(line2);
00828 at2_pdu_extract(privdata, &pdu, line, smsc_number);
00829 if (pdu == NULL) {
00830 error(0, "AT2[%s]: got +CMT but pdu_extract failed",
00831 octstr_get_cstr(privdata->name));
00832 } else {
00833 /* count message even if I can't decode it */
00834 if (output)
00835 ++(*output);
00836 msg = at2_pdu_decode(pdu, privdata);
00837 if (msg != NULL) {
00838 octstr_destroy(msg->sms.smsc_id);
00839 octstr_destroy(msg->sms.smsc_number);
00840 msg->sms.smsc_id = octstr_duplicate(privdata->conn->id);
00841 msg->sms.smsc_number = octstr_duplicate(smsc_number);
00842 bb_smscconn_receive(privdata->conn, msg);
00843 } else {
00844 error(0, "AT2[%s]: could not decode PDU to a message.",
00845 octstr_get_cstr(privdata->name));
00846 }
00847
00848 if (!cmgr_flag) {
00849 if (privdata->phase2plus) {
00850 at2_write_line(privdata, "AT+CNMA");
00851 ++expect_extra_ok;
00852 }
00853 }
00854
00855 O_DESTROY(pdu);
00856 }
00857 }
00858 continue;
00859 }
00860 if ((octstr_search(line, octstr_imm("+CMGS:"),0) != -1) && (output)) {
00861 /*
00862 * found response to a +CMGS command, read the message id
00863 * and return it in output
00864 */
00865 long temp;
00866 if (octstr_parse_long(&temp, line, octstr_search(line, octstr_imm("+CMGS:"), 0) + 6, 10) == -1)
00867 error(0, "AT2[%s]: Got +CMGS but failed to read message id",
00868 octstr_get_cstr(privdata->name));
00869 else
00870 *output = temp;
00871 }
00872 /* finally check if we received a generic error */
00873 if (octstr_search(line, octstr_imm("ERROR"), 0) != -1) {
00874 int errcode;
00875 error(0, "AT2[%s]: Generic error: %s", octstr_get_cstr(privdata->name),
00876 octstr_get_cstr(line));
00877 if (sscanf(octstr_get_cstr(line), "ERROR: %d", &errcode) == 1)
00878 error(0, "AT2[%s]: Generic error: %s (%d)", octstr_get_cstr(privdata->name),
00879 at2_error_string(errcode), errcode);
00880 ret = -1;
00881 goto end;
00882 }
00883 }
00884 }
00885
00886 len = octstr_len(privdata->ilb);
00887 /*
00888 error(0,"AT2[%s]: timeout. received <%s> until now, buffer size is %d, buf=%s",
00889 octstr_get_cstr(privdata->name),
00890 privdata->lines ? octstr_get_cstr(privdata->lines) : "<nothing>", len,
00891 privdata->ilb ? octstr_get_cstr(privdata->ilb) : "<nothing>");
00892 */
00893 O_DESTROY(line);
00894 O_DESTROY(line2);
00895 O_DESTROY(pdu);
00896 O_DESTROY(smsc_number);
00897 return -1; /* timeout */
00898
00899 end:
00900 O_DESTROY(smsc_number);
00901 octstr_append(privdata->lines, line);
00902 octstr_append_cstr(privdata->lines, "\n");
00903 O_DESTROY(line);
00904 O_DESTROY(line2);
00905 O_DESTROY(pdu);
00906 return ret;
00907 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 515 of file smsc_at.c. References debug(), error(), PrivAT2data::fd, gwthread_sleep(), PrivAT2data::modem, PrivAT2data::name, octstr_get_cstr, and ModemDef::sendline_sleep. 00516 {
00517 int count, data_written = 0, write_count = 0;
00518 int s = 0;
00519
00520 debug("bb.smsc.at2", 0, "AT2[%s]: --> %s", octstr_get_cstr(privdata->name), line);
00521
00522 count = strlen(line);
00523 while(count > data_written) {
00524 s = write(privdata->fd, line + data_written, count - data_written);
00525 if (s < 0 && errno == EAGAIN && write_count < RETRY_WRITE) {
00526 gwthread_sleep(1);
00527 ++write_count;
00528 } else if (s > 0) {
00529 data_written += s;
00530 write_count = 0;
00531 } else
00532 break;
00533 }
00534
00535 if (s < 0) {
00536 error(errno, "AT2[%s]: Couldnot write to device.",
00537 octstr_get_cstr(privdata->name));
00538 tcflush(privdata->fd, TCOFLUSH);
00539 return s;
00540 }
00541 tcdrain(privdata->fd);
00542 gwthread_sleep((double) (privdata->modem == NULL ?
00543 100 : privdata->modem->sendline_sleep) / 1000);
00544 return s;
00545 }
|
Here is the call graph for this function:

|
|
Definition at line 486 of file smsc_at.c. References debug(), error(), PrivAT2data::fd, gwthread_sleep(), PrivAT2data::modem, PrivAT2data::name, octstr_get_cstr, and ModemDef::sendline_sleep. 00487 {
00488 int s;
00489 char *ctrlz = "\032" ;
00490 int write_count = 0;
00491
00492 debug("bb.smsc.at2", 0, "AT2[%s]: --> ^Z", octstr_get_cstr(privdata->name));
00493 while (1) {
00494 errno = 0;
00495 s = write(privdata->fd, ctrlz, 1);
00496 if (s < 0 && errno == EAGAIN && write_count < RETRY_WRITE) {
00497 gwthread_sleep(1);
00498 ++write_count;
00499 } else
00500 break;
00501 }
00502 if (s < 0) {
00503 error(errno, "AT2[%s]: Couldnot write to device.",
00504 octstr_get_cstr(privdata->name));
00505 tcflush(privdata->fd, TCOFLUSH);
00506 return s;
00507 }
00508 tcdrain(privdata->fd);
00509 gwthread_sleep((double) (privdata->modem == NULL ?
00510 100 : privdata->modem->sendline_sleep) / 1000);
00511 return s;
00512 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 447 of file smsc_at.c. References debug(), error(), PrivAT2data::fd, gwthread_sleep(), PrivAT2data::modem, PrivAT2data::name, O_DESTROY, octstr_format(), octstr_get_cstr, octstr_len(), and ModemDef::sendline_sleep. 00448 {
00449 int count;
00450 int s = 0;
00451 int write_count = 0, data_written = 0;
00452 Octstr *linestr = NULL;
00453
00454 linestr = octstr_format("%s\r", line);
00455
00456 debug("bb.smsc.at2", 0, "AT2[%s]: --> %s^M", octstr_get_cstr(privdata->name), line);
00457
00458 count = octstr_len(linestr);
00459 while (count > data_written) {
00460 errno = 0;
00461 s = write(privdata->fd, octstr_get_cstr(linestr) + data_written,
00462 count - data_written);
00463 if (s < 0 && errno == EAGAIN && write_count < RETRY_WRITE) {
00464 gwthread_sleep(1);
00465 ++write_count;
00466 } else if (s > 0) {
00467 data_written += s;
00468 write_count = 0;
00469 } else
00470 break;
00471 }
00472 O_DESTROY(linestr);
00473 if (s < 0) {
00474 error(errno, "AT2[%s]: Couldnot write to device.",
00475 octstr_get_cstr(privdata->name));
00476 tcflush(privdata->fd, TCOFLUSH);
00477 return s;
00478 }
00479 tcdrain(privdata->fd);
00480 gwthread_sleep((double) (privdata->modem == NULL ?
00481 100 : privdata->modem->sendline_sleep) / 1000);
00482 return s;
00483 }
|
Here is the call graph for this function:

|
|
Definition at line 1702 of file smsc_at.c. References nibble2hex(), octstr_append_char(), octstr_create, octstr_get_char(), octstr_len(), and pdu. Referenced by at2_pdu_extract(). 01703 {
01704 Octstr *tmp = NULL;
01705 unsigned char c;
01706 unsigned char a;
01707 unsigned char b;
01708 int ton;
01709 int npi;
01710 int len;
01711 int pos;
01712
01713 pos=0;
01714 len = octstr_len(pdu);
01715 if(len<= 0)
01716 return octstr_create("");
01717
01718 ton = octstr_get_char(pdu,pos++);
01719 npi = ton & 0x0F;
01720 ton = (ton >> 4) & 0x07;
01721
01722 switch(ton)
01723 {
01724 case 0: /* unknown */
01725 tmp = octstr_create("");
01726 break;
01727 case 1: /* international */
01728 tmp = octstr_create("+");
01729 break;
01730 case 2: /* national */
01731 tmp = octstr_create("0");
01732 break;
01733 case 3: /* network-specific */
01734 default:
01735 tmp = octstr_create("");
01736 break;
01737 }
01738 while(--len > 0)
01739 {
01740 c = octstr_get_char(pdu,pos++);
01741 a = c & 0x0F;
01742 b = ((c & 0xF0) >> 4);
01743
01744 if((b == 0x0F) && (len < 2))
01745 {
01746 octstr_append_char(tmp, nibble2hex(a));
01747 }
01748 else
01749 {
01750 octstr_append_char(tmp, nibble2hex(a));
01751 octstr_append_char(tmp, nibble2hex(b));
01752 }
01753 }
01754 return tmp;
01755 }
|
Here is the call graph for this function:

|
|
Definition at line 1694 of file smsc_at.c. Referenced by gsm2number(). 01695 {
01696 if(b < 0x0A)
01697 return '0'+ b;
01698 else
01699 return 'A'+ b - 0x0A;
01700 }
|
|
||||||||||||
|
Definition at line 1464 of file smsc_at.c. References at2_device_thread(), at2_read_modems(), cfg_get, cfg_get_bool(), cfg_get_configfile(), cfg_get_integer(), PrivAT2data::configfile, PrivAT2data::conn, smscconn::connect_time, smscconn::data, PrivAT2data::device, PrivAT2data::device_thread, error(), PrivAT2data::fd, gw_prioqueue_create(), gw_prioqueue_destroy(), gwlist_create, gwthread_create, PrivAT2data::ilb, info(), PrivAT2data::is_serial, PrivAT2data::keepalive, PrivAT2data::lines, PrivAT2data::login_prompt, PrivAT2data::max_error_count, PrivAT2data::modem, PrivAT2data::my_number, PrivAT2data::name, ModemDef::name, smscconn::name, O_DESTROY, octstr_compare(), octstr_create, octstr_duplicate, octstr_format(), octstr_get_cstr, octstr_imm(), octstr_len(), octstr_str_compare(), PrivAT2data::outgoing_queue, PrivAT2data::password, PrivAT2data::password_prompt, PrivAT2data::pending_incoming_messages, PrivAT2data::phase2plus, PrivAT2data::pin, PrivAT2data::pin_ready, smscconn::queued, PrivAT2data::rawtcp_host, PrivAT2data::rawtcp_port, smscconn::send_msg, PrivAT2data::shutdown, smscconn::shutdown, PrivAT2data::sms_center, PrivAT2data::sms_memory_poll_interval, sms_priority_compare(), SMSCConn, PrivAT2data::speed, smscconn::start_conn, smscconn::status, PrivAT2data::use_telnet, PrivAT2data::username, PrivAT2data::validityperiod, and smscconn::why_killed. Referenced by smscconn_create(). 01465 {
01466 PrivAT2data *privdata;
01467 Octstr *modem_type_string;
01468 long portno; /* has to be long because of cfg_get_integer */
01469
01470 privdata = gw_malloc(sizeof(PrivAT2data));
01471 privdata->outgoing_queue = gw_prioqueue_create(sms_priority_compare);
01472 privdata->pending_incoming_messages = gwlist_create();
01473
01474 privdata->configfile = cfg_get_configfile(cfg);
01475
01476 privdata->device = cfg_get(cfg, octstr_imm("device"));
01477 if (privdata->device == NULL) {
01478 error(0, "AT2[-]: 'device' missing in at2 configuration.");
01479 goto error;
01480 }
01481
01482 if (octstr_str_compare(privdata->device, "rawtcp") == 0) {
01483 privdata->rawtcp_host = cfg_get(cfg, octstr_imm("host"));
01484 if (privdata->rawtcp_host == NULL) {
01485 error(0, "AT2[-]: 'host' missing in at2 rawtcp configuration.");
01486 goto error;
01487 }
01488 if (cfg_get_integer(&portno, cfg, octstr_imm("port")) == -1) {
01489 error(0, "AT2[-]: 'port' missing in at2 rawtcp configuration.");
01490 goto error;
01491 }
01492 privdata->rawtcp_port = portno;
01493 privdata->is_serial = 0;
01494 privdata->use_telnet = 0;
01495 }
01496 else if (octstr_str_compare(privdata->device, "telnet") == 0) {
01497 privdata->rawtcp_host = cfg_get(cfg, octstr_imm("host"));
01498 if (privdata->rawtcp_host == NULL) {
01499 error(0, "AT2[-]: 'host' missing in at2 telnet configuration.");
01500 goto error;
01501 }
01502 if (cfg_get_integer(&portno, cfg, octstr_imm("port")) == -1) {
01503 error(0, "AT2[-]: 'port' missing in at2 telnet configuration.");
01504 goto error;
01505 }
01506 privdata->rawtcp_port = portno;
01507 privdata->is_serial = 0;
01508 privdata->use_telnet = 1;
01509 }else {
01510 privdata->is_serial = 1;
01511 privdata->use_telnet = 0;
01512 }
01513
01514 privdata->name = cfg_get(cfg, octstr_imm("smsc-id"));
01515 if (privdata->name == NULL) {
01516 privdata->name = octstr_duplicate(privdata->device);
01517 }
01518
01519 privdata->speed = 0;
01520 cfg_get_integer(&privdata->speed, cfg, octstr_imm("speed"));
01521
01522 privdata->keepalive = 0;
01523 cfg_get_integer(&privdata->keepalive, cfg, octstr_imm("keepalive"));
01524
01525 cfg_get_bool(&privdata->sms_memory_poll_interval, cfg, octstr_imm("sim-buffering"));
01526 if (privdata->sms_memory_poll_interval) {
01527 if (privdata->keepalive)
01528 privdata->sms_memory_poll_interval = privdata->keepalive;
01529 else
01530 privdata->sms_memory_poll_interval = AT2_DEFAULT_SMS_POLL_INTERVAL;
01531 }
01532
01533 privdata->my_number = cfg_get(cfg, octstr_imm("my-number"));
01534 privdata->sms_center = cfg_get(cfg, octstr_imm("sms-center"));
01535 privdata->username = cfg_get(cfg, octstr_imm("smsc-username"));
01536 privdata->password = cfg_get(cfg, octstr_imm("smsc-password"));
01537 privdata->login_prompt = cfg_get(cfg, octstr_imm("login-prompt"));
01538 privdata->password_prompt = cfg_get(cfg, octstr_imm("password-prompt"));
01539 modem_type_string = cfg_get(cfg, octstr_imm("modemtype"));
01540
01541 privdata->modem = NULL;
01542
01543 if (modem_type_string != NULL) {
01544 if (octstr_compare(modem_type_string, octstr_imm("auto")) == 0 ||
01545 octstr_compare(modem_type_string, octstr_imm("autodetect")) == 0)
01546 O_DESTROY(modem_type_string);
01547 }
01548
01549 if (octstr_len(modem_type_string) == 0) {
01550 info(0, "AT2[%s]: configuration doesn't show modemtype. will autodetect",
01551 octstr_get_cstr(privdata->name));
01552 } else {
01553 info(0, "AT2[%s]: configuration shows modemtype <%s>",
01554 octstr_get_cstr(privdata->name),
01555 octstr_get_cstr(modem_type_string));
01556 privdata->modem = at2_read_modems(privdata, privdata->configfile,
01557 modem_type_string, 0);
01558 if (privdata->modem == NULL) {
01559 info(0, "AT2[%s]: modemtype not found, revert to autodetect",
01560 octstr_get_cstr(privdata->name));
01561 } else {
01562 info(0, "AT2[%s]: read modem definition for <%s>",
01563 octstr_get_cstr(privdata->name),
01564 octstr_get_cstr(privdata->modem->name));
01565 }
01566 O_DESTROY(modem_type_string);
01567 }
01568
01569 privdata->ilb = octstr_create("");
01570 privdata->fd = -1;
01571 privdata->lines = NULL;
01572 privdata->pin = cfg_get(cfg, octstr_imm("pin"));
01573 privdata->pin_ready = 0;
01574 privdata->conn = conn;
01575 privdata->phase2plus = 0;
01576 privdata->validityperiod = cfg_get(cfg, octstr_imm("validityperiod"));
01577 if (cfg_get_integer((long *) &privdata->max_error_count, cfg, octstr_imm("max-error-count")) == -1)
01578 privdata->max_error_count = -1;
01579
01580 conn->data = privdata;
01581 conn->name = octstr_format("AT2[%s]", octstr_get_cstr(privdata->name));
01582 conn->status = SMSCCONN_CONNECTING;
01583
01584 privdata->shutdown = 0;
01585
01586 conn->status = SMSCCONN_CONNECTING;
01587 conn->connect_time = time(NULL);
01588
01589 if ((privdata->device_thread = gwthread_create(at2_device_thread, conn)) == -1) {
01590 privdata->shutdown = 1;
01591 goto error;
01592 }
01593
01594 conn->shutdown = at2_shutdown_cb;
01595 conn->queued = at2_queued_cb;
01596 conn->start_conn = at2_start_cb;
01597 conn->send_msg = at2_add_msg_cb;
01598 return 0;
01599
01600 error:
01601 error(0, "AT2[%s]: Failed to create at2 smsc connection",
01602 octstr_len(privdata->name) ? octstr_get_cstr(privdata->name) : "");
01603 if (privdata != NULL) {
01604 gw_prioqueue_destroy(privdata->outgoing_queue, NULL);
01605 }
01606 gw_free(privdata);
01607 conn->why_killed = SMSCCONN_KILLED_CANNOT_CONNECT;
01608 conn->status = SMSCCONN_DEAD;
01609 info(0, "AT2[%s]: exiting", octstr_get_cstr(privdata->name));
01610 return -1;
01611 }
|
Here is the call graph for this function:

|
|
Definition at line 2782 of file smsc_at.c. 02783 {
02784 return ( ( byte & 15 ) * 10 ) + ( byte >> 4 );
02785 }
|
|
|
Definition at line 2104 of file smsc_at.c. Referenced by at2_decode7bituncompressed(). |
|
|
Definition at line 2103 of file smsc_at.c. Referenced by at2_decode7bituncompressed(). |