📄 smsc_smasi.c
字号:
} break; case LogonConf: *pending_submits = 0; smasi->conn->status = SMSCCONN_ACTIVE; smasi->conn->connect_time = time(NULL); bb_smscconn_connected(smasi->conn); info(0, "SMASI[%s]: connection to SMSC established.", octstr_get_cstr(smasi->conn->id)); break; case LogonRej: if (octstr_len(pdu->u.LogonRej.Reason) > 0) { error(0, "SMASI[%s]: SMSC rejected login with reason <%s>", octstr_get_cstr(smasi->conn->id), octstr_get_cstr(pdu->u.LogonRej.Reason)); } else { error(0, "SMASI[%s]: SMSC rejected login without reason", octstr_get_cstr(smasi->conn->id)); } break; case LogoffConf: info(0, "SMASI[%s]: SMSC confirmed logoff.", octstr_get_cstr(smasi->conn->id)); smasi->logged_off = 1; break; default: warning(0, "SMASI[%s]: Unknown PDU type <%s>, ignored.", octstr_get_cstr(smasi->conn->id), pdu->type_name); break; } if (resp != NULL) { send_pdu(conn, smasi->conn->id, resp); smasi_pdu_destroy(resp); }}/************************************************************************//* SMASI CONNECTION HANDLING *//************************************************************************//* * Open transmission connection to SMS center. Return NULL for error, * open connection for OK. Caller must set smasi->conn->status correctly * before calling this. */static Connection *open_connection(SMASI *smasi) { Connection *conn = conn_open_tcp(smasi->host, smasi->port, NULL); if (conn == NULL) { error(0, "SMASI[%s]: Couldn't connect to server.", octstr_get_cstr(smasi->conn->id)); return NULL; } else { SMASI_PDU *logon = smasi_pdu_create(LogonReq); logon->u.LogonReq.Name = octstr_duplicate(smasi->username); logon->u.LogonReq.Password = octstr_duplicate(smasi->password); counter_increase(smasi->message_id_counter); send_pdu(conn, smasi->conn->id, logon); smasi_pdu_destroy(logon); } return conn;} static void send_messages(SMASI *smasi, Connection *conn, long *pending_submits) { if (*pending_submits == -1) return; while (*pending_submits < MAX_PENDING_SUBMITS) { SMASI_PDU *pdu = NULL; /* Get next message, quit if none to be sent. */ Msg * msg = list_extract_first(smasi->msgs_to_send); if (msg == NULL) break; /* Send PDU, record it as waiting for ack from SMSC. */ pdu = msg_to_pdu(smasi, msg); if (pdu->u.SubmitReq.Sequence) dict_put(smasi->sent_msgs, pdu->u.SubmitReq.Sequence, msg); send_pdu(conn, smasi->conn->id, pdu); smasi_pdu_destroy(pdu); ++(*pending_submits); }}/* * This is the main function for the background thread for doing I/O on * one SMASI connection (the one for transmitting or receiving messages). * It makes the initial connection to the SMASI server and re-connects * if there are I/O errors or other errors that require it. */static void smasi_thread(void *arg) { long pending_submits; long len; SMASI_PDU *pdu; SMASI *smasi; int logoff_already_sent = 0; int ret; Connection *conn; long last_enquire_sent; double timeout; smasi = arg; while (!smasi->quitting) { conn = open_connection(smasi); if (conn == NULL) { error(0, "SMASI[%s]: Could not connect to SMSC center " \ "(retrying in %ld seconds).", octstr_get_cstr(smasi->conn->id), smasi->reconnect_delay); gwthread_sleep(smasi->reconnect_delay); smasi->conn->status = SMSCCONN_RECONNECTING; continue; } last_enquire_sent = date_universal_now(); pending_submits = -1; len = 0; for (;;) { timeout = last_enquire_sent + smasi->enquire_link_interval - date_universal_now(); /* Send logoff request if module is shutting down. */ if (smasi->quitting && !logoff_already_sent) { send_logoff(smasi, conn); logoff_already_sent = 1; } /* send an enquire link */ send_enquire_link(smasi, conn, &last_enquire_sent); /* Receive incoming PDUs. */ while ((ret = read_pdu(smasi, conn, &pdu)) == 1) { /* Deal with the PDU we just got */ dump_pdu("Got PDU:", smasi->conn->id, pdu); /* Process the received PDU. */ handle_pdu(smasi, conn, pdu, &pending_submits); smasi_pdu_destroy(pdu); /* Bail out if logoff confirmed. */ if (smasi->logged_off) break; /* Make sure we send even if we read a lot. */ if ((!smasi->throttling_err_time || ((time(NULL) - smasi->throttling_err_time) > SMASI_THROTTLING_SLEEP_TIME && !(smasi->throttling_err_time = 0)))) send_messages(smasi, conn, &pending_submits); } /* Check if connection broken. */ if (ret == -1 || conn_wait(conn, -1) == -1) { error(0, "SMASI[%s]: I/O error or other error. Re-connecting.", octstr_get_cstr(smasi->conn->id)); break; } /* Bail out if logoff confirmed. */ if (smasi->logged_off) break; if ((!smasi->throttling_err_time || ((time(NULL) - smasi->throttling_err_time) > SMASI_THROTTLING_SLEEP_TIME && !(smasi->throttling_err_time = 0)))) send_messages(smasi, conn, &pending_submits); } conn_destroy(conn); conn = NULL; } } /************************************************************************//* SMSCCONN INTERFACE *//************************************************************************/static long queued_cb(SMSCConn *conn) { SMASI *smasi = conn->data; conn->load = (smasi ? (conn->status != SMSCCONN_DEAD ? list_len(smasi->msgs_to_send) : 0) : 0); return conn->load;} static int send_msg_cb(SMSCConn *conn, Msg *msg) { SMASI *smasi = conn->data; list_produce(smasi->msgs_to_send, msg_duplicate(msg)); gwthread_wakeup(smasi->thread_handle); return 0;}static int shutdown_cb(SMSCConn *conn, int finish_sending) { SMASI *smasi = NULL; debug("bb.sms.smasi", 0, "Shutting down SMSCConn %s (%s)", octstr_get_cstr(conn->name), finish_sending ? "slow" : "instant"); conn->why_killed = SMSCCONN_KILLED_SHUTDOWN; smasi = conn->data; smasi->quitting = 1; gwthread_wakeup(smasi->thread_handle); gwthread_join(smasi->thread_handle); smasi_destroy(smasi); debug("bb.sms.smasi", 0, "SMSCConn %s shut down.", octstr_get_cstr(conn->name)); conn->status = SMSCCONN_DEAD; bb_smscconn_killed(); /* Clean up. */ octstr_destroy(colon); octstr_destroy(assign); octstr_destroy(comma); octstr_destroy(cr); octstr_destroy(lf); return 0;}/* * Configures the SMASI structure according to the configuration. * * @return 0 on complete success. -1 if failed due to missing or invalid * configuration entry. */static int init_configuration(SMASI *smasi, CfgGroup *config) { /* Read mandatory entries. */ smasi->host = cfg_get(config, octstr_imm("host")); smasi->username = cfg_get(config, octstr_imm("smsc-username")); smasi->password = cfg_get(config, octstr_imm("smsc-password")); /* Check configuration. */ if (smasi->host == NULL) { error(0,"SMASI: Configuration file doesn't specify host"); return -1; } if (smasi->username == NULL) { error(0, "SMASI: Configuration file doesn't specify username."); return -1; } if (smasi->password == NULL) { error(0, "SMASI: Configuration file doesn't specify password."); return -1; } /* Read optional entries. Set default values if not set. */ smasi->my_number = cfg_get(config, octstr_imm("my-number")); if (cfg_get_integer(&smasi->port, config, octstr_imm("port")) == -1) smasi->port = SMASI_DEFAULT_PORT; if (cfg_get_integer(&smasi->reconnect_delay, config, octstr_imm("reconnect-delay")) == -1) smasi->reconnect_delay = SMASI_RECONNECT_DELAY; if (cfg_get_integer(&smasi->source_addr_ton, config, octstr_imm("source-addr-ton")) == -1) smasi->source_addr_ton = SMASI_OVERRIDE_SOURCE_TON; if (cfg_get_integer(&smasi->source_addr_npi, config, octstr_imm("source-addr-npi")) == -1) smasi->source_addr_npi = SMASI_OVERRIDE_SOURCE_NPI; if (cfg_get_integer(&smasi->dest_addr_ton, config, octstr_imm("dest-addr-ton")) == -1) smasi->source_addr_ton = SMASI_OVERRIDE_DEST_TON; if (cfg_get_integer(&smasi->dest_addr_npi, config, octstr_imm("dest-addr-npi")) == -1) smasi->source_addr_npi = SMASI_OVERRIDE_DEST_NPI; if (cfg_get_integer(&smasi->priority, config, octstr_imm("priority")) == -1) smasi->priority = SMASI_DEFAULT_PRIORITY; if (cfg_get_integer(&smasi->enquire_link_interval, config, octstr_imm("enquire-link-interval")) == -1) smasi->enquire_link_interval = SMASI_ENQUIRE_LINK_INTERVAL; /* Configure SMSC connection. */ smasi->conn->data = smasi; smasi->conn->name = octstr_format("SMASI:%S:%d:%S", smasi->host, smasi->port, smasi->username); smasi->conn->id = cfg_get(config, octstr_imm("smsc-id")); if (smasi->conn->id == NULL) smasi->conn->id = octstr_duplicate(smasi->conn->name); return 0;} int smsc_smasi_create(SMSCConn *conn, CfgGroup *config) { SMASI *smasi = NULL; /* Initialize data encoding subsystem. */ colon = octstr_create(":3a"); assign = octstr_create(":3d"); comma = octstr_create(":2c"); cr = octstr_create(":0a"); lf = octstr_create(":0d"); /* Create main SMASI structure and initialize it with configuration * settings. */ smasi = smasi_create(conn); if (init_configuration(smasi, config) != 0) panic(0, "SMASI SMSC module configuration invalid."); conn->status = SMSCCONN_CONNECTING; /* Port is always set to a configured value or defaults to 21500. * Therefore, threads are always started. */ smasi->thread_handle = gwthread_create(smasi_thread, smasi); if (smasi->thread_handle == -1) { error(0, "SMASI[%s]: Couldn't start SMASI thread.", octstr_get_cstr(smasi->conn->id)); smasi_destroy(conn->data); return -1; } /* Setup control function pointers. */ conn->shutdown = shutdown_cb; conn->queued = queued_cb; conn->send_msg = send_msg_cb; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -