gsm_04_11: Support for implicit CP-ACK in case of multi-SMS

See GSM 04.11 Chapter 5.4 for details. The idea is that when
multi-SMS are mobile originated, it's possible the CP-ACK of
the previous transaction to be lost and the reception of a
new CP-DATA for a new transaction should close previous transaction
"as-if" we had received the CP-ACK ...

Note that testing is hard since it's an exceptional condition that's
hard to create. I tested by temporarly disabling CP-ACK processing
and checked it worked as expected.

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
diff --git a/openbsc/src/gsm_04_11.c b/openbsc/src/gsm_04_11.c
index c3a49f3..7f570b8 100644
--- a/openbsc/src/gsm_04_11.c
+++ b/openbsc/src/gsm_04_11.c
@@ -948,6 +948,33 @@
 	switch(msg_type) {
 	case GSM411_MT_CP_DATA:
 		DEBUGPC(DSMS, "RX SMS CP-DATA\n");
+
+		/* 5.4: For MO, if a CP-DATA is received for a new
+		 * transaction, equals reception of an implicit
+		 * last CP-ACK for previous transaction */
+		if (trans->sms.cp_state == GSM411_CPS_IDLE) {
+			int i;
+			struct gsm_trans *ptrans;
+
+			/* Scan through all remote initiated transactions */
+			for (i=8; i<15; i++) {
+				if (i == transaction_id)
+					continue;
+
+				ptrans = trans_find_by_id(lchan->subscr,
+				                          GSM48_PDISC_SMS, i);
+				if (!ptrans)
+					continue;
+
+				DEBUGP(DSMS, "Implicit CP-ACK for trans_id=%x\n", i);
+
+				/* Finish it for good */
+				bsc_del_timer(&ptrans->sms.cp_timer);
+				ptrans->sms.cp_state = GSM411_CPS_IDLE;
+				trans_free(ptrans);
+			}
+		}
+
 		/* 5.2.3.1.3: MO state exists when SMC has received
 		 * CP-DATA, including sending of the assoc. CP-ACK */
 		/* 5.2.3.2.4: MT state exists when SMC has received