mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-21 06:45:39 -06:00
Core: WebSocket improvements
git-svn-id: svn://ultimatepp.org/upp/trunk@11798 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
7d44556c1a
commit
0f93a62163
3 changed files with 55 additions and 22 deletions
|
|
@ -607,6 +607,7 @@ class WebSocket {
|
|||
String host;
|
||||
IpAddrInfo addrinfo;
|
||||
bool ssl;
|
||||
String request_header;
|
||||
|
||||
String data;
|
||||
int data_pos;
|
||||
|
|
@ -646,6 +647,8 @@ class WebSocket {
|
|||
CLOSE = 0x8,
|
||||
PING = 0x9,
|
||||
PONG = 0xa,
|
||||
|
||||
MASK = 0x80,
|
||||
};
|
||||
|
||||
void Clear();
|
||||
|
|
@ -667,13 +670,14 @@ class WebSocket {
|
|||
|
||||
int GetFinIndex() const;
|
||||
|
||||
void SendRaw(int hdr, const String& data);
|
||||
void SendRaw(int hdr, const String& data, dword mask = 0);
|
||||
void Do0();
|
||||
|
||||
static String FormatBlock(const String& s);
|
||||
|
||||
public:
|
||||
WebSocket& NonBlocking(bool b = true) { socket->Timeout(b ? 0 : Null); return *this; }
|
||||
WebSocket& RequestHeader(const String& s) { request_header = s; return *this; }
|
||||
|
||||
bool IsBlocking() const { return IsNull(socket->GetTimeout()); }
|
||||
|
||||
|
|
@ -691,6 +695,7 @@ public:
|
|||
bool IsBinary() const { return current_opcode & BINARY; }
|
||||
|
||||
void SendText(const String& data) { SendRaw(FIN|TEXT, data); }
|
||||
void SendTextMasked(const String& data) { SendRaw(FIN|TEXT, data, MASK); }
|
||||
void SendBinary(const String& data) { SendRaw(FIN|BINARY, data); }
|
||||
void Ping(const String& data) { SendRaw(FIN|PING, data); }
|
||||
|
||||
|
|
@ -699,7 +704,7 @@ public:
|
|||
void Continue(const String& data) { SendRaw(0, data); }
|
||||
void Fin(const String& data) { SendRaw(FIN, data); }
|
||||
|
||||
void Close(const String& msg = Null);
|
||||
void Close(const String& msg = Null, bool wait_reply = false);
|
||||
bool IsOpen() const { return socket->IsOpen(); }
|
||||
bool IsClosed() const { return !IsOpen(); }
|
||||
|
||||
|
|
|
|||
|
|
@ -104,17 +104,18 @@ void WebSocket::SendRequest()
|
|||
for(int i = 0; i < 20; i++)
|
||||
h.Cat(Random());
|
||||
Out( // needs to be the first thing to sent after the connection is established
|
||||
"GET " + uri + " HTTP/1.1\r\n"
|
||||
"Host: " + host + "\r\n"
|
||||
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
|
||||
"Accept-Language: cs,en-US;q=0.7,en;q=0.3\r\n"
|
||||
"Sec-WebSocket-Version: 13\r\n"
|
||||
"Sec-WebSocket-Extensions: permessage-deflate\r\n"
|
||||
"Sec-WebSocket-Key: " + Base64Encode(h) + "\r\n"
|
||||
"Connection: keep-alive, Upgrade\r\n"
|
||||
"Pragma: no-cache\r\n"
|
||||
"Cache-Control: no-cache\r\n"
|
||||
"Upgrade: websocket\r\n\r\n"
|
||||
Nvl(request_header,
|
||||
"GET " + uri + " HTTP/1.1\r\n"
|
||||
"Host: " + host + "\r\n"
|
||||
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
|
||||
"Accept-Language: cs,en-US;q=0.7,en;q=0.3\r\n"
|
||||
"Sec-WebSocket-Version: 13\r\n"
|
||||
"Sec-WebSocket-Extensions: permessage-deflate\r\n"
|
||||
"Sec-WebSocket-Key: " + Base64Encode(h) + "\r\n"
|
||||
"Connection: keep-alive, Upgrade\r\n"
|
||||
"Pragma: no-cache\r\n"
|
||||
"Cache-Control: no-cache\r\n"
|
||||
"Upgrade: websocket\r\n\r\n")
|
||||
);
|
||||
opcode = HTTP_RESPONSE_HEADER;
|
||||
}
|
||||
|
|
@ -291,13 +292,13 @@ void WebSocket::FrameHeader()
|
|||
}
|
||||
}
|
||||
|
||||
void WebSocket::Close(const String& msg)
|
||||
void WebSocket::Close(const String& msg, bool wait_reply)
|
||||
{
|
||||
LLOG("Sending CLOSE");
|
||||
SendRaw(CLOSE|FIN, msg);
|
||||
close_sent = true;
|
||||
if(IsBlocking())
|
||||
while(!IsClosed() && !IsError() && socket->IsOpen())
|
||||
while((wait_reply ? IsOpen() : out_queue.GetCount()) && !IsError() && socket->IsOpen())
|
||||
Do0();
|
||||
}
|
||||
|
||||
|
|
@ -425,7 +426,7 @@ void WebSocket::Output()
|
|||
}
|
||||
}
|
||||
|
||||
void WebSocket::SendRaw(int hdr, const String& data)
|
||||
void WebSocket::SendRaw(int hdr, const String& data, dword mask)
|
||||
{
|
||||
if(IsError())
|
||||
return;
|
||||
|
|
@ -437,7 +438,7 @@ void WebSocket::SendRaw(int hdr, const String& data)
|
|||
header.Cat(hdr);
|
||||
int len = data.GetCount();
|
||||
if(len > 65535) {
|
||||
header.Cat(127);
|
||||
header.Cat(127 | mask);
|
||||
header.Cat(0);
|
||||
header.Cat(0);
|
||||
header.Cat(0);
|
||||
|
|
@ -456,11 +457,28 @@ void WebSocket::SendRaw(int hdr, const String& data)
|
|||
else
|
||||
header.Cat((int)len);
|
||||
|
||||
Out(header);
|
||||
if(mask) {
|
||||
byte Cle[4];
|
||||
for(int i = 0; i < 4; i++)
|
||||
header.Cat(Cle[i] = (byte)Random());
|
||||
|
||||
if(data.GetCount() == 0)
|
||||
return;
|
||||
Out(data);
|
||||
Out(header);
|
||||
|
||||
if(data.GetCount()) {
|
||||
StringBuffer buf(data.GetCount());
|
||||
int n = data.GetCount();
|
||||
for(int i = 0; i < n; i++)
|
||||
buf[i] = data[i] ^ Cle[i & 3];
|
||||
Out(buf);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Out(header);
|
||||
|
||||
if(data.GetCount() == 0)
|
||||
return;
|
||||
Out(data);
|
||||
}
|
||||
}
|
||||
|
||||
bool WebSocket::WebAccept(TcpSocket& socket_, HttpHeader& hdr)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
topic "WebSocket";
|
||||
[2 $$0,0#00000000000000000000000000000000:Default]
|
||||
[i448;a25;kKO9;2 $$1,0#37138531426314131252341829483380:class]
|
||||
[l288;2 $$2,2#27521748481378242620020725143825:desc]
|
||||
[0 $$3,0#96390100711032703541132217272105:end]
|
||||
|
|
@ -8,7 +9,6 @@ topic "WebSocket";
|
|||
[l288;i1121;b17;O9;~~~.1408;2 $$7,0#10431211400427159095818037425705:param]
|
||||
[i448;b42;O9;2 $$8,8#61672508125594000341940100500538:tparam]
|
||||
[b42;2 $$9,9#13035079074754324216151401829390:normal]
|
||||
[2 $$0,0#00000000000000000000000000000000:Default]
|
||||
[{_}
|
||||
[ {{10000@(113.42.0) [s0;%% [*@7;4 WebSocket]]}}&]
|
||||
[s3; &]
|
||||
|
|
@ -24,6 +24,11 @@ topic "WebSocket";
|
|||
is blocking mode.&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:Upp`:`:WebSocket`:`:RequestHeader`(const Upp`:`:String`&`): WbeSocket[@(0.0.255) `&
|
||||
]_[* RequestHeader]([@(0.0.255) const]_[_^Upp`:`:String^ String][@(0.0.255) `&]_[*@3 s])&]
|
||||
[s2;%% Overrides the HTTP the header to be used with Connect.&]
|
||||
[s3;%% &]
|
||||
[s4; &]
|
||||
[s5;:Upp`:`:WebSocket`:`:IsBlocking`(`)const: [@(0.0.255) bool]_[* IsBlocking]()_[@(0.0.255) c
|
||||
onst]&]
|
||||
[s2;%% Returns true if WebSocket is in the blocking mode.&]
|
||||
|
|
@ -82,6 +87,11 @@ calls Do, so there is no need to call it separately.&]
|
|||
[s2;%% Sends a single frame (non`-fragmented) text message.&]
|
||||
[s3;%% &]
|
||||
[s4; &]
|
||||
[s5;:Upp`:`:WebSocket`:`:SendTextMasked`(const Upp`:`:String`&`): [@(0.0.255) void]_[* Se
|
||||
ndTextMasked]([@(0.0.255) const]_[_^Upp`:`:String^ String][@(0.0.255) `&]_[*@3 data])&]
|
||||
[s2;%% Sends masked text message.&]
|
||||
[s3;%% &]
|
||||
[s4; &]
|
||||
[s5;:Upp`:`:WebSocket`:`:SendBinary`(const Upp`:`:String`&`): [@(0.0.255) void]_[* SendBi
|
||||
nary]([@(0.0.255) const]_[_^Upp`:`:String^ String][@(0.0.255) `&]_[*@3 data])&]
|
||||
[s2;%% Sends a single frame (non`-fragmented) binary message.&]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue