Kannel: Open Source WAP and SMS gateway  svn-r5335
wsp_session.c File Reference
#include <string.h>
#include <limits.h>
#include "gwlib/gwlib.h"
#include "wsp.h"
#include "wsp_pdu.h"
#include "wsp_headers.h"
#include "wsp_caps.h"
#include "wsp_strings.h"
#include "cookies.h"
#include "wap.h"
#include "wtp.h"
#include "wsp_server_session_states.def"
#include "wsp_server_method_states.def"
#include "wsp_server_push_states.def"
#include "wsp_server_session_machine.def"
#include "wsp_server_method_machine.def"
#include "wsp_server_push_machine.def"

Go to the source code of this file.

Data Structures

struct  msm_pattern
 

Macros

#define STATE_NAME(name)   name,
 
#define ROW(state, event, condition, action, next_state)
 
#define STATE_NAME(name)   name,
 
#define ROW(state, event, condition, action, next_state)
 
#define STATE_NAME(name)   name,
 
#define ROW(state, event, condition, action, next_state)
 
#define STATE_NAME(name)
 
#define ROW(state_name, event, condition, action, next_state)
 
#define INTEGER(name)   p->name = 0;
 
#define OCTSTR(name)   p->name = NULL;
 
#define HTTPHEADERS(name)   p->name = NULL;
 
#define ADDRTUPLE(name)   p->name = NULL;
 
#define MACHINESLIST(name)   p->name = gwlist_create();
 
#define CAPABILITIES(name)   p->name = NULL;
 
#define COOKIES(name)   p->name = gwlist_create();
 
#define REFERER(name)   p->name = NULL;
 
#define MACHINE(fields)   fields
 
#define INTEGER(name)   p->name = 0;
 
#define OCTSTR(name)   octstr_destroy(p->name);
 
#define HTTPHEADERS(name)   http_destroy_headers(p->name);
 
#define ADDRTUPLE(name)   wap_addr_tuple_destroy(p->name);
 
#define MACHINESLIST(name)   destroy_##name(p->name);
 
#define CAPABILITIES(name)   wsp_cap_destroy_list(p->name);
 
#define COOKIES(name)   cookies_destroy(p->name);
 
#define REFERER(name)   octstr_destroy(p->name);
 
#define MACHINE(fields)   fields
 
#define STATE_NAME(name)
 
#define ROW(state_name, event, condition, action, next_state)
 
#define INTEGER(name)   msm->name = 0;
 
#define ADDRTUPLE(name)   msm->name = NULL;
 
#define EVENT(name)   msm->name = NULL;
 
#define MACHINE(fields)   fields
 
#define INTEGER(name)
 
#define ADDRTUPLE(name)   wap_addr_tuple_destroy(msm->name);
 
#define EVENT(name)   wap_event_destroy(msm->name);
 
#define MACHINE(fields)   fields
 
#define STATE_NAME(name)
 
#define ROW(state_name, event, condition, action, next_state)
 
#define INTEGER(name)   m->name = 0;
 
#define ADDRTUPLE(name)   m->name = NULL;
 
#define HTTPHEADER(name)   m->name = http_create_empty_headers();
 
#define MACHINE(fields)   fields
 
#define INTEGER(name)
 
#define ADDRTUPLE(name)   wap_addr_tuple_destroy(m->name);
 
#define HTTPHEADER(name)   http_destroy_headers(m->name);
 
#define MACHINE(fields)   fields
 
#define STATE_NAME(name)   case name: return #name;
 
#define ROW(state, event, cond, stmt, next_state)
 
#define STATE_NAME(name)   case name: return #name;
 
#define ROW(state, event, cond, stmt, next_state)
 
#define STATE_NAME(name)   case name: return #name;
 
#define ROW(state, event, cond, stmt, next_state)
 

Enumerations

enum  WSPState { ROW, ROW }
 
enum  { limbo, running, terminating }
 

Functions

static WSPMachinefind_session_machine (WAPEvent *event, WSP_PDU *pdu)
 
static void handle_session_event (WSPMachine *machine, WAPEvent *event, WSP_PDU *pdu)
 
static WSPMachinemachine_create (void)
 
static void machine_destroy (void *p)
 
static void handle_method_event (WSPMachine *session, WSPMethodMachine *machine, WAPEvent *event, WSP_PDU *pdu)
 
static void cant_handle_event (WSPMachine *sm, WAPEvent *event)
 
static WSPMethodMachinemethod_machine_create (WSPMachine *, long)
 
static void method_machine_destroy (void *msm)
 
static void handle_push_event (WSPMachine *session, WSPPushMachine *machine, WAPEvent *e)
 
static WSPPushMachinepush_machine_create (WSPMachine *session, long id)
 
static void push_machine_destroy (void *p)
 
static char * state_name (WSPState state)
 
static unsigned long next_wsp_session_id (void)
 
static Listmake_capabilities_reply (WSPMachine *m)
 
static Listmake_reply_headers (WSPMachine *m)
 
static Octstrmake_connectreply_pdu (WSPMachine *m)
 
static Octstrmake_resume_reply_pdu (WSPMachine *m, List *headers)
 
static WSP_PDUmake_confirmedpush_pdu (WAPEvent *e)
 
static WSP_PDUmake_push_pdu (WAPEvent *e)
 
static int transaction_belongs_to_session (void *session, void *tuple)
 
static int find_by_session_id (void *session, void *idp)
 
static int same_client (void *sm1, void *sm2)
 
static WSPMethodMachinefind_method_machine (WSPMachine *, long id)
 
static WSPPushMachinefind_push_machine (WSPMachine *m, long id)
 
static Listunpack_new_headers (WSPMachine *sm, Octstr *hdrs)
 
static void disconnect_other_sessions (WSPMachine *sm)
 
static void send_abort (long reason, long handle)
 
static void indicate_disconnect (WSPMachine *sm, long reason)
 
static void indicate_suspend (WSPMachine *sm, long reason)
 
static void indicate_resume (WSPMachine *sm, WAPAddrTuple *tuple, List *client_headers)
 
static void release_holding_methods (WSPMachine *sm)
 
static void abort_methods (WSPMachine *sm, long reason)
 
static void abort_pushes (WSPMachine *sm, long reason)
 
static void method_abort (WSPMethodMachine *msm, long reason)
 
static void indicate_method_abort (WSPMethodMachine *msm, long reason)
 
static WAPEventmake_abort (long reason, long handle)
 
static void send_invoke (WSPMachine *session, WSP_PDU *pdu, WAPEvent *e, long class)
 
static void send_abort_to_initiator (long reason, long handle)
 
static void indicate_pushabort (WSPPushMachine *machine, long reason)
 
static void confirm_push (WSPPushMachine *machine)
 
static void main_thread (void *)
 
static int id_belongs_to_session (void *, void *)
 
static int wsp_encoding_string_to_version (Octstr *enc)
 
static Octstrwsp_encoding_version_to_string (int version)
 
void wsp_session_init (wap_dispatch_func_t *responder_dispatch, wap_dispatch_func_t *initiator_dispatch, wap_dispatch_func_t *application_dispatch, wap_dispatch_func_t *push_ota_dispatch)
 
void wsp_session_shutdown (void)
 
void wsp_session_dispatch_event (WAPEvent *event)
 
static void destroy_methodmachines (List *machines)
 
static void destroy_pushmachines (List *machines)
 
static void sanitize_capabilities (List *caps, WSPMachine *m)
 
static void reply_known_capabilities (List *caps, List *req, WSPMachine *m)
 
static void refuse_unreplied_capabilities (List *caps, List *req)
 
static int is_default_cap (Capability *cap)
 
static void strip_default_capabilities (List *caps, List *req)
 
static int find_by_method_id (void *wspm_ptr, void *id_ptr)
 
static int find_by_push_id (void *m_ptr, void *id_ptr)
 
static int method_is_holding (void *item, void *pattern)
 
WSPMachinefind_session_machine_by_id (int id)
 

Variables

static enum { ... }  run_status = limbo
 
static wap_dispatch_func_tdispatch_to_wtp_resp
 
static wap_dispatch_func_tdispatch_to_wtp_init
 
static wap_dispatch_func_tdispatch_to_appl
 
static wap_dispatch_func_tdispatch_to_ota
 
static int resume_enabled = 1
 
static Listqueue = NULL
 
static Listsession_machines = NULL
 
static Countersession_id_counter = NULL
 

Macro Definition Documentation

◆ ADDRTUPLE [1/6]

#define ADDRTUPLE (   name)    p->name = NULL;

◆ ADDRTUPLE [2/6]

#define ADDRTUPLE (   name)    wap_addr_tuple_destroy(p->name);

◆ ADDRTUPLE [3/6]

#define ADDRTUPLE (   name)    msm->name = NULL;

◆ ADDRTUPLE [4/6]

#define ADDRTUPLE (   name)    wap_addr_tuple_destroy(msm->name);

◆ ADDRTUPLE [5/6]

#define ADDRTUPLE (   name)    m->name = NULL;

◆ ADDRTUPLE [6/6]

#define ADDRTUPLE (   name)    wap_addr_tuple_destroy(m->name);

◆ CAPABILITIES [1/2]

#define CAPABILITIES (   name)    p->name = NULL;

◆ CAPABILITIES [2/2]

#define CAPABILITIES (   name)    wsp_cap_destroy_list(p->name);

◆ COOKIES [1/2]

#define COOKIES (   name)    p->name = gwlist_create();

◆ COOKIES [2/2]

#define COOKIES (   name)    cookies_destroy(p->name);

◆ EVENT [1/2]

#define EVENT (   name)    msm->name = NULL;

◆ EVENT [2/2]

#define EVENT (   name)    wap_event_destroy(msm->name);

◆ HTTPHEADER [1/2]

#define HTTPHEADER (   name)    m->name = http_create_empty_headers();

◆ HTTPHEADER [2/2]

#define HTTPHEADER (   name)    http_destroy_headers(m->name);

◆ HTTPHEADERS [1/2]

#define HTTPHEADERS (   name)    p->name = NULL;

◆ HTTPHEADERS [2/2]

#define HTTPHEADERS (   name)    http_destroy_headers(p->name);

◆ INTEGER [1/6]

#define INTEGER (   name)    p->name = 0;

◆ INTEGER [2/6]

#define INTEGER (   name)    p->name = 0;

◆ INTEGER [3/6]

#define INTEGER (   name)    msm->name = 0;

◆ INTEGER [4/6]

#define INTEGER (   name)

◆ INTEGER [5/6]

#define INTEGER (   name)    m->name = 0;

◆ INTEGER [6/6]

#define INTEGER (   name)

◆ MACHINE [1/6]

#define MACHINE (   fields)    fields

◆ MACHINE [2/6]

#define MACHINE (   fields)    fields

◆ MACHINE [3/6]

#define MACHINE (   fields)    fields

◆ MACHINE [4/6]

#define MACHINE (   fields)    fields

◆ MACHINE [5/6]

#define MACHINE (   fields)    fields

◆ MACHINE [6/6]

#define MACHINE (   fields)    fields

◆ MACHINESLIST [1/2]

#define MACHINESLIST (   name)    p->name = gwlist_create();

◆ MACHINESLIST [2/2]

#define MACHINESLIST (   name)    destroy_##name(p->name);

◆ OCTSTR [1/2]

#define OCTSTR (   name)    p->name = NULL;

◆ OCTSTR [2/2]

#define OCTSTR (   name)    octstr_destroy(p->name);

◆ REFERER [1/2]

#define REFERER (   name)    p->name = NULL;

◆ REFERER [2/2]

#define REFERER (   name)    octstr_destroy(p->name);

◆ ROW [1/9]

#define ROW (   state,
  event,
  condition,
  action,
  next_state 
)

Definition at line 81 of file wsp_session.c.

◆ ROW [2/9]

#define ROW (   state,
  event,
  condition,
  action,
  next_state 
)

Definition at line 81 of file wsp_session.c.

◆ ROW [3/9]

#define ROW (   state,
  event,
  condition,
  action,
  next_state 
)

Definition at line 81 of file wsp_session.c.

◆ ROW [4/9]

#define ROW (   state_name,
  event,
  condition,
  action,
  next_state 
)
Value:
{ \
struct event *e; \
e = &current_event->u.event; \
if (sm->state == state_name && \
current_event->type == event && \
(condition)) { \
action \
sm->state = next_state; \
debug("wap.wsp", 0, "WSP %ld: New state %s", \
sm->session_id, #next_state); \
goto end; \
} \
}
static char * state_name(WSPState state)
Definition: wsp_session.c:729

Definition at line 81 of file wsp_session.c.

◆ ROW [5/9]

#define ROW (   state_name,
  event,
  condition,
  action,
  next_state 
)
Value:
{ \
struct event *e; \
e = &current_event->u.event; \
if (msm->state == state_name && \
current_event->type == event && \
(condition)) { \
action \
msm->state = next_state; \
debug("wap.wsp", 0, "WSP %ld/%ld: New method state %s", \
msm->session_id, msm->transaction_id, #next_state); \
goto end; \
} \
}
static char * state_name(WSPState state)
Definition: wsp_session.c:729

Definition at line 81 of file wsp_session.c.

◆ ROW [6/9]

#define ROW (   state_name,
  event,
  condition,
  action,
  next_state 
)
Value:
{ \
if (pm->state == state_name && \
current_event->type == event && \
(condition)) { \
action \
pm->state = next_state; \
debug("wap.wsp", 0, "WSP %ld/%ld: New push state %s", \
pm->session_id, pm->transaction_id, #next_state); \
goto end; \
} \
}
static char * state_name(WSPState state)
Definition: wsp_session.c:729

Definition at line 81 of file wsp_session.c.

◆ ROW [7/9]

#define ROW (   state,
  event,
  cond,
  stmt,
  next_state 
)

Definition at line 81 of file wsp_session.c.

◆ ROW [8/9]

#define ROW (   state,
  event,
  cond,
  stmt,
  next_state 
)

Definition at line 81 of file wsp_session.c.

◆ ROW [9/9]

#define ROW (   state,
  event,
  cond,
  stmt,
  next_state 
)

Definition at line 81 of file wsp_session.c.

◆ STATE_NAME [1/9]

#define STATE_NAME (   name)    name,

Definition at line 80 of file wsp_session.c.

◆ STATE_NAME [2/9]

#define STATE_NAME (   name)    name,

Definition at line 80 of file wsp_session.c.

◆ STATE_NAME [3/9]

#define STATE_NAME (   name)    name,

Definition at line 80 of file wsp_session.c.

◆ STATE_NAME [4/9]

#define STATE_NAME (   name)

Definition at line 80 of file wsp_session.c.

◆ STATE_NAME [5/9]

#define STATE_NAME (   name)

Definition at line 80 of file wsp_session.c.

◆ STATE_NAME [6/9]

#define STATE_NAME (   name)

Definition at line 80 of file wsp_session.c.

◆ STATE_NAME [7/9]

#define STATE_NAME (   name)    case name: return #name;

Definition at line 80 of file wsp_session.c.

◆ STATE_NAME [8/9]

#define STATE_NAME (   name)    case name: return #name;

Definition at line 80 of file wsp_session.c.

◆ STATE_NAME [9/9]

#define STATE_NAME (   name)    case name: return #name;

Definition at line 80 of file wsp_session.c.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
limbo 
running 
terminating 

Definition at line 106 of file wsp_session.c.

static enum @91 run_status

◆ WSPState

enum WSPState
Enumerator
ROW 
ROW 

Definition at line 79 of file wsp_session.c.

79  {
80  #define STATE_NAME(name) name,
81  #define ROW(state, event, condition, action, next_state)
83 
84  #define STATE_NAME(name) name,
85  #define ROW(state, event, condition, action, next_state)
87 
88  #define STATE_NAME(name) name,
89  #define ROW(state, event, condition, action, next_state)
91 
92  WSPState_count
93 } WSPState;
WSPState
Definition: wsp_session.c:79

Function Documentation

◆ abort_methods()

static void abort_methods ( WSPMachine sm,
long  reason 
)
static

Definition at line 1395 of file wsp_session.c.

References gwlist_get(), gwlist_len(), handle_method_event(), WAPEvent::u, wap_event_create, and wap_event_destroy().

Referenced by cant_handle_event().

1395  {
1396  WAPEvent *ab;
1397  WSPMethodMachine *msm;
1398  long i, len;
1399 
1400  ab = wap_event_create(Abort_Event);
1401  ab->u.Abort_Event.reason = reason;
1402 
1403  /* This loop goes backward because it has to deal with the
1404  * possibility of method machines disappearing after their event. */
1405  len = gwlist_len(sm->methodmachines);
1406  for (i = len - 1; i >= 0; i--) {
1407  msm = gwlist_get(sm->methodmachines, i);
1408  handle_method_event(sm, msm, ab, NULL);
1409  }
1410 
1411  wap_event_destroy(ab);
1412 }
long gwlist_len(List *list)
Definition: list.c:166
void * gwlist_get(List *list, long pos)
Definition: list.c:292
#define wap_event_create(type)
Definition: wap_events.h:107
static void handle_method_event(WSPMachine *session, WSPMethodMachine *machine, WAPEvent *event, WSP_PDU *pdu)
Definition: wsp_session.c:564
union WAPEvent::@87 u
void wap_event_destroy(WAPEvent *event)
Definition: wap_events.c:102

◆ abort_pushes()

static void abort_pushes ( WSPMachine sm,
long  reason 
)
static

Definition at line 1415 of file wsp_session.c.

References gwlist_get(), gwlist_len(), handle_push_event(), WAPEvent::u, wap_event_create, and wap_event_destroy().

Referenced by cant_handle_event().

1416 {
1417  WAPEvent *ab;
1418  WSPPushMachine *psm;
1419  long i, len;
1420 
1421  ab = wap_event_create(Abort_Event);
1422  ab->u.Abort_Event.reason = reason;
1423 
1424  len = gwlist_len(sm->pushmachines);
1425  for (i = len - 1; i >= 0; i--) {
1426  psm = gwlist_get(sm->pushmachines, i);
1427  handle_push_event(sm, psm, ab);
1428  }
1429 
1430  wap_event_destroy(ab);
1431 }
static void handle_push_event(WSPMachine *session, WSPPushMachine *machine, WAPEvent *e)
Definition: wsp_session.c:650
long gwlist_len(List *list)
Definition: list.c:166
void * gwlist_get(List *list, long pos)
Definition: list.c:292
#define wap_event_create(type)
Definition: wap_events.h:107
union WAPEvent::@87 u
void wap_event_destroy(WAPEvent *event)
Definition: wap_events.c:102

◆ cant_handle_event()

static void cant_handle_event ( WSPMachine sm,
WAPEvent event 
)
static

Definition at line 442 of file wsp_session.c.

References abort_methods(), abort_pushes(), debug(), error(), indicate_disconnect(), send_abort(), WAPEvent::type, WAPEvent::u, wap_event_dump(), warning(), and WSP_ABORT_PROTOERR.

Referenced by handle_method_event(), handle_push_event(), and handle_session_event().

442  {
443  /* We do the rest of the pre-state-machine tests here. The first
444  * four were done in find_session_machine(). The fifth is a
445  * class 1 or 2 TR-Invoke.ind not handled by the state tables. */
446  if (event->type == TR_Invoke_Ind &&
447  (event->u.TR_Invoke_Ind.tcl == 1 ||
448  event->u.TR_Invoke_Ind.tcl == 2)) {
449  warning(0, "WSP: Can't handle TR-Invoke.ind, aborting transaction.");
450  debug("wap.wsp", 0, "WSP: The unhandled event:");
451  wap_event_dump(event);
453  event->u.TR_Invoke_Ind.handle);
454  /* The sixth is a class 0 TR-Invoke.ind not handled by state tables. */
455  } else if (event->type == TR_Invoke_Ind) {
456  warning(0, "WSP: Can't handle TR-Invoke.ind, ignoring.");
457  debug("wap.wsp", 0, "WSP: The ignored event:");
458  wap_event_dump(event);
459  /* The seventh is any other event not handled by state tables. */
460  } else {
461  error(0, "WSP: Can't handle event. Aborting session.");
462  debug("wap.wsp", 0, "WSP: The unhandled event:");
463  wap_event_dump(event);
464  /* TR-Abort.req(PROTOERR) if it is some other transaction
465  * event than abort. */
466  /* Currently that means TR-Result.cnf, because we already
467  * tested for Invoke. */
468  /* FIXME We need a better way to get at event values than
469  * by hardcoding the types. */
470  if (event->type == TR_Result_Cnf) {
472  event->u.TR_Result_Cnf.handle);
473  }
474  /* Abort(PROTOERR) all method and push transactions */
477  /* S-Disconnect.ind(PROTOERR) */
479  }
480 }
void error(int err, const char *fmt,...)
Definition: log.c:648
static void indicate_disconnect(WSPMachine *sm, long reason)
Definition: wsp_session.c:1277
static void abort_methods(WSPMachine *sm, long reason)
Definition: wsp_session.c:1395
static void abort_pushes(WSPMachine *sm, long reason)
Definition: wsp_session.c:1415
void wap_event_dump(WAPEvent *event)
Definition: wap_events.c:181
void warning(int err, const char *fmt,...)
Definition: log.c:660
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
WAPEventName type
Definition: wap_events.h:88
union WAPEvent::@87 u
static void send_abort(long reason, long handle)
Definition: wsp_session.c:1235

◆ confirm_push()

static void confirm_push ( WSPPushMachine machine)
static

Definition at line 1323 of file wsp_session.c.

References dispatch_to_appl, WAPEvent::u, and wap_event_create.

1324 {
1325  WAPEvent *ota_event;
1326 
1327  ota_event = wap_event_create(S_ConfirmedPush_Cnf);
1328  ota_event->u.S_ConfirmedPush_Cnf.server_push_id = m->server_push_id;
1329  ota_event->u.S_ConfirmedPush_Cnf.session_id = m->session_id;
1330  dispatch_to_appl(ota_event);
1331 }
static wap_dispatch_func_t * dispatch_to_appl
Definition: wsp_session.c:110
#define wap_event_create(type)
Definition: wap_events.h:107
union WAPEvent::@87 u

◆ destroy_methodmachines()

static void destroy_methodmachines ( List machines)
static

Definition at line 517 of file wsp_session.c.

References gwlist_destroy(), gwlist_len(), method_machine_destroy(), and warning().

517  {
518  if (gwlist_len(machines) > 0) {
519  warning(0, "Destroying WSP session with %ld active methods\n",
520  gwlist_len(machines));
521  }
522 
524 }
long gwlist_len(List *list)
Definition: list.c:166
void warning(int err, const char *fmt,...)
Definition: log.c:660
static void method_machine_destroy(void *msm)
Definition: wsp_session.c:630
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145

◆ destroy_pushmachines()

static void destroy_pushmachines ( List machines)
static

Definition at line 526 of file wsp_session.c.

References gwlist_destroy(), gwlist_len(), push_machine_destroy(), and warning().

526  {
527  if (gwlist_len(machines) > 0) {
528  warning(0, "Destroying WSP session with %ld active pushes\n",
529  gwlist_len(machines));
530  }
531 
533 }
long gwlist_len(List *list)
Definition: list.c:166
static void push_machine_destroy(void *p)
Definition: wsp_session.c:711
void warning(int err, const char *fmt,...)
Definition: log.c:660
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145

◆ disconnect_other_sessions()

static void disconnect_other_sessions ( WSPMachine sm)
static

Definition at line 1188 of file wsp_session.c.

References gwlist_destroy(), gwlist_get(), gwlist_len(), gwlist_search_all(), handle_session_event(), same_client(), session_machines, and wap_event_create.

1188  {
1189  List *old_sessions;
1190  WAPEvent *disconnect;
1191  WSPMachine *sm2;
1192  long i;
1193 
1194  old_sessions = gwlist_search_all(session_machines, sm, same_client);
1195  if (old_sessions == NULL)
1196  return;
1197 
1198  for (i = 0; i < gwlist_len(old_sessions); i++) {
1199  sm2 = gwlist_get(old_sessions, i);
1200  if (sm2 != sm) {
1201  disconnect = wap_event_create(Disconnect_Event);
1202  handle_session_event(sm2, disconnect, NULL);
1203  }
1204  }
1205 
1206  gwlist_destroy(old_sessions, NULL);
1207 }
static void handle_session_event(WSPMachine *machine, WAPEvent *event, WSP_PDU *pdu)
Definition: wsp_session.c:408
long gwlist_len(List *list)
Definition: list.c:166
void * gwlist_get(List *list, long pos)
Definition: list.c:292
static List * session_machines
Definition: wsp_session.c:123
List * gwlist_search_all(List *list, void *pattern, int(*cmp)(void *, void *))
Definition: list.c:508
static int same_client(void *sm1, void *sm2)
Definition: wsp_session.c:1179
#define wap_event_create(type)
Definition: wap_events.h:107
Definition: list.c:102
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145

◆ find_by_method_id()

static int find_by_method_id ( void *  wspm_ptr,
void *  id_ptr 
)
static

Definition at line 1156 of file wsp_session.c.

Referenced by find_method_machine().

1156  {
1157  WSPMethodMachine *msm = wspm_ptr;
1158  long *idp = id_ptr;
1159 
1160  return msm->transaction_id == *idp;
1161 }

◆ find_by_push_id()

static int find_by_push_id ( void *  m_ptr,
void *  id_ptr 
)
static

Definition at line 1163 of file wsp_session.c.

Referenced by find_push_machine().

1163  {
1164  WSPPushMachine *m = m_ptr;
1165  long *idp = id_ptr;
1166 
1167  return m->transaction_id == *idp;
1168 }

◆ find_by_session_id()

static int find_by_session_id ( void *  session,
void *  idp 
)
static

Definition at line 1148 of file wsp_session.c.

Referenced by find_session_machine().

1148  {
1149  WSPMachine *wsp = wsp_ptr;
1150  long *idp = id_ptr;
1151 
1152  return wsp->session_id == *idp;
1153 }

◆ find_method_machine()

static WSPMethodMachine * find_method_machine ( WSPMachine sm,
long  id 
)
static

Definition at line 1170 of file wsp_session.c.

References find_by_method_id(), and gwlist_search().

1170  {
1171  return gwlist_search(sm->methodmachines, &id, find_by_method_id);
1172 }
void * gwlist_search(List *list, void *pattern, int(*cmp)(void *, void *))
Definition: list.c:486
static int find_by_method_id(void *wspm_ptr, void *id_ptr)
Definition: wsp_session.c:1156

◆ find_push_machine()

static WSPPushMachine * find_push_machine ( WSPMachine m,
long  id 
)
static

Definition at line 1174 of file wsp_session.c.

References find_by_push_id(), and gwlist_search().

1175 {
1176  return gwlist_search(m->pushmachines, &id, find_by_push_id);
1177 }
void * gwlist_search(List *list, void *pattern, int(*cmp)(void *, void *))
Definition: list.c:486
static int find_by_push_id(void *m_ptr, void *id_ptr)
Definition: wsp_session.c:1163

◆ find_session_machine()

static WSPMachine * find_session_machine ( WAPEvent event,
WSP_PDU pdu 
)
static

Definition at line 273 of file wsp_session.c.

References error(), find_by_session_id(), gw_assert(), gwlist_search(), machine_create(), send_abort(), session_machines, transaction_belongs_to_session(), wsp_pdu::type, WAPEvent::type, WAPEvent::u, wsp_pdu::u, wap_addr_tuple_destroy(), wap_addr_tuple_duplicate(), wap_event_dump(), wap_event_name(), and WSP_ABORT_DISCONNECT.

Referenced by main_thread().

273  {
274  WSPMachine *sm;
275  long session_id;
276  WAPAddrTuple *tuple;
277 
278  tuple = NULL;
279  session_id = -1;
280 
281  switch (event->type) {
282  case TR_Invoke_Ind:
283  tuple = wap_addr_tuple_duplicate(
284  event->u.TR_Invoke_Ind.addr_tuple);
285  break;
286 
287  case TR_Invoke_Cnf:
288  tuple = wap_addr_tuple_duplicate(
289  event->u.TR_Invoke_Cnf.addr_tuple);
290  break;
291 
292  case TR_Result_Cnf:
293  tuple = wap_addr_tuple_duplicate(
294  event->u.TR_Result_Cnf.addr_tuple);
295  break;
296 
297  case TR_Abort_Ind:
298  tuple = wap_addr_tuple_duplicate(
299  event->u.TR_Abort_Ind.addr_tuple);
300  break;
301 
302  case S_Connect_Res:
303  session_id = event->u.S_Connect_Res.session_id;
304  break;
305 
306  case S_Resume_Res:
307  session_id = event->u.S_Resume_Res.session_id;
308  break;
309 
310  case Disconnect_Event:
311  session_id = event->u.Disconnect_Event.session_handle;
312  break;
313 
314  case Suspend_Event:
315  session_id = event->u.Suspend_Event.session_handle;
316  break;
317 
318  case S_MethodInvoke_Res:
319  session_id = event->u.S_MethodInvoke_Res.session_id;
320  break;
321 
322  case S_MethodResult_Req:
323  session_id = event->u.S_MethodResult_Req.session_id;
324  break;
325 
326  case S_ConfirmedPush_Req:
327  session_id = event->u.S_ConfirmedPush_Req.session_id;
328  break;
329 
330  case S_Push_Req:
331  session_id = event->u.S_Push_Req.session_id;
332  break;
333 
334  default:
335  error(0, "WSP: Cannot find machine for %s event",
336  wap_event_name(event->type));
337  }
338 
339  gw_assert(tuple != NULL || session_id != -1);
340 
341  /* Pre-state-machine tests, according to 7.1.5. After the tests,
342  * caller will pass the event to sm if sm is not NULL. */
343  sm = NULL;
344  /* First test is for MRUEXCEEDED, and we don't have a MRU */
345 
346  /* Second test is for class 2 TR-Invoke.ind with Connect PDU */
347  if (event->type == TR_Invoke_Ind &&
348  event->u.TR_Invoke_Ind.tcl == 2 &&
349  pdu->type == Connect) {
350  /* Create a new session, even if there is already
351  * a session open for this address. The new session
352  * will take care of killing the old ones. */
353  sm = machine_create();
354  gw_assert(tuple != NULL);
355  sm->addr_tuple = wap_addr_tuple_duplicate(tuple);
356  sm->connect_handle = event->u.TR_Invoke_Ind.handle;
357  /* Third test is for class 2 TR-Invoke.ind with Resume PDU */
358  } else if (event->type == TR_Invoke_Ind &&
359  event->u.TR_Invoke_Ind.tcl == 2 &&
360  pdu->type == Resume) {
361  /* Pass to session identified by session id, not
362  * the address tuple. */
363  session_id = pdu->u.Resume.sessionid;
364  sm = gwlist_search(session_machines, &session_id,
366  if (sm == NULL) {
367  /* No session; TR-Abort.req(DISCONNECT) */
369  event->u.TR_Invoke_Ind.handle);
370  }
371  /* Fourth test is for a class 1 or 2 TR-Invoke.Ind with no
372  * session for that address tuple. We also handle class 0
373  * TR-Invoke.ind here by ignoring them; this seems to be
374  * an omission in the spec table. */
375  } else if (event->type == TR_Invoke_Ind) {
376  sm = gwlist_search(session_machines, tuple,
378  if (sm == NULL && (event->u.TR_Invoke_Ind.tcl == 1 ||
379  event->u.TR_Invoke_Ind.tcl == 2)) {
381  event->u.TR_Invoke_Ind.handle);
382  }
383  /* Other tests are for events not handled by the state tables;
384  * do those later, after we've tried to handle them. */
385  } else {
386  if (session_id != -1) {
387  sm = gwlist_search(session_machines, &session_id,
389  } else {
390  sm = gwlist_search(session_machines, tuple,
392  }
393  /* The table doesn't really say what we should do with
394  * non-Invoke events for which there is no session. But
395  * such a situation means there is an error _somewhere_
396  * in the gateway. */
397  if (sm == NULL) {
398  error(0, "WSP: Cannot find session machine for event.");
399  wap_event_dump(event);
400  }
401  }
402 
403  wap_addr_tuple_destroy(tuple);
404  return sm;
405 }
void error(int err, const char *fmt,...)
Definition: log.c:648
union wsp_pdu::@89 u
void * gwlist_search(List *list, void *pattern, int(*cmp)(void *, void *))
Definition: list.c:486
static int find_by_session_id(void *session, void *idp)
Definition: wsp_session.c:1148
gw_assert(wtls_machine->packet_to_send !=NULL)
static WSPMachine * machine_create(void)
Definition: wsp_session.c:483
void wap_event_dump(WAPEvent *event)
Definition: wap_events.c:181
WAPAddrTuple * wap_addr_tuple_duplicate(WAPAddrTuple *tuple)
Definition: wap_addr.c:125
static List * session_machines
Definition: wsp_session.c:123
const char * wap_event_name(WAPEventName type)
Definition: wap_events.c:169
void wap_addr_tuple_destroy(WAPAddrTuple *tuple)
Definition: wap_addr.c:108
static int transaction_belongs_to_session(void *session, void *tuple)
Definition: wsp_session.c:1137
int type
Definition: wsp_pdu.h:87
WAPEventName type
Definition: wap_events.h:88
union WAPEvent::@87 u
static void send_abort(long reason, long handle)
Definition: wsp_session.c:1235

◆ find_session_machine_by_id()

WSPMachine* find_session_machine_by_id ( int  id)

Definition at line 1434 of file wsp_session.c.

References gwlist_search(), id_belongs_to_session(), and session_machines.

Referenced by return_reply(), and start_fetch().

1434  {
1435 
1437 }
void * gwlist_search(List *list, void *pattern, int(*cmp)(void *, void *))
Definition: list.c:486
static List * session_machines
Definition: wsp_session.c:123
static int id_belongs_to_session(void *, void *)
Definition: wsp_session.c:1440

◆ handle_method_event()

static void handle_method_event ( WSPMachine session,
WSPMethodMachine machine,
WAPEvent event,
WSP_PDU pdu 
)
static

Definition at line 564 of file wsp_session.c.

References cant_handle_event(), debug(), gw_assert(), gwlist_delete_equal(), method_machine_destroy(), state_name(), WAPEvent::type, wap_event_dump(), wap_event_name(), and warning().

Referenced by abort_methods(), and release_holding_methods().

565  {
566 
567  if (msm == NULL) {
568  warning(0, "No method machine for event.");
569  wap_event_dump(current_event);
570  return;
571  }
572 
573  debug("wap.wsp", 0, "WSP: method %ld, state %s, event %s",
574  msm->transaction_id, state_name(msm->state),
575  wap_event_name(current_event->type));
576 
577  gw_assert(sm->session_id == msm->session_id);
578 
579  #define STATE_NAME(name)
580  #define ROW(state_name, event, condition, action, next_state) \
581  { \
582  struct event *e; \
583  e = &current_event->u.event; \
584  if (msm->state == state_name && \
585  current_event->type == event && \
586  (condition)) { \
587  action \
588  msm->state = next_state; \
589  debug("wap.wsp", 0, "WSP %ld/%ld: New method state %s", \
590  msm->session_id, msm->transaction_id, #next_state); \
591  goto end; \
592  } \
593  }
595 
596  cant_handle_event(sm, current_event);
597 
598 end:
599  if (msm->state == NULL_METHOD) {
601  gwlist_delete_equal(sm->methodmachines, msm);
602  }
603 }
gw_assert(wtls_machine->packet_to_send !=NULL)
void wap_event_dump(WAPEvent *event)
Definition: wap_events.c:181
const char * wap_event_name(WAPEventName type)
Definition: wap_events.c:169
long gwlist_delete_equal(List *list, void *item)
Definition: list.c:266
void warning(int err, const char *fmt,...)
Definition: log.c:660
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
static void method_machine_destroy(void *msm)
Definition: wsp_session.c:630
static void cant_handle_event(WSPMachine *sm, WAPEvent *event)
Definition: wsp_session.c:442
static char * state_name(WSPState state)
Definition: wsp_session.c:729

◆ handle_push_event()

static void handle_push_event ( WSPMachine session,
WSPPushMachine machine,
WAPEvent e 
)
static

Definition at line 650 of file wsp_session.c.

References cant_handle_event(), debug(), gw_assert(), gwlist_delete_equal(), push_machine_destroy(), state_name(), WAPEvent::type, wap_event_dump(), wap_event_name(), and warning().

Referenced by abort_pushes().

652 {
653  if (pm == NULL) {
654  warning(0, "No push machine for event.");
655  wap_event_dump(current_event);
656  return;
657  }
658 
659  debug("wap.wsp", 0, "WSP(tid/pid): push %ld/%ld, state %s, event %s",
660  pm->transaction_id, pm->server_push_id, state_name(pm->state),
661  wap_event_name(current_event->type));
662  gw_assert(sm->session_id == pm->session_id);
663 
664  #define STATE_NAME(name)
665  #define ROW(state_name, event, condition, action, next_state) \
666  { \
667  if (pm->state == state_name && \
668  current_event->type == event && \
669  (condition)) { \
670  action \
671  pm->state = next_state; \
672  debug("wap.wsp", 0, "WSP %ld/%ld: New push state %s", \
673  pm->session_id, pm->transaction_id, #next_state); \
674  goto end; \
675  } \
676  }
677  #include "wsp_server_push_states.def"
678 
679  cant_handle_event(sm, current_event);
680 end:
681  if (pm->state == SERVER_PUSH_NULL_STATE) {
683  gwlist_delete_equal(sm->pushmachines, pm);
684  }
685 }
gw_assert(wtls_machine->packet_to_send !=NULL)
static void push_machine_destroy(void *p)
Definition: wsp_session.c:711
void wap_event_dump(WAPEvent *event)
Definition: wap_events.c:181
const char * wap_event_name(WAPEventName type)
Definition: wap_events.c:169
long gwlist_delete_equal(List *list, void *item)
Definition: list.c:266
void warning(int err, const char *fmt,...)
Definition: log.c:660
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
static void cant_handle_event(WSPMachine *sm, WAPEvent *event)
Definition: wsp_session.c:442
static char * state_name(WSPState state)
Definition: wsp_session.c:729

◆ handle_session_event()

static void handle_session_event ( WSPMachine machine,
WAPEvent event,
WSP_PDU pdu 
)
static

Definition at line 408 of file wsp_session.c.

References cant_handle_event(), debug(), machine_destroy(), state_name(), WAPEvent::type, wap_event_destroy(), and wap_event_name().

Referenced by disconnect_other_sessions(), and main_thread().

409  {
410  debug("wap.wsp", 0, "WSP: machine %p, state %s, event %s",
411  (void *) sm,
412  state_name(sm->state),
413  wap_event_name(current_event->type));
414 
415  #define STATE_NAME(name)
416  #define ROW(state_name, event, condition, action, next_state) \
417  { \
418  struct event *e; \
419  e = &current_event->u.event; \
420  if (sm->state == state_name && \
421  current_event->type == event && \
422  (condition)) { \
423  action \
424  sm->state = next_state; \
425  debug("wap.wsp", 0, "WSP %ld: New state %s", \
426  sm->session_id, #next_state); \
427  goto end; \
428  } \
429  }
431 
432  cant_handle_event(sm, current_event);
433 
434 end:
435  wap_event_destroy(current_event);
436 
437  if (sm->state == NULL_SESSION)
438  machine_destroy(sm);
439 }
static void machine_destroy(void *p)
Definition: wsp_session.c:535
const char * wap_event_name(WAPEventName type)
Definition: wap_events.c:169
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
static void cant_handle_event(WSPMachine *sm, WAPEvent *event)
Definition: wsp_session.c:442
void wap_event_destroy(WAPEvent *event)
Definition: wap_events.c:102
static char * state_name(WSPState state)
Definition: wsp_session.c:729

◆ id_belongs_to_session()

static int id_belongs_to_session ( void *  wsp_ptr,
void *  pid 
)
static

Definition at line 1440 of file wsp_session.c.

Referenced by find_session_machine_by_id().

1440  {
1441  WSPMachine *wsp;
1442  int *id;
1443 
1444  wsp = wsp_ptr;
1445  id = (int *) pid;
1446 
1447  if (*id == wsp->session_id) return 1;
1448  return 0;
1449 }

◆ indicate_disconnect()

static void indicate_disconnect ( WSPMachine sm,
long  reason 
)
static

Definition at line 1277 of file wsp_session.c.

References dispatch_to_appl, WAPEvent::u, and wap_event_create.

Referenced by cant_handle_event().

1277  {
1278  WAPEvent *new_event;
1279 
1280  new_event = wap_event_create(S_Disconnect_Ind);
1281  new_event->u.S_Disconnect_Ind.reason_code = reason;
1282  new_event->u.S_Disconnect_Ind.redirect_security = 0;
1283  new_event->u.S_Disconnect_Ind.redirect_addresses = 0;
1284  new_event->u.S_Disconnect_Ind.error_headers = NULL;
1285  new_event->u.S_Disconnect_Ind.error_body = NULL;
1286  new_event->u.S_Disconnect_Ind.session_handle = sm->session_id;
1287  dispatch_to_appl(new_event);
1288 }
static wap_dispatch_func_t * dispatch_to_appl
Definition: wsp_session.c:110
#define wap_event_create(type)
Definition: wap_events.h:107
union WAPEvent::@87 u

◆ indicate_method_abort()

static void indicate_method_abort ( WSPMethodMachine msm,
long  reason 
)
static

Definition at line 1352 of file wsp_session.c.

References dispatch_to_appl, WAPEvent::u, and wap_event_create.

1352  {
1353  WAPEvent *new_event;
1354 
1355  /* Send S-MethodAbort.ind(reason) */
1356  new_event = wap_event_create(S_MethodAbort_Ind);
1357  new_event->u.S_MethodAbort_Ind.transaction_id = msm->transaction_id;
1358  new_event->u.S_MethodAbort_Ind.reason = reason;
1359  new_event->u.S_MethodAbort_Ind.session_handle = msm->session_id;
1360  dispatch_to_appl(new_event);
1361 }
static wap_dispatch_func_t * dispatch_to_appl
Definition: wsp_session.c:110
#define wap_event_create(type)
Definition: wap_events.h:107
union WAPEvent::@87 u

◆ indicate_pushabort()

static void indicate_pushabort ( WSPPushMachine machine,
long  reason 
)
static

Definition at line 1312 of file wsp_session.c.

References dispatch_to_appl, WAPEvent::u, and wap_event_create.

1313 {
1314  WAPEvent *ota_event;
1315 
1316  ota_event = wap_event_create(S_PushAbort_Ind);
1317  ota_event->u.S_PushAbort_Ind.push_id = spm->server_push_id;
1318  ota_event->u.S_PushAbort_Ind.reason = reason;
1319  ota_event->u.S_PushAbort_Ind.session_id = spm->session_id;
1320  dispatch_to_appl(ota_event);
1321 }
static wap_dispatch_func_t * dispatch_to_appl
Definition: wsp_session.c:110
#define wap_event_create(type)
Definition: wap_events.h:107
union WAPEvent::@87 u

◆ indicate_resume()

static void indicate_resume ( WSPMachine sm,
WAPAddrTuple tuple,
List client_headers 
)
static

Definition at line 1301 of file wsp_session.c.

References dispatch_to_appl, http_header_duplicate(), WAPEvent::u, wap_addr_tuple_duplicate(), and wap_event_create.

1302  {
1303  WAPEvent *new_event;
1304 
1305  new_event = wap_event_create(S_Resume_Ind);
1306  new_event->u.S_Resume_Ind.addr_tuple = wap_addr_tuple_duplicate(tuple);
1307  new_event->u.S_Resume_Ind.client_headers = http_header_duplicate(headers);
1308  new_event->u.S_Resume_Ind.session_id = sm->session_id;
1309  dispatch_to_appl(new_event);
1310 }
WAPAddrTuple * wap_addr_tuple_duplicate(WAPAddrTuple *tuple)
Definition: wap_addr.c:125
static wap_dispatch_func_t * dispatch_to_appl
Definition: wsp_session.c:110
#define wap_event_create(type)
Definition: wap_events.h:107
List * http_header_duplicate(List *headers)
Definition: http.c:2969
union WAPEvent::@87 u

◆ indicate_suspend()

static void indicate_suspend ( WSPMachine sm,
long  reason 
)
static

Definition at line 1291 of file wsp_session.c.

References dispatch_to_appl, WAPEvent::u, and wap_event_create.

1291  {
1292  WAPEvent *new_event;
1293 
1294  new_event = wap_event_create(S_Suspend_Ind);
1295  new_event->u.S_Suspend_Ind.reason = reason;
1296  new_event->u.S_Suspend_Ind.session_id = sm->session_id;
1297  dispatch_to_appl(new_event);
1298 }
static wap_dispatch_func_t * dispatch_to_appl
Definition: wsp_session.c:110
#define wap_event_create(type)
Definition: wap_events.h:107
union WAPEvent::@87 u

◆ is_default_cap()

static int is_default_cap ( Capability cap)
static

Definition at line 924 of file wsp_session.c.

References capability::data, capability::id, capability::name, octstr_extract_uintvar(), octstr_get_char(), octstr_len(), WSP_CAPS_ALIASES, WSP_CAPS_CLIENT_SDU_SIZE, WSP_CAPS_EXTENDED_METHODS, WSP_CAPS_HEADER_CODE_PAGES, WSP_CAPS_METHOD_MOR, WSP_CAPS_PROTOCOL_OPTIONS, WSP_CAPS_PUSH_MOR, WSP_CAPS_SERVER_SDU_SIZE, and WSP_NUM_CAPS.

Referenced by strip_default_capabilities().

924  {
925  unsigned long ui;
926 
927  /* All unknown values are empty by default */
928  if (cap->name != NULL || cap->id < 0 || cap->id >= WSP_NUM_CAPS)
929  return cap->data == NULL || octstr_len(cap->data) == 0;
930 
931  switch (cap->id) {
934  return (cap->data != NULL &&
935  octstr_extract_uintvar(cap->data, &ui, 0) >= 0 &&
936  ui == 1400);
938  return cap->data != NULL && octstr_get_char(cap->data, 0) == 0;
939  case WSP_CAPS_METHOD_MOR:
940  case WSP_CAPS_PUSH_MOR:
941  return cap->data != NULL && octstr_get_char(cap->data, 0) == 1;
944  case WSP_CAPS_ALIASES:
945  return cap->data == NULL || octstr_len(cap->data) == 0;
946  default:
947  return 0;
948  }
949 }
int id
Definition: wsp_caps.h:72
Octstr * data
Definition: wsp_caps.h:76
long octstr_len(const Octstr *ostr)
Definition: octstr.c:342
Octstr * name
Definition: wsp_caps.h:73
long octstr_extract_uintvar(Octstr *ostr, unsigned long *value, long pos)
Definition: octstr.c:1954
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:406

◆ machine_create()

static WSPMachine * machine_create ( void  )
static

Definition at line 483 of file wsp_session.c.

References debug(), gwlist_insert(), and session_machines.

Referenced by find_session_machine().

483  {
484  WSPMachine *p;
485 
486  p = gw_malloc(sizeof(WSPMachine));
487  debug("wap.wsp", 0, "WSP: Created WSPMachine %p", (void *) p);
488 
489  #define INTEGER(name) p->name = 0;
490  #define OCTSTR(name) p->name = NULL;
491  #define HTTPHEADERS(name) p->name = NULL;
492  #define ADDRTUPLE(name) p->name = NULL;
493  #define MACHINESLIST(name) p->name = gwlist_create();
494  #define CAPABILITIES(name) p->name = NULL;
495  #define COOKIES(name) p->name = gwlist_create();
496  #define REFERER(name) p->name = NULL;
497  #define MACHINE(fields) fields
499 
500  p->state = NULL_SESSION;
501 
502  /* set capabilities to default values (defined in 1.1) */
503 
504  p->client_SDU_size = 1400;
505  p->MOR_push = 1;
506 
507  /* Insert new machine at the _front_, because 1) it's more likely
508  * to get events than old machines are, so this speeds up the linear
509  * search, and 2) we want the newest machine to get any method
510  * invokes that come through before the Connect is established. */
512 
513  return p;
514 }
static List * session_machines
Definition: wsp_session.c:123
void gwlist_insert(List *list, long pos, void *item)
Definition: list.c:214
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726

◆ machine_destroy()

static void machine_destroy ( void *  p)
static

Definition at line 535 of file wsp_session.c.

References debug(), gwlist_delete_equal(), and session_machines.

Referenced by handle_session_event(), and wsp_session_shutdown().

535  {
536  WSPMachine *p;
537 
538  p = pp;
539  debug("wap.wsp", 0, "Destroying WSPMachine %p", pp);
541 
542  #define INTEGER(name) p->name = 0;
543  #define OCTSTR(name) octstr_destroy(p->name);
544  #define HTTPHEADERS(name) http_destroy_headers(p->name);
545  #define ADDRTUPLE(name) wap_addr_tuple_destroy(p->name);
546  #define MACHINESLIST(name) destroy_##name(p->name);
547  #define CAPABILITIES(name) wsp_cap_destroy_list(p->name);
548  #define COOKIES(name) cookies_destroy(p->name);
549  #define REFERER(name) octstr_destroy(p->name);
550  #define MACHINE(fields) fields
552  gw_free(p);
553 }
static List * session_machines
Definition: wsp_session.c:123
long gwlist_delete_equal(List *list, void *item)
Definition: list.c:266
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726

◆ main_thread()

static void main_thread ( void *  arg)
static

Definition at line 239 of file wsp_session.c.

References find_session_machine(), gwlist_consume(), handle_session_event(), queue, run_status, running, WAPEvent::type, WAPEvent::u, wap_event_assert(), wap_event_destroy(), warning(), wsp_pdu_destroy(), and wsp_pdu_unpack().

Referenced by wsp_session_init(), and wsp_session_shutdown().

239  {
240  WAPEvent *e;
241  WSPMachine *sm;
242  WSP_PDU *pdu;
243 
244  while (run_status == running && (e = gwlist_consume(queue)) != NULL) {
245  wap_event_assert(e);
246  switch (e->type) {
247  case TR_Invoke_Ind:
248  pdu = wsp_pdu_unpack(e->u.TR_Invoke_Ind.user_data);
249  if (pdu == NULL) {
250  warning(0, "WSP: Broken PDU ignored.");
252  continue;
253  }
254  break;
255 
256  default:
257  pdu = NULL;
258  break;
259  }
260 
261  sm = find_session_machine(e, pdu);
262  if (sm == NULL) {
264  } else {
265  handle_session_event(sm, e, pdu);
266  }
267 
268  wsp_pdu_destroy(pdu);
269  }
270 }
static List * queue
Definition: wsp_session.c:122
static void handle_session_event(WSPMachine *machine, WAPEvent *event, WSP_PDU *pdu)
Definition: wsp_session.c:408
static WSPMachine * find_session_machine(WAPEvent *event, WSP_PDU *pdu)
Definition: wsp_session.c:273
void wap_event_assert(WAPEvent *event)
Definition: wap_events.c:220
void warning(int err, const char *fmt,...)
Definition: log.c:660
void wsp_pdu_destroy(WSP_PDU *pdu)
Definition: wsp_pdu.c:102
static enum @91 run_status
void * gwlist_consume(List *list)
Definition: list.c:427
WAPEventName type
Definition: wap_events.h:88
union WAPEvent::@87 u
WSP_PDU * wsp_pdu_unpack(Octstr *data)
Definition: wsp_pdu.c:178
void wap_event_destroy(WAPEvent *event)
Definition: wap_events.c:102

◆ make_abort()

static WAPEvent * make_abort ( long  reason,
long  handle 
)
static

Definition at line 1223 of file wsp_session.c.

References WAPEvent::u, and wap_event_create.

Referenced by send_abort(), and send_abort_to_initiator().

1224 {
1225  WAPEvent *wtp_event;
1226 
1227  wtp_event = wap_event_create(TR_Abort_Req);
1228  wtp_event->u.TR_Abort_Req.abort_type = 0x01;
1229  wtp_event->u.TR_Abort_Req.abort_reason = reason;
1230  wtp_event->u.TR_Abort_Req.handle = handle;
1231 
1232  return wtp_event;
1233 }
#define wap_event_create(type)
Definition: wap_events.h:107
union WAPEvent::@87 u

◆ make_capabilities_reply()

static List * make_capabilities_reply ( WSPMachine m)
static

Definition at line 976 of file wsp_session.c.

References refuse_unreplied_capabilities(), reply_known_capabilities(), sanitize_capabilities(), strip_default_capabilities(), and wsp_cap_duplicate_list().

Referenced by make_connectreply_pdu().

976  {
977  List *caps;
978 
979  /* In principle, copy the application layer's capabilities
980  * response, add refusals for all unknown requested capabilities,
981  * and add responses for all known capabilities that are
982  * not already responded to. Then eliminate any replies that
983  * would have no effect because they are equal to the default. */
984 
985  caps = wsp_cap_duplicate_list(m->reply_caps);
986 
987  /* Don't let the application layer negotiate anything we
988  * cannot handle. Also parse the values it set if we're
989  * interested. */
990  sanitize_capabilities(caps, m);
991 
992  /* Add capability records for all capabilities we know about
993  * that are not already in the reply list. */
994  reply_known_capabilities(caps, m->request_caps, m);
995 
996  /* All remaining capabilities in the request list that are
997  * not in the reply list at this point must be unknown ones
998  * that we want to refuse. */
999  refuse_unreplied_capabilities(caps, m->request_caps);
1000 
1001  /* Now eliminate replies that would be equal to the requested
1002  * value, or (if there was none) to the default value. */
1003  strip_default_capabilities(caps, m->request_caps);
1004 
1005  return caps;
1006 }
static void sanitize_capabilities(List *caps, WSPMachine *m)
Definition: wsp_session.c:754
static void strip_default_capabilities(List *caps, List *req)
Definition: wsp_session.c:954
List * wsp_cap_duplicate_list(List *caps_list)
Definition: wsp_caps.c:125
static void refuse_unreplied_capabilities(List *caps, List *req)
Definition: wsp_session.c:909
static void reply_known_capabilities(List *caps, List *req, WSPMachine *m)
Definition: wsp_session.c:827
Definition: list.c:102

◆ make_confirmedpush_pdu()

static WSP_PDU * make_confirmedpush_pdu ( WAPEvent e)
static

Definition at line 1085 of file wsp_session.c.

References http_create_empty_headers(), http_destroy_headers(), octstr_create, octstr_duplicate, WAPEvent::u, wsp_pdu::u, WSP_1_2, wsp_headers_pack(), and wsp_pdu_create().

1086 {
1087  WSP_PDU *pdu;
1088  List *headers;
1089 
1090  pdu = wsp_pdu_create(ConfirmedPush);
1091 /*
1092  * Both push headers and push body are optional.
1093  */
1094  if (e->u.S_ConfirmedPush_Req.push_headers == NULL) {
1095  headers = http_create_empty_headers();
1096  pdu->u.ConfirmedPush.headers = wsp_headers_pack(headers, 1, WSP_1_2);
1097  http_destroy_headers(headers);
1098  } else
1099  pdu->u.ConfirmedPush.headers =
1100  wsp_headers_pack(e->u.S_ConfirmedPush_Req.push_headers, 1, WSP_1_2);
1101 
1102  if (e->u.S_ConfirmedPush_Req.push_body == NULL)
1103  pdu->u.ConfirmedPush.data = octstr_create("");
1104  else
1105  pdu->u.ConfirmedPush.data =
1106  octstr_duplicate(e->u.S_ConfirmedPush_Req.push_body);
1107 
1108  return pdu;
1109 }
union wsp_pdu::@89 u
Octstr * wsp_headers_pack(List *headers, int separate_content_type, int wsp_version)
Definition: wsp_headers.c:2963
void http_destroy_headers(List *headers)
Definition: http.c:2879
WSP_PDU * wsp_pdu_create(int type)
Definition: wsp_pdu.c:68
List * http_create_empty_headers(void)
Definition: http.c:2872
#define octstr_duplicate(ostr)
Definition: octstr.h:187
#define octstr_create(cstr)
Definition: octstr.h:125
union WAPEvent::@87 u
Definition: wsp.h:72
Definition: list.c:102

◆ make_connectreply_pdu()

static Octstr * make_connectreply_pdu ( WSPMachine m)
static

Definition at line 1034 of file wsp_session.c.

References http_destroy_headers(), make_capabilities_reply(), make_reply_headers(), wsp_pdu::u, wsp_cap_destroy_list(), wsp_cap_pack_list(), wsp_headers_pack(), wsp_pdu_create(), wsp_pdu_destroy(), and wsp_pdu_pack().

1035 {
1036  WSP_PDU *pdu;
1037  Octstr *os;
1038  List *caps;
1039  List *reply_headers;
1040 
1041  pdu = wsp_pdu_create(ConnectReply);
1042 
1043  pdu->u.ConnectReply.sessionid = m->session_id;
1044 
1045  caps = make_capabilities_reply(m);
1046  pdu->u.ConnectReply.capabilities = wsp_cap_pack_list(caps);
1047  wsp_cap_destroy_list(caps);
1048 
1049  reply_headers = make_reply_headers(m);
1050  pdu->u.ConnectReply.headers =
1051  wsp_headers_pack(reply_headers, 0, m->encoding_version);
1052  http_destroy_headers(reply_headers);
1053 
1054  os = wsp_pdu_pack(pdu);
1055  wsp_pdu_destroy(pdu);
1056 
1057  return os;
1058 }
union wsp_pdu::@89 u
void wsp_cap_destroy_list(List *caps_list)
Definition: wsp_caps.c:121
Octstr * wsp_headers_pack(List *headers, int separate_content_type, int wsp_version)
Definition: wsp_headers.c:2963
Octstr * wsp_pdu_pack(WSP_PDU *pdu)
Definition: wsp_pdu.c:271
void http_destroy_headers(List *headers)
Definition: http.c:2879
WSP_PDU * wsp_pdu_create(int type)
Definition: wsp_pdu.c:68
void wsp_pdu_destroy(WSP_PDU *pdu)
Definition: wsp_pdu.c:102
Definition: octstr.c:118
static List * make_reply_headers(WSPMachine *m)
Definition: wsp_session.c:1009
Octstr * wsp_cap_pack_list(List *caps_list)
Definition: wsp_caps.c:207
static List * make_capabilities_reply(WSPMachine *m)
Definition: wsp_session.c:976
Definition: list.c:102

◆ make_push_pdu()

static WSP_PDU * make_push_pdu ( WAPEvent e)
static

Definition at line 1111 of file wsp_session.c.

References http_create_empty_headers(), http_destroy_headers(), octstr_create, octstr_duplicate, WAPEvent::u, wsp_pdu::u, WSP_1_2, wsp_headers_pack(), and wsp_pdu_create().

1112 {
1113  WSP_PDU *pdu;
1114  List *headers;
1115 
1116  pdu = wsp_pdu_create(Push);
1117 /*
1118  * Both push headers and push body are optional
1119  */
1120  if (e->u.S_Push_Req.push_headers == NULL) {
1121  headers = http_create_empty_headers();
1122  pdu->u.Push.headers = wsp_headers_pack(headers, 1, WSP_1_2);
1123  http_destroy_headers(headers);
1124  } else
1125  pdu->u.Push.headers =
1126  wsp_headers_pack(e->u.S_Push_Req.push_headers, 1, WSP_1_2);
1127 
1128  if (e->u.S_Push_Req.push_body == NULL)
1129  pdu->u.Push.data = octstr_create("");
1130  else
1131  pdu->u.Push.data =
1132  octstr_duplicate(e->u.S_Push_Req.push_body);
1133 
1134  return pdu;
1135 }
union wsp_pdu::@89 u
Octstr * wsp_headers_pack(List *headers, int separate_content_type, int wsp_version)
Definition: wsp_headers.c:2963
void http_destroy_headers(List *headers)
Definition: http.c:2879
WSP_PDU * wsp_pdu_create(int type)
Definition: wsp_pdu.c:68
List * http_create_empty_headers(void)
Definition: http.c:2872
#define octstr_duplicate(ostr)
Definition: octstr.h:187
#define octstr_create(cstr)
Definition: octstr.h:125
union WAPEvent::@87 u
Definition: wsp.h:72
Definition: list.c:102

◆ make_reply_headers()

static List * make_reply_headers ( WSPMachine m)
static

Definition at line 1009 of file wsp_session.c.

References http_create_empty_headers(), http_header_add(), octstr_destroy(), octstr_get_cstr, and wsp_encoding_version_to_string().

Referenced by make_connectreply_pdu().

1010 {
1011  List *headers;
1012  Octstr *encoding_version;
1013 
1014  /* Add all server wsp level hop-by-hop headers. Currently only
1015  * Encoding-Version, as defined by wsp, chapter 8.4.2.70.
1016  * What headers belong to which version is defined in appendix A,
1017  * table 39..
1018  encoding_version = request_version = NULL;
1019  * Essentially, if the client sends us an Encoding-Version
1020  * higher than ours (1.3) we send our version number to it,
1021  * if it is lower, we left version number intact. */
1022  /* First the case that we have no Encoding-Version header at all.
1023  * This case we must assume that the client supports version 1.2
1024  * or lower. */
1025 
1026  headers = http_create_empty_headers();
1027  encoding_version = wsp_encoding_version_to_string(m->encoding_version);
1028  http_header_add(headers, "Encoding-Version", octstr_get_cstr(encoding_version));
1029  octstr_destroy(encoding_version);
1030 
1031  return headers;
1032 }
void http_header_add(List *headers, char *name, char *contents)
Definition: http.c:2886
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
List * http_create_empty_headers(void)
Definition: http.c:2872
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
static Octstr * wsp_encoding_version_to_string(int version)
Definition: wsp_session.c:1478
Definition: octstr.c:118
Definition: list.c:102

◆ make_resume_reply_pdu()

static Octstr * make_resume_reply_pdu ( WSPMachine m,
List headers 
)
static

Definition at line 1061 of file wsp_session.c.

References http_create_empty_headers(), http_destroy_headers(), HTTP_OK, octstr_create, wsp_pdu::u, wsp_convert_http_status_to_wsp_status(), wsp_headers_pack(), wsp_pdu_create(), wsp_pdu_destroy(), and wsp_pdu_pack().

1062 {
1063  WSP_PDU *pdu;
1064  Octstr *os;
1065 
1066  pdu = wsp_pdu_create(Reply);
1067 
1068  /* Not specified for Resume replies */
1069  pdu->u.Reply.status = wsp_convert_http_status_to_wsp_status(HTTP_OK);
1070  if (headers == NULL) {
1071  headers = http_create_empty_headers();
1072  pdu->u.Reply.headers = wsp_headers_pack(headers, 1, m->encoding_version);
1073  http_destroy_headers(headers);
1074  } else {
1075  pdu->u.Reply.headers = wsp_headers_pack(headers, 1, m->encoding_version);
1076  }
1077  pdu->u.Reply.data = octstr_create("");
1078 
1079  os = wsp_pdu_pack(pdu);
1080  wsp_pdu_destroy(pdu);
1081 
1082  return os;
1083 }
long wsp_convert_http_status_to_wsp_status(long http_status)
Definition: wsp.c:77
union wsp_pdu::@89 u
Octstr * wsp_headers_pack(List *headers, int separate_content_type, int wsp_version)
Definition: wsp_headers.c:2963
Octstr * wsp_pdu_pack(WSP_PDU *pdu)
Definition: wsp_pdu.c:271
void http_destroy_headers(List *headers)
Definition: http.c:2879
WSP_PDU * wsp_pdu_create(int type)
Definition: wsp_pdu.c:68
Definition: http.h:142
List * http_create_empty_headers(void)
Definition: http.c:2872
#define octstr_create(cstr)
Definition: octstr.h:125
void wsp_pdu_destroy(WSP_PDU *pdu)
Definition: wsp_pdu.c:102
Definition: octstr.c:118

◆ method_abort()

static void method_abort ( WSPMethodMachine msm,
long  reason 
)
static

Definition at line 1333 of file wsp_session.c.

References dispatch_to_wtp_resp, WAPEvent::u, wap_event_create, and WSP_ABORT_PROTOERR.

1333  {
1334  WAPEvent *wtp_event;
1335 
1336  /* Send TR-Abort.req(reason) */
1337  wtp_event = wap_event_create(TR_Abort_Req);
1338  /* FIXME: Specs are unclear about this; we may indeed have to
1339  * guess abort whether this is a WSP or WTP level abort code */
1340  if (reason < WSP_ABORT_PROTOERR) {
1341  wtp_event->u.TR_Abort_Req.abort_type = 0x00;
1342  } else {
1343  wtp_event->u.TR_Abort_Req.abort_type = 0x01;
1344  }
1345  wtp_event->u.TR_Abort_Req.abort_reason = reason;
1346  wtp_event->u.TR_Abort_Req.handle = msm->transaction_id;
1347 
1348  dispatch_to_wtp_resp(wtp_event);
1349 }
#define wap_event_create(type)
Definition: wap_events.h:107
static wap_dispatch_func_t * dispatch_to_wtp_resp
Definition: wsp_session.c:108
union WAPEvent::@87 u

◆ method_is_holding()

static int method_is_holding ( void *  item,
void *  pattern 
)
static

Definition at line 1364 of file wsp_session.c.

Referenced by release_holding_methods().

1364  {
1365  WSPMethodMachine *msm = item;
1366 
1367  return msm->state == HOLDING;
1368 }

◆ method_machine_create()

static WSPMethodMachine * method_machine_create ( WSPMachine sm,
long  wtp_handle 
)
static

Definition at line 606 of file wsp_session.c.

References gwlist_append(), and wap_addr_tuple_duplicate().

607  {
608  WSPMethodMachine *msm;
609 
610  msm = gw_malloc(sizeof(*msm));
611 
612  #define INTEGER(name) msm->name = 0;
613  #define ADDRTUPLE(name) msm->name = NULL;
614  #define EVENT(name) msm->name = NULL;
615  #define MACHINE(fields) fields
617 
618  msm->transaction_id = wtp_handle;
619  msm->state = NULL_METHOD;
620  msm->addr_tuple = wap_addr_tuple_duplicate(sm->addr_tuple);
621  msm->session_id = sm->session_id;
622 
623  gwlist_append(sm->methodmachines, msm);
624 
625  return msm;
626 }
void gwlist_append(List *list, void *item)
Definition: list.c:179
WAPAddrTuple * wap_addr_tuple_duplicate(WAPAddrTuple *tuple)
Definition: wap_addr.c:125

◆ method_machine_destroy()

static void method_machine_destroy ( void *  msm)
static

Definition at line 630 of file wsp_session.c.

References debug().

Referenced by destroy_methodmachines(), and handle_method_event().

630  {
631  WSPMethodMachine *msm;
632 
633  if (p == NULL)
634  return;
635 
636  msm = p;
637 
638  debug("wap.wsp", 0, "Destroying WSPMethodMachine %ld",
639  msm->transaction_id);
640 
641  #define INTEGER(name)
642  #define ADDRTUPLE(name) wap_addr_tuple_destroy(msm->name);
643  #define EVENT(name) wap_event_destroy(msm->name);
644  #define MACHINE(fields) fields
646 
647  gw_free(msm);
648 }
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726

◆ next_wsp_session_id()

static unsigned long next_wsp_session_id ( void  )
static

Definition at line 749 of file wsp_session.c.

References counter_increase(), and session_id_counter.

749  {
751 }
unsigned long counter_increase(Counter *counter)
Definition: counter.c:123
static Counter * session_id_counter
Definition: wsp_session.c:124

◆ push_machine_create()

static WSPPushMachine * push_machine_create ( WSPMachine session,
long  id 
)
static

Definition at line 687 of file wsp_session.c.

References gwlist_append(), and wap_addr_tuple_duplicate().

689 {
690  WSPPushMachine *m;
691 
692  m = gw_malloc(sizeof(WSPPushMachine));
693 
694  #define INTEGER(name) m->name = 0;
695  #define ADDRTUPLE(name) m->name = NULL;
696  #define HTTPHEADER(name) m->name = http_create_empty_headers();
697  #define MACHINE(fields) fields
698  #include "wsp_server_push_machine.def"
699 
700  m->server_push_id = pid;
701  m->transaction_id = pid;
702  m->state = SERVER_PUSH_NULL_STATE;
703  m->addr_tuple = wap_addr_tuple_duplicate(sm->addr_tuple);
704  m->session_id = sm->session_id;
705 
706  gwlist_append(sm->pushmachines, m);
707 
708  return m;
709 }
void gwlist_append(List *list, void *item)
Definition: list.c:179
WAPAddrTuple * wap_addr_tuple_duplicate(WAPAddrTuple *tuple)
Definition: wap_addr.c:125

◆ push_machine_destroy()

static void push_machine_destroy ( void *  p)
static

Definition at line 711 of file wsp_session.c.

References debug().

Referenced by destroy_pushmachines(), and handle_push_event().

712 {
713  WSPPushMachine *m = NULL;
714 
715  if (p == NULL)
716  return;
717  m = p;
718  debug("wap.wsp", 0, "Destroying WSPPushMachine %ld",
719  m->transaction_id);
720  #define INTEGER(name)
721  #define ADDRTUPLE(name) wap_addr_tuple_destroy(m->name);
722  #define HTTPHEADER(name) http_destroy_headers(m->name);
723  #define MACHINE(fields) fields
724  #include "wsp_server_push_machine.def"
725 
726  gw_free(m);
727 }
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726

◆ refuse_unreplied_capabilities()

static void refuse_unreplied_capabilities ( List caps,
List req 
)
static

Definition at line 909 of file wsp_session.c.

References gwlist_append(), gwlist_get(), gwlist_len(), capability::id, capability::name, wsp_cap_count(), and wsp_cap_create().

Referenced by make_capabilities_reply().

909  {
910  long i, len;
911  Capability *cap;
912 
913  len = gwlist_len(req);
914  for (i = 0; i < len; i++) {
915  cap = gwlist_get(req, i);
916  if (wsp_cap_count(caps, cap->id, cap->name) == 0) {
917  cap = wsp_cap_create(cap->id, cap->name, NULL);
918  gwlist_append(caps, cap);
919  }
920  }
921 }
void gwlist_append(List *list, void *item)
Definition: list.c:179
int id
Definition: wsp_caps.h:72
long gwlist_len(List *list)
Definition: list.c:166
void * gwlist_get(List *list, long pos)
Definition: list.c:292
Capability * wsp_cap_create(int id, Octstr *name, Octstr *data)
Definition: wsp_caps.c:71
int wsp_cap_count(List *caps_list, int id, Octstr *name)
Definition: wsp_caps.c:282
Octstr * name
Definition: wsp_caps.h:73

◆ release_holding_methods()

static void release_holding_methods ( WSPMachine sm)
static

Definition at line 1371 of file wsp_session.c.

References gwlist_destroy(), gwlist_get(), gwlist_len(), gwlist_search_all(), handle_method_event(), method_is_holding(), wap_event_create, and wap_event_destroy().

1371  {
1372  WAPEvent *release;
1373  WSPMethodMachine *msm;
1374  List *holding;
1375  long i, len;
1376 
1377  holding = gwlist_search_all(sm->methodmachines, NULL, method_is_holding);
1378  if (holding == NULL)
1379  return;
1380 
1381  /* We can re-use this because wsp_handle_method_event does not
1382  * destroy its event */
1383  release = wap_event_create(Release_Event);
1384 
1385  len = gwlist_len(holding);
1386  for (i = 0; i < len; i++) {
1387  msm = gwlist_get(holding, i);
1388  handle_method_event(sm, msm, release, NULL);
1389  }
1390  gwlist_destroy(holding, NULL);
1391  wap_event_destroy(release);
1392 }
long gwlist_len(List *list)
Definition: list.c:166
void * gwlist_get(List *list, long pos)
Definition: list.c:292
List * gwlist_search_all(List *list, void *pattern, int(*cmp)(void *, void *))
Definition: list.c:508
#define wap_event_create(type)
Definition: wap_events.h:107
static void handle_method_event(WSPMachine *session, WSPMethodMachine *machine, WAPEvent *event, WSP_PDU *pdu)
Definition: wsp_session.c:564
static int method_is_holding(void *item, void *pattern)
Definition: wsp_session.c:1364
Definition: list.c:102
void wap_event_destroy(WAPEvent *event)
Definition: wap_events.c:102
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145

◆ reply_known_capabilities()

static void reply_known_capabilities ( List caps,
List req,
WSPMachine m 
)
static

Definition at line 827 of file wsp_session.c.

References gwlist_append(), octstr_append_char(), octstr_append_uintvar(), octstr_create, wsp_cap_count(), wsp_cap_create(), wsp_cap_get_client_sdu(), wsp_cap_get_method_mor(), wsp_cap_get_push_mor(), wsp_cap_get_server_sdu(), WSP_CAPS_CLIENT_SDU_SIZE, WSP_CAPS_METHOD_MOR, WSP_CAPS_PROTOCOL_OPTIONS, WSP_CAPS_PUSH_MOR, and WSP_CAPS_SERVER_SDU_SIZE.

Referenced by make_capabilities_reply().

827  {
828  unsigned long ui;
829  Capability *cap;
830  Octstr *data;
831 
832  if (wsp_cap_count(caps, WSP_CAPS_CLIENT_SDU_SIZE, NULL) == 0) {
833  if (wsp_cap_get_client_sdu(req, &ui) > 0) {
834  /* Accept value if it is not silly. */
835  if ((ui >= 256 && ui < LONG_MAX) || ui == 0) {
836  m->client_SDU_size = ui;
837  }
838  }
839  /* Reply with the client SDU we decided on */
840  data = octstr_create("");
841  octstr_append_uintvar(data, m->client_SDU_size);
843  NULL, data);
844  gwlist_append(caps, cap);
845  }
846 
847  if (wsp_cap_count(caps, WSP_CAPS_SERVER_SDU_SIZE, NULL) == 0) {
848  /* Accept whatever size the client is willing
849  * to send. If the client did not specify anything,
850  * then use the default. */
851  if (wsp_cap_get_server_sdu(req, &ui) <= 0) {
852  ui = 1400;
853  }
854  data = octstr_create("");
855  octstr_append_uintvar(data, ui);
856  cap = wsp_cap_create(WSP_CAPS_SERVER_SDU_SIZE, NULL, data);
857  gwlist_append(caps, cap);
858  }
859 
860  /* Currently we cannot handle any protocol options */
861  if (wsp_cap_count(caps, WSP_CAPS_PROTOCOL_OPTIONS, NULL) == 0) {
862  data = octstr_create("");
863  octstr_append_char(data, 0);
864  cap = wsp_cap_create(WSP_CAPS_PROTOCOL_OPTIONS, NULL, data);
865  gwlist_append(caps, cap);
866  }
867 
868  /* Accept any Method-MOR the client sent; if it sent none,
869  * use the default. */
870  if (wsp_cap_count(caps, WSP_CAPS_METHOD_MOR, NULL) == 0) {
871  if (wsp_cap_get_method_mor(req, &ui) <= 0) {
872  ui = 1;
873  }
874  data = octstr_create("");
875  octstr_append_char(data, ui);
876  cap = wsp_cap_create(WSP_CAPS_METHOD_MOR, NULL, data);
877  gwlist_append(caps, cap);
878  }
879 
880  /* We will never send any Push requests because we don't support
881  * that yet. But we already specified that in protocol options;
882  * so, pretend we do, and handle the value that way. */
883  if (wsp_cap_count(caps, WSP_CAPS_PUSH_MOR, NULL) == 0) {
884  if (wsp_cap_get_push_mor(req, &ui) > 0) {
885  m->MOR_push = ui;
886  }
887  data = octstr_create("");
888  octstr_append_char(data, m->MOR_push);
889  cap = wsp_cap_create(WSP_CAPS_PUSH_MOR, NULL, data);
890  gwlist_append(caps, cap);
891  }
892 
893  /* Supporting extended methods is up to the application layer,
894  * not up to us. If the application layer didn't specify any,
895  * then we refuse whatever the client requested. The default
896  * is to support none, so we don't really have to add anything here. */
897 
898  /* We do not support any header code pages. sanitize_capabilities
899  * must have already deleted any reply that indicates otherwise.
900  * Again, not adding anything here is the same as refusing support. */
901 
902  /* Listing aliases is something the application layer can do if
903  * it wants to. We don't care. */
904 }
int wsp_cap_get_push_mor(List *caps_list, unsigned long *mor)
Definition: wsp_caps.c:328
int wsp_cap_get_server_sdu(List *caps_list, unsigned long *sdu)
Definition: wsp_caps.c:300
void gwlist_append(List *list, void *item)
Definition: list.c:179
void octstr_append_char(Octstr *ostr, int ch)
Definition: octstr.c:1517
Capability * wsp_cap_create(int id, Octstr *name, Octstr *data)
Definition: wsp_caps.c:71
int wsp_cap_get_client_sdu(List *caps_list, unsigned long *sdu)
Definition: wsp_caps.c:288
int wsp_cap_get_method_mor(List *caps_list, unsigned long *mor)
Definition: wsp_caps.c:312
int wsp_cap_count(List *caps_list, int id, Octstr *name)
Definition: wsp_caps.c:282
#define octstr_create(cstr)
Definition: octstr.h:125
void octstr_append_uintvar(Octstr *ostr, unsigned long value)
Definition: octstr.c:1931
Definition: octstr.c:118

◆ same_client()

static int same_client ( void *  sm1,
void *  sm2 
)
static

Definition at line 1179 of file wsp_session.c.

References wap_addr_tuple_same().

Referenced by disconnect_other_sessions().

1179  {
1180  WSPMachine *sm1, *sm2;
1181 
1182  sm1 = a;
1183  sm2 = b;
1184  return wap_addr_tuple_same(sm1->addr_tuple, sm2->addr_tuple);
1185 }
int wap_addr_tuple_same(WAPAddrTuple *a, WAPAddrTuple *b)
Definition: wap_addr.c:118

◆ sanitize_capabilities()

static void sanitize_capabilities ( List caps,
WSPMachine m 
)
static

Definition at line 754 of file wsp_session.c.

References capability::data, error(), gwlist_delete(), gwlist_get(), gwlist_len(), capability::id, capability::name, octstr_extract_uintvar(), octstr_get_char(), octstr_len(), octstr_set_bits(), warning(), wsp_cap_destroy(), wsp_cap_dump(), WSP_CAPS_CLIENT_SDU_SIZE, WSP_CAPS_EXTENDED_METHODS, WSP_CAPS_HEADER_CODE_PAGES, WSP_CAPS_PROTOCOL_OPTIONS, and WSP_CAPS_SERVER_SDU_SIZE.

Referenced by make_capabilities_reply().

754  {
755  long i;
756  Capability *cap;
757  unsigned long ui;
758 
759  for (i = 0; i < gwlist_len(caps); i++) {
760  cap = gwlist_get(caps, i);
761 
762  /* We only know numbered capabilities. Let the application
763  * layer negotiate whatever it wants for unknown ones. */
764  if (cap->name != NULL)
765  continue;
766 
767  switch (cap->id) {
769  /* Check if it's a valid uintvar. The value is the
770  * max SDU size we will send, and there's no
771  * internal limit to that, so accept any value. */
772  if (cap->data != NULL &&
773  octstr_extract_uintvar(cap->data, &ui, 0) < 0)
774  goto bad_cap;
775  else
776  m->client_SDU_size = ui;
777  break;
778 
780  /* Check if it's a valid uintvar */
781  if (cap->data != NULL &&
782  (octstr_extract_uintvar(cap->data, &ui, 0) < 0))
783  goto bad_cap;
784  /* XXX Our MRU is not quite unlimited, since we
785  * use signed longs in the library functions --
786  * should we make sure we limit the reply value
787  * to LONG_MAX? (That's already a 2GB packet) */
788  break;
789 
791  /* Currently we don't support any Push, nor
792  * session resume, nor acknowledgement headers,
793  * so make sure those bits are not set. */
794  if (cap->data != NULL && octstr_len(cap->data) > 0
795  && (octstr_get_char(cap->data, 0) & 0xf0) != 0) {
796  warning(0, "WSP: Application layer tried to "
797  "negotiate protocol options.");
798  octstr_set_bits(cap->data, 0, 4, 0);
799  }
800  break;
801 
803  /* XXX Check format here */
804  break;
805 
806 
808  /* We don't support any yet, so don't let this
809  * be negotiated. */
810  if (cap->data)
811  goto bad_cap;
812  break;
813  }
814  continue;
815 
816  bad_cap:
817  error(0, "WSP: Found illegal value in capabilities reply.");
818  wsp_cap_dump(cap);
819  gwlist_delete(caps, i, 1);
820  i--;
821  wsp_cap_destroy(cap);
822  continue;
823  }
824 }
void error(int err, const char *fmt,...)
Definition: log.c:648
int id
Definition: wsp_caps.h:72
long gwlist_len(List *list)
Definition: list.c:166
void * gwlist_get(List *list, long pos)
Definition: list.c:292
void octstr_set_bits(Octstr *ostr, long bitpos, int numbits, unsigned long value)
Definition: octstr.c:1849
void wsp_cap_dump(Capability *cap)
Definition: wsp_caps.c:92
Octstr * data
Definition: wsp_caps.h:76
void gwlist_delete(List *list, long pos, long count)
Definition: list.c:232
void warning(int err, const char *fmt,...)
Definition: log.c:660
long octstr_len(const Octstr *ostr)
Definition: octstr.c:342
Octstr * name
Definition: wsp_caps.h:73
long octstr_extract_uintvar(Octstr *ostr, unsigned long *value, long pos)
Definition: octstr.c:1954
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:406
void wsp_cap_destroy(Capability *cap)
Definition: wsp_caps.c:83

◆ send_abort()

static void send_abort ( long  reason,
long  handle 
)
static

Definition at line 1235 of file wsp_session.c.

References dispatch_to_wtp_resp, and make_abort().

Referenced by cant_handle_event(), and find_session_machine().

1235  {
1236  WAPEvent *wtp_event;
1237 
1238  wtp_event = make_abort(reason, handle);
1239  dispatch_to_wtp_resp(wtp_event);
1240 }
static wap_dispatch_func_t * dispatch_to_wtp_resp
Definition: wsp_session.c:108
static WAPEvent * make_abort(long reason, long handle)
Definition: wsp_session.c:1223

◆ send_abort_to_initiator()

static void send_abort_to_initiator ( long  reason,
long  handle 
)
static

Definition at line 1242 of file wsp_session.c.

References dispatch_to_wtp_init, and make_abort().

1243 {
1244  WAPEvent *wtp_event;
1245 
1246  wtp_event = make_abort(reason, handle);
1247  dispatch_to_wtp_init(wtp_event);
1248 }
static WAPEvent * make_abort(long reason, long handle)
Definition: wsp_session.c:1223
static wap_dispatch_func_t * dispatch_to_wtp_init
Definition: wsp_session.c:109

◆ send_invoke()

static void send_invoke ( WSPMachine session,
WSP_PDU pdu,
WAPEvent e,
long  class 
)
static

Definition at line 1254 of file wsp_session.c.

References dispatch_to_wtp_init, WAPEvent::type, WAPEvent::u, USER_ACKNOWLEDGEMENT, wap_addr_tuple_duplicate(), wap_event_create, wsp_pdu_destroy(), and wsp_pdu_pack().

1255 {
1256  WAPEvent *wtp_event;
1257 
1258  wtp_event = wap_event_create(TR_Invoke_Req);
1259  wtp_event->u.TR_Invoke_Req.addr_tuple =
1260  wap_addr_tuple_duplicate(m->addr_tuple);
1261 /*
1262  * There is no mention of acknowledgement type in the specs. But because
1263  * confirmed push is confirmed after response from OTA, provider acknowledge-
1264  * ments seem redundant.
1265  */
1266  wtp_event->u.TR_Invoke_Req.up_flag = USER_ACKNOWLEDGEMENT;
1267  wtp_event->u.TR_Invoke_Req.tcl = class;
1268  if (e->type == S_ConfirmedPush_Req)
1269  wtp_event->u.TR_Invoke_Req.handle =
1270  e->u.S_ConfirmedPush_Req.server_push_id;
1271  wtp_event->u.TR_Invoke_Req.user_data = wsp_pdu_pack(pdu);
1272 
1273  wsp_pdu_destroy(pdu);
1274  dispatch_to_wtp_init(wtp_event);
1275 }
Octstr * wsp_pdu_pack(WSP_PDU *pdu)
Definition: wsp_pdu.c:271
WAPAddrTuple * wap_addr_tuple_duplicate(WAPAddrTuple *tuple)
Definition: wap_addr.c:125
#define wap_event_create(type)
Definition: wap_events.h:107
void wsp_pdu_destroy(WSP_PDU *pdu)
Definition: wsp_pdu.c:102
WAPEventName type
Definition: wap_events.h:88
static wap_dispatch_func_t * dispatch_to_wtp_init
Definition: wsp_session.c:109
union WAPEvent::@87 u

◆ state_name()

static char * state_name ( WSPState  state)
static

Definition at line 729 of file wsp_session.c.

Referenced by handle_method_event(), handle_push_event(), and handle_session_event().

729  {
730  switch (state) {
731  #define STATE_NAME(name) case name: return #name;
732  #define ROW(state, event, cond, stmt, next_state)
734 
735  #define STATE_NAME(name) case name: return #name;
736  #define ROW(state, event, cond, stmt, next_state)
738 
739  #define STATE_NAME(name) case name: return #name;
740  #define ROW(state, event, cond, stmt, next_state)
741  #include "wsp_server_push_states.def"
742 
743  default:
744  return "unknown wsp state";
745  }
746 }

◆ strip_default_capabilities()

static void strip_default_capabilities ( List caps,
List req 
)
static

Definition at line 954 of file wsp_session.c.

References gwlist_delete(), gwlist_get(), gwlist_len(), capability::id, is_default_cap(), capability::name, wsp_cap_count(), and wsp_cap_destroy().

Referenced by make_capabilities_reply().

954  {
955  long i;
956  Capability *cap;
957  int count;
958 
959  /* Hmm, this is an O(N*N) operation, which may be bad. */
960 
961  i = 0;
962  while (i < gwlist_len(caps)) {
963  cap = gwlist_get(caps, i);
964 
965  count = wsp_cap_count(req, cap->id, cap->name);
966  if (count == 0 && is_default_cap(cap)) {
967  gwlist_delete(caps, i, 1);
968  wsp_cap_destroy(cap);
969  } else {
970  i++;
971  }
972  }
973 }
int id
Definition: wsp_caps.h:72
long gwlist_len(List *list)
Definition: list.c:166
void * gwlist_get(List *list, long pos)
Definition: list.c:292
static int is_default_cap(Capability *cap)
Definition: wsp_session.c:924
void gwlist_delete(List *list, long pos, long count)
Definition: list.c:232
int wsp_cap_count(List *caps_list, int id, Octstr *name)
Definition: wsp_caps.c:282
Octstr * name
Definition: wsp_caps.h:73
void wsp_cap_destroy(Capability *cap)
Definition: wsp_caps.c:83

◆ transaction_belongs_to_session()

static int transaction_belongs_to_session ( void *  session,
void *  tuple 
)
static

Definition at line 1137 of file wsp_session.c.

References wap_addr_tuple_same().

Referenced by find_session_machine().

1137  {
1138  WSPMachine *wsp;
1139  WAPAddrTuple *tuple;
1140 
1141  wsp = wsp_ptr;
1142  tuple = tuple_ptr;
1143 
1144  return wap_addr_tuple_same(wsp->addr_tuple, tuple);
1145 }
int wap_addr_tuple_same(WAPAddrTuple *a, WAPAddrTuple *b)
Definition: wap_addr.c:118

◆ unpack_new_headers()

static List * unpack_new_headers ( WSPMachine sm,
Octstr hdrs 
)
static

Definition at line 1210 of file wsp_session.c.

References http_create_empty_headers(), http_header_combine(), octstr_len(), and wsp_headers_unpack().

1210  {
1211  List *new_headers;
1212 
1213  if (hdrs && octstr_len(hdrs) > 0) {
1214  new_headers = wsp_headers_unpack(hdrs, 0);
1215  if (sm->http_headers == NULL)
1216  sm->http_headers = http_create_empty_headers();
1217  http_header_combine(sm->http_headers, new_headers);
1218  return new_headers;
1219  }
1220  return NULL;
1221 }
void http_header_combine(List *old_headers, List *new_headers)
Definition: http.c:3068
List * http_create_empty_headers(void)
Definition: http.c:2872
long octstr_len(const Octstr *ostr)
Definition: octstr.c:342
List * wsp_headers_unpack(Octstr *headers, int content_type_present)
Definition: wsp_headers.c:1331
Definition: list.c:102

◆ wsp_encoding_string_to_version()

static int wsp_encoding_string_to_version ( Octstr enc)
static

Definition at line 1452 of file wsp_session.c.

References octstr_compare(), octstr_imm(), WSP_1_1, WSP_1_2, WSP_1_3, WSP_1_4, and WSP_1_5.

1453 {
1454  int v;
1455 
1456  /* default will be WSP 1.2, as defined by WAPWSP */
1457  v = WSP_1_2;
1458 
1459  if (octstr_compare(enc, octstr_imm("1.1")) == 0) {
1460  v = WSP_1_1;
1461  }
1462  else if (octstr_compare(enc, octstr_imm("1.2")) == 0) {
1463  v = WSP_1_2;
1464  }
1465  else if (octstr_compare(enc, octstr_imm("1.3")) == 0) {
1466  v = WSP_1_3;
1467  }
1468  else if (octstr_compare(enc, octstr_imm("1.4")) == 0) {
1469  v = WSP_1_4;
1470  }
1471  else if (octstr_compare(enc, octstr_imm("1.5")) == 0) {
1472  v = WSP_1_5;
1473  }
1474 
1475  return v;
1476 }
Definition: wsp.h:73
Definition: wsp.h:75
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:283
Definition: wsp.h:74
Definition: wsp.h:71
Definition: wsp.h:72
int octstr_compare(const Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:871

◆ wsp_encoding_version_to_string()

static Octstr * wsp_encoding_version_to_string ( int  version)
static

Definition at line 1478 of file wsp_session.c.

References octstr_create, WSP_1_1, WSP_1_2, WSP_1_3, WSP_1_4, and WSP_1_5.

Referenced by make_reply_headers().

1479 {
1480  Octstr *os;
1481 
1482  switch (version) {
1483  case WSP_1_1:
1484  os = octstr_create("1.1");
1485  break;
1486  case WSP_1_2:
1487  os = octstr_create("1.2");
1488  break;
1489  case WSP_1_3:
1490  os = octstr_create("1.3");
1491  break;
1492  case WSP_1_4:
1493  os = octstr_create("1.4");
1494  break;
1495  case WSP_1_5:
1496  os = octstr_create("1.5");
1497  break;
1498  default:
1499  os = octstr_create("1.2");
1500  break;
1501  }
1502 
1503  return os;
1504 }
Definition: wsp.h:73
Definition: wsp.h:75
#define octstr_create(cstr)
Definition: octstr.h:125
Definition: octstr.c:118
Definition: wsp.h:74
Definition: wsp.h:71
Definition: wsp.h:72

◆ wsp_session_dispatch_event()

void wsp_session_dispatch_event ( WAPEvent event)

Definition at line 228 of file wsp_session.c.

References gwlist_produce(), queue, and wap_event_assert().

Referenced by main(), main_thread(), response_push_connection(), and return_session_reply().

228  {
229  wap_event_assert(event);
230  gwlist_produce(queue, event);
231 }
static List * queue
Definition: wsp_session.c:122
void gwlist_produce(List *list, void *item)
Definition: list.c:411
void wap_event_assert(WAPEvent *event)
Definition: wap_events.c:220

◆ wsp_session_init()

void wsp_session_init ( wap_dispatch_func_t responder_dispatch,
wap_dispatch_func_t initiator_dispatch,
wap_dispatch_func_t application_dispatch,
wap_dispatch_func_t push_ota_dispatch 
)

Definition at line 193 of file wsp_session.c.

References counter_create(), dispatch_to_appl, dispatch_to_ota, dispatch_to_wtp_init, dispatch_to_wtp_resp, gwlist_add_producer(), gwlist_create, gwthread_create, main_thread(), queue, run_status, running, session_id_counter, session_machines, and wsp_strings_init().

Referenced by main().

196  {
197  queue = gwlist_create();
201  dispatch_to_wtp_resp = responder_dispatch;
202  dispatch_to_wtp_init = initiator_dispatch;
203  dispatch_to_appl = application_dispatch;
204  dispatch_to_ota = push_ota_dispatch;
208 }
static List * queue
Definition: wsp_session.c:122
static List * session_machines
Definition: wsp_session.c:123
Counter * counter_create(void)
Definition: counter.c:94
static void main_thread(void *)
Definition: wsp_session.c:239
static wap_dispatch_func_t * dispatch_to_appl
Definition: wsp_session.c:110
#define gwthread_create(func, arg)
Definition: gwthread.h:90
static enum @91 run_status
void wsp_strings_init(void)
Definition: wsp_strings.c:269
static wap_dispatch_func_t * dispatch_to_wtp_resp
Definition: wsp_session.c:108
static wap_dispatch_func_t * dispatch_to_wtp_init
Definition: wsp_session.c:109
#define gwlist_create()
Definition: list.h:136
void gwlist_add_producer(List *list)
Definition: list.c:383
static Counter * session_id_counter
Definition: wsp_session.c:124
static wap_dispatch_func_t * dispatch_to_ota
Definition: wsp_session.c:111

◆ wsp_session_shutdown()

void wsp_session_shutdown ( void  )

Definition at line 211 of file wsp_session.c.

References counter_destroy(), debug(), gw_assert(), gwlist_destroy(), gwlist_len(), gwlist_remove_producer(), gwthread_join_every(), machine_destroy(), main_thread(), queue, run_status, running, session_id_counter, session_machines, terminating, wap_event_destroy_item(), and wsp_strings_shutdown().

Referenced by main().

211  {
216 
218 
219  debug("wap.wsp", 0, "WSP: %ld session machines left.",
222 
225 }
static List * queue
Definition: wsp_session.c:122
gw_assert(wtls_machine->packet_to_send !=NULL)
void counter_destroy(Counter *counter)
Definition: counter.c:110
long gwlist_len(List *list)
Definition: list.c:166
void gwthread_join_every(gwthread_func_t *func)
static List * session_machines
Definition: wsp_session.c:123
void gwlist_remove_producer(List *list)
Definition: list.c:401
void wap_event_destroy_item(void *event)
Definition: wap_events.c:130
static void machine_destroy(void *p)
Definition: wsp_session.c:535
static void main_thread(void *)
Definition: wsp_session.c:239
static enum @91 run_status
void wsp_strings_shutdown(void)
Definition: wsp_strings.c:286
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
static Counter * session_id_counter
Definition: wsp_session.c:124
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145

Variable Documentation

◆ dispatch_to_appl

◆ dispatch_to_ota

wap_dispatch_func_t* dispatch_to_ota
static

Definition at line 111 of file wsp_session.c.

Referenced by wsp_session_init().

◆ dispatch_to_wtp_init

wap_dispatch_func_t* dispatch_to_wtp_init
static

Definition at line 109 of file wsp_session.c.

Referenced by send_abort_to_initiator(), send_invoke(), and wsp_session_init().

◆ dispatch_to_wtp_resp

wap_dispatch_func_t* dispatch_to_wtp_resp
static

Definition at line 108 of file wsp_session.c.

Referenced by method_abort(), send_abort(), and wsp_session_init().

◆ queue

List* queue = NULL
static

◆ resume_enabled

int resume_enabled = 1
static

Definition at line 120 of file wsp_session.c.

◆ run_status

enum { ... } run_status

◆ session_id_counter

Counter* session_id_counter = NULL
static

Definition at line 124 of file wsp_session.c.

Referenced by next_wsp_session_id(), wsp_session_init(), and wsp_session_shutdown().

◆ session_machines

See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.