[PATCH] EMI part 2
Nisan Bloch <[email protected]>
| Newsgroups | gmane.comp.mobile.kannel.devel |
|---|---|
| Message-ID | <[email protected]> |
Hi This patch to the EMI module tries to address the problem of dealing with msgs that do not get acked by the SMSC after the wait-ack period. This should never happen but it does, even with wait-acks in the region of 240-600secs. Thanks to Andreas for his input. It adds a new config var (wait-ack-expire) that defines what to do with such an error. After some discussion between Andreas and I, we decided that a disconnect/reconnect should be the default behavior. The various option for wait-ack-expire are 0x00 - disconnect/reconnect, (default) 0x01 - as is now, requeue, but this could potentially result in the msg arriving twice 0x02 - just carry on waiting (given that the wait-ack should never expire this is the mst accurate) I have submitted this patch distinctly different from the patch to handle the window problem to make voting and testing easier. I have tested it a fair amount, but I think it needs some more. Nisan
smsc_emi2.patch
(application/octet-stream, 4.4 KB)
--- cvs/gateway/gw/smsc/smsc_emi2.c Sun Dec 8 22:44:53 2002
+++ kannel-cvsup/gw/smsc/smsc_emi2.c Sun Dec 8 22:29:08 2002
@@ -56,6 +56,7 @@
int keepalive; /* Seconds to send a Keepalive Command (OT=31) */
int flowcontrol; /* 0=Windowing, 1=Stop-and-Wait */
int waitack; /* Seconds to wait to ack */
+ int waitack_expire; /* What to do on waitack expire */
int throughput; /* Messages per second */
int window; /* In windowed flow-control, the window size */
int can_write; /* write = 1, read = 0, for stop-and-wait flow control */
@@ -1107,7 +1108,7 @@
return 0;
}
-static void emi2_idleprocessing(SMSCConn *conn)
+static void emi2_idleprocessing(SMSCConn *conn, Connection **server)
{
time_t current_time;
int i;
@@ -1121,21 +1122,42 @@
if (PRIVDATA(conn)->unacked && (current_time > (PRIVDATA(conn)->check_time + 30))) {
PRIVDATA(conn)->check_time = current_time;
- for (i = 0; i < EMI2_MAX_TRN; i++) {
+ for (i = 0; i < PRIVDATA(conn)->window; i++) {
if (SLOTBUSY(conn,i)
&& PRIVDATA(conn)->slots[i].sendtime < (current_time - PRIVDATA(conn)->waitack)) {
+
+ if (PRIVDATA(conn)->slots[i].sendtype == 51) {
+ if (PRIVDATA(conn)->waitack_expire == 0x00) {
+ // 0x00 - disconnect/reconnect
+ warning(0, "EMI2[%s]: received neither ACK nor NACK for message %d "
+ "in %d seconds, disconnecting and reconnection",
+ octstr_get_cstr(privdata->name), i, PRIVDATA(conn)->waitack);
PRIVDATA(conn)->slots[i].sendtime = 0;
PRIVDATA(conn)->unacked--;
- if (PRIVDATA(conn)->slots[i].sendtype == 51) {
+ info(0, "EMI2[%s]: closing connection.",
+ octstr_get_cstr(privdata->name));
+ conn_destroy(*server);
+ *server = NULL;
+ break;
+ } else if (PRIVDATA(conn)->waitack_expire == 0x01) {
+ // 0x01 - resend
warning(0, "EMI2[%s]: received neither ACK nor NACK for message %d "
"in %d seconds, resending message", octstr_get_cstr(privdata->name),
i, PRIVDATA(conn)->waitack);
list_produce(PRIVDATA(conn)->outgoing_queue,
PRIVDATA(conn)->slots[i].sendmsg);
+ PRIVDATA(conn)->slots[i].sendtime = 0;
+ PRIVDATA(conn)->unacked--;
if (PRIVDATA(conn)->flowcontrol) PRIVDATA(conn)->can_write=1;
/* Wake up this same thread to send again
* (simpler than avoiding sleep) */
gwthread_wakeup(PRIVDATA(conn)->sender_thread);
+ } else if (PRIVDATA(conn)->waitack_expire == 0x03) {
+ // 0x02 - carry on waiting
+ warning(0, "EMI2[%s]: received neither ACK nor NACK for message %d "
+ "in %d seconds, carrying on waiting", octstr_get_cstr(privdata->name),
+ i, PRIVDATA(conn)->waitack);
+ }
} else if (PRIVDATA(conn)->slots[i].sendtype == 31) {
warning(0, "EMI2[%s]: Alert (operation 31) was not "
"ACKed within %d seconds", octstr_get_cstr(privdata->name),
@@ -1231,7 +1253,7 @@
return; /* reopen the connection */
}
- emi2_idleprocessing (conn);
+ emi2_idleprocessing (conn, server);
emi2_idletimeout_handling (conn, server);
if (PRIVDATA(conn)->shutdown && (PRIVDATA(conn)->unacked == 0)) {
@@ -1510,7 +1532,7 @@
PrivData *privdata;
Octstr *allow_ip, *deny_ip, *host, *alt_host;
long portno, our_port, keepalive, flowcontrol, waitack, throughput,
- idle_timeout, alt_portno, alt_charset;
+ idle_timeout, alt_portno, alt_charset, waitack_expire;
long window;
/* has to be long because of cfg_get_integer */
int i;
@@ -1655,6 +1677,16 @@
goto error;
}
+ if (cfg_get_integer(&waitack_expire, cfg, octstr_imm("wait-ack-expire")) < 0)
+ privdata->waitack_expire = 0;
+ else
+ privdata->waitack_expire = waitack_expire;
+ if (privdata->waitack_expire >3 ) {
+ error(0, "EMI2[%s]: 'wait-ack-expire' invalid in emi2 configuration.",
+ octstr_get_cstr(privdata->name));
+ goto error;
+ }
+
if (privdata->rport < 0 || privdata->rport > 65535) {
error(0, "EMI2[%s]: 'receive-port' missing/invalid in emi2 configuration.",
octstr_get_cstr(privdata->name));