⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 record.c

📁 是一个手机功能的模拟程序
💻 C
📖 第 1 页 / 共 3 页
字号:
  wtls_log_record (rec, LOG_OUTBOUND);
#endif

  if (rec->rec_type & RECTYPE_USE_CS) {
    UINT16 s;

    /* Time for key refresh? */
    s = (~0 << conn->write.key_refresh_rate) & (rec->seqnum);
    if (s != conn->write.last_refresh) {
      conn->write.last_refresh = s;

      return RET_KEY_REFRESH;
    }

    return RET_ENCRYPT_RECORD;
  }

  return RET_OK;
}

/*
 * Create an application data record, for immediate transmission.
 */
SDL_Integer
wtls_rec_prepare_data_record (void *connptr, void *recptr)
{
  wtls_connection_t *conn = (wtls_connection_t *)connptr;
  wtls_record_t     *rec = (wtls_record_t *)recptr;;

  /* Always use a length field. */
  rec->rec_type |= RECTYPE_LENGTH_FIELD;

  rec->seqnum = conn->write.seqnum++;

  if (conn->write.use_cipher_spec) {
    rec->rec_type |= RECTYPE_USE_CS;
  }
  if (conn->write.seqnum_mode == SEQNUMMODE_EXPLICIT) {
    rec->rec_type |= RECTYPE_SEQNUM;
  }

#ifdef LOG_WTLS
  wtls_log_msg (0, "\n--------CREATING OUTBOUND RECORD--------\n");
  wtls_log_record (rec, LOG_OUTBOUND);
#endif

  if (rec->rec_type & RECTYPE_USE_CS) {
    UINT16 s;

    /* Time for key refresh? */
    s = (~0 << conn->write.key_refresh_rate) & (rec->seqnum);
    if (s != conn->write.last_refresh) {
      conn->write.last_refresh = s;

      return RET_KEY_REFRESH;
    }

    return RET_ENCRYPT_RECORD;
  }

  return RET_OK;
}

/*
 * Encode a record in a SDU.
 */
INT16
wtls_rec_create_SDU (void *connptr, void *recptr, TDUnitdataReqType *data_req)
{
  wtls_connection_t *conn = (wtls_connection_t *)connptr;
  wtls_record_t     *rec = (wtls_record_t *)recptr;
  wap_cvt_t         cvt_obj;
  BYTE              *buf;
  UINT16            buflen;

#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);
    wtls_rec_delete_record (rec);
    return -1;
  }
  buflen = (UINT16)cvt_obj.pos;
  buf = NEWARRAY (BYTE, buflen);
  if (buf == NULL) {
    wtls_err_set (ERR_INTERNAL, ERR_INSUFFICIENT_MEMORY,
                  0, ALERT_LEVEL_CRITICAL, ALERT_DESC_INTERNAL_ERROR);
  }

  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);
    wtls_rec_delete_record (rec);
    DEALLOC (&buf);
    return -1;
  }

  /* Allocate a PDU buffer. */
  data_req->UserData = pdubuf_newFromData (buflen, buf);
  if (data_req->UserData == NULL) {
    wtls_rec_delete_record (rec);
    DEALLOC (&buf);
    wtls_err_set (ERR_INTERNAL, ERR_INSUFFICIENT_MEMORY,
                  0, ALERT_LEVEL_CRITICAL, ALERT_DESC_INTERNAL_ERROR);
    return -1;
  }
  pdubuf_setLength (data_req->UserData, buflen);

  /* Copy addresses from the connection state. */
  yAssF_AddressType (data_req->SourceAddress, conn->client_addr, XASS);
  yAssF_AddressType (data_req->DestinationAddress, conn->server_addr, XASS);

  conn->write_cksum [conn->num_cksums++ % 4] =
    wtls_alert_compute_checksum (buf, buflen);

  wtls_rec_delete_record (rec);

  return RET_OK;
}

/*
 * Create a SDU holding the stored outbound handshake records,
 * plus an application data record, for immediate sending.
 */
SDL_Integer
wtls_rec_create_data_and_buffer_SDU (void *connptr,
                                     void *recptr,
                                     TDUnitdataReqType *data_req)
{
  wtls_connection_t *conn = (wtls_connection_t *)connptr;
  wtls_record_t     *rec = (wtls_record_t *)recptr;
  wtls_record_t     *prec;
  wap_cvt_t         cvt_obj;
  UINT16            totlen = 0;
  UINT16            lastlen;
  BYTE              *lastpos;

  /* Compute length of all saved outbound records. */
  totlen = rec->length + RECORD_HEADER_SIZE (rec);
  for (prec = conn->out_records; prec != NULL; prec = prec->next) {
    totlen += prec->length + RECORD_HEADER_SIZE (prec);
  }

  /* Allocate new PDU buffer. */
  data_req->UserData = pdubuf_new (totlen);
  if (data_req->UserData == NULL) {
    wtls_err_set (ERR_INTERNAL, ERR_INSUFFICIENT_MEMORY,
                  0, ALERT_LEVEL_FATAL, ALERT_DESC_INTERNAL_ERROR);
    return -1;
  }
  pdubuf_setLength (data_req->UserData, totlen);

  /* Copy the outgoing data to the PDU buffer. */
#ifdef LOG_WTLS
  wtls_log_msg (0, "\n--------SENDING SDU--------\n");
  wtls_log_msg (0, "SDU[ =>\n");
#endif
  wap_cvt_init (&cvt_obj, WAP_CVT_ENCODE,
                pdubuf_getStart (data_req->UserData), totlen);
  for (prec = conn->out_records; prec != NULL; prec = prec->next) {
    lastpos = cvt_obj.data + cvt_obj.pos;
    if (!wtls_cvt_record (&cvt_obj, prec)) {
      wtls_err_set (ERR_INTERNAL, ERR_ENCODING,
                    0, ALERT_LEVEL_CRITICAL, ALERT_DESC_INTERNAL_ERROR);
      return -1;
    }
    lastlen = (cvt_obj.data + cvt_obj.pos) - lastpos;
#ifdef LOG_WTLS
    wtls_log_record_brief (prec);
#endif
  }
  if (!wtls_cvt_record (&cvt_obj, rec)) {
    wtls_err_set (ERR_INTERNAL, ERR_ENCODING,
                  0, ALERT_LEVEL_CRITICAL, ALERT_DESC_INTERNAL_ERROR);
    return -1;
  }
#ifdef LOG_WTLS
  wtls_log_record_brief (rec);
  wtls_log_msg (0, "]\n");
#endif
  wtls_rec_delete_record (rec);

  /* Copy addresses from the connection state. */
  yAssF_AddressType (data_req->SourceAddress, conn->client_addr, XASS);
  yAssF_AddressType (data_req->DestinationAddress, conn->server_addr, XASS);

  conn->write_cksum [conn->num_cksums++ % 4] =
    wtls_alert_compute_checksum (lastpos, lastlen);

  return RET_OK;
}

/*
 * Create a SDU holding the stored outbound handshake records,
 * for immediate sending.
 */
INT16
wtls_rec_create_buffer_SDU (void *connptr, TDUnitdataReqType *data_req)
{
  wtls_connection_t *conn = (wtls_connection_t *)connptr;
  wtls_record_t     *rec;
  wap_cvt_t         cvt_obj;
  UINT16            totlen;
  UINT16            lastlen;
  BYTE              *lastpos;

  /* Should we allow this, and just return? Then, what should be sent? */
  if (conn->out_records == NULL) {
    wtls_err_set (ERR_INTERNAL, ERR_MISSING_RECORD_BUFFER,
                  1, ALERT_LEVEL_FATAL, ALERT_DESC_INTERNAL_ERROR);
    return -1;
  }

  /* Compute length of all saved outbound records. */
  totlen = 0;
  for (rec = conn->out_records; rec != NULL; rec = rec->next) {
    totlen += rec->length + RECORD_HEADER_SIZE (rec);
  }

  /* Allocate a PDU buffer. */
  data_req->UserData = pdubuf_new (totlen);
  if (data_req->UserData == NULL) {
    wtls_err_set (ERR_INTERNAL, ERR_INSUFFICIENT_MEMORY,
                  1, ALERT_LEVEL_FATAL, ALERT_DESC_INTERNAL_ERROR);
    return -1;
  }
  pdubuf_setLength (data_req->UserData, totlen);

  /* Copy the outgoing data to the PDU buffer. */
#ifdef LOG_WTLS
  wtls_log_msg (0, "\n--------SENDING SDU--------\n");
  wtls_log_msg (0, "SDU[ =>\n");
#endif

  wap_cvt_init (&cvt_obj, WAP_CVT_ENCODE,
                pdubuf_getStart (data_req->UserData), totlen);
  for (rec = conn->out_records; rec != NULL; rec = rec->next) {
    lastpos = cvt_obj.data + cvt_obj.pos;
    if (!wtls_cvt_record (&cvt_obj, rec)) {
      wtls_err_set (ERR_INTERNAL, ERR_ENCODING,
                    0, ALERT_LEVEL_CRITICAL, ALERT_DESC_INTERNAL_ERROR);
      return -1;
    }
    lastlen = (cvt_obj.data + cvt_obj.pos) - lastpos;
#ifdef LOG_WTLS
    wtls_log_record_brief (rec);
#endif
  }
#ifdef LOG_WTLS
  wtls_log_msg (0, "]\n");
#endif

  /* Copy addresses from the connection state. */
  yAssF_AddressType (data_req->SourceAddress, conn->client_addr, XASS);
  yAssF_AddressType (data_req->DestinationAddress, conn->server_addr, XASS);

  /* Compute Alert checksum. */
  conn->write_cksum [conn->num_cksums++ % 4] =
    wtls_alert_compute_checksum (lastpos, lastlen);

  return RET_OK;
}

/*
 * Remove the stored outbound handshake records.
 */
void
wtls_rec_clear_buffer (void *connptr)
{
  wtls_connection_t *conn = (wtls_connection_t *)connptr;

  wtls_rec_list_delete (&(conn->out_records));
}

void
wtls_rec_list_delete (wtls_record_t **rlist)
{
  wtls_record_t *rec;

  while (*rlist != NULL) {
    rec = *rlist;
    *rlist = rec->next;
    DEALLOC (&rec->fragment);
    DEALLOC (&rec);
  }
}


/**********************************************************
 *
 * ROUTINES FOR INCOMING RECORDS
 *
 **********************************************************/


/*
 * The WTLS protocol states that several records may be sent in
 * one SDU. This packaging of records ought to be transparent to
 * the layers above the record layer. However, since Alert messages
 * need to include a checksum computed on the last record sent
 * by the other end, we have to identify and process each record
 * in the SDU we receive before we start passing the records to
 * the layers above. Hence the routine SplitIncomingSDU below.
 *
 * During the initial processing of the records in a SDU we perform
 * a number of checks, to decide whether to accept the record.
 * Only records that pass those checks will be passed to higher
 * layers, and also will affect the sequence numbers and Alert
 * checksums. However, all the records will be extracted and
 * stored in a list of incoming, undelivered records.
 *
 * In the next pass, when the records are passed to the layers above,
 * further checks may yield new errors. For example, decryption
 * is carried out at this stage and may give erroneous results.
 */

/*
 * Handling of sequence numbers.
 * The current value of the read state's seqNum value is one
 * greater than the largest incoming sequence number we have seen.
 * Hence, initially, the value is 0.
 *
 * The current value of the write state's seqNum value, is the
 * sequence number we should use in the next Record we send.
 * Hence, here too, the value is initally 0.
 *
 * We use a sliding window of size 32, and keep track of which
 * sequence numbers we have seen with the help of a bit mask
 * of 32 bits. The rightmost bit in the bit mask represents
 * the largest sequence number we have seen. Each bit in the mask
 * that is set, means that the sequence number has been seen.
 * For example, if the read state's seqNum value is 118, then
 * the bits in the mask represent the sequence numbers 86..117.
 */

#define WINDOW_SIZE       32

/*
 * Check if a given sequence number is acceptable, i.e.,
 * is either larger than the largest seen so far,
 * or is smaller but within the window limits and is not marked
 * as having been seen. Does NOT update the window or mask.
 */
static INT16
wtls_rec_check_seqnum (UINT16 seqnum, wtls_connection_t *conn)
{
  UINT16 diff;

  if (seqnum >= conn->read.seqnum) { /* Larger than largest so far is OK */
    return RET_OK;
  }
  diff = conn->read.seqnum - seqnum;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -