File indexing completed on 2025-01-18 09:29:33
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_BEAST_WEBSOCKET_DETAIL_PMD_EXTENSION_IPP
0011 #define BOOST_BEAST_WEBSOCKET_DETAIL_PMD_EXTENSION_IPP
0012
0013 #include <boost/beast/websocket/detail/pmd_extension.hpp>
0014
0015 namespace boost {
0016 namespace beast {
0017 namespace websocket {
0018 namespace detail {
0019
0020 int
0021 parse_bits(string_view s)
0022 {
0023 if(s.size() == 0)
0024 return -1;
0025 if(s.size() > 2)
0026 return -1;
0027 if(s[0] < '1' || s[0] > '9')
0028 return -1;
0029 unsigned i = 0;
0030 for(auto c : s)
0031 {
0032 if(c < '0' || c > '9')
0033 return -1;
0034 auto const i0 = i;
0035 i = 10 * i + (c - '0');
0036 if(i < i0)
0037 return -1;
0038 }
0039 return static_cast<int>(i);
0040 }
0041
0042
0043
0044 void
0045 pmd_read_impl(pmd_offer& offer, http::ext_list const& list)
0046 {
0047 offer.accept = false;
0048 offer.server_max_window_bits= 0;
0049 offer.client_max_window_bits = 0;
0050 offer.server_no_context_takeover = false;
0051 offer.client_no_context_takeover = false;
0052
0053 for(auto const& ext : list)
0054 {
0055 if(beast::iequals(ext.first, "permessage-deflate"))
0056 {
0057 for(auto const& param : ext.second)
0058 {
0059 if(beast::iequals(param.first,
0060 "server_max_window_bits"))
0061 {
0062 if(offer.server_max_window_bits != 0)
0063 {
0064
0065
0066
0067 return;
0068 }
0069 if(param.second.empty())
0070 {
0071
0072
0073
0074 return;
0075 }
0076 offer.server_max_window_bits =
0077 parse_bits(param.second);
0078 if( offer.server_max_window_bits < 8 ||
0079 offer.server_max_window_bits > 15)
0080 {
0081
0082
0083
0084 return;
0085 }
0086 }
0087 else if(beast::iequals(param.first,
0088 "client_max_window_bits"))
0089 {
0090 if(offer.client_max_window_bits != 0)
0091 {
0092
0093
0094
0095 return;
0096 }
0097 if(! param.second.empty())
0098 {
0099 offer.client_max_window_bits =
0100 parse_bits(param.second);
0101 if( offer.client_max_window_bits < 8 ||
0102 offer.client_max_window_bits > 15)
0103 {
0104
0105
0106
0107 return;
0108 }
0109 }
0110 else
0111 {
0112 offer.client_max_window_bits = -1;
0113 }
0114 }
0115 else if(beast::iequals(param.first,
0116 "server_no_context_takeover"))
0117 {
0118 if(offer.server_no_context_takeover)
0119 {
0120
0121
0122
0123 return;
0124 }
0125 if(! param.second.empty())
0126 {
0127
0128
0129
0130 return;
0131 }
0132 offer.server_no_context_takeover = true;
0133 }
0134 else if(beast::iequals(param.first,
0135 "client_no_context_takeover"))
0136 {
0137 if(offer.client_no_context_takeover)
0138 {
0139
0140
0141
0142 return;
0143 }
0144 if(! param.second.empty())
0145 {
0146
0147
0148
0149 return;
0150 }
0151 offer.client_no_context_takeover = true;
0152 }
0153 else
0154 {
0155
0156
0157
0158 return;
0159 }
0160 }
0161 offer.accept = true;
0162 return;
0163 }
0164 }
0165 }
0166
0167 static_string<512>
0168 pmd_write_impl(pmd_offer const& offer)
0169 {
0170 static_string<512> s = "permessage-deflate";
0171 if(offer.server_max_window_bits != 0)
0172 {
0173 if(offer.server_max_window_bits != -1)
0174 {
0175 s += "; server_max_window_bits=";
0176 s += to_static_string(
0177 offer.server_max_window_bits);
0178 }
0179 else
0180 {
0181 s += "; server_max_window_bits";
0182 }
0183 }
0184 if(offer.client_max_window_bits != 0)
0185 {
0186 if(offer.client_max_window_bits != -1)
0187 {
0188 s += "; client_max_window_bits=";
0189 s += to_static_string(
0190 offer.client_max_window_bits);
0191 }
0192 else
0193 {
0194 s += "; client_max_window_bits";
0195 }
0196 }
0197 if(offer.server_no_context_takeover)
0198 {
0199 s += "; server_no_context_takeover";
0200 }
0201 if(offer.client_no_context_takeover)
0202 {
0203 s += "; client_no_context_takeover";
0204 }
0205
0206 return s;
0207 }
0208
0209 static_string<512>
0210 pmd_negotiate_impl(
0211 pmd_offer& config,
0212 pmd_offer const& offer,
0213 permessage_deflate const& o)
0214 {
0215 static_string<512> s = "permessage-deflate";
0216
0217 config.server_no_context_takeover =
0218 offer.server_no_context_takeover ||
0219 o.server_no_context_takeover;
0220 if(config.server_no_context_takeover)
0221 s += "; server_no_context_takeover";
0222
0223 config.client_no_context_takeover =
0224 o.client_no_context_takeover ||
0225 offer.client_no_context_takeover;
0226 if(config.client_no_context_takeover)
0227 s += "; client_no_context_takeover";
0228
0229 if(offer.server_max_window_bits != 0)
0230 config.server_max_window_bits = (std::min)(
0231 offer.server_max_window_bits,
0232 o.server_max_window_bits);
0233 else
0234 config.server_max_window_bits =
0235 o.server_max_window_bits;
0236 if(config.server_max_window_bits < 15)
0237 {
0238
0239
0240
0241 if(config.server_max_window_bits < 9)
0242 config.server_max_window_bits = 9;
0243
0244 s += "; server_max_window_bits=";
0245 s += to_static_string(
0246 config.server_max_window_bits);
0247 }
0248
0249 switch(offer.client_max_window_bits)
0250 {
0251 case -1:
0252
0253 config.client_max_window_bits =
0254 o.client_max_window_bits;
0255 if(config.client_max_window_bits < 15)
0256 {
0257 s += "; client_max_window_bits=";
0258 s += to_static_string(
0259 config.client_max_window_bits);
0260 }
0261 break;
0262
0263 case 0:
0264
0265
0266
0267
0268
0269
0270
0271 if(o.client_max_window_bits == 15)
0272 config.client_max_window_bits = 15;
0273 else
0274 config.accept = false;
0275 break;
0276
0277 default:
0278
0279 config.client_max_window_bits = (std::min)(
0280 o.client_max_window_bits,
0281 offer.client_max_window_bits);
0282 s += "; client_max_window_bits=";
0283 s += to_static_string(
0284 config.client_max_window_bits);
0285 break;
0286 }
0287
0288 return s;
0289 }
0290
0291 void
0292 pmd_normalize(pmd_offer& offer)
0293 {
0294 if(offer.accept)
0295 {
0296 if( offer.server_max_window_bits == 0)
0297 offer.server_max_window_bits = 15;
0298
0299 if( offer.client_max_window_bits == 0 ||
0300 offer.client_max_window_bits == -1)
0301 offer.client_max_window_bits = 15;
0302 }
0303 }
0304
0305 }
0306 }
0307 }
0308 }
0309
0310 #endif