source: skype/skype.c @ 77c1abe

Last change on this file since 77c1abe was 77c1abe, checked in by VMiklos <vmiklos@…>, at 2007-08-20T04:05:51Z

support receiving messages

  • Property mode set to 100644
File size: 6.7 KB
Line 
1/*
2 * This is the most simple possible BitlBee plugin. To use, compile it as
3 * a shared library and place it in the plugin directory:
4 *
5 * gcc -o example.so -shared example.c `pkg-config --cflags bitlbee`
6 * cp example.so /usr/local/lib/bitlbee
7 */
8#include <stdio.h>
9#include <bitlbee.h>
10
11#define SKYPE_PORT_DEFAULT "2727"
12
13struct skype_data
14{
15        struct im_connection *ic;
16        int fd;
17        char *txq;
18        int tx_len;
19        int r_inpa, w_inpa;
20        // when we receive a new message id, we query the handle, then the body
21        // store the handle here
22        // TODO: it would be nicer to use a hashmap for this or something
23        char *handle;
24};
25
26struct skype_away_state
27{
28        char *code;
29        char *full_name;
30};
31
32const struct skype_away_state skype_away_state_list[] =
33{
34        { "ONLINE",  "Online" },
35        { "SKYPEME",  "Skype Me" },
36        { "AWAY",   "Away" },
37        { "NA",    "Not available" },
38        { "DND",      "Do Not Disturb" },
39        { "INVISIBLE",      "Invisible" },
40        { "OFFLINE",      "Offline" }
41};
42
43static void skype_init( account_t *acc )
44{
45        set_t *s;
46
47        s = set_add( &acc->set, "port", SKYPE_PORT_DEFAULT, set_eval_int, acc );
48        s->flags |= ACC_SET_OFFLINE_ONLY;
49
50        s = set_add( &acc->set, "server", NULL, set_eval_account, acc );
51        s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY;
52}
53
54int skype_write( struct im_connection *ic, char *buf, int len )
55{
56        struct skype_data *sd = ic->proto_data;
57
58        printf("write(): %s", buf);
59        write( sd->fd, buf, len );
60
61        // TODO: error handling
62
63        return TRUE;
64}
65
66static gboolean skype_read_callback( gpointer data, gint fd, b_input_condition cond )
67{
68        struct im_connection *ic = data;
69        struct skype_data *sd = ic->proto_data;
70        char buf[1024];
71        int st;
72        char **lines, **lineptr, *line, *ptr;
73
74        if( sd->fd == -1 )
75                return FALSE;
76        st = read( sd->fd, buf, sizeof( buf ) );
77        if( st > 0 )
78        {
79                buf[st] = '\0';
80                printf("read(): '%s'\n", buf);
81                lines = g_strsplit(buf, "\n", 0);
82                lineptr = lines;
83                while((line = *lineptr))
84                {
85                        if(!strlen(line))
86                                break;
87                        printf("skype_read_callback() new line: '%s'\n", line);
88                        if(!strncmp(line, "USERS ", 6))
89                        {
90                                char **i;
91                                char **nicks;
92
93                                nicks = g_strsplit(line + 6, ", ", 0);
94                                i = nicks;
95                                while(*i)
96                                {
97                                        g_snprintf(buf, 1024, "GET USER %s ONLINESTATUS\n", *i);
98                                        skype_write( ic, buf, strlen( buf ) );
99                                        i++;
100                                }
101                                g_strfreev(nicks);
102                        }
103                        else if(!strncmp(line, "USER ", 5))
104                        {
105                                int flags = 0;
106                                char *status = strrchr(line, ' ');
107                                char *user = strchr(line, ' ');
108                                status++;
109                                ptr = strchr(++user, ' ');
110                                *ptr = '\0';
111                                ptr = g_strdup_printf("%s@skype.com", user);
112                                imcb_add_buddy(ic, ptr, NULL);
113                                if(strcmp(status, "OFFLINE") != 0)
114                                        flags |= OPT_LOGGED_IN;
115                                if(strcmp(status, "ONLINE") != 0 && strcmp(status, "SKYPEME") != 0)
116                                        flags |= OPT_AWAY;
117                                imcb_buddy_status(ic, ptr, flags, NULL, NULL);
118                                g_free(ptr);
119                        }
120                        else if(!strncmp(line, "CHATMESSAGE ", 12))
121                        {
122                                char *id = strchr(line, ' ');
123                                if(++id)
124                                {
125                                        char *info = strchr(id, ' ');
126                                        *info = '\0';
127                                        info++;
128                                        if(!strcmp(info, "STATUS RECEIVED"))
129                                        {
130                                                // new message, request its body
131                                                printf("new received message  #%s\n", id);
132                                                g_snprintf(buf, 1024, "GET CHATMESSAGE %s FROM_HANDLE\n", id);
133                                                skype_write( ic, buf, strlen( buf ) );
134                                                g_snprintf(buf, 1024, "GET CHATMESSAGE %s BODY\n", id);
135                                                skype_write( ic, buf, strlen( buf ) );
136                                        }
137                                        else if(!strncmp(info, "FROM_HANDLE ", 12))
138                                        {
139                                                info += 12;
140                                                // new handle
141                                                sd->handle = g_strdup_printf("%s@skype.com", info);
142                                                printf("new handle: '%s'\n", info);
143                                        }
144                                        else if(!strncmp(info, "BODY ", 5))
145                                        {
146                                                info += 5;
147                                                // new body
148                                                printf("<%s> %s\n", sd->handle, info);
149                                                imcb_buddy_msg(ic, sd->handle, info, 0, 0);
150                                                g_free(sd->handle);
151                                                sd->handle = NULL;
152                                        }
153                                }
154                        }
155                        lineptr++;
156                }
157                g_strfreev(lines);
158        }
159        else if( st == 0 || ( st < 0 && !sockerr_again() ) )
160        {
161                closesocket( sd->fd );
162                sd->fd = -1;
163
164                imcb_error( ic, "Error while reading from server" );
165                imc_logout( ic, TRUE );
166                return FALSE;
167        }
168
169        /* EAGAIN/etc or a successful read. */
170        return TRUE;
171}
172
173gboolean skype_start_stream( struct im_connection *ic )
174{
175        struct skype_data *sd = ic->proto_data;
176        char *buf;
177        int st;
178
179        if( sd->r_inpa <= 0 )
180                sd->r_inpa = b_input_add( sd->fd, GAIM_INPUT_READ, skype_read_callback, ic );
181
182        // download buddies
183        buf = g_strdup_printf("SEARCH FRIENDS\n");
184        st = skype_write( ic, buf, strlen( buf ) );
185        g_free(buf);
186        return st;
187}
188
189gboolean skype_connected( gpointer data, gint source, b_input_condition cond )
190{
191        struct im_connection *ic = data;
192        struct skype_data *sd = ic->proto_data;
193
194        imcb_connected(ic);
195        if( sd->fd < 0 )
196        {
197                imcb_error( ic, "Could not connect to server" );
198                imc_logout( ic, TRUE );
199                return FALSE;
200        }
201        return skype_start_stream(ic);
202}
203
204static void skype_login( account_t *acc )
205{
206        struct im_connection *ic = imcb_new( acc );
207        struct skype_data *sd = g_new0( struct skype_data, 1 );
208
209        ic->proto_data = sd;
210
211        imcb_log( ic, "Connecting" );
212        printf("%s:%d\n", acc->server, set_getint( &acc->set, "port"));
213        sd->fd = proxy_connect(acc->server, set_getint( &acc->set, "port" ), skype_connected, ic );
214        printf("sd->fd: %d\n", sd->fd);
215        /*imcb_add_buddy(ic, "test@skype.com", NULL);
216        imcb_buddy_status(ic, "test@skype.com", OPT_LOGGED_IN, NULL, NULL);
217        imcb_buddy_msg(ic, "test@skype.com", "test from skype plugin", 0, 0);*/
218
219        sd->ic = ic;
220}
221
222static void skype_logout( struct im_connection *ic )
223{
224        struct skype_data *sd = ic->proto_data;
225        g_free(sd);
226}
227
228static int skype_buddy_msg( struct im_connection *ic, char *who, char *message, int flags )
229{
230        char *buf, *ptr, *nick;
231        int st;
232
233        nick = g_strdup_printf("%s", who);
234        ptr = strchr(nick, '@');
235        if(ptr)
236                *ptr = '\0';
237
238        buf = g_strdup_printf("MESSAGE %s %s\n", nick, message);
239        g_free(nick);
240        st = skype_write( ic, buf, strlen( buf ) );
241        g_free(buf);
242
243        return st;
244}
245
246static void skype_set_away( struct im_connection *ic, char *state_txt, char *message )
247{
248}
249
250static GList *skype_away_states( struct im_connection *ic )
251{
252        static GList *l = NULL;
253        int i;
254       
255        if( l == NULL )
256                for( i = 0; skype_away_state_list[i].full_name; i ++ )
257                        l = g_list_append( l, (void*) skype_away_state_list[i].full_name );
258       
259        return l;
260}
261
262static void skype_add_buddy( struct im_connection *ic, char *who, char *group )
263{
264}
265
266static void skype_remove_buddy( struct im_connection *ic, char *who, char *group )
267{
268}
269
270void init_plugin(void)
271{
272        struct prpl *ret = g_new0( struct prpl, 1 );
273
274        ret->name = "skype";
275        ret->login = skype_login;
276        ret->init = skype_init;
277        ret->logout = skype_logout;
278        ret->buddy_msg = skype_buddy_msg;
279        ret->away_states = skype_away_states;
280        ret->add_buddy = skype_add_buddy;
281        ret->remove_buddy = skype_remove_buddy;
282        ret->away_states = skype_away_states;
283        ret->set_away = skype_set_away;
284        ret->handle_cmp = g_strcasecmp;
285        register_protocol( ret );
286}
Note: See TracBrowser for help on using the repository browser.