data, session.self_closing_stream = data:gsub("^($", "%1>");
session.self_closing_stream = (session.self_closing_stream == 1)
data = filter("bytes/in", data);
if data then
local ok, err = stream:feed(data);
if ok then return; end
log("debug", "Received invalid XML (%s) %d bytes: %s", tostring(err), #data, data:sub(1, 300):gsub("[\r\n]+", " "):gsub("[%z\1-\31]", "_"));
session:close("not-well-formed");
end
end
return true;
end
local frameBuffer = "";
function session.data(data)
frameBuffer = frameBuffer .. data;
local frame, length = parse_frame(frameBuffer);
while frame do
frameBuffer = frameBuffer:sub(length + 1);
if not handle_frame(frame) then return; end
frame, length = parse_frame(frameBuffer);
end
end
function session.send(s)
conn:write(build_frame({ FIN = true, opcode = 0x01, data = tostring(s)}));
end
if c2s_timeout then
add_task(c2s_timeout, function ()
if session.type == "c2s_unauthed" then
session:close("connection-timeout");
end
end);
end
session.dispatch_stanza = stream_callbacks.handlestanza;
end
function listener.onincoming(conn, data)
local session = sessions[conn];
if session then
session.data(data);
else
listener.onconnect(conn, data);
session = sessions[conn];
session.data(data);
end
end
function listener.ondisconnect(conn, err)
local session = sessions[conn];
if session then
(session.log or log)("info", "Client disconnected: %s", err or "connection closed");
sm_destroy_session(session, err);
sessions[conn] = nil;
end
end
function listener.associate_session(conn, session)
sessions[conn] = session;
end
function handle_request(event, path)
local request, response = event.request, event.response;
if not request.headers.sec_websocket_key then
response.headers.content_type = "text/html";
return [[Websocket
It works! Now point your WebSocket client to this URL to connect to Prosody.
]];
end
local wants_xmpp = false;
(request.headers.sec_websocket_protocol or ""):gsub("([^,]*),?", function (proto)
if proto == "xmpp" then wants_xmpp = true; end
end);
if not wants_xmpp then
return 501;
end
response.conn:setlistener(listener);
response.status = "101 Switching Protocols";
response.headers.Upgrade = "websocket";
response.headers.Connection = "Upgrade";
response.headers.Sec_WebSocket_Accept = base64(sha1(request.headers.sec_websocket_key .. "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"));
response.headers.Sec_WebSocket_Protocol = "xmpp";
response.headers.Access_Control_Allow_Origin = cross_domain;
return "";
end
function module.add_host(module)
module:depends("http");
module:provides("http", {
name = "xmpp-websocket";
route = {
["GET"] = handle_request;
["GET /"] = handle_request;
};
});
end