📄 wtlsmain.c
字号:
return 0;
}
}
/*
* Check if a received SDU is a clear text Alert message.
*/
INT16
wtls_main_is_cleartext_alert (pdubuf *data)
{
wap_cvt_t cvt_obj;
wtls_record_t rec;
wap_cvt_init (&cvt_obj, WAP_CVT_DECODE_STATIC,
pdubuf_getStart (data), pdubuf_getLength (data));
if (!wtls_cvt_record (&cvt_obj, &rec)) {
wtls_err_set (ERR_GENERAL, ERR_DECODING, 1,
ALERT_LEVEL_CRITICAL, ALERT_DESC_DECODE_ERROR);
return -1;
}
if (((rec.rec_type & RECTYPE_CONTENT_TYPE) == CONTENT_TYPE_ALERT) &&
((rec.rec_type & RECTYPE_USE_CS) == 0)) {
return 0;
}
return -1;
}
/*
* Create a SDU holding a No-Connection Alert, for immediate sending.
* "dataInd" is the message we just received, for which we have no
* connection.
*/
SDL_Integer
wtls_main_create_no_connection_alert (TDUnitdataIndType *dataInd,
TDUnitdataReqType *dataReq)
{
BYTE *p = pdubuf_getStart (dataInd->UserData);
UINT16 len = pdubuf_getLength (dataInd->UserData);
wtls_alert_t alert;
wap_cvt_t cvt_obj;
wtls_record_t rec;
BYTE *buf;
UINT16 buflen;
alert.level = ALERT_LEVEL_CRITICAL;
alert.description = ALERT_DESC_NO_CONNECTION;
alert.checksum = wtls_alert_compute_checksum (p, len);
buflen = 6;
buf = NEWARRAY (BYTE, buflen);
if (buf == NULL) {
wtls_err_set (ERR_INTERNAL, ERR_INSUFFICIENT_MEMORY,
1, ALERT_LEVEL_FATAL, ALERT_DESC_INTERNAL_ERROR);
return -1;
}
wap_cvt_init (&cvt_obj, WAP_CVT_ENCODE, buf, buflen);
if (!wtls_cvt_alert (&cvt_obj, &alert)) {
wtls_err_set (ERR_INTERNAL, ERR_ENCODING, 0,
ALERT_LEVEL_CRITICAL, ALERT_DESC_INTERNAL_ERROR);
return -1;
}
/* Always use a length field. */
rec.rec_type = CONTENT_TYPE_ALERT | RECTYPE_SEQNUM | RECTYPE_LENGTH_FIELD;
rec.seqnum = MAX_SEQNUM;
rec.length = buflen;
rec.fragment = buf;
#ifdef LOG_WTLS
wtls_log_msg (0, "\n--------SENDING SDU--------\n");
wtls_log_msg (0, "SDU[ =>\n");
wtls_log_record_brief (&rec);
wtls_log_msg (0, "]\n");
#endif
wap_cvt_init (&cvt_obj, WAP_CVT_ENCODE_SIZE, NULL, 0);
if (!wtls_cvt_record (&cvt_obj, &rec)) {
wtls_err_set (ERR_INTERNAL, ERR_ENCODING, 0,
ALERT_LEVEL_CRITICAL, ALERT_DESC_INTERNAL_ERROR);
return -1;
}
buflen = (UINT16)cvt_obj.pos;
buf = NEWARRAY (BYTE, buflen);
if (buf == NULL) {
wtls_err_set (ERR_INTERNAL, ERR_INSUFFICIENT_MEMORY,
1, ALERT_LEVEL_FATAL, ALERT_DESC_INTERNAL_ERROR);
return -1;
}
wap_cvt_init (&cvt_obj, WAP_CVT_ENCODE, buf, buflen);
if (!wtls_cvt_record (&cvt_obj, &rec)) {
wtls_err_set (ERR_INTERNAL, ERR_ENCODING, 0,
ALERT_LEVEL_CRITICAL, ALERT_DESC_INTERNAL_ERROR);
DEALLOC (&buf);
return -1;
}
DEALLOC (&(rec.fragment));
/* Allocate a PDU buffer. */
dataReq->UserData = pdubuf_newFromData (buflen, buf);
pdubuf_setLength (dataReq->UserData, buflen);
/* Copy addresses from the connection state. */
yAssF_AddressType (dataReq->SourceAddress, dataInd->DestinationAddress,
XASS);
yAssF_AddressType (dataReq->DestinationAddress, dataInd->SourceAddress,
XASS);
return RET_OK;
}
/*
* Split an incoming SDU into records, and store them in the connection's
* list of incoming records.
*/
SDL_Integer
wtls_main_split_SDU (SDL_PId cm_proc, pdubuf *SDU)
{
list_node *n = wtls_main_find_node (cm_proc);
wtls_record_t *rec = NULL;
wap_cvt_t cvt_obj;
BYTE *p;
UINT16 start;
UINT8 content_type;
UINT8 is_first = 1;
if ((n == NULL) || (SDU == NULL)) {
return -1;
}
#ifdef LOG_WTLS
wtls_log_msg (0, "\n--------RECEIVED SDU--------\n");
wtls_log_msg (0, "SDU[ <=\n");
#endif
wap_cvt_init (&cvt_obj, WAP_CVT_DECODE,
pdubuf_getStart (SDU), pdubuf_getLength (SDU));
while (cvt_obj.pos < cvt_obj.length) {
p = cvt_obj.data + cvt_obj.pos;
start = (UINT16)cvt_obj.pos;
rec = NEWARRAY (wtls_record_t, 1);
if (rec == NULL) {
wtls_err_set (ERR_INTERNAL, ERR_INSUFFICIENT_MEMORY,
1, ALERT_LEVEL_FATAL, ALERT_DESC_INTERNAL_ERROR);
return -1;
}
if (!wtls_cvt_record (&cvt_obj, rec)) {
wtls_err_set (ERR_GENERAL, ERR_DECODING, 1,
ALERT_LEVEL_CRITICAL, ALERT_DESC_DECODE_ERROR);
wtls_rec_delete_record (rec);
return -1;
}
content_type = rec->rec_type & RECTYPE_CONTENT_TYPE;
/* Check that we have a content type we recognize. */
if ((content_type != CONTENT_TYPE_CCS) &&
(content_type != CONTENT_TYPE_ALERT) &&
(content_type != CONTENT_TYPE_HANDSHAKE) &&
(content_type != CONTENT_TYPE_DATA)) {
/* Unknown content type; ignore this record.
* We cannot trust any information in this record,
* so we have to assume that the record occupies the entire SDU. */
wtls_rec_delete_record (rec);
return -1;
}
#ifdef LOG_WTLS
wtls_log_record_brief (rec);
#endif
rec->is_first = is_first;
is_first = 0;
wtls_rec_list_append (rec, &(n->msgs_in));
/* Compute the Alert checksum. We tentatively accept this record,
* and hence will use its checksum when we send an Alert. */
((wtls_connection_t *)(n->connptr))->read_cksum =
wtls_alert_compute_checksum (p, (UINT16)(cvt_obj.pos - start));
}
#ifdef LOG_WTLS
wtls_log_msg (0, "]\n");
#endif
return RET_OK;
}
/************************************************************
* External routines called from other C functions.
************************************************************/
/*
* Store a pointer to the connection record.
*/
void
wtls_main_set_connection_pointer (SDL_PId pid, void *connptr)
{
list_node *n = wtls_main_find_node (pid);
if (n == NULL) {
return;
}
n->connptr = connptr;
}
/*
* Get a pointer to the connection record for the specified SDL process.
*/
void *
wtls_main_get_connection_pointer (SDL_PId pid)
{
list_node *n = wtls_main_find_node (pid);
if (n == NULL) {
return NULL;
}
return n->connptr;
}
/*
* Remove, and return, the first message in the message queue
* for the indicated Connection Manager process.
* Returns NULL, in case the queue is empty.
*/
wtls_record_t *
wtls_main_pop_incoming_message (SDL_PId pid)
{
list_node *n = wtls_main_find_node (pid);
if (n == NULL) {
return NULL;
}
return wtls_rec_list_pop (&(n->msgs_in));
}
wtls_record_t *
wtls_main_peek_incoming_message (SDL_PId pid)
{
list_node *n = wtls_main_find_node (pid);
if (n == NULL) {
return NULL;
}
return n->msgs_in;
}
wtls_record_t *
wtls_main_pop_outbound_message (SDL_PId pid)
{
list_node *n = wtls_main_find_node (pid);
if (n == NULL) {
return NULL;
}
return wtls_rec_list_pop (&(n->msgs_out));
}
/*
* Check if a received PDU is a Hello Request message in clear text,
* from a source that we can accept.
* Returns 0 if we should act on this request, -1 otherwise.
*/
SDL_Integer
wtls_main_check_hello_request (pdubuf *pdu)
{
wap_cvt_t cvt_obj;
wtls_record_t rec;
SDL_Integer retval = -1;
wap_cvt_init (&cvt_obj, WAP_CVT_DECODE_STATIC,
pdubuf_getStart (pdu), pdubuf_getLength (pdu));
if (!wtls_cvt_record (&cvt_obj, &rec)) {
return -1;
}
if (((rec.rec_type & RECTYPE_CONTENT_TYPE) == CONTENT_TYPE_HANDSHAKE) &&
((rec.rec_type & RECTYPE_USE_CS) == 0) &&
(rec.length == 3) &&
(rec.fragment[0] == 0) &&
(rec.fragment[1] == 0) &&
(rec.fragment[2] == 0)) {
retval = 0;
}
return retval;
}
/************************************************************
* Local functions
************************************************************/
/*
* Return a pointer to the list node with given PId.
* Returns NULL in case the given PId is not in the list.
*/
static list_node *
wtls_main_find_node (SDL_PId cm_proc)
{
list_node *n;
for (n = connection_list; n != NULL; n = n->next) {
if (n->cm_proc == cm_proc)
return n;
}
return NULL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -