iswydt.vala
author Stiletto <blasux@blasux.ru>
Wed, 24 Oct 2012 00:37:31 +0400
changeset 7 a49fb1ec5e2a
parent 3 dd7a02c6d476
child 12 d3e36b368fc5
permissions -rw-r--r--
Send a reason when interrupted by sigint


class Connection : Object {
    public Lm.Connection cn;
    public string jid;
    public string password;
    public string resource;
    public string server;
	public int port;
    public bool ssl;

    public enum State {
        DISCONNECTED,
        CONNECTING,
        AUTHENTICATING,
        CONNECTED
    }
        
    protected State _state;

    public State state {
        get { return _state; }
    }

    public Gee.ArrayList<Module> modules;

    public signal void state_changed(State old_state, State new_state, string description);
    public signal void check_time();
    protected void _change_state(State new_state, string description) {
        var old_state = this._state;
        if (old_state != new_state) {
            this._state = new_state;
            stderr.printf("State changed %s -> %s : %s\n",old_state.to_string(), new_state.to_string(), description);
            state_changed(old_state, new_state, description);
        } else
            stderr.printf("State not changed %s : %s\n",old_state.to_string(), description);
    }

    public Connection(Config cfg) {
        this.modules = new Gee.ArrayList<Module>();
        this.jid = cfg["server","jid"];
        this.password = cfg["server","password"];

        this.server = cfg.get_default("server", "server", this.jid.split("@",2)[1]);

        if (cfg.has_key("server", "port"))
            this.port = cfg["server", "port"].to_int();
        else
            this.port = Lm.Connection.DEFAULT_PORT;

        this.ssl = (cfg.get_default("server", "ssl", "yes")=="yes");

        this.resource = cfg.get_default("server", "resource", "iswydt");

        cn = new Lm.Connection(this.server);
        cn.set_disconnect_function((connection, reason) => {
            stderr.printf("Disconnected: %s\n",reason.to_string());
            _change_state(State.DISCONNECTED,reason.to_string());
        }, null);
        var msg_handler = new Lm.MessageHandler((handler, connection, message) => {
            stdout.printf("Got msg\n");
            var node = message.get_node();
            var body = node.find_child("body");
            if (body!=null) {
                stdout.printf("MSG %s to %s: %s\n", node.get_attribute("from"), node.get_attribute("to"), body.get_value());
            }
            return Lm.HandlerResult.ALLOW_MORE_HANDLERS;
        }, null);
        cn.register_message_handler(msg_handler, Lm.MessageType.MESSAGE, Lm.HandlerPriority.NORMAL);
        /*var muc_handler = new Lm.MessageHandler((handler, connection, message) => {
            var node = message.node;
            var from = node.get_attribute("from");
            if (from != null) {
                var froms = from.split("/",2);
                //stdout.printf("From: %s %s\n",node.to_string(),message.get_type().to_string());
                if (rooms.has_key(froms[0])) {
                    return rooms[froms[0]].muc_handler(handler, connection, message);
                }
            }
            return Lm.HandlerResult.ALLOW_MORE_HANDLERS;
        }, null);
        cn.register_message_handler(muc_handler, Lm.MessageType.MESSAGE, Lm.HandlerPriority.NORMAL);
        cn.register_message_handler(muc_handler, Lm.MessageType.PRESENCE, Lm.HandlerPriority.NORMAL);
        cn.register_message_handler(muc_handler, Lm.MessageType.IQ, Lm.HandlerPriority.NORMAL);*/
        state_changed.connect( (olds, news, desc) => {
            if (news == Connection.State.CONNECTED) {
                cn.send_raw("<message to='stiletto@stiletto.name'><body>ТХБ</body></message>");
                /*var room = new Conference(this, "говнохост@conference.blasux.ru", "Ζαλυπα");
                room.join("Oh hai");
                this.rooms[room.jid] = room;*/
            }
        });
        check_time.connect( () => {
            if (_state == State.DISCONNECTED)
                open();
        });
    }
    public void add_module(Module module) {
        modules.add(module);
    }
    public void open() {

        stderr.printf("Connecting to %s:%d as %s\n",server,port,jid);
        cn.set_port(port);
        cn.set_jid(jid);
        _change_state(State.CONNECTING,"");
        try {
            var result = cn.open((connection, consuc) => {
                stderr.printf("Connection success: %s\n",consuc.to_string());
                if (consuc) {
                    _change_state(State.AUTHENTICATING,"");
                    stderr.printf("Authing\n");
                    cn.authenticate(jid.split("@",2)[0],password, resource, (connection, authsuc) => {
                        stderr.printf("Auth success: %s\n",authsuc.to_string());
                        if (authsuc) {
                            _change_state(State.CONNECTED,"");
                        } else
                            cn.close();
                    }, null);
                } else {
                    _change_state(State.DISCONNECTED, "Connection not successful");
                }
            }, null);
            if (!result)
                _change_state(State.DISCONNECTED, "Open failed");
        } catch (Error e) {
            stderr.printf("Error: %s\n", e.message);
            _change_state(State.DISCONNECTED, e.message);
        }
    }
    public void close(string reason) {
        if ((state==State.CONNECTED)&&(reason != null)) {
            var prs = new Lm.Message(null, Lm.MessageType.PRESENCE);
            prs.node.set_attribute("type","unavailable");
            prs.node.add_child("status",reason);
            cn.send(prs);
        }
        cn.close();
    }
}
    

static Connection account;
static MainLoop loop;

int main(string[] args) {
    if (args.length<2) {
        stderr.printf("Usage: %s <config file>\n",args[0]);
        return 1;
    }
    Log.set_handler("Muc", (LogLevelFlags)65535, (domain, levels, message) => {
        stderr.printf("--- %s\n", message);
    });
    Log.set_handler("muc_log", (LogLevelFlags)65535, (domain, levels, message) => {
        stderr.printf("--- %s\n", message);
    });
    log("LM", LogLevelFlags.LEVEL_DEBUG, "HATE HATE");
    var cfg = new Config.from_file(args[1]);
    loop = new MainLoop();
    account = new Connection(cfg);
    //account.open();
    stdout.printf("Fuck yeah\n");
    var checktimer = new TimeoutSource(2000);
    checktimer.set_callback(() => {
        account.check_time();
        //stderr.printf("TimeoutSource OLOLO\n");
        return true;
    });
    checktimer.attach(loop.get_context());

    account.add_module(new ModuleMuc(cfg, account));
    account.add_module(new ModuleMucLog(cfg, account));

    Posix.sigaction_t action = Posix.sigaction_t();
    action.sa_handler = ((i) => {
        if (account.state != Connection.State.CONNECTED)
            loop.quit();
        else {
            account.state_changed.connect( (olds, news, desc) => {
                if (news == Connection.State.DISCONNECTED)
                    loop.quit();
            });
            account.close("Received SIGINT");
        }
    });
    Posix.sigaction(Posix.SIGINT, action, null);

    loop.run();
    return 0;
}