~roger.light/ubuntu/vivid/libwebsockets/fix-for-1422623

« back to all changes in this revision

Viewing changes to lib/handshake.c

  • Committer: Roger A. Light
  • Date: 2015-02-19 16:00:08 UTC
  • mfrom: (1.1.1)
  • Revision ID: roger@atchoo.org-20150219160008-162cd9naiu2yekny
New upstream release 1.3.

Show diffs side-by-side

added added

removed removed

Lines of Context:
60
60
        size_t n;
61
61
 
62
62
        switch (wsi->state) {
 
63
 
 
64
        case WSI_STATE_HTTP_BODY:
 
65
http_postbody:
 
66
                while (len--) {
 
67
 
 
68
                        if (wsi->u.http.content_length_seen >= wsi->u.http.content_length)
 
69
                                break;
 
70
 
 
71
                        wsi->u.http.post_buffer[wsi->u.http.body_index++] = *buf++;
 
72
                        wsi->u.http.content_length_seen++;
 
73
                        n = wsi->protocol->rx_buffer_size;
 
74
                        if (!n)
 
75
                                n = LWS_MAX_SOCKET_IO_BUF;
 
76
 
 
77
                        if (wsi->u.http.body_index != n &&
 
78
                            wsi->u.http.content_length_seen != wsi->u.http.content_length)
 
79
                                continue;
 
80
 
 
81
                        if (wsi->protocol->callback) {
 
82
                                n = wsi->protocol->callback(
 
83
                                        wsi->protocol->owning_server, wsi,
 
84
                                            LWS_CALLBACK_HTTP_BODY,
 
85
                                            wsi->user_space, wsi->u.http.post_buffer,
 
86
                                                        wsi->u.http.body_index);
 
87
                                wsi->u.http.body_index = 0;
 
88
                                if (n)
 
89
                                        goto bail;
 
90
                        }
 
91
 
 
92
                        if (wsi->u.http.content_length_seen == wsi->u.http.content_length) {
 
93
                                /* he sent the content in time */
 
94
                                libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
 
95
                                n = wsi->protocol->callback(
 
96
                                        wsi->protocol->owning_server, wsi,
 
97
                                            LWS_CALLBACK_HTTP_BODY_COMPLETION,
 
98
                                            wsi->user_space, NULL, 0);
 
99
                                wsi->u.http.body_index = 0;
 
100
                                if (n)
 
101
                                        goto bail;
 
102
                        }
 
103
 
 
104
                }
 
105
 
 
106
                /* 
 
107
                 * we need to spill here so everything is seen in the case
 
108
                 * there is no content-length
 
109
                 */
 
110
                if (wsi->u.http.body_index && wsi->protocol->callback) {
 
111
                        n = wsi->protocol->callback(
 
112
                                wsi->protocol->owning_server, wsi,
 
113
                                    LWS_CALLBACK_HTTP_BODY,
 
114
                                    wsi->user_space, wsi->u.http.post_buffer,
 
115
                                                wsi->u.http.body_index);
 
116
                        wsi->u.http.body_index = 0;
 
117
                        if (n)
 
118
                                goto bail;
 
119
                }
 
120
                break;
 
121
 
63
122
        case WSI_STATE_HTTP_ISSUING_FILE:
64
123
        case WSI_STATE_HTTP:
65
124
                wsi->state = WSI_STATE_HTTP_HEADERS;
70
129
 
71
130
                lwsl_parser("issuing %d bytes to parser\n", (int)len);
72
131
 
73
 
#ifndef LWS_NO_CLIENT
74
 
                switch (wsi->mode) {
75
 
                case LWS_CONNMODE_WS_CLIENT_WAITING_PROXY_REPLY:
76
 
                case LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE:
77
 
                case LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY:
78
 
                case LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT:
79
 
                case LWS_CONNMODE_WS_CLIENT:
80
 
                        for (n = 0; n < len; n++)
81
 
                                if (libwebsocket_client_rx_sm(wsi, *buf++)) {
82
 
                                        lwsl_info("client_rx_sm failed\n");
83
 
                                        goto bail;
84
 
                                }
85
 
                        return 0;
86
 
                default:
87
 
                        break;
88
 
                }
89
 
#endif
90
 
#ifndef LWS_NO_SERVER
91
 
                /* LWS_CONNMODE_WS_SERVING */
92
 
 
93
 
                for (n = 0; n < len; n++)
94
 
                        if (libwebsocket_parse(wsi, *buf++)) {
95
 
                                lwsl_info("libwebsocket_parse failed\n");
96
 
                                goto bail;
97
 
                        }
98
 
 
99
 
                if (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE)
100
 
                        break;
101
 
 
102
 
                lwsl_parser("libwebsocket_parse sees parsing complete\n");
103
 
 
104
 
                /* is this websocket protocol or normal http 1.0? */
105
 
 
106
 
                if (!lws_hdr_total_length(wsi, WSI_TOKEN_UPGRADE) ||
107
 
                             !lws_hdr_total_length(wsi, WSI_TOKEN_CONNECTION)) {
108
 
 
109
 
                        /* it's not websocket.... shall we accept it as http? */
110
 
 
111
 
                        if (!lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI)) {
112
 
                                lwsl_warn("Missing URI in HTTP request\n");
113
 
                                /* drop the header info */
114
 
                                if (wsi->u.hdr.ah)
115
 
                                        free(wsi->u.hdr.ah);
116
 
                                goto bail;
117
 
                        }
118
 
 
119
 
                        lwsl_info("HTTP request for '%s'\n", lws_hdr_simple_ptr(wsi, WSI_TOKEN_GET_URI));
120
 
 
121
 
                        wsi->state = WSI_STATE_HTTP;
122
 
                        n = 0;
123
 
                        if (wsi->protocol->callback)
124
 
                                n = wsi->protocol->callback(context, wsi,
125
 
                                    LWS_CALLBACK_HTTP,
126
 
                                    wsi->user_space,
127
 
                                    lws_hdr_simple_ptr(wsi, WSI_TOKEN_GET_URI),
128
 
                                  lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI));
129
 
 
130
 
                        /* drop the header info */
131
 
                        if (wsi->u.hdr.ah)
132
 
                                free(wsi->u.hdr.ah);
133
 
 
134
 
                        if (n) {
135
 
                                lwsl_info("LWS_CALLBACK_HTTP closing\n");
136
 
                                goto bail;
137
 
                        }
138
 
 
139
 
                        return 0;
140
 
                }
141
 
 
142
 
                if (!wsi->protocol)
143
 
                        lwsl_err("NULL protocol at libwebsocket_read\n");
144
 
 
145
 
                /*
146
 
                 * It's websocket
147
 
                 *
148
 
                 * Make sure user side is happy about protocol
149
 
                 */
150
 
 
151
 
                while (wsi->protocol->callback) {
152
 
 
153
 
                        if (!lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL)) {
154
 
                                if (wsi->protocol->name == NULL)
155
 
                                        break;
156
 
                        } else
157
 
                                if (wsi->protocol->name && strcmp(
158
 
                                        lws_hdr_simple_ptr(wsi,
159
 
                                                WSI_TOKEN_PROTOCOL),
160
 
                                                      wsi->protocol->name) == 0)
161
 
                                        break;
162
 
 
163
 
                        wsi->protocol++;
164
 
                }
165
 
 
166
 
                /* we didn't find a protocol he wanted? */
167
 
 
168
 
                if (wsi->protocol->callback == NULL) {
169
 
                        if (lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL) ==
170
 
                                                                         NULL) {
171
 
                                lwsl_info("no protocol -> prot 0 handler\n");
172
 
                                wsi->protocol = &context->protocols[0];
173
 
                        } else {
174
 
                                lwsl_err("Req protocol %s not supported\n",
175
 
                                   lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL));
176
 
                                goto bail;
177
 
                        }
178
 
                }
179
 
 
180
 
                /*
181
 
                 * Give the user code a chance to study the request and
182
 
                 * have the opportunity to deny it
183
 
                 */
184
 
 
185
 
                if ((wsi->protocol->callback)(wsi->protocol->owning_server, wsi,
186
 
                                LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION,
187
 
                                lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL),
188
 
                                                                     NULL, 0)) {
189
 
                        lwsl_warn("User code denied connection\n");
190
 
                        goto bail;
191
 
                }
192
 
 
193
 
 
194
 
                /*
195
 
                 * Perform the handshake according to the protocol version the
196
 
                 * client announced
197
 
                 */
198
 
 
199
 
                switch (wsi->ietf_spec_revision) {
200
 
                case 13:
201
 
                        lwsl_parser("lws_parse calling handshake_04\n");
202
 
                        if (handshake_0405(context, wsi)) {
203
 
                                lwsl_info("hs0405 has failed the connection\n");
204
 
                                goto bail;
205
 
                        }
206
 
                        break;
207
 
 
208
 
                default:
209
 
                        lwsl_warn("Unknown client spec version %d\n",
210
 
                                                       wsi->ietf_spec_revision);
211
 
                        goto bail;
212
 
                }
213
 
 
214
 
                /* drop the header info */
215
 
 
216
 
                if (wsi->u.hdr.ah)
217
 
                        free(wsi->u.hdr.ah);
218
 
 
219
 
                wsi->mode = LWS_CONNMODE_WS_SERVING;
220
 
 
221
 
                /* union transition */
222
 
                memset(&wsi->u, 0, sizeof(wsi->u));
223
 
 
224
 
                /*
225
 
                 * create the frame buffer for this connection according to the
226
 
                 * size mentioned in the protocol definition.  If 0 there, use
227
 
                 * a big default for compatibility
228
 
                 */
229
 
 
230
 
                n = wsi->protocol->rx_buffer_size;
231
 
                if (!n)
232
 
                        n = LWS_MAX_SOCKET_IO_BUF;
233
 
                n += LWS_SEND_BUFFER_PRE_PADDING + LWS_SEND_BUFFER_POST_PADDING;
234
 
                wsi->u.ws.rx_user_buffer = malloc(n);
235
 
                if (!wsi->u.ws.rx_user_buffer) {
236
 
                        lwsl_err("Out of Mem allocating rx buffer %d\n", n);
237
 
                        goto bail;
238
 
                }
239
 
                lwsl_info("Allocating RX buffer %d\n", n);
240
 
 
241
 
                lwsl_parser("accepted v%02d connection\n",
242
 
                                                       wsi->ietf_spec_revision);
243
 
#endif
 
132
                if (lws_handshake_client(wsi, &buf, len))
 
133
                        goto bail;
 
134
 
 
135
                switch (lws_handshake_server(context, wsi, &buf, len)) {
 
136
                case 1:
 
137
                        goto bail;
 
138
                case 2:
 
139
                        goto http_postbody;
 
140
                }
244
141
                break;
245
142
 
246
143
        case WSI_STATE_AWAITING_CLOSE_ACK:
247
144
        case WSI_STATE_ESTABLISHED:
248
 
#ifndef LWS_NO_CLIENT
 
145
                if (lws_handshake_client(wsi, &buf, len))
 
146
                        goto bail;
249
147
                switch (wsi->mode) {
250
 
                case LWS_CONNMODE_WS_CLIENT:
251
 
                        for (n = 0; n < len; n++)
252
 
                                if (libwebsocket_client_rx_sm(
253
 
                                                             wsi, *buf++) < 0) {
254
 
                                        lwsl_info("client rx has bailed\n");
255
 
                                        goto bail;
256
 
                                }
 
148
                case LWS_CONNMODE_WS_SERVING:
257
149
 
258
 
                        return 0;
259
 
                default:
 
150
                        if (libwebsocket_interpret_incoming_packet(wsi, buf, len) < 0) {
 
151
                                lwsl_info("interpret_incoming_packet has bailed\n");
 
152
                                goto bail;
 
153
                        }
260
154
                        break;
261
155
                }
262
 
#endif
263
 
#ifndef LWS_NO_SERVER
264
 
                /* LWS_CONNMODE_WS_SERVING */
265
 
 
266
 
                if (libwebsocket_interpret_incoming_packet(wsi, buf, len) < 0) {
267
 
                        lwsl_info("interpret_incoming_packet has bailed\n");
268
 
                        goto bail;
269
 
                }
270
 
#endif
271
156
                break;
272
157
        default:
273
158
                lwsl_err("libwebsocket_read: Unhandled state\n");
277
162
        return 0;
278
163
 
279
164
bail:
280
 
        lwsl_info("closing connection at libwebsocket_read bail:\n");
 
165
        lwsl_debug("closing connection at libwebsocket_read bail:\n");
281
166
 
282
167
        libwebsocket_close_and_free_session(context, wsi,
283
168
                                                     LWS_CLOSE_STATUS_NOSTATUS);