int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
{
    int al, i, j, ret;
    unsigned int n;
    SSL3_RECORD *rr;
    void (*cb) (const SSL *ssl, int type2, int val) = NULL;
    if (!SSL3_BUFFER_is_initialised(&s->rlayer.rbuf)) {
        if (!ssl3_setup_buffers(s))
            return (-1);
    }
    if ((type && (type != SSL3_RT_APPLICATION_DATA) &&
         (type != SSL3_RT_HANDSHAKE)) ||
        (peek && (type != SSL3_RT_APPLICATION_DATA))) {
        SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR);
        return -1;
    }
    if ((ret = have_handshake_fragment(s, type, buf, len, peek)))
        return ret;
#ifndef OPENSSL_NO_SCTP
    if ((!s->in_handshake && SSL_in_init(s)) ||
        (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
         (s->state == DTLS1_SCTP_ST_SR_READ_SOCK
          || s->state == DTLS1_SCTP_ST_CR_READ_SOCK)
         && s->s3->in_read_app_data != 2))
#else
    if (!s->in_handshake && SSL_in_init(s))
#endif
    {
        i = s->handshake_func(s);
        if (i < 0)
            return (i);
        if (i == 0) {
            SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_SSL_HANDSHAKE_FAILURE);
            return (-1);
        }
    }
 start:
    s->rwstate = SSL_NOTHING;
    rr = &s->rlayer.rrec;
    if (s->state == SSL_ST_OK && SSL3_RECORD_get_length(rr) == 0) {
        pitem *item;
        item = pqueue_pop(s->rlayer.d->buffered_app_data.q);
        if (item) {
#ifndef OPENSSL_NO_SCTP
            if (BIO_dgram_is_sctp(SSL_get_rbio(s))) {
                DTLS1_RECORD_DATA *rdata = (DTLS1_RECORD_DATA *)item->data;
                BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_SET_RCVINFO,
                         sizeof(rdata->recordinfo), &rdata->recordinfo);
            }
#endif
            dtls1_copy_record(s, item);
            OPENSSL_free(item->data);
            pitem_free(item);
        }
    }
    if (dtls1_handle_timeout(s) > 0)
        goto start;
    if ((SSL3_RECORD_get_length(rr) == 0)
            || (s->rlayer.rstate == SSL_ST_READ_BODY)) {
        ret = dtls1_get_record(s);
        if (ret <= 0) {
            ret = dtls1_read_failed(s, ret);
            if (ret <= 0)
                return (ret);
            else
                goto start;
        }
    }
    if (s->d1->listen && rr->type != SSL3_RT_HANDSHAKE) {
        SSL3_RECORD_set_length(rr, 0);
        goto start;
    }
    if (s->s3->change_cipher_spec
        && (SSL3_RECORD_get_type(rr) != SSL3_RT_HANDSHAKE)) {
        if (dtls1_buffer_record(s, &(s->rlayer.d->buffered_app_data),
            SSL3_RECORD_get_seq_num(rr)) < 0) {
            SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR);
            return -1;
        }
        SSL3_RECORD_set_length(rr, 0);
        goto start;
    }
    if (s->shutdown & SSL_RECEIVED_SHUTDOWN) {
        SSL3_RECORD_set_length(rr, 0);
        s->rwstate = SSL_NOTHING;
        return (0);
    }
    if (type == SSL3_RECORD_get_type(rr)) {
        if (SSL_in_init(s) && (type == SSL3_RT_APPLICATION_DATA) &&
            (s->enc_read_ctx == NULL)) {
            al = SSL_AD_UNEXPECTED_MESSAGE;
            SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_APP_DATA_IN_HANDSHAKE);
            goto f_err;
        }
        if (len <= 0)
            return (len);
        if ((unsigned int)len > SSL3_RECORD_get_length(rr))
            n = SSL3_RECORD_get_length(rr);
        else
            n = (unsigned int)len;
        memcpy(buf, &(SSL3_RECORD_get_data(rr)[SSL3_RECORD_get_off(rr)]), n);
        if (!peek) {
            SSL3_RECORD_add_length(rr, -n);
            SSL3_RECORD_add_off(rr, n);
            if (SSL3_RECORD_get_length(rr) == 0) {
                s->rlayer.rstate = SSL_ST_READ_HEADER;
                SSL3_RECORD_set_off(rr, 0);
            }
        }
#ifndef OPENSSL_NO_SCTP
        if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
            SSL3_RECORD_get_type(rr) == SSL3_RT_APPLICATION_DATA &&
            (s->state == DTLS1_SCTP_ST_SR_READ_SOCK
             || s->state == DTLS1_SCTP_ST_CR_READ_SOCK)) {
            s->rwstate = SSL_READING;
            BIO_clear_retry_flags(SSL_get_rbio(s));
            BIO_set_retry_read(SSL_get_rbio(s));
        }
        if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
            s->d1->shutdown_received
            && !BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s))) {
            s->shutdown |= SSL_RECEIVED_SHUTDOWN;
            return (0);
        }
#endif
        return (n);
    }
    {
        unsigned int k, dest_maxlen = 0;
        unsigned char *dest = NULL;
        unsigned int *dest_len = NULL;
        if (SSL3_RECORD_get_type(rr) == SSL3_RT_HANDSHAKE) {
            dest_maxlen = sizeof s->rlayer.d->handshake_fragment;
            dest = s->rlayer.d->handshake_fragment;
            dest_len = &s->rlayer.d->handshake_fragment_len;
        } else if (SSL3_RECORD_get_type(rr) == SSL3_RT_ALERT) {
            dest_maxlen = sizeof(s->rlayer.d->alert_fragment);
            dest = s->rlayer.d->alert_fragment;
            dest_len = &s->rlayer.d->alert_fragment_len;
        }
#ifndef OPENSSL_NO_HEARTBEATS
        else if (SSL3_RECORD_get_type(rr) == TLS1_RT_HEARTBEAT) {
            if(dtls1_process_heartbeat(s, SSL3_RECORD_get_data(rr),
                    SSL3_RECORD_get_length(rr)) < 0) {
                return -1;
            }
            SSL3_RECORD_set_length(rr, 0);
            s->rwstate = SSL_READING;
            BIO_clear_retry_flags(SSL_get_rbio(s));
            BIO_set_retry_read(SSL_get_rbio(s));
            return (-1);
        }
#endif
        else if (SSL3_RECORD_get_type(rr) != SSL3_RT_CHANGE_CIPHER_SPEC) {
            if (SSL3_RECORD_get_type(rr)  == SSL3_RT_APPLICATION_DATA) {
                BIO *bio;
                s->s3->in_read_app_data = 2;
                bio = SSL_get_rbio(s);
                s->rwstate = SSL_READING;
                BIO_clear_retry_flags(bio);
                BIO_set_retry_read(bio);
                return (-1);
            }
            al = SSL_AD_UNEXPECTED_MESSAGE;
            SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_UNEXPECTED_RECORD);
            goto f_err;
        }
        if (dest_maxlen > 0) {
            if (SSL3_RECORD_get_length(rr)  < dest_maxlen) {
#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
                FIX ME
#endif
                s->rlayer.rstate = SSL_ST_READ_HEADER;
                SSL3_RECORD_set_length(rr, 0);
                goto start;
            }
            for (k = 0; k < dest_maxlen; k++) {
                dest[k] = SSL3_RECORD_get_data(rr)[SSL3_RECORD_get_off(rr)];
                SSL3_RECORD_add_off(rr, 1);
                SSL3_RECORD_add_length(rr, -1);
            }
            *dest_len = dest_maxlen;
        }
    }
    if ((!s->server) &&
        (s->rlayer.d->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) &&
        (s->rlayer.d->handshake_fragment[0] == SSL3_MT_HELLO_REQUEST) &&
        (s->session != NULL) && (s->session->cipher != NULL)) {
        s->rlayer.d->handshake_fragment_len = 0;
        if ((s->rlayer.d->handshake_fragment[1] != 0) ||
            (s->rlayer.d->handshake_fragment[2] != 0) ||
            (s->rlayer.d->handshake_fragment[3] != 0)) {
            al = SSL_AD_DECODE_ERROR;
            SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_BAD_HELLO_REQUEST);
            goto err;
        }
        if (s->msg_callback)
            s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
                            s->rlayer.d->handshake_fragment, 4, s,
                            s->msg_callback_arg);
        if (SSL_is_init_finished(s) &&
            !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) &&
            !s->s3->renegotiate) {
            s->d1->handshake_read_seq++;
            s->new_session = 1;
            ssl3_renegotiate(s);
            if (ssl3_renegotiate_check(s)) {
                i = s->handshake_func(s);
                if (i < 0)
                    return (i);
                if (i == 0) {
                    SSLerr(SSL_F_DTLS1_READ_BYTES,
                           SSL_R_SSL_HANDSHAKE_FAILURE);
                    return (-1);
                }
                if (!(s->mode & SSL_MODE_AUTO_RETRY)) {
                    if (SSL3_BUFFER_get_left(&s->rlayer.rbuf) == 0) {
                        BIO *bio;
                        s->rwstate = SSL_READING;
                        bio = SSL_get_rbio(s);
                        BIO_clear_retry_flags(bio);
                        BIO_set_retry_read(bio);
                        return (-1);
                    }
                }
            }
        }
        goto start;
    }
    if (s->rlayer.d->alert_fragment_len >= DTLS1_AL_HEADER_LENGTH) {
        int alert_level = s->rlayer.d->alert_fragment[0];
        int alert_descr = s->rlayer.d->alert_fragment[1];
        s->rlayer.d->alert_fragment_len = 0;
        if (s->msg_callback)
            s->msg_callback(0, s->version, SSL3_RT_ALERT,
                            s->rlayer.d->alert_fragment, 2, s,
                            s->msg_callback_arg);
        if (s->info_callback != NULL)
            cb = s->info_callback;
        else if (s->ctx->info_callback != NULL)
            cb = s->ctx->info_callback;
        if (cb != NULL) {
            j = (alert_level << 8) | alert_descr;
            cb(s, SSL_CB_READ_ALERT, j);
        }
        if (alert_level == SSL3_AL_WARNING) {
            s->s3->warn_alert = alert_descr;
            if (alert_descr == SSL_AD_CLOSE_NOTIFY) {
#ifndef OPENSSL_NO_SCTP
                if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
                    BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s))) {
                    s->d1->shutdown_received = 1;
                    s->rwstate = SSL_READING;
                    BIO_clear_retry_flags(SSL_get_rbio(s));
                    BIO_set_retry_read(SSL_get_rbio(s));
                    return -1;
                }
#endif
                s->shutdown |= SSL_RECEIVED_SHUTDOWN;
                return (0);
            }
#if 0
            if (alert_descr == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE) {
                unsigned short seq;
                unsigned int frag_off;
                unsigned char *p = &(s->rlayer.d->alert_fragment[2]);
                n2s(p, seq);
                n2l3(p, frag_off);
                dtls1_retransmit_message(s,
                                         dtls1_get_queue_priority
                                         (frag->msg_header.seq, 0), frag_off,
                                         &found);
                if (!found && SSL_in_init(s)) {
                    ssl3_send_alert(s, SSL3_AL_WARNING,
                                    DTLS1_AD_MISSING_HANDSHAKE_MESSAGE);
                }
            }
#endif
        } else if (alert_level == SSL3_AL_FATAL) {
            char tmp[16];
            s->rwstate = SSL_NOTHING;
            s->s3->fatal_alert = alert_descr;
            SSLerr(SSL_F_DTLS1_READ_BYTES,
                   SSL_AD_REASON_OFFSET + alert_descr);
            BIO_snprintf(tmp, sizeof tmp, "%d", alert_descr);
            ERR_add_error_data(2, "SSL alert number ", tmp);
            s->shutdown |= SSL_RECEIVED_SHUTDOWN;
            SSL_CTX_remove_session(s->ctx, s->session);
            return (0);
        } else {
            al = SSL_AD_ILLEGAL_PARAMETER;
            SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_UNKNOWN_ALERT_TYPE);
            goto f_err;
        }
        goto start;
    }
    if (s->shutdown & SSL_SENT_SHUTDOWN) {
        s->rwstate = SSL_NOTHING;
        SSL3_RECORD_set_length(rr, 0);
        return (0);
    }
    if (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC) {
        struct ccs_header_st ccs_hdr;
        unsigned int ccs_hdr_len = DTLS1_CCS_HEADER_LENGTH;
        dtls1_get_ccs_header(SSL3_RECORD_get_data(rr), &ccs_hdr);
        if (s->version == DTLS1_BAD_VER)
            ccs_hdr_len = 3;
        if ((SSL3_RECORD_get_length(rr) != ccs_hdr_len)
                || (SSL3_RECORD_get_off(rr) != 0)
                || (SSL3_RECORD_get_data(rr)[0] != SSL3_MT_CCS)) {
            i = SSL_AD_ILLEGAL_PARAMETER;
            SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_BAD_CHANGE_CIPHER_SPEC);
            goto err;
        }
        SSL3_RECORD_set_length(rr, 0);
        if (s->msg_callback)
            s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC,
                SSL3_RECORD_get_data(rr), 1, s, s->msg_callback_arg);
        if (!s->d1->change_cipher_spec_ok) {
            goto start;
        }
        s->d1->change_cipher_spec_ok = 0;
        s->s3->change_cipher_spec = 1;
        if (!ssl3_do_change_cipher_spec(s))
            goto err;
        dtls1_reset_seq_numbers(s, SSL3_CC_READ);
        if (s->version == DTLS1_BAD_VER)
            s->d1->handshake_read_seq++;
#ifndef OPENSSL_NO_SCTP
        BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD, 1, NULL);
#endif
        goto start;
    }
    if ((s->rlayer.d->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) &&
        !s->in_handshake) {
        struct hm_header_st msg_hdr;
        dtls1_get_message_header(rr->data, &msg_hdr);
        if (SSL3_RECORD_get_epoch(rr) != s->rlayer.d->r_epoch) {
            SSL3_RECORD_set_length(rr, 0);
            goto start;
        }
        if (msg_hdr.type == SSL3_MT_FINISHED) {
            if (dtls1_check_timeout_num(s) < 0)
                return -1;
            dtls1_retransmit_buffered_messages(s);
            SSL3_RECORD_set_length(rr, 0);
            goto start;
        }
        if (((s->state & SSL_ST_MASK) == SSL_ST_OK) &&
            !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)) {
            s->state = s->server ? SSL_ST_ACCEPT : SSL_ST_CONNECT;
            s->renegotiate = 1;
            s->new_session = 1;
        }
        i = s->handshake_func(s);
        if (i < 0)
            return (i);
        if (i == 0) {
            SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_SSL_HANDSHAKE_FAILURE);
            return (-1);
        }
        if (!(s->mode & SSL_MODE_AUTO_RETRY)) {
            if (SSL3_BUFFER_get_left(&s->rlayer.rbuf) == 0) {
                BIO *bio;
                s->rwstate = SSL_READING;
                bio = SSL_get_rbio(s);
                BIO_clear_retry_flags(bio);
                BIO_set_retry_read(bio);
                return (-1);
            }
        }
        goto start;
    }
    switch (SSL3_RECORD_get_type(rr)) {
    default:
        if (s->version == TLS1_VERSION) {
            SSL3_RECORD_set_length(rr, 0);
            goto start;
        }
        al = SSL_AD_UNEXPECTED_MESSAGE;
        SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_UNEXPECTED_RECORD);
        goto f_err;
    case SSL3_RT_CHANGE_CIPHER_SPEC:
    case SSL3_RT_ALERT:
    case SSL3_RT_HANDSHAKE:
        al = SSL_AD_UNEXPECTED_MESSAGE;
        SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR);
        goto f_err;
    case SSL3_RT_APPLICATION_DATA:
        if (s->s3->in_read_app_data &&
            (s->s3->total_renegotiations != 0) &&
            (((s->state & SSL_ST_CONNECT) &&
              (s->state >= SSL3_ST_CW_CLNT_HELLO_A) &&
              (s->state <= SSL3_ST_CR_SRVR_HELLO_A)
             ) || ((s->state & SSL_ST_ACCEPT) &&
                   (s->state <= SSL3_ST_SW_HELLO_REQ_A) &&
                   (s->state >= SSL3_ST_SR_CLNT_HELLO_A)
             )
            )) {
            s->s3->in_read_app_data = 2;
            return (-1);
        } else {
            al = SSL_AD_UNEXPECTED_MESSAGE;
            SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_UNEXPECTED_RECORD);
            goto f_err;
        }
    }
 f_err:
    ssl3_send_alert(s, SSL3_AL_FATAL, al);
 err:
    return (-1);
}
['int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)\n{\n    int al, i, j, ret;\n    unsigned int n;\n    SSL3_RECORD *rr;\n    void (*cb) (const SSL *ssl, int type2, int val) = NULL;\n    if (!SSL3_BUFFER_is_initialised(&s->rlayer.rbuf)) {\n        if (!ssl3_setup_buffers(s))\n            return (-1);\n    }\n    if ((type && (type != SSL3_RT_APPLICATION_DATA) &&\n         (type != SSL3_RT_HANDSHAKE)) ||\n        (peek && (type != SSL3_RT_APPLICATION_DATA))) {\n        SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR);\n        return -1;\n    }\n    if ((ret = have_handshake_fragment(s, type, buf, len, peek)))\n        return ret;\n#ifndef OPENSSL_NO_SCTP\n    if ((!s->in_handshake && SSL_in_init(s)) ||\n        (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&\n         (s->state == DTLS1_SCTP_ST_SR_READ_SOCK\n          || s->state == DTLS1_SCTP_ST_CR_READ_SOCK)\n         && s->s3->in_read_app_data != 2))\n#else\n    if (!s->in_handshake && SSL_in_init(s))\n#endif\n    {\n        i = s->handshake_func(s);\n        if (i < 0)\n            return (i);\n        if (i == 0) {\n            SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_SSL_HANDSHAKE_FAILURE);\n            return (-1);\n        }\n    }\n start:\n    s->rwstate = SSL_NOTHING;\n    rr = &s->rlayer.rrec;\n    if (s->state == SSL_ST_OK && SSL3_RECORD_get_length(rr) == 0) {\n        pitem *item;\n        item = pqueue_pop(s->rlayer.d->buffered_app_data.q);\n        if (item) {\n#ifndef OPENSSL_NO_SCTP\n            if (BIO_dgram_is_sctp(SSL_get_rbio(s))) {\n                DTLS1_RECORD_DATA *rdata = (DTLS1_RECORD_DATA *)item->data;\n                BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_SET_RCVINFO,\n                         sizeof(rdata->recordinfo), &rdata->recordinfo);\n            }\n#endif\n            dtls1_copy_record(s, item);\n            OPENSSL_free(item->data);\n            pitem_free(item);\n        }\n    }\n    if (dtls1_handle_timeout(s) > 0)\n        goto start;\n    if ((SSL3_RECORD_get_length(rr) == 0)\n            || (s->rlayer.rstate == SSL_ST_READ_BODY)) {\n        ret = dtls1_get_record(s);\n        if (ret <= 0) {\n            ret = dtls1_read_failed(s, ret);\n            if (ret <= 0)\n                return (ret);\n            else\n                goto start;\n        }\n    }\n    if (s->d1->listen && rr->type != SSL3_RT_HANDSHAKE) {\n        SSL3_RECORD_set_length(rr, 0);\n        goto start;\n    }\n    if (s->s3->change_cipher_spec\n        && (SSL3_RECORD_get_type(rr) != SSL3_RT_HANDSHAKE)) {\n        if (dtls1_buffer_record(s, &(s->rlayer.d->buffered_app_data),\n            SSL3_RECORD_get_seq_num(rr)) < 0) {\n            SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR);\n            return -1;\n        }\n        SSL3_RECORD_set_length(rr, 0);\n        goto start;\n    }\n    if (s->shutdown & SSL_RECEIVED_SHUTDOWN) {\n        SSL3_RECORD_set_length(rr, 0);\n        s->rwstate = SSL_NOTHING;\n        return (0);\n    }\n    if (type == SSL3_RECORD_get_type(rr)) {\n        if (SSL_in_init(s) && (type == SSL3_RT_APPLICATION_DATA) &&\n            (s->enc_read_ctx == NULL)) {\n            al = SSL_AD_UNEXPECTED_MESSAGE;\n            SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_APP_DATA_IN_HANDSHAKE);\n            goto f_err;\n        }\n        if (len <= 0)\n            return (len);\n        if ((unsigned int)len > SSL3_RECORD_get_length(rr))\n            n = SSL3_RECORD_get_length(rr);\n        else\n            n = (unsigned int)len;\n        memcpy(buf, &(SSL3_RECORD_get_data(rr)[SSL3_RECORD_get_off(rr)]), n);\n        if (!peek) {\n            SSL3_RECORD_add_length(rr, -n);\n            SSL3_RECORD_add_off(rr, n);\n            if (SSL3_RECORD_get_length(rr) == 0) {\n                s->rlayer.rstate = SSL_ST_READ_HEADER;\n                SSL3_RECORD_set_off(rr, 0);\n            }\n        }\n#ifndef OPENSSL_NO_SCTP\n        if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&\n            SSL3_RECORD_get_type(rr) == SSL3_RT_APPLICATION_DATA &&\n            (s->state == DTLS1_SCTP_ST_SR_READ_SOCK\n             || s->state == DTLS1_SCTP_ST_CR_READ_SOCK)) {\n            s->rwstate = SSL_READING;\n            BIO_clear_retry_flags(SSL_get_rbio(s));\n            BIO_set_retry_read(SSL_get_rbio(s));\n        }\n        if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&\n            s->d1->shutdown_received\n            && !BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s))) {\n            s->shutdown |= SSL_RECEIVED_SHUTDOWN;\n            return (0);\n        }\n#endif\n        return (n);\n    }\n    {\n        unsigned int k, dest_maxlen = 0;\n        unsigned char *dest = NULL;\n        unsigned int *dest_len = NULL;\n        if (SSL3_RECORD_get_type(rr) == SSL3_RT_HANDSHAKE) {\n            dest_maxlen = sizeof s->rlayer.d->handshake_fragment;\n            dest = s->rlayer.d->handshake_fragment;\n            dest_len = &s->rlayer.d->handshake_fragment_len;\n        } else if (SSL3_RECORD_get_type(rr) == SSL3_RT_ALERT) {\n            dest_maxlen = sizeof(s->rlayer.d->alert_fragment);\n            dest = s->rlayer.d->alert_fragment;\n            dest_len = &s->rlayer.d->alert_fragment_len;\n        }\n#ifndef OPENSSL_NO_HEARTBEATS\n        else if (SSL3_RECORD_get_type(rr) == TLS1_RT_HEARTBEAT) {\n            if(dtls1_process_heartbeat(s, SSL3_RECORD_get_data(rr),\n                    SSL3_RECORD_get_length(rr)) < 0) {\n                return -1;\n            }\n            SSL3_RECORD_set_length(rr, 0);\n            s->rwstate = SSL_READING;\n            BIO_clear_retry_flags(SSL_get_rbio(s));\n            BIO_set_retry_read(SSL_get_rbio(s));\n            return (-1);\n        }\n#endif\n        else if (SSL3_RECORD_get_type(rr) != SSL3_RT_CHANGE_CIPHER_SPEC) {\n            if (SSL3_RECORD_get_type(rr)  == SSL3_RT_APPLICATION_DATA) {\n                BIO *bio;\n                s->s3->in_read_app_data = 2;\n                bio = SSL_get_rbio(s);\n                s->rwstate = SSL_READING;\n                BIO_clear_retry_flags(bio);\n                BIO_set_retry_read(bio);\n                return (-1);\n            }\n            al = SSL_AD_UNEXPECTED_MESSAGE;\n            SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_UNEXPECTED_RECORD);\n            goto f_err;\n        }\n        if (dest_maxlen > 0) {\n            if (SSL3_RECORD_get_length(rr)  < dest_maxlen) {\n#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE\n                FIX ME\n#endif\n                s->rlayer.rstate = SSL_ST_READ_HEADER;\n                SSL3_RECORD_set_length(rr, 0);\n                goto start;\n            }\n            for (k = 0; k < dest_maxlen; k++) {\n                dest[k] = SSL3_RECORD_get_data(rr)[SSL3_RECORD_get_off(rr)];\n                SSL3_RECORD_add_off(rr, 1);\n                SSL3_RECORD_add_length(rr, -1);\n            }\n            *dest_len = dest_maxlen;\n        }\n    }\n    if ((!s->server) &&\n        (s->rlayer.d->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) &&\n        (s->rlayer.d->handshake_fragment[0] == SSL3_MT_HELLO_REQUEST) &&\n        (s->session != NULL) && (s->session->cipher != NULL)) {\n        s->rlayer.d->handshake_fragment_len = 0;\n        if ((s->rlayer.d->handshake_fragment[1] != 0) ||\n            (s->rlayer.d->handshake_fragment[2] != 0) ||\n            (s->rlayer.d->handshake_fragment[3] != 0)) {\n            al = SSL_AD_DECODE_ERROR;\n            SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_BAD_HELLO_REQUEST);\n            goto err;\n        }\n        if (s->msg_callback)\n            s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,\n                            s->rlayer.d->handshake_fragment, 4, s,\n                            s->msg_callback_arg);\n        if (SSL_is_init_finished(s) &&\n            !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) &&\n            !s->s3->renegotiate) {\n            s->d1->handshake_read_seq++;\n            s->new_session = 1;\n            ssl3_renegotiate(s);\n            if (ssl3_renegotiate_check(s)) {\n                i = s->handshake_func(s);\n                if (i < 0)\n                    return (i);\n                if (i == 0) {\n                    SSLerr(SSL_F_DTLS1_READ_BYTES,\n                           SSL_R_SSL_HANDSHAKE_FAILURE);\n                    return (-1);\n                }\n                if (!(s->mode & SSL_MODE_AUTO_RETRY)) {\n                    if (SSL3_BUFFER_get_left(&s->rlayer.rbuf) == 0) {\n                        BIO *bio;\n                        s->rwstate = SSL_READING;\n                        bio = SSL_get_rbio(s);\n                        BIO_clear_retry_flags(bio);\n                        BIO_set_retry_read(bio);\n                        return (-1);\n                    }\n                }\n            }\n        }\n        goto start;\n    }\n    if (s->rlayer.d->alert_fragment_len >= DTLS1_AL_HEADER_LENGTH) {\n        int alert_level = s->rlayer.d->alert_fragment[0];\n        int alert_descr = s->rlayer.d->alert_fragment[1];\n        s->rlayer.d->alert_fragment_len = 0;\n        if (s->msg_callback)\n            s->msg_callback(0, s->version, SSL3_RT_ALERT,\n                            s->rlayer.d->alert_fragment, 2, s,\n                            s->msg_callback_arg);\n        if (s->info_callback != NULL)\n            cb = s->info_callback;\n        else if (s->ctx->info_callback != NULL)\n            cb = s->ctx->info_callback;\n        if (cb != NULL) {\n            j = (alert_level << 8) | alert_descr;\n            cb(s, SSL_CB_READ_ALERT, j);\n        }\n        if (alert_level == SSL3_AL_WARNING) {\n            s->s3->warn_alert = alert_descr;\n            if (alert_descr == SSL_AD_CLOSE_NOTIFY) {\n#ifndef OPENSSL_NO_SCTP\n                if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&\n                    BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s))) {\n                    s->d1->shutdown_received = 1;\n                    s->rwstate = SSL_READING;\n                    BIO_clear_retry_flags(SSL_get_rbio(s));\n                    BIO_set_retry_read(SSL_get_rbio(s));\n                    return -1;\n                }\n#endif\n                s->shutdown |= SSL_RECEIVED_SHUTDOWN;\n                return (0);\n            }\n#if 0\n            if (alert_descr == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE) {\n                unsigned short seq;\n                unsigned int frag_off;\n                unsigned char *p = &(s->rlayer.d->alert_fragment[2]);\n                n2s(p, seq);\n                n2l3(p, frag_off);\n                dtls1_retransmit_message(s,\n                                         dtls1_get_queue_priority\n                                         (frag->msg_header.seq, 0), frag_off,\n                                         &found);\n                if (!found && SSL_in_init(s)) {\n                    ssl3_send_alert(s, SSL3_AL_WARNING,\n                                    DTLS1_AD_MISSING_HANDSHAKE_MESSAGE);\n                }\n            }\n#endif\n        } else if (alert_level == SSL3_AL_FATAL) {\n            char tmp[16];\n            s->rwstate = SSL_NOTHING;\n            s->s3->fatal_alert = alert_descr;\n            SSLerr(SSL_F_DTLS1_READ_BYTES,\n                   SSL_AD_REASON_OFFSET + alert_descr);\n            BIO_snprintf(tmp, sizeof tmp, "%d", alert_descr);\n            ERR_add_error_data(2, "SSL alert number ", tmp);\n            s->shutdown |= SSL_RECEIVED_SHUTDOWN;\n            SSL_CTX_remove_session(s->ctx, s->session);\n            return (0);\n        } else {\n            al = SSL_AD_ILLEGAL_PARAMETER;\n            SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_UNKNOWN_ALERT_TYPE);\n            goto f_err;\n        }\n        goto start;\n    }\n    if (s->shutdown & SSL_SENT_SHUTDOWN) {\n        s->rwstate = SSL_NOTHING;\n        SSL3_RECORD_set_length(rr, 0);\n        return (0);\n    }\n    if (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC) {\n        struct ccs_header_st ccs_hdr;\n        unsigned int ccs_hdr_len = DTLS1_CCS_HEADER_LENGTH;\n        dtls1_get_ccs_header(SSL3_RECORD_get_data(rr), &ccs_hdr);\n        if (s->version == DTLS1_BAD_VER)\n            ccs_hdr_len = 3;\n        if ((SSL3_RECORD_get_length(rr) != ccs_hdr_len)\n                || (SSL3_RECORD_get_off(rr) != 0)\n                || (SSL3_RECORD_get_data(rr)[0] != SSL3_MT_CCS)) {\n            i = SSL_AD_ILLEGAL_PARAMETER;\n            SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_BAD_CHANGE_CIPHER_SPEC);\n            goto err;\n        }\n        SSL3_RECORD_set_length(rr, 0);\n        if (s->msg_callback)\n            s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC,\n                SSL3_RECORD_get_data(rr), 1, s, s->msg_callback_arg);\n        if (!s->d1->change_cipher_spec_ok) {\n            goto start;\n        }\n        s->d1->change_cipher_spec_ok = 0;\n        s->s3->change_cipher_spec = 1;\n        if (!ssl3_do_change_cipher_spec(s))\n            goto err;\n        dtls1_reset_seq_numbers(s, SSL3_CC_READ);\n        if (s->version == DTLS1_BAD_VER)\n            s->d1->handshake_read_seq++;\n#ifndef OPENSSL_NO_SCTP\n        BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD, 1, NULL);\n#endif\n        goto start;\n    }\n    if ((s->rlayer.d->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) &&\n        !s->in_handshake) {\n        struct hm_header_st msg_hdr;\n        dtls1_get_message_header(rr->data, &msg_hdr);\n        if (SSL3_RECORD_get_epoch(rr) != s->rlayer.d->r_epoch) {\n            SSL3_RECORD_set_length(rr, 0);\n            goto start;\n        }\n        if (msg_hdr.type == SSL3_MT_FINISHED) {\n            if (dtls1_check_timeout_num(s) < 0)\n                return -1;\n            dtls1_retransmit_buffered_messages(s);\n            SSL3_RECORD_set_length(rr, 0);\n            goto start;\n        }\n        if (((s->state & SSL_ST_MASK) == SSL_ST_OK) &&\n            !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)) {\n            s->state = s->server ? SSL_ST_ACCEPT : SSL_ST_CONNECT;\n            s->renegotiate = 1;\n            s->new_session = 1;\n        }\n        i = s->handshake_func(s);\n        if (i < 0)\n            return (i);\n        if (i == 0) {\n            SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_SSL_HANDSHAKE_FAILURE);\n            return (-1);\n        }\n        if (!(s->mode & SSL_MODE_AUTO_RETRY)) {\n            if (SSL3_BUFFER_get_left(&s->rlayer.rbuf) == 0) {\n                BIO *bio;\n                s->rwstate = SSL_READING;\n                bio = SSL_get_rbio(s);\n                BIO_clear_retry_flags(bio);\n                BIO_set_retry_read(bio);\n                return (-1);\n            }\n        }\n        goto start;\n    }\n    switch (SSL3_RECORD_get_type(rr)) {\n    default:\n        if (s->version == TLS1_VERSION) {\n            SSL3_RECORD_set_length(rr, 0);\n            goto start;\n        }\n        al = SSL_AD_UNEXPECTED_MESSAGE;\n        SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_UNEXPECTED_RECORD);\n        goto f_err;\n    case SSL3_RT_CHANGE_CIPHER_SPEC:\n    case SSL3_RT_ALERT:\n    case SSL3_RT_HANDSHAKE:\n        al = SSL_AD_UNEXPECTED_MESSAGE;\n        SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR);\n        goto f_err;\n    case SSL3_RT_APPLICATION_DATA:\n        if (s->s3->in_read_app_data &&\n            (s->s3->total_renegotiations != 0) &&\n            (((s->state & SSL_ST_CONNECT) &&\n              (s->state >= SSL3_ST_CW_CLNT_HELLO_A) &&\n              (s->state <= SSL3_ST_CR_SRVR_HELLO_A)\n             ) || ((s->state & SSL_ST_ACCEPT) &&\n                   (s->state <= SSL3_ST_SW_HELLO_REQ_A) &&\n                   (s->state >= SSL3_ST_SR_CLNT_HELLO_A)\n             )\n            )) {\n            s->s3->in_read_app_data = 2;\n            return (-1);\n        } else {\n            al = SSL_AD_UNEXPECTED_MESSAGE;\n            SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_UNEXPECTED_RECORD);\n            goto f_err;\n        }\n    }\n f_err:\n    ssl3_send_alert(s, SSL3_AL_FATAL, al);\n err:\n    return (-1);\n}']