1/*
2 Copyright (c) 2007-2019 Contributors as noted in the AUTHORS file
3
4 This file is part of libzmq, the ZeroMQ core engine in C++.
5
6 libzmq is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License (LGPL) as published
8 by the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 As a special exception, the Contributors give you permission to link
12 this library with independent modules to produce an executable,
13 regardless of the license terms of these independent modules, and to
14 copy and distribute the resulting executable under terms of your choice,
15 provided that you also meet, for each linked independent module, the
16 terms and conditions of the license of that module. An independent
17 module is a module which is not derived from or based on this library.
18 If you modify this library, you must extend this exception to your
19 version of the library.
20
21 libzmq is distributed in the hope that it will be useful, but WITHOUT
22 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
24 License for more details.
25
26 You should have received a copy of the GNU Lesser General Public License
27 along with this program. If not, see <http://www.gnu.org/licenses/>.
28*/
29
30#ifndef __ZMQ_WS_ENGINE_HPP_INCLUDED__
31#define __ZMQ_WS_ENGINE_HPP_INCLUDED__
32
33#include "io_object.hpp"
34#include "address.hpp"
35#include "msg.hpp"
36#include "stream_engine_base.hpp"
37#include "ws_address.hpp"
38
39#define WS_BUFFER_SIZE 8192
40#define MAX_HEADER_NAME_LENGTH 1024
41#define MAX_HEADER_VALUE_LENGTH 2048
42
43namespace zmq
44{
45class io_thread_t;
46class session_base_t;
47
48typedef enum
49{
50 handshake_initial = 0,
51 request_line_G,
52 request_line_GE,
53 request_line_GET,
54 request_line_GET_space,
55 request_line_resource,
56 request_line_resource_space,
57 request_line_H,
58 request_line_HT,
59 request_line_HTT,
60 request_line_HTTP,
61 request_line_HTTP_slash,
62 request_line_HTTP_slash_1,
63 request_line_HTTP_slash_1_dot,
64 request_line_HTTP_slash_1_dot_1,
65 request_line_cr,
66 header_field_begin_name,
67 header_field_name,
68 header_field_colon,
69 header_field_value_trailing_space,
70 header_field_value,
71 header_field_cr,
72 handshake_end_line_cr,
73 handshake_complete,
74
75 handshake_error = -1
76} ws_server_handshake_state_t;
77
78
79typedef enum
80{
81 client_handshake_initial = 0,
82 response_line_H,
83 response_line_HT,
84 response_line_HTT,
85 response_line_HTTP,
86 response_line_HTTP_slash,
87 response_line_HTTP_slash_1,
88 response_line_HTTP_slash_1_dot,
89 response_line_HTTP_slash_1_dot_1,
90 response_line_HTTP_slash_1_dot_1_space,
91 response_line_status_1,
92 response_line_status_10,
93 response_line_status_101,
94 response_line_status_101_space,
95 response_line_s,
96 response_line_sw,
97 response_line_swi,
98 response_line_swit,
99 response_line_switc,
100 response_line_switch,
101 response_line_switchi,
102 response_line_switchin,
103 response_line_switching,
104 response_line_switching_space,
105 response_line_p,
106 response_line_pr,
107 response_line_pro,
108 response_line_prot,
109 response_line_proto,
110 response_line_protoc,
111 response_line_protoco,
112 response_line_protocol,
113 response_line_protocols,
114 response_line_cr,
115 client_header_field_begin_name,
116 client_header_field_name,
117 client_header_field_colon,
118 client_header_field_value_trailing_space,
119 client_header_field_value,
120 client_header_field_cr,
121 client_handshake_end_line_cr,
122 client_handshake_complete,
123
124 client_handshake_error = -1
125} ws_client_handshake_state_t;
126
127class ws_engine_t : public stream_engine_base_t
128{
129 public:
130 ws_engine_t (fd_t fd_,
131 const options_t &options_,
132 const endpoint_uri_pair_t &endpoint_uri_pair_,
133 ws_address_t &address_,
134 bool client_);
135 ~ws_engine_t ();
136
137 protected:
138 bool handshake ();
139 void plug_internal ();
140 void start_ws_handshake ();
141
142 private:
143 int routing_id_msg (msg_t *msg_);
144 int process_routing_id_msg (msg_t *msg_);
145
146 bool select_protocol (char *protocol);
147
148 bool client_handshake ();
149 bool server_handshake ();
150
151 bool _client;
152 ws_address_t _address;
153
154 ws_client_handshake_state_t _client_handshake_state;
155 ws_server_handshake_state_t _server_handshake_state;
156
157 unsigned char _read_buffer[WS_BUFFER_SIZE];
158 unsigned char _write_buffer[WS_BUFFER_SIZE];
159 char _header_name[MAX_HEADER_NAME_LENGTH + 1];
160 int _header_name_position;
161 char _header_value[MAX_HEADER_VALUE_LENGTH + 1];
162 int _header_value_position;
163
164 bool _header_upgrade_websocket;
165 bool _header_connection_upgrade;
166 char _websocket_protocol[256];
167 char _websocket_key[MAX_HEADER_VALUE_LENGTH + 1];
168 char _websocket_accept[MAX_HEADER_VALUE_LENGTH + 1];
169};
170}
171
172#endif
173