Re: SAR Patch for Kannel
Dave White <[email protected]>
| Newsgroups | gmane.comp.mobile.kannel.devel |
|---|---|
| Message-ID | <[email protected]> |
[email protected] wrote: > Hello Dave, > > You once "promissed" :) to send your updated SAR patch to the Kannel > mailing list. I tried to find this email on the list but couldn't find it. > > Could you send your latest version to the list? Possible with > your findings like quality, missing features, working phones. > Alternatively I can offer you some hosting space on my ADSL box if > nescessary. This would allow a simple web-page with detailed info on the > patch. > > Best regards, > > Ruud Schramp > > I adapted this patch from the two SAR patches posted to the list; the changes I made to the work of Igor and Vjacheslav were only simple changes needed to apply the path to the latest Kannel CVS snapshot. "It worked for me" -- sort of. Since I didn't have time to go after the problems, I haven't sent it out or tried to identify the concrete problems. In particular, SAR on responses seems to work about 50% of the time with a Nokia 7650 (tested by downloading J2ME apps) and SAR on requests seems not to work at all with Nokia devices (tested with attempted MMS-Post). Furthermore, I suspect that CVS has changed enough that this new patch won't apply. Here it is; I suspect that members of the core team are quite a bit further along, and I'd recommend waiting for their output. I would not recommend this patch for a production system; I have seen numerous wapbox hangs (not crashes, hangs) using this. David WHITE CONNECT AUSTRIA
SAR-cumulative.patch
(text/plain, 23.5 KB)
diff -ub wap/wap_events.def ../kannel-snapshot/wap/wap_events.def
--- wap/wap_events.def Thu Dec 13 13:25:08 2001
+++ ../kannel-snapshot/wap/wap_events.def Fri Sep 13 05:55:02 2002
@@ -438,6 +438,17 @@
ADDRTUPLE(addr_tuple)
)
+WAPEVENT(RcvSegInvoke, "RcvSegInvoke",
+ OCTSTR(user_data)
+ INTEGER(tid)
+ INTEGER(rid)
+ INTEGER(no_cache_supported)
+ INTEGER(gtr)
+ INTEGER(ttr)
+ INTEGER(psn)
+ ADDRTUPLE(addr_tuple)
+ )
+
WAPEVENT(RcvAbort, "RcvAbort",
INTEGER(tid)
INTEGER(abort_type)
@@ -449,6 +460,15 @@
INTEGER(tid)
INTEGER(tid_ok)
INTEGER(rid)
+ INTEGER(psn)
+ ADDRTUPLE(addr_tuple)
+ )
+
+WAPEVENT(RcvNegativeAck, "RcvNack",
+ INTEGER(tid)
+ INTEGER(rid)
+ INTEGER(nmissing)
+ OPTIONAL_OCTSTR(missing)
ADDRTUPLE(addr_tuple)
)
diff -ub wap/wtp.c ../kannel-snapshot/wap/wtp.c
--- wap/wtp.c Mon Nov 20 21:55:54 2000
+++ ../kannel-snapshot/wap/wtp.c Tue Sep 24 18:34:40 2002
@@ -26,7 +26,9 @@
static int concatenated_message(Octstr *user_data);
static int truncated_datagram(WAPEvent *event);
static WAPEvent *unpack_invoke(WTP_PDU *pdu, WAPAddrTuple *addr_tuple);
+static WAPEvent *unpack_segmented_invoke(WTP_PDU *pdu, WAPAddrTuple *addr_tuple);
static WAPEvent *unpack_ack(WTP_PDU *pdu, WAPAddrTuple *addr_tuple);
+static WAPEvent *unpack_negative_ack(WTP_PDU *pdu, WAPAddrTuple *addr_tuple);
static WAPEvent *unpack_abort(WTP_PDU *pdu, WAPAddrTuple *addr_tuple);
static WAPEvent *pack_error(WAPEvent *datagram);
@@ -101,9 +103,15 @@
case RcvInvoke:
return event->u.RcvInvoke.tid < INITIATOR_TID_LIMIT;
+ case RcvSegInvoke:
+ return event->u.RcvSegInvoke.tid < INITIATOR_TID_LIMIT;
+
case RcvAck:
return event->u.RcvAck.tid < INITIATOR_TID_LIMIT;
+ case RcvNegativeAck:
+ return event->u.RcvNegativeAck.tid < INITIATOR_TID_LIMIT;
+
case RcvAbort:
return event->u.RcvAbort.tid < INITIATOR_TID_LIMIT;
@@ -156,9 +164,29 @@
return event;
}
+static WAPEvent *unpack_segmented_invoke(WTP_PDU *pdu, WAPAddrTuple *addr_tuple)
+{
+ WAPEvent *event;
+
+ event = wap_event_create(RcvSegInvoke);
+ event->u.RcvSegInvoke.user_data =
+ octstr_duplicate(pdu->u.Segmented_invoke.user_data);
+ event->u.RcvSegInvoke.tid = pdu->u.Segmented_invoke.tid;
+ event->u.RcvSegInvoke.rid = pdu->u.Segmented_invoke.rid;
+ event->u.RcvSegInvoke.no_cache_supported = 0;
+ event->u.RcvSegInvoke.gtr = pdu->u.Segmented_invoke.gtr;
+ event->u.RcvSegInvoke.ttr = pdu->u.Segmented_invoke.ttr;
+ event->u.RcvSegInvoke.psn = pdu->u.Segmented_invoke.psn;
+ event->u.RcvSegInvoke.addr_tuple = wap_addr_tuple_duplicate(addr_tuple);
+
+ return event;
+}
+
static WAPEvent *unpack_ack(WTP_PDU *pdu, WAPAddrTuple *addr_tuple)
{
WAPEvent *event;
+ WTP_TPI *tpi;
+ int i,num_tpis;
event = wap_event_create(RcvAck);
event->u.RcvAck.tid = pdu->u.Ack.tid;
@@ -166,6 +194,31 @@
event->u.RcvAck.rid = pdu->u.Ack.rid;
event->u.RcvAck.addr_tuple = wap_addr_tuple_duplicate(addr_tuple);
+ /* Set default to 0 because Ask on 1 piece message has no tpi */
+ event->u.RcvAck.psn = 0;
+ num_tpis = list_len(pdu->options);
+ for (i = 0; i < num_tpis; i++) {
+ tpi = list_get(pdu->options, i);
+ if (tpi->type == TPI_PSN ) {
+ event->u.RcvAck.psn = octstr_get_bits(tpi->data,0,8);
+ break;
+ }
+ }
+
+ return event;
+}
+
+static WAPEvent *unpack_negative_ack(WTP_PDU *pdu, WAPAddrTuple *addr_tuple)
+{
+ WAPEvent *event;
+
+ event = wap_event_create(RcvNegativeAck);
+ event->u.RcvNegativeAck.tid = pdu->u.Negative_ack.tid;
+ event->u.RcvNegativeAck.rid = pdu->u.Negative_ack.rid;
+ event->u.RcvNegativeAck.nmissing = pdu->u.Negative_ack.nmissing;
+ event->u.RcvNegativeAck.missing = octstr_duplicate(pdu->u.Negative_ack.missing);
+ event->u.RcvNegativeAck.addr_tuple = wap_addr_tuple_duplicate(addr_tuple);
+
return event;
}
@@ -247,10 +300,18 @@
}
break;
+ case Segmented_invoke:
+ event = unpack_segmented_invoke(pdu, datagram->u.T_DUnitdata_Ind.addr_tuple);
+ break;
+
case Ack:
event = unpack_ack(pdu, datagram->u.T_DUnitdata_Ind.addr_tuple);
break;
+ case Negative_ack:
+ event = unpack_negative_ack(pdu, datagram->u.T_DUnitdata_Ind.addr_tuple);
+ break;
+
case Abort:
event = unpack_abort(pdu, datagram->u.T_DUnitdata_Ind.addr_tuple);
break;
diff -ub wap/wtp.h ../kannel-snapshot/wap/wtp.h
--- wap/wtp.h Fri Dec 8 15:31:21 2000
+++ ../kannel-snapshot/wap/wtp.h Fri Sep 13 05:55:02 2002
@@ -25,7 +25,7 @@
*/
enum {
NUMBER_OF_ABORT_TYPES = 2,
- NUMBER_OF_ABORT_REASONS = 9,
+ NUMBER_OF_ABORT_REASONS = 10,
NUMBER_OF_TRANSACTION_CLASSES = 3
};
@@ -82,7 +82,8 @@
WTPVERSIONZERO = 0x06,
CAPTEMPEXCEEDED = 0x07,
NORESPONSE = 0x08,
- MESSAGETOOLARGE = 0x09
+ MESSAGETOOLARGE = 0x09,
+ NOTIMPLEMENTEDESAR = 0x0A
};
/*
@@ -110,6 +111,15 @@
RESPONDER_INDICATION = 1
};
+enum {
+ TPI_ERROR = 0,
+ TPI_INFO = 1,
+ TPI_OPTION = 2,
+ TPI_PSN = 3,
+ TPI_SDU_BOUNDARY = 4,
+ TPI_FRAME_BOUNDARY = 5
+};
+
/*
* Responder set first tid, initiator not. So all tids send by initiator are
* greater than 2**15.
diff -ub wap/wtp_pack.c ../kannel-snapshot/wap/wtp_pack.c
--- wap/wtp_pack.c Tue Mar 27 17:35:17 2001
+++ ../kannel-snapshot/wap/wtp_pack.c Fri Sep 13 05:55:02 2002
@@ -27,7 +27,9 @@
ERROR_DATA = 0x00,
INFO_DATA = 0x01,
OPTION = 0x02,
- PACKET_SEQUENCE_NUMBER = 0x03
+ PACKET_SEQUENCE_NUMBER = 0x03,
+ SDU_BOUNDARY = 0x04,
+ FRAME_BOUNDARY = 0x05
};
/*****************************************************************************
@@ -106,6 +108,54 @@
return dgram;
}
+WAPEvent *wtp_pack_sar_result(WTPRespMachine *machine, int psn)
+{
+ WAPEvent *dgram = NULL;
+ WTP_PDU *pdu = NULL;
+ Octstr *data = NULL;
+ int gtr,ttr;
+
+ gw_assert(machine->sar && machine->sar->data);
+
+ if (psn > machine->sar->nsegm)
+ return dgram;
+
+ ttr = psn == machine->sar->nsegm ? 1 : 0;
+ gtr = ttr ? 0 : (psn+1)%SAR_GROUP_LEN ? 0 : 1;
+ if (gtr || ttr)
+ machine->sar->tr = 1;
+
+ data = octstr_copy(machine->sar->data,psn*SAR_SEGM_SIZE,SAR_SEGM_SIZE);
+
+ if (!psn) {
+ pdu = wtp_pdu_create(Result);
+ pdu->u.Result.con = 0;
+ pdu->u.Result.gtr = gtr;
+ pdu->u.Result.ttr = ttr;
+ pdu->u.Result.rid = 0;
+ pdu->u.Result.tid = send_tid(machine->tid);
+ pdu->u.Result.user_data = data;
+ }
+ else {
+ pdu = wtp_pdu_create(Segmented_result);
+ pdu->u.Segmented_result.con = 0;
+ pdu->u.Segmented_result.gtr = gtr;
+ pdu->u.Segmented_result.ttr = ttr;
+ pdu->u.Segmented_result.rid = 0;
+ pdu->u.Segmented_result.tid = send_tid(machine->tid);
+ pdu->u.Segmented_result.psn = psn;
+ pdu->u.Segmented_result.user_data = data;
+ }
+
+ dgram = wap_event_create(T_DUnitdata_Req);
+ dgram->u.T_DUnitdata_Req.addr_tuple =
+ wap_addr_tuple_duplicate(machine->addr_tuple);
+ dgram->u.T_DUnitdata_Req.user_data = wtp_pdu_pack(pdu);
+ wtp_pdu_destroy(pdu);
+
+ return dgram;
+}
+
void wtp_pack_set_rid(WAPEvent *dgram, long rid)
{
gw_assert(dgram != NULL);
@@ -148,6 +198,29 @@
dgram = wap_event_create(T_DUnitdata_Req);
dgram->u.T_DUnitdata_Req.addr_tuple = wap_addr_tuple_duplicate(address);
+ dgram->u.T_DUnitdata_Req.user_data = wtp_pdu_pack(pdu);
+ wtp_pdu_destroy(pdu);
+
+ return dgram;
+}
+
+WAPEvent *wtp_pack_sar_ack(long ack_type, long tid, WAPAddrTuple *address, int psn)
+{
+ WAPEvent *dgram = NULL;
+ WTP_PDU *pdu;
+ unsigned char cpsn;
+ sprintf(&cpsn,"%c",psn);
+
+ pdu = wtp_pdu_create(Ack);
+ pdu->u.Ack.con = 1;
+ pdu->u.Ack.tidverify = ack_type;
+ pdu->u.Ack.rid = 0;
+ pdu->u.Ack.tid = send_tid(tid);
+
+ wtp_pdu_append_tpi(pdu, 3, octstr_create_from_data((char *)&cpsn, 1));
+
+ dgram = wap_event_create(T_DUnitdata_Req);
+ dgram->u.T_DUnitdata_Req.addr_tuple = wap_addr_tuple_duplicate(address);
dgram->u.T_DUnitdata_Req.user_data = wtp_pdu_pack(pdu);
wtp_pdu_destroy(pdu);
diff -ub wap/wtp_pack.h ../kannel-snapshot/wap/wtp_pack.h
--- wap/wtp_pack.h Mon Nov 20 21:55:54 2000
+++ ../kannel-snapshot/wap/wtp_pack.h Fri Sep 13 05:55:02 2002
@@ -34,6 +34,8 @@
WAPEvent *wtp_pack_result(WTPRespMachine *resp_machine, WAPEvent *event);
+WAPEvent *wtp_pack_sar_result(WTPRespMachine *resp_machine, int psn);
+
/*
* Create a datagram event, having abort PDU as user data. Fetches SDU
* from WTP event, address four-tuple from WTP machine.
@@ -54,6 +56,8 @@
WAPEvent *wtp_pack_ack(long ack_type, int rid_flag, long tid,
WAPAddrTuple *address);
+WAPEvent *wtp_pack_sar_ack(long ack_type, long tid, WAPAddrTuple *address, int psn);
+
/*
* Set or unset the retransmission indicator on a PDU that has already
* been packed as a datagram. dgram must be of type T_DUnitdata_Req.
diff -ub wap/wtp_pdu.c ../kannel-snapshot/wap/wtp_pdu.c
--- wap/wtp_pdu.c Mon Jan 15 18:18:52 2001
+++ ../kannel-snapshot/wap/wtp_pdu.c Fri Sep 13 05:55:02 2002
@@ -38,7 +38,7 @@
#undef UINT
#undef PDU
default:
- warning(0, "Cannot destroy unknown WTP PDU type %d", pdu->type);
+ warning(0, "Cannot create unknown WTP PDU type %d", pdu->type);
break;
}
diff -ub wap/wtp_resp.c ../kannel-snapshot/wap/wtp_resp.c
--- wap/wtp_resp.c Fri Apr 19 19:01:07 2002
+++ ../kannel-snapshot/wap/wtp_resp.c Fri Sep 13 07:08:51 2002
@@ -54,6 +54,9 @@
*/
extern int wtp_forced_sar;
+static void sar_info_destroy(void *sar_info);
+static void sardata_destroy(void *sardata);
+
/*****************************************************************************
*
* Prototypes of internal functions:
@@ -124,6 +127,17 @@
static void handle_wrong_version(WAPEvent *event);
/*
+ * SAR functions
+ */
+static WAPEvent *assembly_sar_event (WTPRespMachine *machine, int last_psn);
+static int add_sar_transaction (WTPRespMachine *machine, Octstr *data, int psn);
+/* static int is_wanted_sar_data (void *a, void *b); */
+static int process_sar_transaction(WTPRespMachine *machine, WAPEvent **event);
+
+static void begin_sar_result(WTPRespMachine *machine, WAPEvent *event);
+static void continue_sar_result(WTPRespMachine *machine, WAPEvent *event);
+
+/*
* Create a datagram with an Abort PDU and send it to the WDP layer.
*/
static void send_abort(WTPRespMachine *machine, long type, long reason);
@@ -199,12 +213,15 @@
while (resp_run_status == running &&
(e = list_consume(resp_queue)) != NULL) {
+
sm = resp_machine_find_or_create(e);
- if (sm == NULL)
+
+ if (sm == NULL) {
wap_event_destroy(e);
- else
+ } else {
resp_event_handle(sm, e);
}
+ }
}
/*
@@ -230,6 +247,18 @@
static void resp_event_handle(WTPRespMachine *resp_machine, WAPEvent *event)
{
WAPEvent *wsp_event = NULL;
+ WAPEvent *e = NULL; /* For SAR acknowledgment */
+
+ /* We doesn't feed sar packets into state machine untill get the whole message */
+ if (process_sar_transaction(resp_machine,&event) == 0) {
+ debug("wap.wtp", 0, "SAR event recieved, wait for continue");
+ /* For removing state machine in case of incomplete sar */
+ start_timer_W(resp_machine);
+ if (event != NULL) {
+ wap_event_destroy(event);
+ }
+ return;
+ }
debug("wap.wtp", 0, "WTP: resp_machine %ld, state %s, event %s.",
resp_machine->mid,
@@ -293,15 +322,7 @@
*/
static int erroneous_field_in(WAPEvent *event)
{
- /*
- * If clients request WTP-SAR should we force to continue
- * or act as be should do by telling the client to call back.
- */
- if (wtp_forced_sar)
- return 0;
-
- return event->type == RcvInvoke && (event->u.RcvInvoke.version != 0 ||
- !event->u.RcvInvoke.ttr || !event->u.RcvInvoke.gtr);
+ return event->type == RcvInvoke && event->u.RcvInvoke.version != 0;
}
/*
@@ -317,11 +338,13 @@
handle_wrong_version(event);
}
+/*
if (!event->u.RcvInvoke.ttr || !event->u.RcvInvoke.gtr){
debug("wap.wtp_resp", 0, "WTP_RESP: no sar implemented,"
"aborting transaction");
handle_no_sar(event);
}
+*/
}
}
@@ -359,6 +382,11 @@
}
break;
+ case RcvSegInvoke:
+ tid = event->u.RcvSegInvoke.tid;
+ tuple = event->u.RcvSegInvoke.addr_tuple;
+ break;
+
case RcvAck:
tid = event->u.RcvAck.tid;
tuple = event->u.RcvAck.addr_tuple;
@@ -428,11 +456,26 @@
case RcvInvoke:
resp_machine = resp_machine_create(tuple, tid,
event->u.RcvInvoke.tcl);
+ /* if SAR requested */
+ if (!event->u.RcvInvoke.gtr || !event->u.RcvInvoke.ttr) {
+ resp_machine->sar = gw_malloc(sizeof(WTPSARData));
+ resp_machine->sar->nsegm = 0;
+ resp_machine->sar->csegm = 0;
+ resp_machine->sar->lsegm = 0;
+ resp_machine->sar->data = NULL;
+ }
+
break;
/*
* This and the following branch implement test nro 3 in WTP 10.2.
*/
+
+ case RcvSegInvoke:
+ info(0, "WTP_RESP: resp_machine_find_or_create:"
+ " segmented invoke received, yet having no machine");
+ break;
+
case RcvAck:
info(0, "WTP_RESP: resp_machine_find_or_create:"
" ack received, yet having no machine");
@@ -512,6 +555,8 @@
#define INTEGER(name) resp_machine->name = 0;
#define TIMER(name) resp_machine->name = gwtimer_create(resp_queue);
#define ADDRTUPLE(name) resp_machine->name = NULL;
+ #define LIST(name) resp_machine->name = NULL;
+ #define SARDATA(name) resp_machine->name = NULL;
#define MACHINE(field) field
#include "wtp_resp_machine.def"
@@ -548,6 +593,8 @@
#define INTEGER(name) resp_machine->name = 0;
#define TIMER(name) gwtimer_destroy(resp_machine->name);
#define ADDRTUPLE(name) wap_addr_tuple_destroy(resp_machine->name);
+ #define LIST(name) list_destroy(resp_machine->name,sar_info_destroy);
+ #define SARDATA(name) sardata_destroy(resp_machine->name);
#define MACHINE(field) field
#include "wtp_resp_machine.def"
gw_free(resp_machine);
@@ -653,3 +700,206 @@
e = wtp_pack_ack(ack_type, rid_flag, machine->tid, machine->addr_tuple);
dispatch_to_wdp(e);
}
+
+/* Process incoming event, checking for WTP SAR */
+
+static int process_sar_transaction(WTPRespMachine *machine, WAPEvent **event) {
+ WAPEvent *e,*orig_event;
+ int psn;
+
+ orig_event = *event;
+
+ if (orig_event->type == RcvInvoke) {
+ if (!orig_event->u.RcvInvoke.ttr || !orig_event->u.RcvInvoke.gtr) { /* SAR */
+ /* Ericcson set TTR flag even if we have the only part */
+ if (orig_event->u.RcvInvoke.ttr == 1) {
+ return 1; /* Not SAR although TTR flag was set */
+ } else {
+ /* save initial event */
+ machine->sar_invoke = wap_event_duplicate(orig_event);
+
+ /* save data into list with psn = 0 */
+ add_sar_transaction(machine, orig_event->u.RcvInvoke.user_data, 0);
+
+ if (orig_event->u.RcvInvoke.gtr == 1) { /* Need to acknowledge */
+ e = wtp_pack_sar_ack(ACKNOWLEDGEMENT, machine->tid,
+ machine->addr_tuple, 0);
+ dispatch_to_wdp(e);
+ }
+ return 0;
+ }
+ } else {
+ return 1; /* Not SAR */
+ }
+ }
+
+ if (orig_event->type == RcvSegInvoke) {
+ add_sar_transaction(machine, orig_event->u.RcvSegInvoke.user_data,
+ orig_event->u.RcvSegInvoke.psn);
+
+ if (orig_event->u.RcvSegInvoke.gtr == 1) { /* Need to acknowledge */
+ e = wtp_pack_sar_ack(ACKNOWLEDGEMENT, machine->tid, machine->addr_tuple,
+ orig_event->u.RcvSegInvoke.psn);
+ dispatch_to_wdp(e);
+ }
+
+ if (orig_event->u.RcvSegInvoke.ttr == 1) { /* Need to feed to WSP */
+ /* Create assembled event */
+
+ psn = orig_event->u.RcvSegInvoke.psn;
+ wap_event_destroy(orig_event);
+
+ *event = assembly_sar_event(machine,psn);
+
+ gw_assert(event != NULL);
+
+ return 1;
+ }
+ return 0;
+ }
+
+ /* Not SAR message */
+ return 1;
+}
+
+static int is_wanted_sar_data (void *a, void *b) {
+ sar_info_t *s;
+ int *i;
+ s = a;
+ i = b;
+
+ if (*i == s->sar_psn) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+/*
+ * Return 0 if transaction added suscessufully, 1 overwise
+ */
+
+static int add_sar_transaction (WTPRespMachine *machine, Octstr *data, int psn) {
+ sar_info_t *sar_info;
+
+ if (machine->sar_info == NULL) {
+ machine->sar_info = list_create();
+ }
+
+ if (list_search(machine->sar_info, &psn, is_wanted_sar_data) == NULL) {
+ sar_info = gw_malloc(sizeof(sar_info_t));
+ sar_info->sar_psn = psn;
+ sar_info->sar_data = octstr_duplicate(data);
+ list_append(machine->sar_info, sar_info);
+ return 0;
+ } else {
+ debug("wap.wtp", 0, "Duplicated psn found, ignore packet");
+ return 1;
+ }
+}
+
+static WAPEvent *assembly_sar_event (WTPRespMachine *machine, int last_psn) {
+ WAPEvent *e;
+ int i;
+ sar_info_t *sar_info;
+
+
+ e = wap_event_duplicate(machine->sar_invoke);
+
+ for (i = 1; i<=last_psn; i++) {
+ if ((sar_info = list_search(machine->sar_info, &i, is_wanted_sar_data)) != NULL) {
+ octstr_append(e->u.RcvInvoke.user_data,sar_info->sar_data);
+ } else {
+ debug("wap.wtp", 0, "Packet with psn %d not found",i);
+ return e;
+ }
+ }
+ return e;
+}
+
+static void sar_info_destroy(void *p) {
+ sar_info_t *sar_info;
+
+ sar_info = p;
+
+ octstr_destroy(sar_info->sar_data);
+ gw_free(sar_info);
+}
+
+
+static void sardata_destroy(void *p)
+{
+ WTPSARData * sardata;
+ if (p) {
+ sardata = p;
+ octstr_destroy(sardata->data);
+ gw_free(sardata);
+ }
+}
+
+static void begin_sar_result(WTPRespMachine *resp_machine, WAPEvent *event)
+{
+ WAPEvent *result;
+ WTPSARData *sar;
+ int psn;
+
+ gw_assert(resp_machine->sar != NULL);
+
+ sar = resp_machine->sar;
+
+ sar->data = octstr_duplicate(event->u.TR_Result_Req.user_data);
+ sar->nsegm = (octstr_len(sar->data)-1)/SAR_SEGM_SIZE;
+ sar->tr = sar->lsegm = 0;
+ sar->csegm = -1;
+
+ debug("wap.wtp", 0, "WTP: begin_sar_result(): data len = %lu",octstr_len(sar->data));
+
+ for (psn=0;!sar->tr;psn++) {
+ result = wtp_pack_sar_result(resp_machine, psn);
+ if (sar->tr)
+ resp_machine->result = wap_event_duplicate(result);
+
+ debug("wap.wtp", 0, "WTP: dispath_to_wdp(): psn = %u",psn);
+
+ dispatch_to_wdp(result);
+ sar->lsegm = psn;
+ }
+
+ resp_machine->rid = 1;
+}
+
+static void continue_sar_result(WTPRespMachine *resp_machine, WAPEvent *event)
+{
+ WAPEvent *result;
+ WTPSARData *sar;
+ int psn;
+
+ gw_assert(resp_machine->sar != NULL && event->type == RcvAck);
+
+ sar = resp_machine->sar;
+
+ debug("wap.wtp", 0, "WTP: continue_sar_result(): lsegm=%d, nsegm=%d, csegm=%d",sar->lsegm,sar->nsegm,sar->csegm);
+
+ start_timer_R(resp_machine);
+
+ if (event->u.RcvAck.psn>sar->csegm) {
+ sar->csegm = event->u.RcvAck.psn;
+ }
+ sar->tr = 0;
+ wap_event_destroy(resp_machine->result);
+ resp_machine->result = NULL;
+
+ for (psn=sar->csegm+1;!sar->tr;psn++) {
+ result = wtp_pack_sar_result(resp_machine, psn);
+ if (sar->tr)
+ resp_machine->result = wap_event_duplicate(result);
+
+ debug("wap.wtp", 0, "WTP: dispath_to_wdp(): psn = %u",psn);
+
+ dispatch_to_wdp(result);
+ sar->lsegm = psn;
+ }
+
+}
+
+
diff -ub wap/wtp_resp.h ../kannel-snapshot/wap/wtp_resp.h
--- wap/wtp_resp.h Tue May 14 14:05:08 2002
+++ ../kannel-snapshot/wap/wtp_resp.h Fri Sep 13 05:55:02 2002
@@ -13,6 +13,27 @@
#include "wap_events.h"
#include "timers.h"
+typedef struct sar_info_t {
+ int sar_psn;
+ Octstr *sar_data;
+} sar_info_t;
+
+/*
+ * Structure to keep SAR data during transmission
+ */
+typedef struct WTPSARData {
+ int nsegm; /* number of the last segment, i.e. total number - 1 */
+ int csegm; /* last segment confirmed by recipient */
+ int lsegm; /* last sent segment */
+ int tr; /* if current psn is gtr or ttr */
+ Octstr *data;
+} WTPSARData;
+
+/* Nokia wap gw uses the size of 576, but mobiles use 1,5K size,
+ * I will think later what is better to use
+ */
+#define SAR_SEGM_SIZE 576
+#define SAR_GROUP_LEN 3
/*
* Responder machine states and responder WTP machine.
* See file wtp_resp_state-decl.h for comments. Note that we must define macro
@@ -38,6 +59,8 @@
#define ADDRTUPLE(name) WAPAddrTuple *name;
#define ENUM(name) resp_states name;
#define EVENT(name) WAPEvent *name;
+ #define LIST(name) List *name;
+ #define SARDATA(name) WTPSARData *name;
#define MACHINE(field) field
#include "wtp_resp_machine.def"
};
diff -ub wap/wtp_resp_machine.def ../kannel-snapshot/wap/wtp_resp_machine.def
--- wap/wtp_resp_machine.def Mon Nov 20 21:55:54 2000
+++ ../kannel-snapshot/wap/wtp_resp_machine.def Fri Sep 13 05:55:02 2002
@@ -42,6 +42,10 @@
#error "Macro TIMER is missing."
#elif !defined(EVENT)
#error "Macro EVENT is missing."
+#elif !defined(LIST)
+ #error "Macro LIST is missing."
+#elif !defined(SARDATA)
+ #error "Macro SARDATA is missing."
#elif !defined(ADDRTUPLE)
#error "Macro ADDRTUPLE is missing."
#endif
@@ -63,6 +67,9 @@
in the global timers list */
EVENT(invoke_indication) /* packed wsp invoke indication - for tid
verification */
+ EVENT(sar_invoke) /* initial invoke for SAR, accumulate user_data */
+ LIST(sar_info)
+ SARDATA(sar) /* ! NULL if were we asked for SAR */
)
#undef MACHINE
@@ -71,3 +78,5 @@
#undef TIMER
#undef EVENT
#undef ADDRTUPLE
+#undef LIST
+#undef SARDATA
diff -ub wap/wtp_resp_states.def ../kannel-snapshot/wap/wtp_resp_states.def
--- wap/wtp_resp_states.def Tue Mar 27 17:35:39 2001
+++ ../kannel-snapshot/wap/wtp_resp_states.def Fri Sep 13 07:09:04 2002
@@ -165,6 +165,15 @@
LISTEN)
/*
+ * Need to control SAR incomplete packets
+ */
+ROW(LISTEN,
+ TimerTO_W,
+ 1,
+ {},
+ LISTEN)
+
+/*
* We must cache the newly accepted tid item, otherwise every tid after a
* suspected one will be validated. We use wsp event stored by the responder
* machine.
@@ -275,7 +284,7 @@
ROW(INVOKE_RESP_WAIT,
TR_Result_Req,
- 1,
+ resp_machine->sar == NULL,
{
WAPEvent *result;
@@ -291,6 +300,21 @@
},
RESULT_RESP_WAIT)
+ROW(INVOKE_RESP_WAIT,
+ TR_Result_Req,
+ resp_machine->sar != NULL,
+ {
+ WAPEvent *result;
+
+ resp_machine->rcr = 0;
+
+ start_timer_R(resp_machine);
+ wap_event_destroy(resp_machine->result);
+ resp_machine->rid = 0;
+ begin_sar_result(resp_machine, event);
+ },
+ RESULT_RESP_WAIT)
+
/*
* Conditions below do not correspond wholly ones found from the spec. (If
* they does, user acknowledgement flag would never be used by the protocol,
@@ -368,7 +392,7 @@
ROW(RESULT_WAIT,
TR_Result_Req,
- 1,
+ resp_machine->sar == NULL,
{
WAPEvent *result;
resp_machine->rcr = 0;
@@ -384,6 +408,23 @@
},
RESULT_RESP_WAIT)
+
+ROW(RESULT_WAIT,
+ TR_Result_Req,
+ resp_machine->sar != NULL,
+ {
+ WAPEvent *result;
+ resp_machine->rcr = 0;
+
+ start_timer_R(resp_machine);
+
+ wap_event_destroy(resp_machine->result);
+ resp_machine->rid = 0;
+ begin_sar_result(resp_machine, event);
+ },
+ RESULT_RESP_WAIT)
+
+
ROW(RESULT_WAIT,
RcvAbort,
1,
@@ -473,13 +514,21 @@
ROW(RESULT_RESP_WAIT,
RcvAck,
- 1,
+ resp_machine->sar == NULL || event->u.RcvAck.psn == resp_machine->sar->nsegm,
{
wsp_event = create_tr_result_cnf(resp_machine);
wsp_session_dispatch_event(wsp_event);
},
LISTEN)
+ROW(RESULT_RESP_WAIT,
+ RcvAck,
+ resp_machine->sar != NULL && event->u.RcvAck.psn != resp_machine->sar->nsegm,
+ {
+ continue_sar_result(resp_machine, event);
+ },
+ RESULT_RESP_WAIT)
+
/*
* Specs does not tell what to do, when wtp responder receives invoke pdu and
* its state is RESULT_RESP_WAIT. This can happen, however: event causing the