📄 smsc_at.c
字号:
at2_close_device(privdata); reconnecting = 1; goto reconnect; } idle_timeout = time(NULL); } if (privdata->sms_memory_poll_interval && memory_poll_timeout + privdata->sms_memory_poll_interval < time(NULL)) { if (at2_read_sms_memory(privdata) == -1) { at2_close_device(privdata); reconnecting = 1; goto reconnect; } memory_poll_timeout = time(NULL); } } at2_close_device(privdata); mutex_lock(conn->flow_mutex); conn->status = SMSCCONN_DISCONNECTED; mutex_unlock(conn->flow_mutex); /* maybe some cleanup here? */ at2_destroy_modem(privdata->modem); octstr_destroy(privdata->device); octstr_destroy(privdata->ilb); octstr_destroy(privdata->lines); octstr_destroy(privdata->pin); octstr_destroy(privdata->validityperiod); octstr_destroy(privdata->my_number); octstr_destroy(privdata->sms_center); octstr_destroy(privdata->name); octstr_destroy(privdata->configfile); gw_prioqueue_destroy(privdata->outgoing_queue, NULL); gwlist_destroy(privdata->pending_incoming_messages, octstr_destroy_item); gw_free(conn->data); conn->data = NULL; mutex_lock(conn->flow_mutex); conn->why_killed = SMSCCONN_KILLED_SHUTDOWN; conn->status = SMSCCONN_DEAD; mutex_unlock(conn->flow_mutex); bb_smscconn_killed();}static int at2_shutdown_cb(SMSCConn *conn, int finish_sending){ PrivAT2data *privdata = conn->data; debug("bb.sms", 0, "AT2[%s]: Shutting down SMSCConn, %s", octstr_get_cstr(privdata->name), finish_sending ? "slow" : "instant"); /* * Documentation claims this would have been done by smscconn.c, * but isn't when this code is being written. */ conn->why_killed = SMSCCONN_KILLED_SHUTDOWN; privdata->shutdown = 1; /* * Separate from why_killed to avoid locking, as * why_killed may be changed from outside? */ if (finish_sending == 0) { Msg *msg; while ((msg = gw_prioqueue_remove(privdata->outgoing_queue)) != NULL) { bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_SHUTDOWN, NULL); } } gwthread_wakeup(privdata->device_thread); return 0;}static long at2_queued_cb(SMSCConn *conn){ long ret; PrivAT2data *privdata = conn->data; if (conn->status == SMSCCONN_DEAD) /* I'm dead, why would you care ? */ return -1; ret = gw_prioqueue_len(privdata->outgoing_queue); /* use internal queue as load, maybe something else later */ conn->load = ret; return ret;}static void at2_start_cb(SMSCConn *conn){ PrivAT2data *privdata = conn->data; if (conn->status == SMSCCONN_DISCONNECTED) conn->status = SMSCCONN_ACTIVE; /* in case there are messages in the buffer already */ gwthread_wakeup(privdata->device_thread); debug("smsc.at2", 0, "AT2[%s]: start called", octstr_get_cstr(privdata->name));}static int at2_add_msg_cb(SMSCConn *conn, Msg *sms){ PrivAT2data *privdata = conn->data; Msg *copy; copy = msg_duplicate(sms); gw_prioqueue_produce(privdata->outgoing_queue, copy); gwthread_wakeup(privdata->device_thread); return 0;}int smsc_at2_create(SMSCConn *conn, CfgGroup *cfg){ PrivAT2data *privdata; Octstr *modem_type_string; long portno; /* has to be long because of cfg_get_integer */ privdata = gw_malloc(sizeof(PrivAT2data)); privdata->outgoing_queue = gw_prioqueue_create(sms_priority_compare); privdata->pending_incoming_messages = gwlist_create(); privdata->configfile = cfg_get_configfile(cfg); privdata->device = cfg_get(cfg, octstr_imm("device")); if (privdata->device == NULL) { error(0, "AT2[-]: 'device' missing in at2 configuration."); goto error; } if (octstr_str_compare(privdata->device, "rawtcp") == 0) { privdata->rawtcp_host = cfg_get(cfg, octstr_imm("host")); if (privdata->rawtcp_host == NULL) { error(0, "AT2[-]: 'host' missing in at2 rawtcp configuration."); goto error; } if (cfg_get_integer(&portno, cfg, octstr_imm("port")) == -1) { error(0, "AT2[-]: 'port' missing in at2 rawtcp configuration."); goto error; } privdata->rawtcp_port = portno; privdata->is_serial = 0; } else { privdata->is_serial = 1; } privdata->name = cfg_get(cfg, octstr_imm("smsc-id")); if (privdata->name == NULL) { privdata->name = octstr_duplicate(privdata->device); } privdata->speed = 0; cfg_get_integer(&privdata->speed, cfg, octstr_imm("speed")); privdata->keepalive = 0; cfg_get_integer(&privdata->keepalive, cfg, octstr_imm("keepalive")); cfg_get_bool(&privdata->sms_memory_poll_interval, cfg, octstr_imm("sim-buffering")); if (privdata->sms_memory_poll_interval) { if (privdata->keepalive) privdata->sms_memory_poll_interval = privdata->keepalive; else privdata->sms_memory_poll_interval = AT2_DEFAULT_SMS_POLL_INTERVAL; } privdata->my_number = cfg_get(cfg, octstr_imm("my-number")); privdata->sms_center = cfg_get(cfg, octstr_imm("sms-center")); modem_type_string = cfg_get(cfg, octstr_imm("modemtype")); privdata->modem = NULL; if (modem_type_string != NULL) { if (octstr_compare(modem_type_string, octstr_imm("auto")) == 0 || octstr_compare(modem_type_string, octstr_imm("autodetect")) == 0) O_DESTROY(modem_type_string); } if (octstr_len(modem_type_string) == 0) { info(0, "AT2[%s]: configuration doesn't show modemtype. will autodetect", octstr_get_cstr(privdata->name)); } else { info(0, "AT2[%s]: configuration shows modemtype <%s>", octstr_get_cstr(privdata->name), octstr_get_cstr(modem_type_string)); privdata->modem = at2_read_modems(privdata, privdata->configfile, modem_type_string, 0); if (privdata->modem == NULL) { info(0, "AT2[%s]: modemtype not found, revert to autodetect", octstr_get_cstr(privdata->name)); } else { info(0, "AT2[%s]: read modem definition for <%s>", octstr_get_cstr(privdata->name), octstr_get_cstr(privdata->modem->name)); } O_DESTROY(modem_type_string); } privdata->ilb = octstr_create(""); privdata->fd = -1; privdata->lines = NULL; privdata->pin = cfg_get(cfg, octstr_imm("pin")); privdata->pin_ready = 0; privdata->conn = conn; privdata->phase2plus = 0; privdata->validityperiod = cfg_get(cfg, octstr_imm("validityperiod")); if (cfg_get_integer((long*) &privdata->max_error_count, cfg, octstr_imm("max-error-count")) == -1) privdata->max_error_count = -1; conn->data = privdata; conn->name = octstr_format("AT2[%s]", octstr_get_cstr(privdata->name)); conn->status = SMSCCONN_CONNECTING; privdata->shutdown = 0; conn->status = SMSCCONN_CONNECTING; conn->connect_time = time(NULL); if ((privdata->device_thread = gwthread_create(at2_device_thread, conn)) == -1) { privdata->shutdown = 1; goto error; } conn->shutdown = at2_shutdown_cb; conn->queued = at2_queued_cb; conn->start_conn = at2_start_cb; conn->send_msg = at2_add_msg_cb; return 0;error: error(0, "AT2[%s]: Failed to create at2 smsc connection", octstr_len(privdata->name) ? octstr_get_cstr(privdata->name) : ""); if (privdata != NULL) { gw_prioqueue_destroy(privdata->outgoing_queue, NULL); } gw_free(privdata); conn->why_killed = SMSCCONN_KILLED_CANNOT_CONNECT; conn->status = SMSCCONN_DEAD; info(0, "AT2[%s]: exiting", octstr_get_cstr(privdata->name)); return -1;}static int at2_pdu_extract(PrivAT2data *privdata, Octstr **pdu, Octstr *line, Octstr *smsc_number){ Octstr *buffer; long len = 0; int pos = 0; int tmp; Octstr *numtmp; Octstr *tmp2; buffer = octstr_duplicate(line); /* find the beginning of a message from the modem*/ if ((pos = octstr_search(buffer, octstr_imm("+CDS:"), 0)) != -1) pos += 5; else { if ((pos = octstr_search(buffer, octstr_imm("+CMT:"), 0)) != -1) pos += 5; else if ((pos = octstr_search(buffer, octstr_imm("+CMGR:"), 0)) != -1) { /* skip status field in +CMGR response */ if ((pos = octstr_search(buffer, octstr_imm(","), pos + 6)) != -1) pos++; else goto nomsg; } else goto nomsg; /* skip the next comma in CMGR and CMT responses */ tmp = octstr_search(buffer, octstr_imm(","), pos); if (!privdata->modem->broken && tmp == -1) goto nomsg; if (tmp != -1) pos = tmp + 1; } /* read the message length */ pos = octstr_parse_long(&len, buffer, pos, 10); if (pos == -1) goto nomsg; /* skip the spaces and line return */ while (isspace(octstr_get_char(buffer, pos))) pos++; octstr_truncate(smsc_number,0); /* skip the SMSC address on some modem types */ if (!privdata->modem->no_smsc) { tmp = at2_hexchar(octstr_get_char(buffer, pos)) * 16 + at2_hexchar(octstr_get_char(buffer, pos + 1)); if (tmp < 0) goto nomsg; numtmp = octstr_create_from_data(octstr_get_cstr(buffer)+pos+2,tmp * 2); /* we now have the hexchars of the SMSC in GSM encoding */ octstr_hex_to_binary(numtmp); tmp2 = gsm2number(numtmp); debug("bb.smsc.at2", 0, "AT2[%s]: received message from SMSC: %s", octstr_get_cstr(privdata->name), octstr_get_cstr(tmp2)); octstr_destroy(numtmp); octstr_append(smsc_number,tmp2); octstr_destroy(tmp2); pos += 2 + tmp * 2; } /* check if the buffer is long enough to contain the full message */ if (!privdata->modem->broken && octstr_len(buffer) < len * 2 + pos) goto nomsg; if (privdata->modem->broken && octstr_len(buffer) < len * 2) goto nomsg; /* copy the PDU then remove it from the input buffer*/ *pdu = octstr_copy(buffer, pos, len * 2); octstr_destroy(buffer); return 1;nomsg: octstr_destroy(buffer); return 0;}static unsigned char nibble2hex(unsigned char b){ if(b < 0x0A) return '0'+ b; else return 'A'+ b - 0x0A;}static Octstr *gsm2number(Octstr *pdu){ Octstr *tmp = NULL; unsigned char c; unsigned char a; unsigned char b; int ton; int npi; int len; int pos; pos=0; len = octstr_len(pdu); ton = octstr_get_char(pdu,pos++); npi = ton & 0x0F; ton = (ton >> 4) & 0x07; switch(ton) { case 0: /* unknown */ tmp = octstr_create(""); break; case 1: /* international */ tmp = octstr_create("+"); break; case 2: /* national */ tmp = octstr_create("0"); break; case 3: /* network-specific */ default: tmp = octstr_create(""); break; } while(--len) { c = octstr_get_char(pdu,pos++); a = c & 0x0F; b = ((c & 0xF0) >> 4); if((b == 0x0F) && (len < 2)) { octstr_append_char(tmp, nibble2hex(a)); } else { octstr_append_char(tmp, nibble2hex(a)); octstr_append_char(tmp, nibble2hex(b)); } } return tmp;}static int at2_hexchar(int hexc){ hexc = toupper(hexc) - 48; return (hexc > 9) ? hexc - 7 : hexc;}static Msg *at2_pdu_decode(Octstr *data, PrivAT2data *privdata){ int type; Msg *msg = NULL; /* Get the PDU type */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -