00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 #include "gwlib/gwlib.h"
00065 #include "wtp_resp.h"
00066 #include "wtp_pack.h"
00067 #include "wtp_tid.h"
00068 #include "wtp.h"
00069 #include "timers.h"
00070 #include "wap.h"
00071
00072
00073
00074
00075
00076
00077 static List *resp_machines = NULL;
00078
00079
00080
00081
00082
00083 static Counter *resp_machine_id_counter = NULL;
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 static enum { limbo, running, terminating } resp_run_status = limbo;
00097
00098
00099 wap_dispatch_func_t *dispatch_to_wdp;
00100 wap_dispatch_func_t *dispatch_to_wsp;
00101 wap_dispatch_func_t *dispatch_to_push;
00102
00103
00104
00105
00106 static List *resp_queue = NULL;
00107
00108
00109
00110
00111 static long resp_timer_freq = -1;
00112
00113
00114
00115
00116
00117
00118
00119
00120 static WTPRespMachine *resp_machine_create(WAPAddrTuple *tuple, long tid,
00121 long tcl);
00122 static void resp_machine_destroy(void *sm);
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136 static WTPRespMachine *resp_machine_find_or_create(WAPEvent *event);
00137
00138
00139
00140
00141
00142
00143
00144 static void resp_event_handle(WTPRespMachine *machine, WAPEvent *event);
00145
00146
00147
00148
00149 static char *name_resp_state(int name);
00150
00151
00152
00153
00154
00155
00156
00157 static WTPRespMachine *resp_machine_find(WAPAddrTuple *tuple, long tid,
00158 long mid);
00159 static void main_thread(void *);
00160
00161
00162
00163
00164 static void start_timer_A(WTPRespMachine *machine);
00165
00166
00167
00168
00169 static void start_timer_R(WTPRespMachine *machine);
00170
00171
00172
00173
00174 static void start_timer_W(WTPRespMachine *machine);
00175 static WAPEvent *create_tr_invoke_ind(WTPRespMachine *sm, Octstr *user_data);
00176 static WAPEvent *create_tr_abort_ind(WTPRespMachine *sm, long abort_reason);
00177 static WAPEvent *create_tr_result_cnf(WTPRespMachine *sm);
00178 static int erroneous_field_in(WAPEvent *event);
00179 static void handle_wrong_version(WAPEvent *event);
00180
00181
00182
00183
00184 static WAPEvent *assembly_sar_event (WTPRespMachine *machine, int last_psn);
00185 static int add_sar_transaction (WTPRespMachine *machine, Octstr *data, int psn);
00186
00187 static int process_sar_transaction(WTPRespMachine *machine, WAPEvent **event);
00188 static void begin_sar_result(WTPRespMachine *machine, WAPEvent *event);
00189 static void continue_sar_result(WTPRespMachine *machine, WAPEvent *event);
00190 static void resend_sar_result(WTPRespMachine *resp_machine, WAPEvent *event);
00191 static void sar_info_destroy(void *sar_info);
00192 static void sardata_destroy(void *sardata);
00193
00194
00195
00196
00197 static void send_abort(WTPRespMachine *machine, long type, long reason);
00198
00199
00200
00201
00202 static void send_ack(WTPRespMachine *machine, long ack_type, int rid_flag);
00203
00204
00205
00206
00207
00208
00209
00210
00211 void wtp_resp_init(wap_dispatch_func_t *datagram_dispatch,
00212 wap_dispatch_func_t *session_dispatch,
00213 wap_dispatch_func_t *push_dispatch,
00214 long timer_freq)
00215 {
00216 resp_machines = gwlist_create();
00217 resp_machine_id_counter = counter_create();
00218
00219 resp_queue = gwlist_create();
00220 gwlist_add_producer(resp_queue);
00221
00222 dispatch_to_wdp = datagram_dispatch;
00223 dispatch_to_wsp = session_dispatch;
00224 dispatch_to_push = push_dispatch;
00225
00226 timers_init();
00227 resp_timer_freq = timer_freq;
00228 wtp_tid_cache_init();
00229
00230 gw_assert(resp_run_status == limbo);
00231 resp_run_status = running;
00232 gwthread_create(main_thread, NULL);
00233 }
00234
00235 void wtp_resp_shutdown(void)
00236 {
00237 gw_assert(resp_run_status == running);
00238 resp_run_status = terminating;
00239 gwlist_remove_producer(resp_queue);
00240 gwthread_join_every(main_thread);
00241
00242 debug("wap.wtp", 0, "wtp_resp_shutdown: %ld resp_machines left",
00243 gwlist_len(resp_machines));
00244 gwlist_destroy(resp_machines, resp_machine_destroy);
00245 gwlist_destroy(resp_queue, wap_event_destroy_item);
00246
00247 counter_destroy(resp_machine_id_counter);
00248
00249 wtp_tid_cache_shutdown();
00250 timers_shutdown();
00251 }
00252
00253 void wtp_resp_dispatch_event(WAPEvent *event)
00254 {
00255 gwlist_produce(resp_queue, event);
00256 }
00257
00258
00259
00260
00261
00262
00263
00264
00265 static void main_thread(void *arg)
00266 {
00267 WTPRespMachine *sm;
00268 WAPEvent *e;
00269
00270 while (resp_run_status == running &&
00271 (e = gwlist_consume(resp_queue)) != NULL) {
00272
00273 sm = resp_machine_find_or_create(e);
00274 if (sm == NULL) {
00275 wap_event_destroy(e);
00276 } else {
00277 resp_event_handle(sm, e);
00278 }
00279 }
00280 }
00281
00282
00283
00284
00285 static char *name_resp_state(int s)
00286 {
00287 switch (s) {
00288 #define STATE_NAME(state) case state: return #state;
00289 #define ROW(state, event, condition, action, new_state)
00290 #include "wtp_resp_states.def"
00291 default:
00292 return "unknown state";
00293 }
00294 }
00295
00296
00297
00298
00299
00300
00301
00302 static void resp_event_handle(WTPRespMachine *resp_machine, WAPEvent *event)
00303 {
00304 WAPEvent *wsp_event = NULL;
00305
00306
00307
00308
00309
00310 if (process_sar_transaction(resp_machine,&event) == 0) {
00311 debug("wap.wtp", 0, "SAR event received, wait for continue");
00312
00313 start_timer_W(resp_machine);
00314 if (event != NULL) {
00315 wap_event_destroy(event);
00316 }
00317 return;
00318 }
00319
00320 debug("wap.wtp", 0, "WTP: resp_machine %ld, state %s, event %s.",
00321 resp_machine->mid,
00322 name_resp_state(resp_machine->state),
00323 wap_event_name(event->type));
00324
00325 #define STATE_NAME(state)
00326 #define ROW(wtp_state, event_type, condition, action, next_state) \
00327 if (resp_machine->state == wtp_state && \
00328 event->type == event_type && \
00329 (condition)) { \
00330 action \
00331 resp_machine->state = next_state; \
00332 debug("wap.wtp", 0, "WTP %ld: New state %s", resp_machine->mid, #next_state); \
00333 } else
00334 #include "wtp_resp_states.def"
00335 {
00336 error(0, "WTP: handle_event: unhandled event!");
00337 debug("wap.wtp", 0, "WTP: handle_event: Unhandled event was:");
00338 wap_event_dump(event);
00339 wap_event_destroy(event);
00340 return;
00341 }
00342
00343 if (event != NULL) {
00344 wap_event_destroy(event);
00345 }
00346
00347 if (resp_machine->state == LISTEN)
00348 resp_machine_destroy(resp_machine);
00349 }
00350
00351 static void handle_wrong_version(WAPEvent *event)
00352 {
00353 WAPEvent *ab;
00354
00355 if (event->type == RcvInvoke) {
00356 ab = wtp_pack_abort(PROVIDER, WTPVERSIONZERO, event->u.RcvInvoke.tid,
00357 event->u.RcvInvoke.addr_tuple);
00358 dispatch_to_wdp(ab);
00359 }
00360 }
00361
00362
00363
00364
00365 static int erroneous_field_in(WAPEvent *event)
00366 {
00367 return event->type == RcvInvoke && event->u.RcvInvoke.version != 0;
00368 }
00369
00370
00371
00372
00373
00374 static void handle_erroneous_field_in(WAPEvent *event)
00375 {
00376 if (event->type == RcvInvoke) {
00377 if (event->u.RcvInvoke.version != 0) {
00378 debug("wap.wtp_resp", 0, "WTP_RESP: wrong version, aborting"
00379 "transaction");
00380 handle_wrong_version(event);
00381 }
00382 }
00383 }
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397 static WTPRespMachine *resp_machine_find_or_create(WAPEvent *event)
00398 {
00399 WTPRespMachine *resp_machine = NULL;
00400 long tid, mid;
00401 WAPAddrTuple *tuple;
00402
00403 tid = -1;
00404 tuple = NULL;
00405 mid = -1;
00406
00407 switch (event->type) {
00408 case RcvInvoke:
00409
00410 if (erroneous_field_in(event)) {
00411 handle_erroneous_field_in(event);
00412 return NULL;
00413 } else {
00414 tid = event->u.RcvInvoke.tid;
00415 tuple = event->u.RcvInvoke.addr_tuple;
00416 }
00417 break;
00418
00419 case RcvSegInvoke:
00420 tid = event->u.RcvSegInvoke.tid;
00421 tuple = event->u.RcvSegInvoke.addr_tuple;
00422 break;
00423
00424 case RcvAck:
00425 tid = event->u.RcvAck.tid;
00426 tuple = event->u.RcvAck.addr_tuple;
00427 break;
00428
00429 case RcvNegativeAck:
00430 tid = event->u.RcvAck.tid;
00431 tuple = event->u.RcvAck.addr_tuple;
00432 break;
00433
00434 case RcvAbort:
00435 tid = event->u.RcvAbort.tid;
00436 tuple = event->u.RcvAbort.addr_tuple;
00437 break;
00438
00439 case RcvErrorPDU:
00440 tid = event->u.RcvErrorPDU.tid;
00441 tuple = event->u.RcvErrorPDU.addr_tuple;
00442 break;
00443
00444 case TR_Invoke_Res:
00445 mid = event->u.TR_Invoke_Res.handle;
00446 break;
00447
00448 case TR_Result_Req:
00449 mid = event->u.TR_Result_Req.handle;
00450 break;
00451
00452 case TR_Abort_Req:
00453 mid = event->u.TR_Abort_Req.handle;
00454 break;
00455
00456 case TimerTO_A:
00457 mid = event->u.TimerTO_A.handle;
00458 break;
00459
00460 case TimerTO_R:
00461 mid = event->u.TimerTO_R.handle;
00462 break;
00463
00464 case TimerTO_W:
00465 mid = event->u.TimerTO_W.handle;
00466 break;
00467
00468 default:
00469 debug("wap.wtp", 0, "WTP: resp_machine_find_or_create:"
00470 "unhandled event");
00471 wap_event_dump(event);
00472 return NULL;
00473 }
00474
00475 gw_assert(tuple != NULL || mid != -1);
00476 resp_machine = resp_machine_find(tuple, tid, mid);
00477
00478 if (resp_machine == NULL){
00479
00480 switch (event->type) {
00481
00482
00483
00484
00485
00486
00487
00488 case RcvErrorPDU:
00489 debug("wap.wtp_resp", 0, "an erronous pdu received");
00490 wap_event_dump(event);
00491 resp_machine = resp_machine_create(tuple, tid,
00492 event->u.RcvInvoke.tcl);
00493 break;
00494
00495 case RcvInvoke:
00496 resp_machine = resp_machine_create(tuple, tid,
00497 event->u.RcvInvoke.tcl);
00498
00499 if (!event->u.RcvInvoke.gtr || !event->u.RcvInvoke.ttr) {
00500 resp_machine->sar = gw_malloc(sizeof(WTPSARData));
00501 resp_machine->sar->nsegm = 0;
00502 resp_machine->sar->csegm = 0;
00503 resp_machine->sar->lsegm = 0;
00504 resp_machine->sar->data = NULL;
00505 }
00506
00507 break;
00508
00509 case RcvSegInvoke:
00510 info(0, "WTP_RESP: resp_machine_find_or_create:"
00511 " segmented invoke received, yet having no machine");
00512 break;
00513
00514
00515
00516
00517 case RcvAck:
00518 info(0, "WTP_RESP: resp_machine_find_or_create:"
00519 " ack received, yet having no machine");
00520 break;
00521
00522 case RcvNegativeAck:
00523 info(0, "WTP_RESP: resp_machine_find_or_create:"
00524 " negative ack received, yet having no machine");
00525 break;
00526
00527 case RcvAbort:
00528 info(0, "WTP_RESP: resp_machine_find_or_create:"
00529 " abort received, yet having no machine");
00530 break;
00531
00532 case TR_Invoke_Res:
00533 case TR_Result_Req:
00534 case TR_Abort_Req:
00535 error(0, "WTP_RESP: resp_machine_find_or_create: WSP primitive to"
00536 " a wrong WTP machine");
00537 break;
00538
00539 case TimerTO_A:
00540 case TimerTO_R:
00541 case TimerTO_W:
00542 error(0, "WTP_RESP: resp_machine_find_or_create: timer event"
00543 " without a corresponding machine");
00544 break;
00545
00546 default:
00547 error(0, "WTP_RESP: resp_machine_find_or_create: unhandled event");
00548 wap_event_dump(event);
00549 break;
00550 }
00551 }
00552 return resp_machine;
00553 }
00554
00555 static int is_wanted_resp_machine(void *a, void *b)
00556 {
00557 machine_pattern *pat;
00558 WTPRespMachine *m;
00559
00560 m = a;
00561 pat = b;
00562
00563 if (m->mid == pat->mid)
00564 return 1;
00565
00566 if (pat->mid != -1)
00567 return 0;
00568
00569 return m->tid == pat->tid &&
00570 wap_addr_tuple_same(m->addr_tuple, pat->tuple);
00571 }
00572
00573
00574 static WTPRespMachine *resp_machine_find(WAPAddrTuple *tuple, long tid,
00575 long mid)
00576 {
00577 machine_pattern pat;
00578 WTPRespMachine *m;
00579
00580 pat.tuple = tuple;
00581 pat.tid = tid;
00582 pat.mid = mid;
00583
00584 m = gwlist_search(resp_machines, &pat, is_wanted_resp_machine);
00585 return m;
00586 }
00587
00588
00589 static WTPRespMachine *resp_machine_create(WAPAddrTuple *tuple, long tid,
00590 long tcl)
00591 {
00592 WTPRespMachine *resp_machine;
00593
00594 resp_machine = gw_malloc(sizeof(WTPRespMachine));
00595
00596 #define ENUM(name) resp_machine->name = LISTEN;
00597 #define EVENT(name) resp_machine->name = NULL;
00598 #define INTEGER(name) resp_machine->name = 0;
00599 #define TIMER(name) resp_machine->name = gwtimer_create(resp_queue);
00600 #define ADDRTUPLE(name) resp_machine->name = NULL;
00601 #define LIST(name) resp_machine->name = NULL;
00602 #define SARDATA(name) resp_machine->name = NULL;
00603 #define MACHINE(field) field
00604 #include "wtp_resp_machine.def"
00605
00606 gwlist_append(resp_machines, resp_machine);
00607
00608 resp_machine->mid = counter_increase(resp_machine_id_counter);
00609 resp_machine->addr_tuple = wap_addr_tuple_duplicate(tuple);
00610 resp_machine->tid = tid;
00611 resp_machine->tcl = tcl;
00612
00613 debug("wap.wtp", 0, "WTP: Created WTPRespMachine %p (%ld)",
00614 (void *) resp_machine, resp_machine->mid);
00615
00616 return resp_machine;
00617 }
00618
00619
00620
00621
00622
00623
00624 static void resp_machine_destroy(void * p)
00625 {
00626 WTPRespMachine *resp_machine;
00627
00628 resp_machine = p;
00629 debug("wap.wtp", 0, "WTP: Destroying WTPRespMachine %p (%ld)",
00630 (void *) resp_machine, resp_machine->mid);
00631
00632 gwlist_delete_equal(resp_machines, resp_machine);
00633
00634 #define ENUM(name) resp_machine->name = LISTEN;
00635 #define EVENT(name) wap_event_destroy(resp_machine->name);
00636 #define INTEGER(name) resp_machine->name = 0;
00637 #define TIMER(name) gwtimer_destroy(resp_machine->name);
00638 #define ADDRTUPLE(name) wap_addr_tuple_destroy(resp_machine->name);
00639 #define LIST(name) gwlist_destroy(resp_machine->name,sar_info_destroy);
00640 #define SARDATA(name) sardata_destroy(resp_machine->name);
00641 #define MACHINE(field) field
00642 #include "wtp_resp_machine.def"
00643 gw_free(resp_machine);
00644 }
00645
00646
00647
00648
00649 static WAPEvent *create_tr_invoke_ind(WTPRespMachine *sm, Octstr *user_data)
00650 {
00651 WAPEvent *event;
00652
00653 event = wap_event_create(TR_Invoke_Ind);
00654 event->u.TR_Invoke_Ind.ack_type = sm->u_ack;
00655 event->u.TR_Invoke_Ind.user_data = octstr_duplicate(user_data);
00656 event->u.TR_Invoke_Ind.tcl = sm->tcl;
00657 event->u.TR_Invoke_Ind.addr_tuple =
00658 wap_addr_tuple_duplicate(sm->addr_tuple);
00659 event->u.TR_Invoke_Ind.handle = sm->mid;
00660 return event;
00661 }
00662
00663
00664
00665
00666
00667 static WAPEvent *create_tr_result_cnf(WTPRespMachine *sm)
00668 {
00669 WAPEvent *event;
00670
00671 event = wap_event_create(TR_Result_Cnf);
00672 event->u.TR_Result_Cnf.addr_tuple =
00673 wap_addr_tuple_duplicate(sm->addr_tuple);
00674 event->u.TR_Result_Cnf.handle = sm->mid;
00675 return event;
00676 }
00677
00678
00679
00680
00681
00682 static WAPEvent *create_tr_abort_ind(WTPRespMachine *sm, long abort_reason) {
00683 WAPEvent *event;
00684
00685 event = wap_event_create(TR_Abort_Ind);
00686 event->u.TR_Abort_Ind.abort_code = abort_reason;
00687 event->u.TR_Abort_Ind.addr_tuple =
00688 wap_addr_tuple_duplicate(sm->addr_tuple);
00689 event->u.TR_Abort_Ind.handle = sm->mid;
00690 event->u.TR_Abort_Ind.ir_flag = RESPONDER_INDICATION;
00691
00692 return event;
00693 }
00694
00695
00696
00697
00698
00699 static void start_timer_A(WTPRespMachine *machine)
00700 {
00701 WAPEvent *timer_event;
00702
00703 timer_event = wap_event_create(TimerTO_A);
00704 timer_event->u.TimerTO_A.handle = machine->mid;
00705 gwtimer_start(machine->timer, L_A_WITH_USER_ACK * resp_timer_freq,
00706 timer_event);
00707 }
00708
00709
00710
00711
00712 static void start_timer_R(WTPRespMachine *machine)
00713 {
00714 WAPEvent *timer_event;
00715
00716 timer_event = wap_event_create(TimerTO_R);
00717 timer_event->u.TimerTO_R.handle = machine->mid;
00718 gwtimer_start(machine->timer, L_R_WITH_USER_ACK * resp_timer_freq,
00719 timer_event);
00720 }
00721
00722
00723
00724
00725
00726 static void start_timer_W(WTPRespMachine *machine)
00727 {
00728 WAPEvent *timer_event;
00729
00730 timer_event = wap_event_create(TimerTO_W);
00731 timer_event->u.TimerTO_W.handle = machine->mid;
00732 gwtimer_start(machine->timer, W_WITH_USER_ACK * resp_timer_freq,
00733 timer_event);
00734 }
00735
00736 static void send_abort(WTPRespMachine *machine, long type, long reason)
00737 {
00738 WAPEvent *e;
00739
00740 e = wtp_pack_abort(type, reason, machine->tid, machine->addr_tuple);
00741 dispatch_to_wdp(e);
00742 }
00743
00744 static void send_ack(WTPRespMachine *machine, long ack_type, int rid_flag)
00745 {
00746 WAPEvent *e;
00747
00748 e = wtp_pack_ack(ack_type, rid_flag, machine->tid, machine->addr_tuple);
00749 dispatch_to_wdp(e);
00750 }
00751
00752
00753
00754
00755 static int process_sar_transaction(WTPRespMachine *machine, WAPEvent **event)
00756 {
00757 WAPEvent *e, *orig_event;
00758 int psn;
00759
00760 orig_event = *event;
00761
00762 if (orig_event->type == RcvInvoke) {
00763 if (!orig_event->u.RcvInvoke.ttr || !orig_event->u.RcvInvoke.gtr) {
00764
00765 if (orig_event->u.RcvInvoke.ttr == 1) {
00766 return 1;
00767 } else {
00768
00769 machine->sar_invoke = wap_event_duplicate(orig_event);
00770
00771
00772 add_sar_transaction(machine, orig_event->u.RcvInvoke.user_data, 0);
00773
00774 if (orig_event->u.RcvInvoke.gtr == 1) {
00775 e = wtp_pack_sar_ack(ACKNOWLEDGEMENT, machine->tid,
00776 machine->addr_tuple, 0);
00777 dispatch_to_wdp(e);
00778 }
00779 return 0;
00780 }
00781 } else {
00782 return 1;
00783 }
00784 }
00785
00786 if (orig_event->type == RcvSegInvoke) {
00787 add_sar_transaction(machine, orig_event->u.RcvSegInvoke.user_data,
00788 orig_event->u.RcvSegInvoke.psn);
00789
00790 if (orig_event->u.RcvSegInvoke.gtr == 1) {
00791 e = wtp_pack_sar_ack(ACKNOWLEDGEMENT, machine->tid, machine->addr_tuple,
00792 orig_event->u.RcvSegInvoke.psn);
00793 dispatch_to_wdp(e);
00794 }
00795
00796 if (orig_event->u.RcvSegInvoke.ttr == 1) {
00797
00798
00799 psn = orig_event->u.RcvSegInvoke.psn;
00800 wap_event_destroy(orig_event);
00801
00802 *event = assembly_sar_event(machine,psn);
00803
00804 gw_assert(event != NULL);
00805
00806 return 1;
00807 }
00808 return 0;
00809 }
00810
00811
00812 return 1;
00813 }
00814
00815 static int is_wanted_sar_data(void *a, void *b)
00816 {
00817 sar_info_t *s;
00818 int *i;
00819
00820 s = a;
00821 i = b;
00822
00823 if (*i == s->sar_psn) {
00824 return 1;
00825 } else {
00826 return 0;
00827 }
00828 }
00829
00830
00831
00832
00833 static int add_sar_transaction(WTPRespMachine *machine, Octstr *data, int psn)
00834 {
00835 sar_info_t *sar_info;
00836
00837 if (machine->sar_info == NULL) {
00838 machine->sar_info = gwlist_create();
00839 }
00840
00841 if (gwlist_search(machine->sar_info, &psn, is_wanted_sar_data) == NULL) {
00842 sar_info = gw_malloc(sizeof(sar_info_t));
00843 sar_info->sar_psn = psn;
00844 sar_info->sar_data = octstr_duplicate(data);
00845 gwlist_append(machine->sar_info, sar_info);
00846 return 0;
00847 } else {
00848 debug("wap.wtp", 0, "Duplicated psn found, ignore packet");
00849 return 1;
00850 }
00851 }
00852
00853 static WAPEvent *assembly_sar_event(WTPRespMachine *machine, int last_psn)
00854 {
00855 WAPEvent *e;
00856 int i;
00857 sar_info_t *sar_info;
00858
00859 e = wap_event_duplicate(machine->sar_invoke);
00860
00861 for (i = 1; i <= last_psn; i++) {
00862 if ((sar_info = gwlist_search(machine->sar_info, &i, is_wanted_sar_data)) != NULL) {
00863 octstr_append(e->u.RcvInvoke.user_data,sar_info->sar_data);
00864 } else {
00865 debug("wap.wtp", 0, "Packet with psn %d not found", i);
00866 return e;
00867 }
00868 }
00869
00870 return e;
00871 }
00872
00873 static void sar_info_destroy(void *p)
00874 {
00875 sar_info_t *sar_info;
00876
00877 sar_info = p;
00878
00879 octstr_destroy(sar_info->sar_data);
00880 gw_free(sar_info);
00881 }
00882
00883 static void sardata_destroy(void *p)
00884 {
00885 WTPSARData * sardata;
00886
00887 if (p) {
00888 sardata = p;
00889 octstr_destroy(sardata->data);
00890 gw_free(sardata);
00891 }
00892 }
00893
00894 static void begin_sar_result(WTPRespMachine *resp_machine, WAPEvent *event)
00895 {
00896 WAPEvent *result;
00897 WTPSARData *sar;
00898 int psn;
00899
00900 gw_assert(resp_machine->sar != NULL);
00901
00902 sar = resp_machine->sar;
00903 sar->data = octstr_duplicate(event->u.TR_Result_Req.user_data);
00904 sar->nsegm = (octstr_len(sar->data)-1)/SAR_SEGM_SIZE;
00905 sar->tr = sar->lsegm = 0;
00906 sar->csegm = -1;
00907
00908 debug("wap.wtp", 0, "WTP: begin_sar_result(): data len = %lu",
00909 octstr_len(sar->data));
00910
00911 for (psn = 0; !sar->tr; psn++) {
00912 result = wtp_pack_sar_result(resp_machine, psn);
00913 if (sar->tr)
00914 resp_machine->result = wap_event_duplicate(result);
00915
00916 debug("wap.wtp", 0, "WTP: dispath_to_wdp(): psn = %u", psn);
00917 dispatch_to_wdp(result);
00918 sar->lsegm = psn;
00919 }
00920
00921 resp_machine->rid = 1;
00922 }
00923
00924 static void continue_sar_result(WTPRespMachine *resp_machine, WAPEvent *event)
00925 {
00926 WAPEvent *result;
00927 WTPSARData *sar;
00928 int psn;
00929
00930 gw_assert(resp_machine->sar != NULL && event->type == RcvAck);
00931
00932 sar = resp_machine->sar;
00933
00934 debug("wap.wtp", 0, "WTP: continue_sar_result(): lsegm=%d, nsegm=%d, csegm=%d",
00935 sar->lsegm, sar->nsegm, sar->csegm);
00936
00937 start_timer_R(resp_machine);
00938
00939 if (event->u.RcvAck.psn>sar->csegm) {
00940 sar->csegm = event->u.RcvAck.psn;
00941 }
00942
00943 sar->tr = 0;
00944 wap_event_destroy(resp_machine->result);
00945 resp_machine->result = NULL;
00946
00947 for (psn = sar->csegm + 1; !sar->tr; psn++) {
00948 result = wtp_pack_sar_result(resp_machine, psn);
00949 if (sar->tr)
00950 resp_machine->result = wap_event_duplicate(result);
00951
00952 debug("wap.wtp", 0, "WTP: dispath_to_wdp(): psn = %u",psn);
00953 dispatch_to_wdp(result);
00954 sar->lsegm = psn;
00955 }
00956 }
00957
00958 static void resend_sar_result(WTPRespMachine *resp_machine, WAPEvent *event)
00959 {
00960 WAPEvent *result;
00961 WTPSARData *sar;
00962 int psn, i;
00963
00964 gw_assert(resp_machine->sar != NULL && event->type == RcvNegativeAck);
00965
00966 sar = resp_machine->sar;
00967
00968 debug("wap.wtp", 0, "WTP: resend_sar_result(): lsegm=%d, nsegm=%d, csegm=%d",
00969 sar->lsegm, sar->nsegm, sar->csegm);
00970
00971 start_timer_R(resp_machine);
00972
00973 if (event->u.RcvNegativeAck.nmissing) {
00974
00975 for(i = 0; i < event->u.RcvNegativeAck.nmissing; i++) {
00976 if ((psn = octstr_get_char(event->u.RcvNegativeAck.missing, i)) >= 0) {
00977 result = wtp_pack_sar_result(resp_machine, psn);
00978 wtp_pack_set_rid(result, 1);
00979 debug("wap.wtp", 0, "WTP: dispath_to_wdp(): psn = %u", psn);
00980 dispatch_to_wdp(result);
00981 }
00982 }
00983 } else {
00984
00985 sar->tr = 0;
00986 for (psn = sar->csegm+1; !sar->tr; psn++) {
00987 result = wtp_pack_sar_result(resp_machine, psn);
00988 wtp_pack_set_rid(result, 1);
00989 debug("wap.wtp", 0, "WTP: dispath_to_wdp(): psn = %u", psn);
00990 dispatch_to_wdp(result);
00991 }
00992 }
00993 }
00994
00995
00996
See file LICENSE for details about the license agreement for using,
modifying, copying or deriving work from this software.