lsquic_chsk_stream.c revision 50aadb33
1/* Copyright (c) 2017 LiteSpeed Technologies Inc.  See LICENSE. */
2/*
3 * Stream/crypto handshake adapter for the client side.
4 *
5 * The client composes CHLO, writes it to the stream, and wait for the
6 * server response, which it processes.
7 */
8
9#include <assert.h>
10#include <errno.h>
11#include <stdarg.h>
12#include <stdlib.h>
13#include <string.h>
14
15#include "lsquic_int_types.h"
16#include "lsquic.h"
17
18#include "lsquic_handshake.h"
19#include "lsquic_chsk_stream.h"
20#include "lsquic_ver_neg.h"
21#include "lsquic_conn.h"
22#include "lsquic_mm.h"
23
24#define LSQUIC_LOGGER_MODULE LSQLM_HSK_ADAPTER
25#define LSQUIC_LOG_CONN_ID lsquic_conn_id(c_hsk->lconn)
26#include "lsquic_logger.h"
27
28
29static lsquic_stream_ctx_t *
30hsk_client_on_new_stream (void *stream_if_ctx, lsquic_stream_t *stream)
31{
32    struct client_hsk_ctx *const c_hsk = stream_if_ctx;
33
34    LSQ_DEBUG("stream created");
35
36
37    lsquic_stream_wantwrite(stream, 1);
38
39    return (void *) c_hsk;
40}
41
42
43static void
44hsk_client_on_read (lsquic_stream_t *stream, struct lsquic_stream_ctx *sh)
45{
46    struct client_hsk_ctx *const c_hsk = (struct client_hsk_ctx *) sh;
47    ssize_t nread;
48    int s;
49
50    if (!c_hsk->buf_in)
51    {
52        c_hsk->buf_in  = lsquic_mm_get_16k(c_hsk->mm);
53        if (!c_hsk->buf_in)
54        {
55            LSQ_WARN("could not get buffer: %s", strerror(errno));
56            lsquic_stream_wantread(stream, 0);
57            lsquic_conn_close(c_hsk->lconn);
58            return;
59        }
60        c_hsk->buf_sz  = 16 * 1024;
61        c_hsk->buf_off = 0;
62    }
63
64    nread = lsquic_stream_read(stream, c_hsk->buf_in + c_hsk->buf_off,
65                                            c_hsk->buf_sz - c_hsk->buf_off);
66    if (nread <= 0)
67    {
68        if (nread < 0)
69            LSQ_INFO("Could not read from handshake stream: %s",
70                                                            strerror(errno));
71        else
72            LSQ_INFO("Handshake stream closed (odd)");
73        lsquic_mm_put_16k(c_hsk->mm, c_hsk->buf_in);
74        c_hsk->buf_in = NULL;
75        lsquic_stream_wantread(stream, 0);
76        lsquic_conn_close(c_hsk->lconn);
77        return;
78    }
79    c_hsk->buf_off += nread;
80
81    s = handle_chlo_reply(c_hsk->lconn->cn_enc_session,
82                                        c_hsk->buf_in, c_hsk->buf_off);
83    LSQ_DEBUG("handle_chlo_reply returned %d", s);
84    switch (s)
85    {
86    case DATA_NOT_ENOUGH:
87        if (c_hsk->buf_off < c_hsk->buf_sz)
88            LSQ_INFO("not enough server response has arrived, continue "
89                                                                "buffering");
90        else
91        {
92            LSQ_INFO("read in %u bytes of server response, and it is still "
93                        "not enough: giving up", c_hsk->buf_off);
94            lsquic_mm_put_16k(c_hsk->mm, c_hsk->buf_in);
95            c_hsk->buf_in = NULL;
96            lsquic_stream_wantread(stream, 0);
97            lsquic_conn_close(c_hsk->lconn);
98        }
99        break;
100    case DATA_NO_ERROR:
101        lsquic_mm_put_16k(c_hsk->mm, c_hsk->buf_in);
102        c_hsk->buf_in = NULL;
103        lsquic_stream_wantread(stream, 0);
104        if (is_hs_done(c_hsk->lconn->cn_enc_session))
105        {
106            LSQ_DEBUG("handshake is complete, inform connection");
107            c_hsk->lconn->cn_if->ci_handshake_done(c_hsk->lconn);
108        }
109        else
110        {
111            LSQ_DEBUG("handshake not yet complete, will generate another "
112                                                                    "message");
113            lsquic_stream_wantwrite(stream, 1);
114        }
115        break;
116    default:
117        LSQ_WARN("handle_chlo_reply returned unknown value %d", s);
118    case DATA_FORMAT_ERROR:
119        LSQ_INFO("handle_chlo_reply returned an error");
120        break;
121    }
122}
123
124
125/* In this function, we assume that we can write the whole message in one
126 * shot.  Otherwise, this is an error.
127 */
128static void
129hsk_client_on_write (lsquic_stream_t *stream, struct lsquic_stream_ctx *sh)
130{
131    struct client_hsk_ctx *const c_hsk = (struct client_hsk_ctx *) sh;
132    unsigned char *buf;
133    size_t len;
134    ssize_t nw;
135
136    lsquic_stream_wantwrite(stream, 0);
137
138    buf = lsquic_mm_get_4k(c_hsk->mm);
139    if (!buf)
140    {
141        LSQ_WARN("cannot allocate buffer: %s", strerror(errno));
142        lsquic_conn_close(c_hsk->lconn);
143        return;
144    }
145    len = 4 * 1024;
146
147    if (0 != gen_chlo(c_hsk->lconn->cn_enc_session, c_hsk->ver_neg->vn_ver,
148                                                                    buf, &len))
149    {
150        LSQ_WARN("cannot create CHLO message");
151        lsquic_mm_put_4k(c_hsk->mm, buf);
152        lsquic_conn_close(c_hsk->lconn);
153        return;
154    }
155
156    nw = lsquic_stream_write(stream, buf, len);
157    lsquic_mm_put_4k(c_hsk->mm, buf);
158
159    if (nw < 0)
160        LSQ_INFO("error writing to stream: %s", strerror(errno));
161    else if ((size_t) nw == len)
162    {
163        LSQ_INFO("wrote %zd bytes of CHLO to stream", nw);
164        lsquic_stream_flush(stream);
165        lsquic_stream_wantread(stream, 1);
166    }
167    else
168        LSQ_INFO("could only write %zd bytes to stream instead of %zd",
169                                                                    nw, len);
170}
171
172
173static void
174hsk_client_on_close (lsquic_stream_t *stream, struct lsquic_stream_ctx *sh)
175{
176    struct client_hsk_ctx *const c_hsk = (struct client_hsk_ctx *) sh;
177    if (c_hsk->buf_in)
178        lsquic_mm_put_16k(c_hsk->mm, c_hsk->buf_in);
179    LSQ_DEBUG("stream closed");
180}
181
182
183const struct lsquic_stream_if lsquic_client_hsk_stream_if =
184{
185    .on_new_stream = hsk_client_on_new_stream,
186    .on_read       = hsk_client_on_read,
187    .on_write      = hsk_client_on_write,
188    .on_close      = hsk_client_on_close,
189};
190