📄 smsc_at2.c
字号:
{ SMSCConn *conn = arg; PrivAT2data *privdata = conn->data; int l, wait = 0; long idle_timeout, memory_poll_timeout = 0; conn->status = SMSCCONN_CONNECTING;reconnect: do { if (wait) { if (conn->status == SMSCCONN_ACTIVE) { mutex_lock(conn->flow_mutex); conn->status = SMSCCONN_RECONNECTING; mutex_unlock(conn->flow_mutex); } info(0, "AT2[%s]: waiting for %d %s before trying to connect again", octstr_get_cstr(privdata->name), (wait < 60 ? wait : wait / 60), (wait < 60 ? "seconds" : "minutes")); gwthread_sleep(wait); wait = wait > (privdata->retry ? 3600 : 600) ? (privdata->retry ? 3600 : 600) : wait * 2; } else wait = 15; /* If modems->speed is defined, try to use it, else autodetect */ if (privdata->speed == 0 && privdata->modem != NULL && privdata->modem->speed != 0) { info(0, "AT2[%s]: trying to use speed <%ld> from modem definition", octstr_get_cstr(privdata->name), privdata->modem->speed); if(0 == at2_test_speed(privdata, privdata->modem->speed)) { privdata->speed = privdata->modem->speed; info(0, "AT2[%s]: speed is %ld", octstr_get_cstr(privdata->name), privdata->speed); } else { info(0, "AT2[%s]: speed in modem definition don't work, will autodetect", octstr_get_cstr(privdata->name)); } } if (privdata->speed == 0) { if (at2_detect_speed(privdata) == -1) { if (!privdata->retry) return; else continue; } } if (privdata->modem == NULL) { if (at2_detect_modem_type(privdata) == -1) { if (!privdata->retry) return; else continue; } } if (at2_open_device(privdata)) { error(errno, "AT2[%s]: at2_device_thread: open_at2_device failed. Terminating", octstr_get_cstr(privdata->name)); if (!privdata->retry) return; else continue; } if (at2_init_device(privdata) != 0) { error(0, "AT2[%s]: Opening failed. Terminating", octstr_get_cstr(privdata->name)); if (!privdata->retry) { privdata->shutdown = 1; //return; } else continue; } /* If we got here, then the device is opened */ break; } while (privdata->retry && !privdata->shutdown); conn->status = SMSCCONN_ACTIVE; bb_smscconn_connected(conn); idle_timeout = 0; while (!privdata->shutdown) { l = list_len(privdata->outgoing_queue); if (l > 0) { at2_send_messages(privdata); idle_timeout = time(NULL); } else at2_wait_modem_command(privdata, 1, 0, NULL); if (privdata->keepalive && idle_timeout + privdata->keepalive < time(NULL)) { if (at2_send_modem_command(privdata, octstr_get_cstr(privdata->modem->keepalive_cmd), 5, 0) < 0) { at2_close_device(privdata); conn->status = SMSCCONN_RECONNECTING; wait = 15; goto reconnect; } idle_timeout = time(NULL); } if (privdata->sms_memory_poll_interval && memory_poll_timeout + privdata->sms_memory_poll_interval < time(NULL)) { at2_read_sms_memory(privdata); memory_poll_timeout = time(NULL); } } at2_close_device(privdata); conn->status = SMSCCONN_DISCONNECTED; /* 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); list_destroy(privdata->outgoing_queue, NULL); gw_free(conn->data); conn->data = NULL; conn->why_killed = SMSCCONN_KILLED_SHUTDOWN; conn->status = SMSCCONN_DEAD; bb_smscconn_killed();}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 = list_extract_first(privdata->outgoing_queue)) != NULL) { bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_SHUTDOWN); } } gwthread_wakeup(privdata->device_thread); return 0;}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 = list_len(privdata->outgoing_queue); /* use internal queue as load, maybe something else later */ conn->load = ret; return ret;}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));}int at2_add_msg_cb(SMSCConn *conn, Msg *sms){ PrivAT2data *privdata = conn->data; Msg *copy; copy = msg_duplicate(sms); list_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; privdata = gw_malloc(sizeof(PrivAT2data)); privdata->outgoing_queue = list_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; } 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; } cfg_get_bool(&privdata->retry, cfg, octstr_imm("retry")); 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")); cfg_get_bool(&privdata->alt_dcs, cfg, octstr_imm("alt-dcs")); conn->data = privdata; conn->name = octstr_format("AT2[%s]", octstr_get_cstr(privdata->name)); 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) { list_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;}int at2_pdu_extract(PrivAT2data *privdata, Octstr **pdu, Octstr *line){ Octstr *buffer; long len = 0; int pos = 0; int tmp; 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++; /* 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; tmp = 2 + tmp * 2; pos += tmp; } /* 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;}int at2_hexchar(int hexc){ hexc = toupper(hexc) - 48; return (hexc > 9) ? hexc - 7 : hexc;}Msg *at2_pdu_decode(Octstr *data, PrivAT2data *privdata){ int type; Msg *msg = NULL; /* Get the PDU type */ type = octstr_get_char(data, 1) & 3; switch (type) { case AT_DELIVER_SM: msg = at2_pdu_decode_deliver_sm(data, privdata); break; case AT_STATUS_REPORT_SM: msg = at2_pdu_decode_report_sm(data, privdata);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -