Chinaunix首页 | 论坛 | 博客
  • 博客访问: 663014
  • 博文数量: 109
  • 博客积分: 6081
  • 博客等级: 准将
  • 技术积分: 1318
  • 用 户 组: 普通用户
  • 注册时间: 2009-10-24 10:28
文章分类
文章存档

2011年(8)

2010年(39)

2009年(62)

分类: C/C++

2010-08-20 22:34:00

基于ikssemel 的gtalk的简单client
这个程序是基于ikssemel1.4 的包的iksroster 进行修改,用与登录gtalk,获取登录账号的roster,当接受到别人发送的message时,返回一个message 消息。

#include "common.h"
#include "iksemel.h"
#ifdef HAVE_GETOPT_LONG
#include
#endif
#ifdef _WIN32
#include
#endif
#ifdef HAVE_GETOPT_LONG
static struct option longopts[] = {
        { "backup", required_argument, 0, 'b' },
        { "restore", required_argument, 0, 'r' },
        { "file", required_argument, 0, 'f' },
        { "timeout", required_argument, 0, 't' },
        { "secure", 0, 0, 's' },
        { "sasl", 0, 0, 'a' },
        { "plain", 0, 0, 'p' },
        { "log", 0, 0, 'l' },
        { "help", 0, 0, 'h' },
        { "version", 0, 0, 'V' },
        { 0, 0, 0, 0 }
};
#endif
static char *shortopts = "b:r:f:t:saplhV";
static void
print_usage (void)
{
        puts ("Usage: iksroster [OPTIONS]\n"
                "This is a backup tool for your jabber roster.\n"
                " -b, --backup=JID    Download roster from the server.\n"
                " -r, --restore=JID   Upload roster to the server.\n"
                " -f, --file=FILE     Load/Save roster to this file.\n"
                " -t, --timeout=SECS  Set network timeout.\n"
                " -s, --secure        Use encrypted connection.\n"
                " -a, --sasl          Use SASL authentication.\n"
                " -p, --plain         Use plain text authentication.\n"
                " -l, --log           Print exchanged xml data.\n"
                " -h, --help          Print this text and exit.\n"
                " -V, --version       Print version and exit.\n"
#ifndef HAVE_GETOPT_LONG
                "(long options are not supported on your system)\n"
#endif
#ifndef HAVE_GNUTLS
                "(secure connections are not supported on your system)\n"
#endif
                "Report bugs to <iksemel-dev@jabberstudio.org>.");
}
/* stuff we keep per session */
struct session {
        iksparser *prs;
        iksid *acc;
        char *pass;
        int features;
        int authorized;
        int counter;
        int set_roster;
        int job_done;
};
/* precious roster we'll deal with */
iks *my_roster;
/* out packet filter */
iksfilter *my_filter;
/* connection time outs if nothing comes for this much seconds */
int opt_timeout = 30;
/* connection flags */
int opt_use_tls;
int opt_use_sasl;
int opt_use_plain;
int opt_log;
void
j_error (char *msg)
{
        fprintf (stderr, "iksroster: %s\n", msg);
        exit (2);
}
int
on_result (struct session *sess, ikspak *pak)
{
        iks *x;
        iks *pre;
        iks *y;
 //设置在线
 //iks_make_pres (enum ikshowtype show, const char *status)  //char *t(chat,away,xa,dnd,null)
 //  char *status

        pre=iks_make_pres (IKS_SHOW_CHAT, "online") ;
        iks_send (sess->prs, pre);
        iks_delete (pre);
        y=iks_make_session();
        iks_send (sess->prs, y);
        iks_delete (y);
        if (sess->set_roster == 0) {
                x = iks_make_iq (IKS_TYPE_GET, IKS_NS_ROSTER);
                iks_insert_attrib (x, "id", "roster");
                iks_send (sess->prs, x);
                iks_delete (x);
        } else {
                iks_insert_attrib (my_roster, "type", "set");
                iks_send (sess->prs, my_roster);
        }
        return IKS_FILTER_EAT;
}
int
on_stream (struct session *sess, int type, iks *node)
{
        sess->counter = opt_timeout;
        switch (type) {
                case IKS_NODE_START:
                        if (opt_use_tls && !iks_is_secure (sess->prs)) {
                                iks_start_tls (sess->prs);
                                break;
                        }
                        if (!opt_use_sasl) {
                                iks *x;
                                char *sid = NULL;
                                if (!opt_use_plain) sid = iks_find_attrib (node, "id");
                                x = iks_make_auth (sess->acc, sess->pass, sid);
                                iks_insert_attrib (x, "id", "auth");
                                //
                                //iks_insert_attrib (x, "mechanism","PLAIN");
                                //iks_insert_attrib(x,"ga:client-uses-full-bind-result","true");
                                //
                                iks_send (sess->prs, x);
                                iks_delete (x);
                        }
                        break;
                case IKS_NODE_NORMAL:
                        if (strcmp ("stream:features", iks_name (node)) == 0) {
                                sess->features = iks_stream_features (node);
                                if (opt_use_sasl) {
                                        if (opt_use_tls && !iks_is_secure (sess->prs)) break;
                                        if (sess->authorized) {
                                                iks *t;
                                                if (sess->features & IKS_STREAM_BIND) {
                                                        t = iks_make_resource_bind (sess->acc);
                                                        iks_send (sess->prs, t);
                                                        iks_delete (t);
                                                }
                                                if (sess->features & IKS_STREAM_SESSION) {
                                                        t = iks_make_session ();
                                                        iks_insert_attrib (t, "id", "auth");
                                                        iks_send (sess->prs, t);
                                                        iks_delete (t);
                                                }
                                        } else {
                                                if (sess->features & IKS_STREAM_SASL_MD5)
                                                        iks_start_sasl (sess->prs, IKS_SASL_DIGEST_MD5, sess->acc->user, sess->pass);
                                                else if (sess->features & IKS_STREAM_SASL_PLAIN)
                                                        iks_start_sasl (sess->prs, IKS_SASL_PLAIN, sess->acc->user, sess->pass);
                                        }
                                }
                        } else if (strcmp ("failure", iks_name (node)) == 0) {
                                j_error ("sasl authentication failed");
                        } else if (strcmp ("success", iks_name (node)) == 0) {
                                sess->authorized = 1;
                                iks_send_header (sess->prs, sess->acc->server);
                        } else {
                                ikspak *pak;
                                pak = iks_packet (node);
                                iks_filter_packet (my_filter, pak);
                                if (sess->job_done == 1) return IKS_HOOK;
                        }
                        break;
                case IKS_NODE_STOP:
                        j_error ("server disconnected");
                case IKS_NODE_ERROR:
                        j_error ("stream error");
        }
        if (node) iks_delete (node);
        return IKS_OK;
}
int
on_error (void *user_data, ikspak *pak)
{
        j_error ("authorization failed");
        return IKS_FILTER_EAT;
}
//int on_roster (struct session *sess, ikspak *pak)
//{
//      my_roster = pak->x;
//      sess->job_done = 1;
//      return IKS_FILTER_EAT;
//}
int
on_roster (struct session *sess, ikspak *pak)  //获取 roster之后,给其中一个人发一个 hello 的信息 。
{
        iks *child;
        my_roster = pak->x;
        //sess->job_done = 1;
        //return IKS_FILTER_EAT;
        //找出一个联系人
    child=iks_child(my_roster);
    child=iks_child(child);
    child=iks_next(child);
    char *jid=iks_find_attrib(child,"jid"); //roster中的一个用户
   
        //给该联系人发一个hell 信息
        //iks_make_msg (enum iksubtype type, const char *to, const char *body)   ////生成message 的 iks
    //char *body
    iks *msg=iks_make_msg(IKS_TYPE_CHAT,jid,"hello,test msg!");
    iks_insert_attrib (msg, "id", "msglai");  /// iks *iks_insert_attrib (iks *x, const char *name, const char *value);
    iks_send (sess->prs, msg);
    iks_delete (msg);
    return IKS_FILTER_EAT;
}
int
on_msg (struct session *sess, ikspak *pak)
{
        //根据ikspak 的类型判读
   if(pak->type==IKS_PAK_MESSAGE) //接收到的是message pak
    if(pak->subtype==IKS_TYPE_CHAT)
    {                               //给他会一个消息
    iks *msg=iks_make_msg(IKS_TYPE_CHAT,pak->from->full,"your msg ,I have received!");
    iks_insert_attrib(msg, "id", "msglai");  /// iks *iks_insert_attrib (iks *x, const char *name, const char *value);
    iks_send (sess->prs, msg);
    iks_delete (msg);
    }
    return IKS_FILTER_EAT;
}
int
on_presence(struct session *sess, ikspak *pak)
{
//iks_make_s10n (enum iksubtype type, const char *to, const char *msg) // char *msg
    iks *pre=iks_make_s10n(IKS_TYPE_SUBSCRIBED,pak->from->full,"wo shi lailai! hehehe");
    //iks_insert_attrib (pre, "id", "msglai");  /// iks *iks_insert_attrib (iks *x, const char *name, const char *value);
    iks_send (sess->prs, pre);
    iks_delete (pre);
    return IKS_FILTER_EAT;
}
void
on_log (struct session *sess, const char *data, size_t size, int is_incoming)
{
        if (iks_is_secure (sess->prs)) fprintf (stderr, "Sec");
        if (is_incoming) fprintf (stderr, "RECV"); else fprintf (stderr, "SEND");
        fprintf (stderr, "[%s]\n", data);
}
void
j_setup_filter (struct session *sess)
{
        if (my_filter) iks_filter_delete (my_filter);
        my_filter = iks_filter_new ();
        iks_filter_add_rule (my_filter, (iksFilterHook *) on_result, sess,
                IKS_RULE_TYPE, IKS_PAK_IQ,
                IKS_RULE_SUBTYPE, IKS_TYPE_RESULT,
                IKS_RULE_ID, "auth",
                IKS_RULE_DONE);
        iks_filter_add_rule (my_filter, on_error, sess,
                IKS_RULE_TYPE, IKS_PAK_IQ,
                IKS_RULE_SUBTYPE, IKS_TYPE_ERROR,
                IKS_RULE_ID, "auth",
                IKS_RULE_DONE);
        iks_filter_add_rule (my_filter, (iksFilterHook *) on_roster, sess,
                IKS_RULE_TYPE, IKS_PAK_IQ,
                IKS_RULE_SUBTYPE, IKS_TYPE_RESULT,
                IKS_RULE_ID, "roster",
                IKS_RULE_DONE);
                iks_filter_add_rule (my_filter, (iksFilterHook *) on_msg, sess,  //当返回时,  执行。
                IKS_RULE_TYPE, IKS_PAK_MESSAGE,
                IKS_RULE_SUBTYPE, IKS_TYPE_CHAT,
                IKS_RULE_FROM_PARTIAL, "",
                IKS_RULE_DONE);
        //当接受到 presence 请求加为好友时
 //
                iks_filter_add_rule (my_filter, (iksFilterHook *) on_presence, sess,  //当返回时,  执行。
                IKS_RULE_TYPE, IKS_PAK_PRESENCE,
                IKS_RULE_SUBTYPE, IKS_TYPE_SUBSCRIBE,
                //IKS_RULE_FROM_PARTIAL, "",
                IKS_RULE_DONE);
}

void
j_connect (char *jabber_id, char *pass, int set_roster)
{
        struct session sess;
        int e;
        memset (&sess, 0, sizeof (sess));
        sess.prs = iks_stream_new (IKS_NS_CLIENT, &sess, (iksStreamHook *) on_stream);
        if (opt_log) iks_set_log_hook (sess.prs, (iksLogHook *) on_log);
        sess.acc = iks_id_new (iks_parser_stack (sess.prs), jabber_id);
        if (NULL == sess.acc->resource) {
                /* user gave no resource name, use the default */
                char *tmp;
                tmp = iks_malloc (strlen (sess.acc->user) + strlen (sess.acc->server) + 9 + 3);
                sprintf (tmp, "", sess.acc->user, sess.acc->server, "iksroster");
                sess.acc = iks_id_new (iks_parser_stack (sess.prs), tmp);
                iks_free (tmp);
        }
        sess.pass = pass;
        sess.set_roster = set_roster;
        j_setup_filter (&sess);
        //e = iks_connect_tcp (sess.prs, sess.acc->server, IKS_JABBER_PORT);
        e = iks_connect_tcp (sess.prs,"talk.google.com", IKS_JABBER_PORT);
        switch (e) {
                case IKS_OK:
                        break;
                case IKS_NET_NODNS:
                        j_error ("hostname lookup failed");
                case IKS_NET_NOCONN:
                        j_error ("connection failed");
                default:
                        j_error ("io error");
        }
        sess.counter = opt_timeout;
        while (1) {
                e = iks_recv (sess.prs, 1);
                if (IKS_HOOK == e) break;
                if (IKS_NET_TLSFAIL == e) j_error ("tls handshake failed");
                if (IKS_OK != e) j_error ("io error");
                sess.counter--;
                if (sess.counter == 0) j_error ("network timeout");
        }
        iks_parser_delete (sess.prs);
}
int
main (int argc, char *argv[])
{
        char *from = NULL;
        char *to = NULL;
        char *file = NULL;
        char from_pw[128], to_pw[128];
        int c;
#ifdef HAVE_GETOPT_LONG
        int i;
        while ((c = getopt_long (argc, argv, shortopts, longopts, &i)) != -1) {
#else
        while ((c = getopt (argc, argv, shortopts)) != -1) {
#endif
                switch (c) {
                        case 'b':
                                from = optarg;
                                printf ("Password for %s: ", optarg);
                                fflush (stdout);
                                fgets (from_pw, 127, stdin);
                                strtok (from_pw, "\r\n");
                                break;
                        case 'r':
                                to = optarg;
                                printf ("Password for %s: ", optarg);
                                fflush (stdout);
                                fgets (to_pw, 127, stdin);
                                strtok (to_pw, "\r\n");
                                break;
                        case 'f':
                                file = strdup (optarg);
                                break;
                        case 't':
                                opt_timeout = atoi (optarg);
                                if (opt_timeout < 10) opt_timeout = 10;
                                break;
                        case 's':
                                if (!iks_has_tls ()) {
                                        puts ("Cannot make encrypted connections.");
                                        puts ("iksemel library is not compiled with GnuTLS support.");
                                        exit (1);
                                }
                                opt_use_tls = 1;
                                break;
                        case 'a':
                                opt_use_sasl = 1;
                                break;
                        case 'p':
                                opt_use_plain = 1;
                                opt_use_sasl = 0;
                                break;
                        case 'l':
                                opt_log = 1;
                                break;
                        case 'h':
                                print_usage ();
                                exit (0);
                        case 'V':
                                puts ("iksroster (iksemel) "VERSION);
                                exit (0);
                }
        }
        if (from == NULL && to == NULL) {
                puts ("What I'm supposed to do?");
                print_usage ();
                exit (1);
        }
        if (to && (from == NULL && file == NULL)) {
                puts ("Store which roster?");
                print_usage ();
                exit (1);
        }
#ifdef _WIN32
        WSADATA wsaData;
        WSAStartup (MAKEWORD (1,1), &wsaData);
#endif
        if (from) {
                j_connect (from, from_pw, 0);
                if (file) {
                        switch (iks_save (file, my_roster)) {
                                case IKS_OK:
                                        break;
                                case IKS_FILE_NOACCESS:
                                        j_error ("cannot write to file");
                                default:
                                        j_error ("file io error");
                        }
                }
        } else {
                switch (iks_load (file, &my_roster)) {
                        case IKS_OK:
                                break;
                        case IKS_FILE_NOFILE:
                                j_error ("file not found");
                        case IKS_FILE_NOACCESS:
                                j_error ("cannot read file");
                        default:
                                j_error ("file io error");
                }
        }
        if (to) {
                j_connect (to, to_pw, 1);
        }
#ifdef _WIN32
        WSACleanup ();
#endif
        return 0;
}
阅读(3309) | 评论(2) | 转发(0) |
给主人留下些什么吧!~~

zhouguangyou0072011-08-15 14:31:51

你好,看了你的文章,我觉得写的非常好,收藏了,谢谢!

laigq2010-08-21 17:37:33

希望学习 xmmp 协议。研究IM 的同学共同讨论学习。 谢谢!