639
|
1 A lot of people have tried to hack gaim, but haven't been able to because
|
|
2 the code is just so horrid. Well, the code isn't getting better anytime
|
1237
|
3 soon (I hate GNU indent), so to help all you would-be hackers help out
|
|
4 gaim, here's a brief tutorial on how gaim works. I'll quickly describe
|
|
5 the logical flow of things, then what you'll find in each of the source
|
|
6 files. As an added bonus, I'll try and describe as best I can how multiple
|
|
7 connections and multiple protocols work. Depending on how much I want
|
|
8 to avoid my final tomorrow I may even describe other parts of gaim that
|
|
9 I particularly want to brag about. Hopefully that's enough to get most
|
|
10 of you going.
|
639
|
11
|
708
|
12 If you're going to hack gaim, PLEASE, PLEASE PLEASE PLEASE send patches
|
|
13 against the absolute latest CVS. I get really annoyed when I get patches
|
1237
|
14 against the last released version, especially since I don't usually
|
|
15 have a copy of it on my computer, and gaim tends to change a lot between
|
708
|
16 versions. (I sometimes get annoyed when they're against CVS from 3 days
|
|
17 ago, but can't complain because it's usually my fault that I haven't
|
|
18 looked at the patch yet.) To get gaim from CVS (if you haven't already),
|
|
19 run the following commands:
|
|
20
|
774
|
21 $ export CVSROOT=:pserver:anonymous@cvs.gaim.sourceforge.net:/cvsroot/gaim
|
1237
|
22 $ cvs login (hit enter as the password)
|
708
|
23 $ cvs co gaim
|
|
24 (you'll see it getting all of the files)
|
|
25 $ cd gaim
|
|
26 $ ./gen
|
|
27
|
|
28 You'll now have your normal gaim tree with ./configure and all. (If you
|
|
29 want to make your life really simple, learn how CVS works. CVS is your
|
1237
|
30 friend.) To make a patch, just edit the files right there in that tree
|
|
31 (don't bother with two trees, or even two copies of the same file). Then
|
|
32 when you're ready to make your patch, simply run 'cvs diff -u >my.patch'
|
|
33 and send it off.
|
708
|
34
|
1237
|
35 This file was last modified by $Author: warmenhoven $ on
|
1653
|
36 $Date: 2001-03-27 16:01:29 -0500 (Tue, 27 Mar 2001) $.
|
684
|
37
|
639
|
38
|
|
39 PROGRAM FLOW
|
|
40 ============
|
|
41
|
979
|
42 Before gaim does anything you can see, it initializes itself, which is
|
1038
|
43 mostly just reading .gaimrc (handled by the functions in gaimrc.c) and
|
|
44 parsing command-line options. It then draws the login window by calling
|
|
45 show_login, and waits for input.
|
979
|
46
|
|
47 At the login window, when "Accounts" is clicked, account_editor() is
|
1237
|
48 called. This then displays all of the users and various information
|
|
49 about them. If the user clicks the "Signon" button instead, serv_login
|
|
50 is called.
|
979
|
51
|
|
52 When the "Sign on/off" button is clicked, serv_login is passed the
|
|
53 username and the password for the account. If the password length is
|
1237
|
54 zero (the password field is a character array rather than pointer so it
|
|
55 will not be NULL) then the Signon callback will prompt for the password
|
|
56 before calling serv_login. serv_login then signs in the user using the
|
|
57 appropriate protocol. We'll assume TOC for the rest of this discussion;
|
|
58 even the libfaim guys get scared by oscar.c, and I'll talk about the
|
|
59 PRPLs later.
|
979
|
60
|
|
61 After you're signed in (I'll skip that discussion - I doubt many people
|
|
62 are going to change the login process, since it pretty much just follows
|
|
63 PROTOCOL), Gaim draws the buddy list by calling show_buddy_list, and
|
1237
|
64 waits for input from two places: the server and the user. The first
|
|
65 place it gets input from after signon is usually the server, when the
|
|
66 server tells Gaim which buddies are signed on.
|
979
|
67
|
|
68 When there is information ready to be read from the server, toc_callback
|
|
69 is called (by GDK) to parse the incoming information. On an UPDATE,
|
|
70 serv_got_update is called, which takes care of things like notifying
|
|
71 conversation windows of the update if need be; notifying the plugins;
|
|
72 and finally, calling set_buddy.
|
|
73
|
1237
|
74 set_buddy is responsible for a lot of stuff, but most of it is done
|
|
75 implicitly. It's responsible for the sounds (which is just a call to
|
|
76 play_sound), but the biggest thing it does is call new_group_show and
|
|
77 new_buddy_show if necessary. There's only one group_show per group name,
|
|
78 even between connections, and only one buddy_show per group_show per
|
|
79 buddy name, even between connections. (If that's not confusing enough,
|
|
80 wait until I really start describing how the buddy list works.)
|
|
81
|
|
82 New connections happen the exact same way as described above. Each
|
|
83 aim_user can have one gaim_connection associated with it. aim_user and
|
|
84 gaim_connection both have a protocol field; gaim_connection's should
|
|
85 be constant once it is set. (I'll talk about the gaim_connection struct
|
|
86 more later.)
|
979
|
87
|
|
88 When the user opens a new conversation window, new_conversation is called.
|
|
89 That's easy enough. If there isn't a conversation with the person already
|
|
90 open (checked by calling find_conversation), show_conv is called to
|
|
91 create the new window. All sorts of neat things happen there, but it's
|
1038
|
92 mostly drawing the window. show_conv is the best place to edit the UI.
|
979
|
93
|
|
94 That's pretty much it for the quick tutorial. I know it wasn't much but
|
|
95 it's enough to get you started. Make sure you know GTK before you get too
|
|
96 involved. Most of the back-end stuff is pretty basic; most of gaim is GTK.
|
639
|
97
|
|
98
|
|
99 SOURCE FILES
|
|
100 ============
|
|
101
|
|
102 about.c:
|
|
103 Not much to say here, just a few basic functions.
|
|
104
|
|
105 aim.c:
|
|
106 This is where the main() function is. It takes care of a lot of the
|
|
107 initialization stuff, and showing the login window. It's pretty tiny
|
1237
|
108 and there's not really much to edit in it. This has some of the most
|
|
109 pointless functions, like gaim_setup, which optionally turns off sounds
|
|
110 on signon. A lot of this file should actually be part of other files.
|
639
|
111
|
1558
|
112 applet.c:
|
|
113 This controls most things that are related to the applet. I don't like
|
|
114 looking at this file because it still has functionsLikeThis. But at
|
|
115 least it doesn't have many of them anymore. Anyway, this file isn't
|
|
116 very big because there's really not much difference between the panel
|
|
117 version and the app version.
|
|
118
|
639
|
119 away.c:
|
|
120 This takes care of most of the away stuff: setting the away message
|
1237
|
121 (do_away_message); coming back (do_im_back); drawing the away window;
|
1558
|
122 etc. Away messages work really oddly due to multiple connections and
|
|
123 multiple protocols; I think there are really only two or three people
|
1619
|
124 who know how it works and I don't think any of us know why it works
|
1558
|
125 that way.
|
639
|
126
|
|
127 browser.c:
|
|
128 Code for opening a browser window. Most of the code is trying to deal
|
|
129 with Netscape. The most important function here is open_url. Have fun.
|
1237
|
130 (This file may give you problems with GTK 2.0, because it uses parts
|
|
131 of GDK that it's not supposed to know about.)
|
639
|
132
|
|
133 buddy.c:
|
1237
|
134 This takes care of not only nearly everything buddy-related (the
|
|
135 buddy lists, the window, etc.), but also a lot of the code flow and
|
|
136 util functions. Look for good things like find_buddy, set_buddy,
|
|
137 and signoff here.
|
639
|
138
|
|
139 buddy_chat.c:
|
|
140 This takes care of the buddy chat stuff. This used to be a lot bigger
|
|
141 until the chat and IM windows got merged in the code. Now it mostly
|
|
142 just takes care of chat-specific stuff, like ignoring people and
|
|
143 keeping track of who's in the room. This is also where the chat window
|
|
144 is created.
|
|
145
|
|
146 conversation.c:
|
|
147 This is where most of the functions dealing with the IM and chat windows
|
|
148 are hidden. It tries to abstract things as much as possible, but doesn't
|
|
149 do a very good job. This is also where things like "Enter sends" and
|
|
150 "Ctrl-{B/I/U/S}" options get carried out (look for send_callback). The
|
1237
|
151 chat and IM toolbar (with the B/I/U/S buttons) are both built from
|
|
152 the same function, build_conv_toolbar.
|
639
|
153
|
|
154 dialogs.c:
|
1237
|
155 A massive file with a lot of little utility functions. This is where all
|
|
156 of those little dialog windows are created. Things like the warn dialog
|
|
157 and the add buddy dialog are here. Not all of the dialogs in gaim are in
|
|
158 this file, though. But most of them are. This is also where do_import
|
|
159 is housed, to import buddy lists. (The actual buddy list parsing code
|
|
160 is in util.c for winaim lists and toc.c for gaim's own lists.)
|
639
|
161
|
|
162 gaimrc.c:
|
|
163 This controls everything about the .gaimrc file. There's not really much
|
|
164 to say about it; this is probably one of the better designed and easier
|
|
165 to follow files in gaim. The important functions are towards the bottom.
|
|
166
|
1558
|
167 gtkimhtml.c:
|
|
168 This is gaim's HTML widget. It replaced the old widget, GtkHtml (which
|
|
169 was different than GNOME's GtkHTML). It's self-contained (it doesn't
|
|
170 use any of gaim's code) and is actually a separate project from gaim
|
|
171 (but is maintained by Eric).
|
639
|
172
|
1558
|
173 gtkspell.c:
|
|
174 This controls spell checking. It's not a widget per se but it does have
|
|
175 some influence over the GtkText widget. It's a separate project from
|
|
176 gaim; if you have a patch for this file send it to the author (the
|
|
177 contact info is in the file).
|
639
|
178
|
|
179 gtkticker.c:
|
|
180 Syd, our resident GTK God, wrote a GtkWidget, GtkTicker. This is that
|
|
181 widget. It's cool, and it's tiny.
|
|
182
|
|
183 html.c:
|
|
184 Don't ask my why this is called html.c. Most of it is just grab_url,
|
|
185 which does like the name says; it downloads a URL to show in the
|
|
186 GtkHTML widget. http.c would be a more appropriate name, but that's OK.
|
|
187
|
|
188 idle.c:
|
1038
|
189 This file used to be entirely #if 0'd out of existance. However, thanks
|
|
190 to some very generous people who submitted patches, this takes care of
|
|
191 reporting idle time (imagine that). It's a pretty straight-forward file.
|
1237
|
192 This also takes care of the auto-away stuff.
|
639
|
193
|
979
|
194 multi.c:
|
|
195 This is the file that tries to take care of most of the major issues
|
|
196 with multiple connections. The best function in here by far is the
|
1237
|
197 account_editor(). auto_login() is also in here (I'm just reading multi.h
|
|
198 now...). account_editor is really the only function that the UI needs
|
|
199 to be concerned with.
|
979
|
200
|
639
|
201 oscar.c:
|
|
202 One big hack of copied code. This is supposed to be the libfaim tie-in
|
|
203 in gaim. Most of it is just copied straight from faimtest, the small
|
|
204 program that comes with libfaim. I'm not even sure how half of it works,
|
|
205 if that makes you feel any better.
|
|
206
|
|
207 perl.c:
|
|
208 This was basically copied straight from X-Chat through the power of
|
|
209 the GPL. Perl is the biggest, most confusing piece of C code I've ever
|
|
210 seen in my life (and keep in mind I'm a gaim hacker). I have a basic
|
|
211 idea of what's going on in it, but I couldn't tell you exactly. The
|
|
212 top half sets up perl and tells it what's going on and the bottom half
|
|
213 implements the AIM module.
|
|
214
|
|
215 plugins.c:
|
|
216 This is the "plugin plug", as the file states. This file is probably
|
|
217 the only file in all of gaim that at the top has all of the functions
|
|
218 and global and static variables named out for you. It makes reading
|
|
219 it a little easier, but not by much. A lot of the code in here deals
|
|
220 with the plugin window rather than the plugins themselves.
|
|
221
|
|
222 prefs.c:
|
|
223 The important function in here is build_prefs, but the most useful
|
|
224 function is gaim_button. build_prefs draws the window, and calls
|
|
225 gaim_button probably 30 or 40 times. (I don't really wanna run grep
|
|
226 | wc to count.) This is where you add the toggle button for gaim
|
|
227 preferences. It's very simple, and if you look at a couple of the
|
1237
|
228 calls to gaim_button you'll figure it out right away. The new prefs
|
|
229 window uses a CList instead of a Notebook, and there's a pretty bad
|
|
230 hack to get it to work. I won't tell you what though.
|
639
|
231
|
1038
|
232 prpl.c:
|
1237
|
233 This file is what lets gaim dynamically load protocols, sort of. All
|
|
234 of the actual dlopen(), dlsym() stuff is in plugins.c. But this
|
|
235 contains all of the functions that the protocol plugin needs to call,
|
|
236 and manages all of the protocols. It's a pretty simple file actually.
|
1038
|
237
|
639
|
238 proxy.c:
|
1237
|
239 Adam (of libfaim glory) got bored one day and rewrote this file, so
|
|
240 now everything actually works. The main function is proxy_connect,
|
|
241 which figures out which proxy you want to use (if you want to use one
|
|
242 at all) and passes off the data to the appropriate function. This file
|
|
243 should be pretty straight-forward.
|
639
|
244
|
|
245 rvous.c:
|
|
246 This was originally going to be the stuff for all of the Buddy Icon
|
|
247 and Voice Chat stuff, but I got really sick of protocol hacking really
|
|
248 quick. Now it only houses the file transfer stuff, which only works
|
1237
|
249 for TOC. ("Works" being a very subjective statement. This file needs
|
|
250 to be rewritten.)
|
639
|
251
|
|
252 server.c:
|
1237
|
253 This is where all of the differentiation between the different protocols
|
|
254 is done. Nearly everything that's network related goes through here
|
639
|
255 at one point or another. This has good things like serv_send_im and
|
|
256 serv_got_update. Most of it should be pretty self-explanatory.
|
|
257
|
|
258 sound.c:
|
1038
|
259 The main function in this file is play_sound, which plays one of 8
|
1237
|
260 (maybe 9?) sounds based on preferences. All that the rest of the code
|
|
261 should have to do is call play_sound(BUDDY_ARRIVE), for example, and
|
|
262 this file will take care of determining if a sound should be played
|
1038
|
263 and which file should be played.
|
639
|
264
|
|
265 ticker.c:
|
|
266 Syd is just so cool. I really can't get over it. He let me come
|
|
267 visit him at Netscape one day, and I got to see all of their toys
|
|
268 (don't worry, I'm under an NDA). Anyway, this file is for the buddy
|
|
269 ticker. This is also a damn cool file because it's got all of the
|
|
270 functions that you'd want right up at the top. Someday I want to be
|
|
271 as cool as Syd.
|
|
272
|
|
273 toc.c:
|
|
274 This handles everything TOC-related, including parsing gaim's buddy
|
|
275 list. Most of this file is toc_callback, which parses the incoming
|
1237
|
276 information from the server. I really don't like TOC though. (I've spent
|
|
277 waaayyyy too much time with TOC. I rewrote the signon process for this
|
|
278 file at one point, so that read was only called when data was pending.
|
|
279 Since then the TOC server has been blocking my IP (probably my own
|
|
280 stupid fault, sending bad strings or some such).)
|
639
|
281
|
|
282 util.c:
|
|
283 There's not really a lot of cohesion to this file; it's just a lot of
|
|
284 stuff that happened to be thrown into it for no apparent reason. None
|
|
285 of it is particularly tasty; it's all just utility functions. Just
|
|
286 like the name says.
|
|
287
|
1653
|
288 PRPL sources:
|
|
289 -------------
|
|
290
|
|
291 plugins/yay: Yahoo
|
|
292 All of the files in here were written by Eric. All of the .c and .h
|
|
293 files except yay.c are part of a library that Eric wrote, libyay.
|
|
294 yay.c is what interacts with gaim.
|
|
295
|
|
296 plugins/icq: ICQ (UDP v5)
|
|
297 All of the .c and .h files in here, with the exception of gaim_icq.c,
|
|
298 are part of ICQLib, by Bill Soudan and others. gaim_icq.c is what
|
|
299 interacts with gaim, and Eric wrote it. ICQLib is a fairly complete
|
|
300 implementation of the ICQ protocol, so if you want to add a new
|
|
301 feature you're probably going to be adding it to gaim_icq.c and not
|
|
302 to ICQLib.
|
|
303
|
|
304 plugins/msn: MSN
|
|
305 Rob wrote msn.c, and md5.c is a standard file. MSN doesn't use its
|
|
306 own library; all of the networking code is included inside of msn.c.
|
|
307
|
|
308 plugins/irc.c: IRC
|
|
309 Rob wrote irc.c, and since it is only one file it stands by itself.
|
|
310 All of the networking code is contained inside this file, as well as
|
|
311 the parts that interact with gaim.
|
|
312
|
|
313 plugins/jabber: Jabber
|
|
314 jabber.c was written by Adam Fritzler (the guy that wrote libfaim),
|
|
315 and is maintained by Eric. The other .c and .h files belong to
|
|
316 libxode and libjabber, which were written by the Jabber developers.
|
|
317
|
|
318 plugins/napster.c: Napster
|
|
319 Rob wrote napster.c, and since it is only one file it stands by
|
|
320 itself.
|
|
321
|
639
|
322
|
1237
|
323 HOW THE BUDDY LIST WORKS
|
|
324 ========================
|
|
325
|
|
326 The buddy list is a pain in the ass. Let me start off by saying that. The
|
|
327 most difficult part about getting gaim to do multiple connections was
|
|
328 the buddy list. In its current state it's very much like the UI for
|
|
329 0.10.x and earlier, which is what I was aiming for. However, the code
|
|
330 is completely different. And not much better.
|
|
331
|
|
332 All of the buddy list stuff is in buddy.c, so you'll only have to have
|
|
333 that one file open (and possibly gaim.h for the struct definitions). There
|
|
334 are two sets of functions: those that deal with the buddy lists, and
|
|
335 those that deal with the window. (I say lists because each connection
|
|
336 has their own buddy list, independent of the others, even though the UI
|
|
337 merges them.)
|
|
338
|
|
339 The buddy list functions work pretty much the same way they did before;
|
|
340 except now that each buddy and group belongs to a connection, things
|
|
341 like find_buddy take an additional argument, the connection you want to
|
|
342 search for the buddy in. Read gaim.h for a good list of them: find_buddy,
|
|
343 find_group, add_buddy, remove_buddy, remove_group.
|
|
344
|
|
345 The window is a lot more fun. There's really only one function that
|
|
346 does anything interesting, and that's set_buddy. (There's also things
|
|
347 like build_edit_tree, but that's boring.) set_buddy is called by
|
|
348 serv_got_update (and should only be called by that function) any time
|
|
349 a user signs on, signs off, goes away, comes back, goes idle, etc, etc,
|
|
350 etc. Various things happen depending on the new state of the buddy.
|
|
351
|
|
352 struct buddy has a member, present, which is set to either 0, 1, or
|
|
353 2. You can check if the buddy is online with "if (b->present)". This
|
|
354 becomes important. present is set to either 0 or 1 by serv_got_update,
|
|
355 or is not set at all. When the buddy is passed to set_buddy, if present
|
|
356 is 1 then set_buddy plays the BUDDY_ARRIVE sound, and sets present to 2,
|
|
357 to indicate it has already received notification of arrival. It then
|
|
358 does other signin-related stuff: setting the pixmap to the login icon;
|
|
359 updating the conversation windows; etc.
|
|
360
|
|
361 The most important thing it does though, if a buddy is present, is it
|
|
362 checks for the existance of the appropriate group_show and buddy_show for
|
|
363 that buddy. Each buddy must belong to a group. group_shows are based on
|
|
364 name; there can only be one group_show for each group name. buddy_shows
|
|
365 are based both on name and on group_show; there can only be one buddy_show
|
|
366 in a group_show for each name. However, there can be two buddy_shows
|
|
367 with the same name as long as they have different group_shows.
|
|
368
|
|
369 Each buddy_show has a GList of connections that has registered its related
|
|
370 buddy as being online. set_buddy makes sure that the connection that it's
|
|
371 being passed is part of the connlist for the buddy_show associated with
|
|
372 the struct buddy that it's passed (it helps to know your data structures).
|
|
373
|
|
374 If a buddy logs off (b->present == 0), and a buddy_show exists for
|
|
375 that buddy, then set_buddy will play the logoff sound, change the icon,
|
|
376 remove the connection from the connlist for the buddy_show, etc.
|
|
377
|
|
378 And that's how that works. For the buddy lists, connections own buddies;
|
|
379 for the window, the buddies own the connections. When the buddy_show
|
|
380 connlist count drops to zero it disappears from existance.
|
|
381
|
|
382
|
|
383 PLUGINS
|
|
384 =======
|
|
385
|
|
386 OK, so you want to load a plugin. You go through whatever UI (you
|
|
387 can read all about the UI in plugins.c or whereever). You finally get
|
|
388 to load_plugin, the meat of the plugins stuff (plugins can actually
|
|
389 call load_plugin themselves to load other plugins). load_plugin
|
|
390 is passed the full path to the plugin you want to load
|
|
391 (e.g. /usr/local/lib/gaim/irc.so).
|
|
392
|
|
393 load_plugin does a few things with that filename. The first is to see
|
|
394 if you've already loaded that plugin. If you have, load_plugin unloads
|
|
395 the one that is currently loaded. You might wonder why; it's because
|
|
396 the same plugin can't be loaded twice. If you call g_module_open on a
|
|
397 filename twice, both times it will return the same pointer, and both times
|
|
398 increment the reference count on the GModule * that it returns. This
|
|
399 means you really do have the same plugin twice, which fucks up the
|
|
400 callback system to no end. So it's better that you can only have it
|
|
401 loaded once at any given time.
|
|
402
|
|
403 Now that we're assured that we don't have this particular plugin loaded
|
|
404 yet, we better load it. g_module_open, baby. Much more portable than
|
|
405 dlopen(). In fact, for Linux it actually is the equivalent of dlopen()
|
|
406 (you can read the gmodule source and see for yourself). There's only one
|
|
407 quirk. It always logically ORs the options you pass with RTLD_GLOBAL,
|
|
408 which means that plugins share symbols. I haven't figured out yet if
|
|
409 this means just functions or variables too; but in either case make every
|
|
410 function and variable in your plugin static except for gaim_plugin_*(),
|
|
411 name(), and description(). It's good coding practice anyway.
|
|
412
|
|
413 So, assuming we didn't get NULL back from g_module_open, we then make sure
|
|
414 it's a valid gaim plugin by looking for and calling gaim_plugin_init,
|
|
415 courtesy g_module_symbol (g_module_symbol is actually what's portable
|
|
416 about gmodule as opposed to dl*; some BSD's require '_' prepended to
|
|
417 symbol names and g_module_symbol guarantees we do The Right Thing).
|
|
418
|
|
419 Assuming we've found gaim_plugin_init and it hasn't returned non-NULL
|
|
420 to us, we then add it to our list of plugins and go merrily about our way.
|
|
421
|
|
422 So when do the callbacks happen?! plugin_event, baby, plugin_event. Any
|
|
423 time you want to trigger a plugin event simply call plugin_even with the
|
|
424 parameters to be passed to any event handlers and you're set. plugin_event
|
|
425 then makes sure that any plugins waiting for the event get passed the
|
|
426 arguments properly and passes it on to perl.
|
|
427
|
|
428 Speaking of perl. If you really want to know how this works, you're
|
|
429 better off reading X-Chat's documentation of it, because it's better
|
|
430 than what I could provide.
|
|
431
|
|
432
|
1063
|
433 MULTIPLE CONNECTIONS AND PRPLS
|
|
434 ==============================
|
|
435
|
|
436 OK, let's start with the basics. There are users. Each user is contained
|
|
437 in an aim_user struct, and kept track of in the aim_users GList (GSList?).
|
|
438 Each aim_user has certain features: a username, a password, and user_info.
|
1237
|
439 It also has certain options, and the protocol it uses to sign on (kept
|
|
440 as an int which is #define'd in prpl.h). The way the management of the
|
|
441 users works is, there will (hopefully) only be one user for a given
|
|
442 screenname/ protocol pair (i.e. you may have two user warmenhoven's,
|
|
443 but they'll both have a different protocol number).
|
1063
|
444
|
1237
|
445 Now then, there are protocols that gaim knows about. Each protocol is
|
|
446 in a prpl struct and kept track of in the protocols GSList. The way the
|
|
447 management of the protocols is, there will only ever be one prpl per
|
|
448 numeric protocol. Each prpl defines a basic set of functions: login,
|
|
449 logout, send_im, etc. The prpl is responsible not only for handling
|
|
450 these functions, but also for calling the appropriate serv_got functions
|
|
451 (e.g. serv_got_update when a buddy comes online/goes offline/goes
|
|
452 idle/etc). It handles each of these on a per-connection basis.
|
1063
|
453
|
1237
|
454 So why's it called a PRPL? It stands for PRotocol PLugin. That means
|
|
455 that it's possible to dynamically add new protocols to gaim. However,
|
|
456 all protocols must be implemented the same way: by using a prpl struct
|
|
457 and being loaded, regardless of whether they are static or dynamic.
|
1063
|
458
|
1237
|
459 Here's how struct gaim_connection fits into all of this. At some point
|
|
460 the User (capitalized to indicate a person and not a name) will try to
|
|
461 sign on one of Their users. serv_login is then called for that user. It
|
|
462 searches for the prpl that is assigned to that user, and calls that prpl's
|
|
463 login function, passing it the aim_user struct that is attempting to sign
|
|
464 on. The prpl is then responsible for seeing that the gaim_connection
|
|
465 is created (by calling new_gaim_connection), and registering it as
|
|
466 being online (by calling account_online and passing it the aim_user and
|
|
467 gaim_connection structs). At that point, the aim_user and gaim_connection
|
|
468 structs have pointers to each other, and the gaim_connection struct has
|
|
469 a pointer to the prpl struct that it is using. The gaim_connections are
|
|
470 stored in the connections GSList. The way connection management works is,
|
|
471 there will always only be one gaim_connection per user, and the prpl that
|
|
472 the gaim_connection uses will be constant for the gaim_connection's life.
|
1063
|
473
|
1237
|
474 So at certain points the User is going to want to do certain things,
|
|
475 like send a message. They must send the message on a connection. So the UI
|
|
476 figures out which gaim_connection the User want to send a message on (for
|
|
477 our example), and calls serv_send_im, telling it which gaim_connection to
|
|
478 use, and the necessary information (who to send it to, etc). The serv_
|
|
479 function then calls the handler of the prpl of the connection for that
|
|
480 event (that was way too many prepositions). OK, each prpl has a send_im
|
|
481 function. Each connection has a prpl. so you call gc->prpl->send_im and
|
|
482 pass it the connection and all the necessary info. And that's how things
|
|
483 get done.
|
1063
|
484
|
|
485 I hope some of that made sense. Looking back at it it makes absolutely no
|
|
486 sense to me. Thank god I wrote the code; otherwise I'm sure I'd be lost.
|