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;
> }
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.