Исходник WebSocket сервер на Lua для общения

Randewoo

Потрачен
Автор темы
110
33
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Hai (привет по русски).
От нечего делать решил запились WS-сервер, а там уже и чАтИк)))***)))), но уперлось все в то, что мой ебучий мутант nginx при компиляции чето себе в жопу вставил и короче говоря не дает норм работать, пересобирать его я не хочу, ну потому что в натуре бля мутант ебаный под спидами.
Дак вот, ближе к делу.
Вот сурс:
Lua:
local copas = require('copas');
local cjson = require('cjson');
local sha = require('sha2');


local users = {};
local sockets = {};
local users_online = {};

local messages = {};

local get_login_by_id = {};
local get_login_by_token = {};

local server = require'websocket'.server.copas.listen
{
    port = 7777,
    protocols = {
        echo = function(ws)
            while true do
                local message = ws:receive()
                
                if (message) then
                    local json = cjson.decode(message);

                    local methods = {
                        ['user.join'] = function ()
                            if (not users[json.login:lower()]) then

                                local login = json.login:lower();
                                
                                if (login:len() < 5) then ws:send(message{code = 500});
                                elseif (login:len() > 15) then ws:send(message{code = 501});
                                elseif (not login:gsub('^[A-Za-z0-9]+$')) then ws:send(message{code = 502});
                                elseif (json.password:len() < 5) then ws:send(message{code = 503});
                                elseif (json.password:len() > 20) then ws:send(message{code = 504});
                                elseif (not json.password:gsub('^[A-Za-z0-9]+$')) then ws:send(message({code = 505}));
                                else
                                    local token = sha.sha256(os.clock() .. login .. os.clock());

                                    sockets[#sockets + 1] = ws;
                                    users_online[#users_online + 1] = login;
                                    get_login_by_token[token] = login;
                                    get_login_by_id[#users + 1] = login;

                                    users[login] = {
                                        socket = ws,
                                        id = #users + 1,
                                        login = login,
                                        password = sha.sha256(json.password),
                                        access_token = token,
                                        create_at = os.clock(),
                                        update_at = os.clock(),
                                        is_online = true,
                                        is_admin = false,
                                    };
                                    
                                    for _, v in paris(sockets) do
                                        v:send(message({
                                            status = true,
                                            code = 506,
                                            message_content = {
                                                sender = {
                                                    id = users[login],
                                                    login = login,
                                                },
                                            }
                                        }));
                                    end;

                                    ws:send(message({
                                        status = true,
                                        code = 507,
                                        user_content = {
                                            id = users[login].id,
                                            login = login,
                                            token = access_token,
                                        }
                                    }));
                                end;
                            else
                                if (users[login].is_online) then ws:send(message({code = 508}));
                                elseif (users[login].password ~= sha2.sha256(json.password)) then ws:send(message({code = 509}));
                                else
                                    local token = sha.sha256(os.clock() .. login .. os.clock());

                                    sockets[#sockets + 1] = ws;
                                    users_online[#users_online + 1] = login;
                                    get_login_by_token[token] = login;
                                    get_login_by_id[users[login].id] = login;

                                    users[login] = {
                                        socket = ws,
                                        id = users[login].id,
                                        login = users[login].login,
                                        password = users[login].password,
                                        access_token = token,
                                        create_at = users[login].create_at,
                                        update_at = os.clock(),
                                        is_online = true,
                                        is_admin = users[login].is_admin,
                                    };
                                    
                                    for _, v in paris(sockets) do
                                        v:send(message({
                                            status = true,
                                            code = 510,
                                            message_content = {
                                                sender = {
                                                    id = users[login],
                                                    login = login,
                                                }
                                            }
                                        }));
                                    end;

                                    ws:send(message({
                                        status = true,
                                        code = 511,
                                        user_content = {
                                            id = users[login].id,
                                            login = login,
                                            access_token = token,
                                        }
                                    }));
                                end;
                            end;
                        end,
                        ['user.leave'] = function ()
                            if (not get_login_by_token[json.access_token]) then ws:send(message({code = 500}));
                            else
                                local login = get_login_by_token[json.access_token];
                                users[login] = {
                                    socket = nil,
                                    id = users[login].id,
                                    login = users[login].login,
                                    password = users[login].password,
                                    access_token = users[login].access_token,
                                    create_at = users[login].create_at,
                                    update_at = os.clock(),
                                    is_online = false,
                                    is_admin = users[login].is_admin,
                                };
                                

                                for _, v in pairs(sockets) do
                                    if (v == ws) then sockets[v] = nil end;
                                end;

                                for _, v in pairs(users_online) do
                                    if (v == get_login_by_token[json.access_token]) then users_online[login] = nil end;
                                end;

                                for _, v in paris(sockets) do
                                    v:send(message({
                                        status = true,
                                        code = 501,
                                        message_content = {
                                            sender = {
                                                id = users_online[login].id,
                                                login = login,
                                            }
                                        }
                                    }));
                                end;

                                ws:send(message({
                                    status = true,
                                    code = 502,
                                }));

                                ws:close();

                                sockets[ws] = nil;
                                users_online[login] = nil;
                                get_login_by_id[login] = nil;
                                get_login_by_token[json.access_token] = nil;
                            end;
                        end,
                        ['message.send'] = function ()
                            if (not get_login_by_token[json.access_token]) then ws:send(message({code = 500}));
                            elseif (json.message:len() < 3) then ws:send(message({code = 501}));
                            elseif (json.message:len() > 120) then ws:send(message({code = 502}));
                            elseif (json.message == json.message:upper()) then ws:send(message({code = 503}));
                            elseif (os.clock() - users[get_login_by_token[json.access_token]].last_message < 5) then ws:send(message({code = 504}));

                                local login = get_login_by_token[json.access_token];

                                users[login] = {
                                    socket = ws,
                                    id = users[login].id,
                                    login = users[login].login,
                                    password = users[login].password,
                                    access_token = token,
                                    create_at = users[login].create_at,
                                    update_at = os.clock(),
                                    is_online = users[login].is_online,
                                    is_admin = users[login].is_admin,
                                    last_message = os.clock(),
                                };

                                messages[#messages + 1] = {
                                    id = #messages + 1,
                                    sender = {
                                        id = users[login].id,
                                    },
                                    ts = os.clock(),
                                }

                                for _, v in paris(sockets) do
                                    v:send(message({
                                        status = true,
                                        code = 505,
                                        message_content = {
                                            id = #messages,
                                            sender = {
                                                id = users[login].id,
                                            },
                                            ts = os.clock(),
                                        }
                                    }));
                                end;
                            end;
                        end,
                    }

                    if (type(methods) ~= 'table') then ws:send(message({code = 100}));
                    else methods[json.method]() end;
                end
            end
        end
    }
}

function message(array)
    local table = {
        response = {
            status = array.status or false,
            code = array.code or -1,
        },
        server = {
            time = os.time(),
        },
        users = {
            count = #users,
            online = online_count,
        }
    }

    for k, v in pairs(array) do
        if (not table.response[k]) then table.response[k] = v end;
    end;

    return cjson.encode(array);
end;

copas.loop()

Зависимости: copas, cjson, sha*
Ну, и я надеюсь, ты понимаешь, что эту вундервафлю надо запускать в качестве демона на сервере?
Запускать могешь так:
Bash:
nohup luajit *filename*.lua &
А если хочешь мониторить в консоль че оно там пиздит, то так:
Bash:
luajit *filename*.lua &

Сразу скажу!!! Если ты думаешь, что можешь собрать nginx/1.17.8, вместе с ngx_devel_kit-0.3.1, вместе с Lua 5.1.5 - то разочарую, нет.
Работать эта ебала будет, но через такую жопу, которая тебе и не снилась.
Рекомендую просто установить все из коробочки (box) и радоваться жизни:
Bash:
sudo apt-get install -y nginx-extras
Щас умные диванные войска подлетят и начнут хуесосить, а че ты FFI не подрубил!!!!!!!!!!!! фууу гей чмо!!!!!!!!!!!!
А нет, в этой оболочке ваш FFI в хуй не дул, сколько раз замерял, скорость такая же, если не больше на пару микро нано милли секунд. Короче говоря, нихуя не влияет это при работе с Linux, а уж тем более и с nginx, который как то переворачивает Lua туда сюда туда сюда туда сюда.

А дак вот!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Как подключаться к вундервафле (пример на JS):

HTML:
<!DOCTYPE html>
<html>
<head>
    <title>who)</title>
</head>
<body class="uk-background-secondary">
    <script type="text/javascript">
        var socket = new WebSocket('wss://telegraph.muxui.cc');

        socket.onopen = function() {
            socket.send(JSON.stringify({"method":"user.join","login":"muxui","password":"zmanevgaypidor228chmolox1337"}));
        };

        socket.onclose = function(event) {
            if (event.wasClean) {
                alert('Соединение закрыто чисто');
            } else {
                alert('Обрыв соединения');
            }
                alert('Код: ' + event.code + ' причина: ' + event.reason);
            };

        socket.onmessage = function(event) {
            alert('Сообщение з сервiру: ' + event.data);
        };

        socket.onerror = function(error) {
            alert("Ошибка " + error.message);
        };
    </script>
</body>
</html>


А вот, какие методы поддерживает:

1) user.join - присоединиться к чАтИкУ))**
Ему похуй, зареган ты или нет. Если не зареган - создаст акк, если нет - проверит пасс, и если все верно - выдаст токен (его надо сохранить!!!!!!!!)

2) user.leave - выйти з чатiку. Вообще, в башке мысль, что оно тригернет при событии onclose(), но похуям вообще, просто для красоты сделан.
Принимает access_token, который мы (кто мы то) получили при user.join

3) message.send - отправляет сообщение всем участникам чата, требуются параметры - access_token, [/ICODE]message[/ICODE].


Вот, вроде все.
Если что-то интересно будет - спрашивайте, отвечу, может даже помогу.
Все, я опять полетел в закат, прощайте!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

А и еще!!!! Хотел сказать что у Боба Марли вчера (ну для меня сегодня) был день рождения!
С Днем Рождения, легенда!!!!!!!!!!!!!!!!!!!!!!!!!!

Все. Пока.
А!!! И еще у этой хуйни нет БД, потому что нужна скорость (speed), да, и еще эта хуйня работает как демон, то есть 24/7 без перезагрузки, поэтому норм все будет не боись).
Все хранится в массивах и можно написать дроппер хуеппер чоб по крону вытаскивал файлы в бд/мемкэш/мускул/сарай/гараж.
 
Последнее редактирование: