📄 wdpsuppt.c
字号:
/*
* Copyright (C) Ericsson Mobile Communications AB, 2000.
* Licensed to AU-System AB.
* All rights reserved.
*
* This software is covered by the license agreement between
* the end user and AU-System AB, and may be used and copied
* only in accordance with the terms of the said agreement.
*
* Neither Ericsson Mobile Communications AB nor AU-System AB
* assumes any responsibility or liability for any errors or inaccuracies in
* this software, or any consequential, incidental or indirect damage arising
* out of the use of the Generic WAP Client software.
*/
/*
* wdpsuppt.c
*
* Created by Anders Edenbrandt, Wed Aug 16 12:43:53 2000.
*
* Revision history:
*
*/
#include "wdpsuppt.h"
#include "cmmnrsrc.h"
#include "capiclnt.h"
#include "sdl_cfgw.h"
/************************************************************
* Routines that handle the port table, i.e.,
* a table holding information about current connections.
************************************************************/
typedef struct st_port_table_node {
struct st_port_table_node *next;
UINT16 portnum;
SDL_PId pid;
SDL_Natural config;
SDL_Octet bearer;
SDL_Octet view_id;
SDL_Octet channel_id;
} port_table_t;
static port_table_t *port_table = 0;
/*
* Initialize the port table.
*/
void
wdp_porttbl_init (void)
{
port_table = 0;
#ifdef CONFIG_PUSH
#ifdef CONFIG_WTLS
wdp_porttbl_update (2949, XPTID_WTLS_Main, MODE_CL_WTLS, 0, 0, 0);
#endif
#endif
}
/*
* Remove all elements from the port table.
*/
void
wdp_porttbl_clear (void)
{
while (port_table) {
port_table_t *pn = port_table;
port_table = port_table->next;
OSConnectorFree (pn);
}
}
/*
* Locate an entry in the port table.
*/
static port_table_t *
wdp_porttbl_find (UINT16 portnum)
{
port_table_t *pn;
for (pn = port_table; pn; pn = pn->next) {
if (pn->portnum == portnum) {
break;
}
}
return pn;
}
/*
* Add or update an element in the port table.
*/
void
wdp_porttbl_update (SDL_Integer portn, SDL_PId pid,
SDL_Natural config, SDL_Octet bearer,
SDL_Octet view_id, SDL_Octet channel_id)
{
port_table_t *pn;
UINT16 portnum = (UINT16)portn;
pn = wdp_porttbl_find (portnum);
if (!pn) {
pn = OSConnectorAlloc (sizeof (port_table_t));
pn->next = port_table;
port_table = pn;
pn->portnum = portnum;
}
pn->pid = pid;
pn->config = config;
pn->bearer = bearer;
pn->view_id = view_id;
pn->channel_id = channel_id;
}
/*
* Delete the element with the specified port number
* from the port table.
*/
void
wdp_porttbl_delete (SDL_Integer portn)
{
port_table_t *pn, *qn;
UINT16 portnum = (UINT16)portn;
for (qn = 0, pn = port_table; pn; qn = pn, pn = pn->next) {
if (pn->portnum == portnum) {
break;
}
}
if (!pn) {
return;
}
if (qn) {
qn->next = pn->next;
}
else {
port_table = pn->next;
}
OSConnectorFree (pn);
}
/*
* Retrieve values from the port table, stored under
* the specified port number.
* Returns SDL_True if the port number was found,
* and SDL_False otherwise.
*/
SDL_Boolean
wdp_porttbl_lookup (SDL_Integer portn, SDL_PId *pid,
SDL_Natural *config, SDL_Octet *bearer,
SDL_Octet *view_id, SDL_Octet *channel_id)
{
port_table_t *pn;
UINT16 portnum = (UINT16)portn;
pn = wdp_porttbl_find (portnum);
if (!pn) {
return SDL_False;
}
*pid = pn->pid;
*config = pn->config;
*bearer = pn->bearer;
*view_id = pn->view_id;
*channel_id = pn->channel_id;
return SDL_True;
}
#ifdef CONFIG_SMS
/************************************************************
* Message building and parsing.
************************************************************/
#define SEGMENTED_HEADER_SIZE 12
#define NONSEGMENTED_HEADER_SIZE 7
/*
* Construct an SMS segment holding the first "length" bytes
* in the given PDU buffer.
* The result is stored in "segment" and "seglen".
*/
void
wdp_segment_build (pdubuf *pb, SDL_Integer length,
SDL_Integer dst_port, SDL_Integer src_port,
SDL_Natural refnum, SDL_Natural total_num_segments,
SDL_Natural segnum,
void** segment, SDL_Natural *seglen)
{
BYTE *ptr;
if (total_num_segments > 1) {
*seglen = length + SEGMENTED_HEADER_SIZE;
*segment = OSConnectorAlloc (*seglen);
ptr = (BYTE *)*segment;
ptr[0] = 11;
ptr[1] = IE_ID_PORT_NUMBER;
ptr[2] = 4;
ptr[3] = (UINT8)(dst_port >> 8);
ptr[4] = (UINT8)(dst_port & 0xff);
ptr[5] = (UINT8)(src_port >> 8);
ptr[6] = (UINT8)(src_port & 0xff);
ptr[7] = IE_ID_SAR_SHORT;
ptr[8] = 3;
ptr[9] = (BYTE)refnum;
ptr[10] = (BYTE)total_num_segments;
ptr[11] = (BYTE)segnum;
memcpy (ptr + SEGMENTED_HEADER_SIZE, pdubuf_getStart (pb), length);
}
else {
*seglen = length + NONSEGMENTED_HEADER_SIZE;
*segment = OSConnectorAlloc (*seglen);
ptr = (BYTE *)*segment;
ptr[0] = 6;
ptr[1] = IE_ID_PORT_NUMBER;
ptr[2] = 4;
ptr[3] = (UINT8)(dst_port >> 8);
ptr[4] = (UINT8)(dst_port & 0xff);
ptr[5] = (UINT8)(src_port >> 8);
ptr[6] = (UINT8)(src_port & 0xff);
memcpy (ptr + NONSEGMENTED_HEADER_SIZE, pdubuf_getStart (pb), length);
}
}
/*
* Extract values from a User Data Header.
* Returns SDL_True if the extraction succeeded, and
* SDL_False otherwise.
*/
SDL_Boolean
wdp_UDH_extract (void *segment, SDL_Natural length,
SDL_Boolean *is_segmented,
SDL_Natural *header_length,
SDL_Integer *dst_port, SDL_Integer *src_port,
SDL_Natural *refnum, SDL_Natural *total_num_segments,
SDL_Natural *segnum,
SDL_Boolean *has_WCMP,
void **WCMP_ptr, SDL_Natural *WCMP_length)
{
BYTE *p = segment;
UINT16 i;
UINT16 portnum, tmp;
if (length <= 0) {
return SDL_False;
}
*header_length = (UINT16)p[0] + 1;
if (length < *header_length) {
return SDL_False;
}
*is_segmented = SDL_False;
*has_WCMP = SDL_False;
for (i = 1; i < *header_length;) {
switch (p[i]) {
case IE_ID_PORT_NUMBER:
if (i + 5 >= *header_length) {
return SDL_False;
}
if (p[i + 1] != 4) {
return SDL_False;
}
portnum = p[i + 2];
portnum <<= 8;
portnum |= p[i + 3];
*dst_port = (SDL_Integer)portnum;
portnum = p[i + 4];
portnum <<= 8;
portnum |= p[i + 5];
*src_port = (SDL_Integer)portnum;
i += 6;
break;
case IE_ID_SAR_SHORT:
if (i + 4 >= *header_length) {
return SDL_False;
}
if (p[i + 1] != 3) {
return SDL_False;
}
*is_segmented = SDL_True;
*refnum = (p[i + 2] & 0xff);
*total_num_segments = (p[i + 3] & 0xff);
*segnum = (p[i + 4] & 0xff);
i += 5;
break;
case IE_ID_SAR_LONG:
if (i + 5 >= *header_length) {
return SDL_False;
}
if (p[i + 1] != 4) {
return SDL_False;
}
*is_segmented = SDL_True;
tmp = p[i + 2];
tmp <<= 8;
tmp |= p[i + 3];
*refnum = tmp;
*total_num_segments = (p[i + 4] & 0xff);
*segnum = (p[i + 5] & 0xff);
i += 6;
break;
case IE_ID_WCMP:
if (i + 1 >= *header_length) {
return SDL_False;
}
*has_WCMP = SDL_True;
*WCMP_ptr = &(p[i + 2]);
*WCMP_length = (SDL_Integer)(p[i + 1] & 0xff);
i += p[i + 1] + 2;
break;
default:
/* Unknown IE Identifier, skip past it. */
if (i + 1 >= *header_length) {
return SDL_False;
}
i += p[i] + 2;
break;
}
}
return SDL_True;
}
/*
* Construct a WCMP message.
*/
void
wdp_wcmp_build_msg (SDL_Octet type, SDL_Octet code,
SDL_Integer dst_port, SDL_Integer src_port,
DeviceAddress *addr,
void *old_msg, SDL_Natural old_msg_length,
void **msg, SDL_Natural *msg_length,
SDL_Boolean is_udcp_msg)
{
BYTE *p;
UINT8 IE_length, package_length;
if (type == WCMP_MESSAGE_TOO_BIG) {
IE_length = (UINT8)(6 + 2 + addr->length + 2);
package_length = 2 + IE_length;
*msg_length = package_length + 1;
p = *msg = OSConnectorAlloc (*msg_length);
p[addr->length + 11] = (MaxPDUsize >> 8) & 0xff;
p[addr->length + 12] = (MaxPDUsize & 0xff);
}
else if (type == WCMP_DESTINATION_UNREACHABLE) {
IE_length = (UINT8)(6 + 2 + addr->length);
package_length = 2 + IE_length;
*msg_length = package_length + 1;
p = *msg = OSConnectorAlloc (*msg_length);
}
else if (type == WCMP_ECHO_REPLY) {
IE_length = (UINT8)old_msg_length;
package_length = 2 + IE_length;
*msg_length = package_length + 1;
p = *msg = OSConnectorAlloc (*msg_length);
memcpy (p + 3, old_msg, old_msg_length);
p[0] = package_length;
p[1] = 9;
p[2] = IE_length;
p[3] = WCMP_ECHO_REPLY;
return;
}
else {
*msg = NULL;
*msg_length = 0;
return;
}
p[0] = package_length;
p[1] = 9;
p[2] = (UINT8)IE_length;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -