smscconn cimd2
Kalle Marjola <[email protected]>
| Newsgroups | gmane.comp.mobile.kannel.devel |
|---|---|
| Message-ID | <[email protected]> |
The attached patch changes cimd2 to use SMSCConn instead of old SMSCenter. However, notes: - diffed against latest CVS version (just did cvs udpate) - not tested! We do not have cimd2 currently available. Compiles, however =] - had some problem with merge, so it could have been made more efficiently (in original version, only PrivData was moved around, not entire SMSCConn, but DLR merge required modifications) - does not fully utilize SMSCConn possibilities, it is more like smsc_wrapper moved to cimd2. But it is easier to start using them after this works (and get rid of smsc_wrapper...) - includes some notes of various extra code which I couldn't include in the patch as then it would require patching of yet another big pile of files. However, if this can be merged, they might come next. -- &kalle marjola product concept manager NETikos finland (http://www.netikos.fi)
cimd2.patch
(text/plain, 33.2 KB)
Index: gw/smscconn.c
===================================================================
RCS file: /home/cvs/gateway/gw/smscconn.c,v
retrieving revision 1.32
diff -r1.32 smscconn.c
74a75,76
> else if (octstr_compare(smsc_type, octstr_imm("cimd2")) == 0)
> ret = smsc_cimd2_create(conn, grp);
Index: gw/smscconn_p.h
===================================================================
RCS file: /home/cvs/gateway/gw/smscconn_p.h,v
retrieving revision 1.32
diff -r1.32 smscconn_p.h
180a181,183
> /* Responsible file: smsc/smsc_cimd2.c */
> int smsc_cimd2_create(SMSCConn *conn, CfgGroup *cfg);
>
Index: gw/smsc/smsc.c
===================================================================
RCS file: /home/cvs/gateway/gw/smsc/smsc.c,v
retrieving revision 1.1
diff -r1.1 smsc.c
76,87d75
< /* CIMD 2 */
< smsc->cimd2_hostname = NULL;
< smsc->cimd2_port = -1;
< smsc->cimd2_username = NULL;
< smsc->cimd2_password = NULL;
< smsc->cimd2_send_seq = 1;
< smsc->cimd2_receive_seq = 0;
< smsc->cimd2_inbuffer = NULL;
< smsc->cimd2_received = NULL;
< smsc->cimd2_error = 0;
< smsc->cimd2_next_ping = 0;
<
158,165d145
< /* CIMD 2 */
< octstr_destroy(smsc->cimd2_hostname);
< octstr_destroy(smsc->cimd2_username);
< octstr_destroy(smsc->cimd2_password);
< octstr_destroy(smsc->cimd2_inbuffer);
< octstr_destroy(smsc->sender_prefix);
< list_destroy(smsc->cimd2_received, NULL);
<
216,220d195
< case SMSC_TYPE_CIMD2:
< if (cimd2_submit_msg(smsc, msg) == -1)
< goto error;
< break;
<
272,277d246
< case SMSC_TYPE_CIMD2:
< ret = cimd2_receive_msg(smsc, msg);
< if (ret == -1)
< goto error;
< break;
<
336,341d304
< case SMSC_TYPE_CIMD2:
< ret = cimd2_pending_smsmessage(smsc);
< if (ret == -1)
< goto error;
< break;
<
503,504d465
< else if (octstr_compare(type, octstr_imm("cimd2")) == 0)
< typeno = SMSC_TYPE_CIMD2;
579,590d539
< case SMSC_TYPE_CIMD2:
< if (host == NULL || port == 0 || username == NULL || password == NULL)
< error(0, "Required field missing for CIMD 2 center.");
< else
< smsc = cimd2_open(host,
< port,
< username,
< password,
< keepalive,
< sender_prefix);
< break;
<
708,710d656
< case SMSC_TYPE_CIMD2:
< ret = cimd2_reopen(smsc);
< break;
754,758d699
< errors = 1;
< break;
<
< case SMSC_TYPE_CIMD2:
< if (cimd2_close(smsc) == -1)
Index: gw/smsc/smsc_p.h
===================================================================
RCS file: /home/cvs/gateway/gw/smsc/smsc_p.h,v
retrieving revision 1.1
diff -r1.1 smsc_p.h
26d25
< SMSC_TYPE_CIMD2,
92,104d90
< /* CIMD 2 */
< Octstr *cimd2_hostname;
< int cimd2_port;
< Octstr *cimd2_username;
< Octstr *cimd2_password;
< int cimd2_send_seq;
< int cimd2_receive_seq;
< Octstr *cimd2_inbuffer;
< List *cimd2_received;
< int cimd2_error;
< time_t cimd2_next_ping;
< Octstr *sender_prefix;
<
199,208d184
<
< /*
< * Interface to Nokia SMS centers using CIMD 2.
< */
< SMSCenter *cimd2_open(Octstr *hostname, int port, Octstr *username, Octstr *password, int keepalive, Octstr *sender_prefix);
< int cimd2_reopen(SMSCenter *smsc);
< int cimd2_close(SMSCenter *smsc);
< int cimd2_pending_smsmessage(SMSCenter *smsc);
< int cimd2_submit_msg(SMSCenter *smsc, Msg *msg);
< int cimd2_receive_msg(SMSCenter *smsc, Msg **msg);
Index: gw/smsc/smsc_cimd2.c
===================================================================
RCS file: /home/cvs/gateway/gw/smsc/smsc_cimd2.c,v
retrieving revision 1.2
diff -r1.2 smsc_cimd2.c
3a4,5
> *
> * Merge of SMSC Wrapper 2002 Kalle Marjola
31c33,37
< #include "smsc_p.h"
---
> #include "smscconn.h"
> #include "smscconn_p.h"
> #include "bb_smscconn_cb.h"
>
> #include "shared.h"
39a46,77
> /* Our private data (km 02) */
>
> typedef struct privdata {
> Octstr *username;
> Octstr *password;
> Octstr *hostname;
> long port;
> long keepalive;
>
> int socket;
> int send_seq;
> int receive_seq;
>
> Octstr *inbuffer;
> List *received;
>
> time_t next_ping;
> Octstr *sender_prefix;
>
> /* these following ones are directly from SMSC wrapper,
> * get rid of them as need to. */
>
> List *outgoing_queue;
> List *stopped; /* list-trick for suspend/isolate */
> long receiver_thread;
> long sender_thread;
> Mutex *reconnect_mutex;
>
> } PrivData;
>
>
>
357c395
< * stored as a valid encoded packet, and decoded as necessary.
---
> * stored as a valid encoded packet, and decoded as necessary.
382c420,421
< static Msg *cimd2_accept_delivery_report_message(struct packet *request, SMSCenter *smsc);
---
> static Msg *cimd2_accept_delivery_report_message(struct packet *request,
> SMSCConn *conn);
1280d1318
< spaceleft -= octstr_len(msg->sms.udhdata);
1287a1326
>
1308,1311d1346
< #if CIMD2_TRACE
< debug("bb.sms.cimd2", 0, "After CIMD2 encoding:");
< octstr_dump(text, 0);
< #endif
1317a1353,1358
> /* VALIDITY PERIOD NOT SET YET
> * packet_add_int_parm(packet, P_VALIDITY_PERIOD_RELATIVE,
> validity_minutes_to_gsm(msg->sms.validity -
> (time(NULL) - msg->sms.gw_time) / 60));
> */
>
1332c1373
< static void packet_set_send_sequence(struct packet *packet, SMSCenter *smsc)
---
> static void packet_set_send_sequence(struct packet *packet, PrivData *pdata)
1334c1375
< gw_assert(smsc != NULL);
---
> gw_assert(pdata != NULL);
1336c1377
< gw_assert(smsc->cimd2_send_seq % 2 == 1);
---
> gw_assert(pdata->send_seq % 2 == 1);
1338,1341c1379,1382
< packet_set_sequence(packet, smsc->cimd2_send_seq);
< smsc->cimd2_send_seq += 2;
< if (smsc->cimd2_send_seq > 256)
< smsc->cimd2_send_seq = 1;
---
> packet_set_sequence(packet, pdata->send_seq);
> pdata->send_seq += 2;
> if (pdata->send_seq > 256)
> pdata->send_seq = 1;
1344c1385
< static struct packet *cimd2_get_packet(SMSCenter *smsc, Octstr **ts)
---
> static struct packet *cimd2_get_packet(PrivData *pdata, Octstr **ts)
1348c1389
< gw_assert(smsc != NULL);
---
> gw_assert(pdata != NULL);
1351c1392
< packet = packet_extract(smsc->cimd2_inbuffer);
---
> packet = packet_extract(pdata->inbuffer);
1354c1395
< if (read_available(smsc->socket, RESPONSE_TIMEOUT) != 1) {
---
> if (read_available(pdata->socket, RESPONSE_TIMEOUT) != 1) {
1359c1400
< if (octstr_append_from_socket(smsc->cimd2_inbuffer, smsc->socket) <= 0) {
---
> if (octstr_append_from_socket(pdata->inbuffer, pdata->socket) <= 0) {
1364c1405
< packet = packet_extract(smsc->cimd2_inbuffer);
---
> packet = packet_extract(pdata->inbuffer);
1369,1370c1410,1411
< if(ts)
< *ts = packet_get_parm(packet,P_MC_TIMESTAMP);
---
> if(ts)
> *ts = packet_get_parm(packet,P_MC_TIMESTAMP);
1372,1373c1413,1414
< if (smsc->keepalive > 0)
< smsc->cimd2_next_ping = time(NULL) + 60 * smsc->keepalive;
---
> if (pdata->keepalive > 0)
> pdata->next_ping = time(NULL) + 60 * pdata->keepalive;
1380c1421
< static void cimd2_send_response(struct packet *request, SMSCenter *smsc)
---
> static void cimd2_send_response(struct packet *request, PrivData *pdata)
1392c1433
< octstr_write_to_socket(smsc->socket, response->data);
---
> octstr_write_to_socket(pdata->socket, response->data);
1408c1449
< * yy = 00, default alphabet
---
> * yy = 00, default alphabet
1410c1451
< * yy = 10, UCS2 (can't handle yet)
---
> * yy = 10, UCS2
1424,1427d1464
< #if CIMD2_TRACE
< debug("bb.sms.cimd2", 0, "CIMD2 received message. Text:");
< octstr_dump(text, 0);
< #endif
1429,1433c1466
< charset_gsm_to_latin1(text);
< #if CIMD2_TRACE
< debug("bb.sms.cimd", 0, "Text in latin1:");
< octstr_dump(text, 0);
< #endif
---
> /* charset = charset_gsm; /* This overrides what we got from the DCS */
1434a1468,1473
> /*
> * FIXME: If DCS indicates GSM charset, and we get it in binary,
> * then it's probably bit-packed. We'll have to undo it because
> * our "charset_gsm" means one gsm character per octet. This is
> * not currently supported. -- RB
> */
1436,1439d1474
< #if CIMD2_TRACE
< debug("bb.sms.cimd2", 0, "CIMD2 received message. Text:");
< octstr_dump(text, 0);
< #endif
1444c1479
< * lack them. If they should not be discarded, then the code
---
> * lack them. If they should not be discarded, then the code
1484c1519
< static void cimd2_handle_request(struct packet *request, SMSCenter *smsc)
---
> static void cimd2_handle_request(struct packet *request, SMSCConn *conn)
1486a1522
> PrivData *pdata = conn->data;
1492c1528
< message = cimd2_accept_delivery_report_message(request,smsc);
---
> message = cimd2_accept_delivery_report_message(request, conn);
1494c1530
< list_append(smsc->cimd2_received, message);
---
> list_append(pdata->received, message);
1499c1535
< list_append(smsc->cimd2_received, message);
---
> list_append(pdata->received, message);
1502c1538
< cimd2_send_response(request, smsc);
---
> cimd2_send_response(request, pdata);
1506c1542
< * an error code, attempt to correct and retry.
---
> * an error code, attempt to correct and retry.
1519c1555
< static int cimd2_request(struct packet *request, SMSCenter *smsc, Octstr **ts)
---
> static int cimd2_request(struct packet *request, SMSCConn *conn)
1520a1557
> PrivData *pdata = conn->data;
1524a1562
> Octstr *ts;
1526c1564
< gw_assert(smsc != NULL);
---
> gw_assert(pdata != NULL);
1530c1568
< if (smsc->socket < 0) {
---
> if (pdata->socket < 0) {
1536c1574
< packet_set_send_sequence(request, smsc);
---
> packet_set_send_sequence(request, pdata);
1539c1577
< ret = octstr_write_to_socket(smsc->socket, request->data);
---
> ret = octstr_write_to_socket(pdata->socket, request->data);
1544,1545c1582,1584
< /*reply = cimd2_get_packet(smsc,ts);*/
< reply = cimd2_get_packet(smsc, NULL);
---
> packet_destroy(reply); // destroy old, if any
> reply = cimd2_get_packet(pdata, &ts);
>
1558,1559c1597,1598
< (long) smsc->cimd2_send_seq, (long) reply->seq);
< smsc->cimd2_send_seq = reply->seq;
---
> (long) pdata->send_seq, (long) reply->seq);
> pdata->send_seq = reply->seq;
1572,1573c1611
< cimd2_handle_request(reply, smsc);
< packet_destroy(reply);
---
> cimd2_handle_request(reply, conn);
1601a1640
>
1623c1662
< static void cimd2_close_socket(SMSCenter *smsc)
---
> static void cimd2_close_socket(PrivData *pdata)
1625c1664
< gw_assert(smsc != NULL);
---
> gw_assert(pdata != NULL);
1627c1666
< if (smsc->socket < 0)
---
> if (pdata->socket < 0)
1630c1669
< if (close(smsc->socket) < 0)
---
> if (close(pdata->socket) < 0)
1632c1671
< smsc->socket = -1;
---
> pdata->socket = -1;
1639c1678
< static int cimd2_login(SMSCenter *smsc)
---
> static int cimd2_login(SMSCConn *conn)
1640a1680
> PrivData *pdata = conn->data;
1644c1684
< gw_assert(smsc != NULL);
---
> gw_assert(pdata != NULL);
1646c1686
< if (smsc->socket >= 0) {
---
> if (pdata->socket >= 0) {
1648c1688
< cimd2_close_socket(smsc);
---
> cimd2_close_socket(pdata);
1651,1654c1691,1693
< smsc->socket = tcpip_connect_to_server(octstr_get_cstr(smsc->cimd2_hostname),
< smsc->cimd2_port, NULL);
< /* XXX add interface_name if required */
< if (smsc->socket == -1)
---
> pdata->socket = tcpip_connect_to_server(octstr_get_cstr(pdata->hostname),
> pdata->port, NULL);
> if (pdata->socket == -1)
1658,1659c1697,1700
< packet_add_string_parm(packet, P_USER_IDENTITY, smsc->cimd2_username);
< packet_add_string_parm(packet, P_PASSWORD, smsc->cimd2_password);
---
> packet_add_string_parm(packet, P_USER_IDENTITY, pdata->username);
> packet_add_string_parm(packet, P_PASSWORD, pdata->password);
>
> ret = cimd2_request(packet, conn);
1661d1701
< ret = cimd2_request(packet, smsc, NULL);
1666c1706,1707
< info(0, "%s logged in.", smsc_name(smsc));
---
> /* XXX was: smsc_name() but remoevd to get rid of SMSCenter struct */
> info(0, "CIMD2 logged in.");
1672c1713
< cimd2_close_socket(smsc);
---
> cimd2_close_socket(pdata);
1677c1718
< static void cimd2_logout(SMSCenter *smsc)
---
> static void cimd2_logout(SMSCConn *conn)
1678a1720
> PrivData *pdata = conn->data;
1681c1723
< gw_assert(smsc != NULL);
---
> gw_assert(pdata != NULL);
1685c1727,1728
< cimd2_request(packet, smsc,NULL);
---
>
> cimd2_request(packet, conn);
1689c1732
< static int cimd2_send_alive(SMSCenter *smsc)
---
> static int cimd2_send_alive(SMSCConn *conn)
1690a1734
> PrivData *pdata = conn->data;
1694c1738
< gw_assert(smsc != NULL);
---
> gw_assert(pdata != NULL);
1697c1741
< ret = cimd2_request(packet, smsc,NULL);
---
> ret = cimd2_request(packet, conn);
1706,1708d1749
< /***************************************************************************/
< /* SMSC Interface, as defined in smsc_interface.def */
< /***************************************************************************/
1710,1711c1751
< SMSCenter *cimd2_open(Octstr *hostname, int port, Octstr *username,
< Octstr *password, int keepalive, Octstr *sender_prefix)
---
> static void cimd2_destroy(PrivData *pdata)
1713,1714c1753,1768
< SMSCenter *smsc = NULL;
< int maxlen;
---
> int discarded;
>
> if (pdata == NULL)
> return;
> octstr_destroy(pdata->hostname);
> octstr_destroy(pdata->username);
> octstr_destroy(pdata->password);
> octstr_destroy(pdata->inbuffer);
> octstr_destroy(pdata->sender_prefix);
>
> discarded = list_len(pdata->received);
> list_destroy(pdata->received, msg_destroy_item);
>
> list_destroy(pdata->outgoing_queue, NULL);
> list_destroy(pdata->stopped, NULL);
> mutex_destroy(pdata->reconnect_mutex);
1716,1717c1770
< smsc = smscenter_construct();
< gw_assert(smsc != NULL);
---
> gw_free(pdata);
1719,1731c1772,1780
< smsc->type = SMSC_TYPE_CIMD2;
< smsc->keepalive = keepalive;
< smsc->cimd2_hostname = octstr_duplicate(hostname);
< smsc->cimd2_port = port;
< smsc->cimd2_username = octstr_duplicate(username);
< smsc->cimd2_password = octstr_duplicate(password);
< smsc->sender_prefix = octstr_duplicate(sender_prefix);
< sprintf(smsc->name, "CIMD2:%s:%d:%s", octstr_get_cstr(hostname), port, octstr_get_cstr(username));
< smsc->cimd2_received = list_create();
< smsc->cimd2_inbuffer = octstr_create("");
< smsc->cimd2_error = 0;
< if (keepalive > 0)
< smsc->cimd2_next_ping = time(NULL) + keepalive * 60;
---
> if (discarded > 0)
> warning(0, "CIMD2: discarded %d received messages", discarded);
> }
>
>
>
> /***************************************************************************
> * Old SMSC interface. Get rid of this as soon as other moves work.
> */
1732a1782,1819
>
> static Octstr *cimd2_open(SMSCConn *conn, CfgGroup *grp)
> {
> PrivData *pdata = conn->data;
> Octstr *name = NULL;
> int maxlen;
>
> pdata->hostname = cfg_get(grp, octstr_imm("host"));
> pdata->username = cfg_get(grp, octstr_imm("smsc-username"));
> pdata->password = cfg_get(grp, octstr_imm("smsc-password"));
> pdata->sender_prefix = cfg_get(grp, octstr_imm("sender-prefix"));
>
> if (cfg_get_integer(&(pdata->port), grp, octstr_imm("port")) == -1)
> pdata->port = 0;
>
> if (cfg_get_integer(&(pdata->keepalive), grp,
> octstr_imm("keepalive")) == -1)
> pdata->keepalive = 0;
>
> if (!pdata->hostname || !pdata->username || !pdata->password ||
> pdata->port == 0) {
> error(0, "CIMD2: missing configuration variables");
> goto error;
> }
> name = octstr_format("CIMD2:%s:%d:%s",
> octstr_get_cstr(pdata->hostname),
> pdata->port, octstr_get_cstr(pdata->username));
>
> pdata->received = list_create();
> pdata->inbuffer = octstr_create("");
>
> pdata->send_seq = 1;
> pdata->receive_seq = 0;
>
> if (pdata->keepalive > 0) {
> debug("sms.cimd2", 0, "Keepalive set to %ld", pdata->keepalive);
> pdata->next_ping = time(NULL) + pdata->keepalive * 60;
> }
1734,1735c1821,1822
< if (octstr_len(smsc->cimd2_username) > maxlen) {
< octstr_truncate(smsc->cimd2_username, maxlen);
---
> if (octstr_len(pdata->username) > maxlen) {
> octstr_truncate(pdata->username, maxlen);
1740,1741c1827,1828
< if (octstr_len(smsc->cimd2_password) > maxlen) {
< octstr_truncate(smsc->cimd2_password, maxlen);
---
> if (octstr_len(pdata->password) > maxlen) {
> octstr_truncate(pdata->password, maxlen);
1745c1832
< if (cimd2_login(smsc) < 0)
---
> if (cimd2_login(conn) < 0)
1748c1835
< return smsc;
---
> return name;
1752,1753c1839,1840
< smscenter_destruct(smsc);
< return NULL;
---
> octstr_destroy(name);
> return NULL; /* pdata is destroyed there */
1756c1843,1844
< int cimd2_reopen(SMSCenter *smsc)
---
>
> static int cimd2_reopen(SMSCConn *conn)
1758c1846,1847
< gw_assert(smsc != NULL);
---
> PrivData *pdata = conn->data;
> gw_assert(pdata != NULL);
1762c1851
< cimd2_close_socket(smsc);
---
> cimd2_close_socket(pdata);
1765,1766c1854,1855
< smsc->cimd2_send_seq = 1;
< smsc->cimd2_receive_seq = 0;
---
> pdata->send_seq = 1;
> pdata->receive_seq = 0;
1769,1770c1858,1859
< octstr_destroy(smsc->cimd2_inbuffer);
< smsc->cimd2_inbuffer = octstr_create("");
---
> octstr_destroy(pdata->inbuffer);
> pdata->inbuffer = octstr_create("");
1772c1861
< return cimd2_login(smsc);
---
> return cimd2_login(conn);
1775c1864,1865
< int cimd2_close(SMSCenter *smsc)
---
>
> static int cimd2_reconnect(SMSCConn *conn)
1776a1867,1868
> PrivData *pdata = conn->data;
> Msg *msg;
1778c1870
< int discarded;
---
> int wait = 1;
1780c1872,1932
< gw_assert(smsc != NULL);
---
> /* disable double-reconnect
> * NOTE: it is still possible that we do oduble-connect if
> * first thread gets through this if-statement and then
> * execution switches to another thread.. this can be avoided
> * via double-mutex system, but I do not feel it is worth it,
> * maybe later --rpr
> */
> if (conn->status == SMSCCONN_RECONNECTING) {
> mutex_lock(pdata->reconnect_mutex); /* wait here */
> mutex_unlock(pdata->reconnect_mutex);
> return 0;
> }
> mutex_lock(pdata->reconnect_mutex);
>
> debug("bb.sms", 0, "smsc_cimd2 <%s>: reconnect started",
> octstr_get_cstr(conn->name));
>
> while((msg = list_extract_first(pdata->outgoing_queue))!=NULL) {
> bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_TEMPORARILY);
> }
> conn->status = SMSCCONN_RECONNECTING;
>
> while(conn->why_killed == SMSCCONN_ALIVE) {
> ret = cimd2_reopen(conn);
> if (ret == 0) {
> info(0, "Re-open of %s succeeded.", octstr_get_cstr(conn->name));
> mutex_lock(conn->flow_mutex);
> conn->status = SMSCCONN_ACTIVE;
> conn->connect_time = time(NULL);
> mutex_unlock(conn->flow_mutex);
> bb_smscconn_connected(conn);
> break;
> }
> else if (ret == -2) {
> error(0, "Re-open of %s failed permanently",
> octstr_get_cstr(conn->name));
> mutex_lock(conn->flow_mutex);
> conn->status = SMSCCONN_DISCONNECTED;
> mutex_unlock(pdata->reconnect_mutex);
> mutex_unlock(conn->flow_mutex);
> return -1; /* permanent failure */
> }
> else {
> error(0, "Re-open to <%s> failed, retrying after %d minutes...",
> octstr_get_cstr(conn->name), wait);
> gwthread_sleep(wait*60.0);
>
> wait = wait > 10 ? 10 : wait * 2 + 1;
> }
> }
> mutex_unlock(pdata->reconnect_mutex);
> return 0;
> }
>
>
> static int cimd2_close(SMSCConn *conn)
> {
> PrivData *pdata = conn->data;
> int ret;
>
> gw_assert(pdata != NULL);
1784c1936
< if (smsc->socket < 0) {
---
> if (pdata->socket < 0) {
1789c1941
< cimd2_logout(smsc);
---
> cimd2_logout(conn);
1791,1805c1943,1944
< ret = close(smsc->socket);
< smsc->socket = -1;
<
< smsc->cimd2_send_seq = 0;
< smsc->cimd2_receive_seq = 1;
< octstr_destroy(smsc->cimd2_hostname);
< octstr_destroy(smsc->cimd2_username);
< octstr_destroy(smsc->cimd2_password);
< octstr_destroy(smsc->cimd2_inbuffer);
<
< discarded = list_len(smsc->cimd2_received);
< list_destroy(smsc->cimd2_received, msg_destroy_item);
<
< if (discarded > 0)
< warning(0, "CIMD2: discarded %d received messages", discarded);
---
> ret = close(pdata->socket);
> cimd2_destroy(pdata);
1810c1949
< int cimd2_submit_msg(SMSCenter *smsc, Msg *msg)
---
> static int cimd2_submit_msg(SMSCConn *conn, Msg *msg)
1811a1951
> PrivData *pdata = conn->data;
1814,1816d1953
< int tries;
< Octstr *ts;
< ts = NULL;
1818,1843c1955,1965
< gw_assert(smsc != NULL);
<
< packet = packet_encode_message(msg, smsc->sender_prefix);
< if (!packet)
< return 0; /* We can't signal protocol errors yet */
<
< for (tries = 0; tries < 3; tries++) {
< ret = cimd2_request(packet, smsc,&ts);
< if((ret == 0) && (ts) && (msg->sms.dlr_mask & 0x03))
< {
< dlr_add(smsc->name,
< octstr_get_cstr(ts),
< octstr_get_cstr(msg->sms.sender),
< octstr_get_cstr(msg->sms.receiver),
< octstr_get_cstr(msg->sms.service),
< octstr_get_cstr(msg->sms.dlr_url),
< msg->sms.dlr_mask);
< octstr_destroy(ts);
< ts = NULL;
< }
< if (ret == 0 || ret == -1)
< break;
< if (cimd2_reopen(smsc) < 0) {
< ret = -1;
< break;
< }
---
> gw_assert(pdata != NULL);
> debug("bb.sms", 0, "smscconn_sender (%s): sending message",
> octstr_get_cstr(conn->name));
>
> packet = packet_encode_message(msg, pdata->sender_prefix);
> if (!packet) {
> /* This is a protocol error. Does this help? I doubt..
> * But nevermind that.
> */
> bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_MALFORMED);
> return -1;
1845a1968,1981
> ret = cimd2_request(packet, conn);
> if (ret == 0) { /* successful */
> packet_destroy(packet);
> bb_smscconn_sent(conn, msg);
> return 0;
> }
> else if (ret == -1) {
> packet_destroy(packet);
> bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_REJECTED);
> return -1;
> }
> /*
> * other error, re-rout message and reconnect
> */
1847c1983,1988
< return ret;
---
> bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_TEMPORARILY);
>
> if (cimd2_reconnect(conn) == -1) /* this should NOT happen */
> smscconn_shutdown(conn, 0);
>
> return -1;
1855c1996
< int cimd2_pending_smsmessage(SMSCenter *smsc)
---
> static int cimd2_receive_msg(SMSCConn *conn, Msg **msg)
1858a2000
> PrivData *pdata = conn->data;
1860,1861c2002
< gw_assert(smsc != NULL);
< gw_assert(smsc->type == SMSC_TYPE_CIMD2);
---
> gw_assert(pdata != NULL);
1863c2004,2005
< if (list_len(smsc->cimd2_received) > 0)
---
> if (list_len(pdata->received) > 0) {
> *msg = list_consume(pdata->received);
1864a2007
> }
1866c2009
< if (smsc->socket < 0) {
---
> if (pdata->socket < 0) {
1870c2013
< * way. */
---
> * way. */
1874c2017
< ret = read_available(smsc->socket, 0);
---
> ret = read_available(pdata->socket, 0);
1876,1880c2019,2021
< if (smsc->keepalive > 0 && smsc->cimd2_next_ping < time(NULL)) {
< if (cimd2_send_alive(smsc) < 0) {
< smsc->cimd2_error = 1;
< return 1;
< }
---
> if (pdata->keepalive > 0 && pdata->next_ping < time(NULL)) {
> if (cimd2_send_alive(conn) < 0)
> return -1;
1886,1888c2027,2028
< warning(errno, "cimd2_pending_smsmessage: read_available failed");
< smsc->cimd2_error = 1;
< return 1;
---
> warning(errno, "cimd2_receive_msg: read_available failed");
> return -1;
1892c2032
< ret = octstr_append_from_socket(smsc->cimd2_inbuffer, smsc->socket);
---
> ret = octstr_append_from_socket(pdata->inbuffer, pdata->socket);
1895,1897c2035,2036
< warning(0, "cimd2_pending_smsmessage: service center closed connection.");
< smsc->cimd2_error = 1;
< return 1;
---
> warning(0, "cimd2_receive_msg: service center closed connection.");
> return -1;
1900,1902c2039,2040
< warning(0, "cimd2_pending_smsmessage: read failed");
< smsc->cimd2_error = 1;
< return 1;
---
> warning(0, "cimd2_receive_msg: read failed");
> return -1;
1906c2044
< packet = packet_extract(smsc->cimd2_inbuffer);
---
> packet = packet_extract(pdata->inbuffer);
1914c2052
< cimd2_handle_request(packet, smsc);
---
> cimd2_handle_request(packet, conn);
1923c2061,2062
< if (list_len(smsc->cimd2_received) > 0)
---
> if (list_len(pdata->received) > 0) {
> *msg = list_consume(pdata->received);
1925,1936d2063
<
< return 0;
< }
<
< int cimd2_receive_msg(SMSCenter *smsc, Msg **msg)
< {
< gw_assert(smsc != NULL);
< gw_assert(msg != NULL);
<
< if (smsc->cimd2_error) {
< smsc->cimd2_error = 0;
< return -1;
1938,1941c2065
<
< *msg = list_consume(smsc->cimd2_received);
<
< return 1;
---
> return 0;
1946c2070,2071
< static Msg *cimd2_accept_delivery_report_message(struct packet *request, SMSCenter *smsc)
---
> static Msg *cimd2_accept_delivery_report_message(struct packet *request,
> SMSCConn *conn)
1974,1976c2099,2101
< msg = dlr_find(smsc->name,
< octstr_get_cstr(timestamp),
< octstr_get_cstr(destination),
---
> msg = dlr_find(octstr_get_cstr(conn->name),
> octstr_get_cstr(timestamp),
> octstr_get_cstr(destination),
1990a2116,2353
>
>
> static Msg *sms_receive(SMSCConn *conn)
> {
> int ret;
> Msg *newmsg = NULL;
>
> ret = cimd2_receive_msg(conn, &newmsg);
> if (ret == 1) {
>
> /* if any smsc_id available, use it */
> newmsg->sms.smsc_id = octstr_duplicate(conn->id);
>
> return newmsg;
> } else if (ret == 0) { /* no message, just retry... */
> return NULL;
> } else { /* error. reconnect. */
> msg_destroy(newmsg);
> if (cimd2_reconnect(conn) == -1) /* XXX evil, should not happen.. */
> smscconn_shutdown(conn, 0);
> return NULL;
> }
> return NULL;
> }
>
>
> static void sms_receiver(void *arg)
> {
> Msg *msg;
> SMSCConn *conn = arg;
> PrivData *pdata = conn->data;
> /* SmscWrapper *wrap = conn->data; ** non-used */
> double sleep = 0.0001;
>
>
> /* remove messages from SMSC until we are killed */
> while(conn->why_killed == SMSCCONN_ALIVE) {
>
> list_consume(pdata->stopped); /* block here if suspended/isolated */
>
> msg = sms_receive(conn);
> if (msg) {
> debug("bb.sms", 0, "smscconn (%s): new message received",
> octstr_get_cstr(conn->name));
> sleep = 0.0001;
> bb_smscconn_receive(conn, msg);
> }
> else {
> /* note that this implementations means that we sleep even
> * when we fail connection.. but time is very short, anyway
> */
> gwthread_sleep(sleep);
> /* gradually sleep longer and longer times until something starts to
> * happen - this of course reduces response time, but that's better than
> * extensive CPU usage when it is not used
> */
> sleep *= 2;
> if (sleep >= 2.0)
> sleep = 1.999999;
> }
> }
> conn->why_killed = SMSCCONN_KILLED_SHUTDOWN;
>
> /* this thread is joined at sender */
> }
>
>
>
>
>
> static void sms_sender(void *arg)
> {
> Msg *msg;
> SMSCConn *conn = arg;
> PrivData *pdata = conn->data;
>
> /* send messages to SMSC until our putgoing_list is empty and
> * no producer anymore (we are set to shutdown) */
> while(conn->status != SMSCCONN_DEAD) {
> if ((msg = list_consume(pdata->outgoing_queue)) == NULL)
> break;
>
> (void) cimd2_submit_msg(conn,msg);
> }
> /* cleanup, we are now dying */
>
> debug("bb.sms", 0, "SMSCConn %s sender died, waiting for receiver",
> octstr_get_cstr(conn->name));
>
> conn->why_killed = SMSCCONN_KILLED_SHUTDOWN;
>
> if (conn->is_stopped) {
> list_remove_producer(pdata->stopped);
> conn->is_stopped = 0;
> }
>
> gwthread_wakeup(pdata->receiver_thread);
> gwthread_join(pdata->receiver_thread);
>
> /* call 'failed' to all messages still in queue */
>
> mutex_lock(conn->flow_mutex);
>
> conn->status = SMSCCONN_DEAD;
>
> while((msg = list_extract_first(pdata->outgoing_queue))!=NULL) {
> bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_SHUTDOWN);
> }
>
> cimd2_close(conn);
> conn->data = NULL;
>
> mutex_unlock(conn->flow_mutex);
>
> bb_smscconn_killed();
> }
>
>
>
> static int cimd2_add_msg(SMSCConn *conn, Msg *sms)
> {
> PrivData *pdata = conn->data;
>
> list_produce(pdata->outgoing_queue, sms);
>
> return 0;
> }
>
>
> static int cimd2_shutdown(SMSCConn *conn, int finish_sending)
> {
> PrivData *pdata = conn->data;
>
> debug("bb.sms", 0, "Shutting down SMSCConn %s, %s",
> octstr_get_cstr(conn->name), finish_sending ? "slow" : "instant");
>
> if (finish_sending == 0) {
> Msg *msg;
> while((msg = list_extract_first(pdata->outgoing_queue))!=NULL) {
> bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_SHUTDOWN);
> }
> }
> list_remove_producer(pdata->outgoing_queue);
> gwthread_wakeup(pdata->sender_thread);
> gwthread_wakeup(pdata->receiver_thread);
> return 0;
> }
>
> static void cimd2_stop(SMSCConn *conn)
> {
> PrivData *pdata = conn->data;
>
> debug("smscconn", 0, "Stopping CIMD2");
> list_add_producer(pdata->stopped);
>
> }
>
> static void cimd2_start(SMSCConn *conn)
> {
> PrivData *pdata = conn->data;
>
> debug("smscconn", 0, "Starting CIMD2");
> list_remove_producer(pdata->stopped);
> }
>
>
> static long cimd2_queued(SMSCConn *conn)
> {
> PrivData *pdata = conn->data;
> long ret = list_len(pdata->outgoing_queue);
>
> /* use internal queue as load, maybe something else later */
>
> conn->load = ret;
> return ret;
> }
>
> int smsc_cimd2_create(SMSCConn *conn, CfgGroup *cfg)
> {
> /* 1. Call smsc_open()
> * 2. create sender/receiver threads
> * 3. fill up the conn
> *
> * XXX open() SHOULD be done in distinct thread, not here!
> */
>
> PrivData *pdata;
>
> pdata = gw_malloc(sizeof(PrivData));
> conn->data = pdata;
> conn->send_msg = cimd2_add_msg;
>
> pdata->outgoing_queue = list_create();
> pdata->stopped = list_create();
> pdata->reconnect_mutex = mutex_create();
> list_add_producer(pdata->outgoing_queue);
>
> if (conn->is_stopped)
> list_add_producer(pdata->stopped);
>
> conn->name = cimd2_open(conn, cfg);
> if (conn->name == NULL)
> goto error;
>
> conn->status = SMSCCONN_ACTIVE;
> conn->connect_time = time(NULL);
>
>
> /* XXX here we could fail things... especially if the second one
> * fails.. so fix this ASAP
> *
> * moreover, open should be in sender/receiver, so that we can continue
> * while tyring to open... maybe move this, or just wait for new
> * implementations of various SMSC protocols
> */
>
> if ((pdata->receiver_thread = gwthread_create(sms_receiver, conn))==-1)
> goto error;
>
> if ((pdata->sender_thread = gwthread_create(sms_sender, conn))==-1)
> goto error;
>
> conn->shutdown = cimd2_shutdown;
> conn->queued = cimd2_queued;
> conn->stop_conn = cimd2_stop;
> conn->start_conn = cimd2_start;
>
> return 0;
>
> error:
> error(0, "Failed to create CIMD2 wrapper");
> conn->data = NULL;
> cimd2_destroy(pdata);
> conn->why_killed = SMSCCONN_KILLED_CANNOT_CONNECT;
> conn->status = SMSCCONN_DEAD;
> return -1;
> }
>