Mercurial > pidgin.yaz
comparison src/protocols/sametime/meanwhile/channel.c @ 11943:0110fc7c6a8a
[gaim-migrate @ 14234]
Bringing things up to date with the last Meanwhile release, 0.5.0 and the last
gaim-meanwhile plugin release, 1.2.5 (which should be the last plugin release
against oldstatus, if all goes well with HEAD and no major bugs crop up)
It builds, so that's a start. The status bits that have been empty since the
first import of the sametime stuff are still empty, but I'm going to try and
fill those in tomorrow. I've decided to try and start using HEAD actively, to
encourage me to get this freaking prpl fully functional.
committer: Tailor Script <tailor@pidgin.im>
author | Christopher O'Brien <siege@pidgin.im> |
---|---|
date | Wed, 02 Nov 2005 03:39:03 +0000 |
parents | 3ef77720e577 |
children |
comparison
equal
deleted
inserted
replaced
11942:a24cfe32961a | 11943:0110fc7c6a8a |
---|---|
57 struct mwOpaque addtl_create; | 57 struct mwOpaque addtl_create; |
58 struct mwOpaque addtl_accept; | 58 struct mwOpaque addtl_accept; |
59 | 59 |
60 /** all those supported ciphers */ | 60 /** all those supported ciphers */ |
61 GHashTable *supported; | 61 GHashTable *supported; |
62 guint16 offered_policy; /**< @see enum mwEncryptPolicy */ | |
63 guint16 policy; /**< @see enum mwEncryptPolicy */ | |
62 | 64 |
63 /** cipher information determined at channel acceptance */ | 65 /** cipher information determined at channel acceptance */ |
64 struct mwCipherInstance *cipher; | 66 struct mwCipherInstance *cipher; |
65 | 67 |
66 /** statistics table */ | 68 /** statistics table */ |
96 default: return "UNKNOWN"; | 98 default: return "UNKNOWN"; |
97 } | 99 } |
98 } | 100 } |
99 | 101 |
100 | 102 |
101 static void state(struct mwChannel *chan, enum mwChannelState state) { | 103 static void state(struct mwChannel *chan, enum mwChannelState state, |
104 guint32 err_code) { | |
105 | |
102 g_return_if_fail(chan != NULL); | 106 g_return_if_fail(chan != NULL); |
103 | 107 |
104 if(chan->state == state) return; | 108 if(chan->state == state) return; |
105 | 109 |
106 chan->state = state; | 110 chan->state = state; |
107 g_message("channel 0x%08x state: %s", chan->id, state_str(state)); | 111 |
112 if(err_code) { | |
113 g_message("channel 0x%08x state: %s (0x%08x)", | |
114 chan->id, state_str(state), err_code); | |
115 } else { | |
116 g_message("channel 0x%08x state: %s", chan->id, state_str(state)); | |
117 } | |
108 } | 118 } |
109 | 119 |
110 | 120 |
111 static gpointer get_stat(struct mwChannel *chan, | 121 static gpointer get_stat(struct mwChannel *chan, |
112 enum mwChannelStatField field) { | 122 enum mwChannelStatField field) { |
164 chan->supported = g_hash_table_new_full(g_direct_hash, g_direct_equal, | 174 chan->supported = g_hash_table_new_full(g_direct_hash, g_direct_equal, |
165 NULL, sup_free); | 175 NULL, sup_free); |
166 | 176 |
167 g_hash_table_insert(cs->map, GUINT_TO_POINTER(id), chan); | 177 g_hash_table_insert(cs->map, GUINT_TO_POINTER(id), chan); |
168 | 178 |
169 state(chan, mwChannel_WAIT); | 179 state(chan, mwChannel_WAIT, 0); |
170 | 180 |
171 return chan; | 181 return chan; |
172 } | 182 } |
173 | 183 |
174 | 184 |
184 do { | 194 do { |
185 id = ++cs->counter; | 195 id = ++cs->counter; |
186 } while(g_hash_table_lookup(cs->map, GUINT_TO_POINTER(id))); | 196 } while(g_hash_table_lookup(cs->map, GUINT_TO_POINTER(id))); |
187 | 197 |
188 chan = mwChannel_newIncoming(cs, id); | 198 chan = mwChannel_newIncoming(cs, id); |
189 state(chan, mwChannel_INIT); | 199 state(chan, mwChannel_INIT, 0); |
190 | 200 |
191 return chan; | 201 return chan; |
192 } | 202 } |
193 | 203 |
194 | 204 |
265 | 275 |
266 void mwChannel_setProtoVer(struct mwChannel *chan, guint32 proto_ver) { | 276 void mwChannel_setProtoVer(struct mwChannel *chan, guint32 proto_ver) { |
267 g_return_if_fail(chan != NULL); | 277 g_return_if_fail(chan != NULL); |
268 g_return_if_fail(chan->state == mwChannel_INIT); | 278 g_return_if_fail(chan->state == mwChannel_INIT); |
269 chan->proto_ver = proto_ver; | 279 chan->proto_ver = proto_ver; |
280 } | |
281 | |
282 | |
283 guint16 mwChannel_getEncryptPolicy(struct mwChannel *chan) { | |
284 g_return_val_if_fail(chan != NULL, 0x00); | |
285 return chan->policy; | |
270 } | 286 } |
271 | 287 |
272 | 288 |
273 guint32 mwChannel_getOptions(struct mwChannel *chan) { | 289 guint32 mwChannel_getOptions(struct mwChannel *chan) { |
274 g_return_val_if_fail(chan != NULL, 0x00); | 290 g_return_val_if_fail(chan != NULL, 0x00); |
343 msg->proto_type = chan->proto_type; | 359 msg->proto_type = chan->proto_type; |
344 msg->proto_ver = chan->proto_ver; | 360 msg->proto_ver = chan->proto_ver; |
345 msg->options = chan->options; | 361 msg->options = chan->options; |
346 mwOpaque_clone(&msg->addtl, &chan->addtl_create); | 362 mwOpaque_clone(&msg->addtl, &chan->addtl_create); |
347 | 363 |
348 for(list = l = mwChannel_getSupportedCipherInstances(chan); l; l = l->next) { | 364 list = mwChannel_getSupportedCipherInstances(chan); |
349 struct mwEncryptItem *ei = mwCipherInstance_newItem(l->data); | |
350 msg->encrypt.items = g_list_append(msg->encrypt.items, ei); | |
351 } | |
352 if(list) { | 365 if(list) { |
353 msg->encrypt.mode = 0x1000; | 366 /* offer what we have */ |
354 msg->encrypt.extra = 0x1000; | 367 for(l = list; l; l = l->next) { |
355 } | 368 struct mwEncryptItem *ei = mwCipherInstance_offer(l->data); |
356 g_list_free(list); | 369 msg->encrypt.items = g_list_append(msg->encrypt.items, ei); |
370 } | |
371 | |
372 /* we're easy to get along with */ | |
373 chan->offered_policy = mwEncrypt_WHATEVER; | |
374 g_list_free(list); | |
375 | |
376 } else { | |
377 /* we apparently don't support anything */ | |
378 chan->offered_policy = mwEncrypt_NONE; | |
379 } | |
380 | |
381 msg->encrypt.mode = chan->offered_policy; | |
382 msg->encrypt.extra = chan->offered_policy; | |
357 | 383 |
358 ret = mwSession_send(chan->session, MW_MESSAGE(msg)); | 384 ret = mwSession_send(chan->session, MW_MESSAGE(msg)); |
359 mwMessage_free(MW_MESSAGE(msg)); | 385 mwMessage_free(MW_MESSAGE(msg)); |
360 | 386 |
361 state(chan, (ret)? mwChannel_ERROR: mwChannel_WAIT); | 387 state(chan, (ret)? mwChannel_ERROR: mwChannel_WAIT, ret); |
362 | 388 |
363 return ret; | 389 return ret; |
364 } | 390 } |
365 | 391 |
366 | 392 |
367 static void channel_open(struct mwChannel *chan) { | 393 static void channel_open(struct mwChannel *chan) { |
368 state(chan, mwChannel_OPEN); | 394 state(chan, mwChannel_OPEN, 0); |
369 timestamp_stat(chan, mwChannelStat_OPENED_AT); | 395 timestamp_stat(chan, mwChannelStat_OPENED_AT); |
370 flush_channel(chan); | 396 flush_channel(chan); |
371 } | 397 } |
372 | 398 |
373 | 399 |
374 int mwChannel_accept(struct mwChannel *chan) { | 400 int mwChannel_accept(struct mwChannel *chan) { |
375 struct mwSession *session; | 401 struct mwSession *session; |
376 struct mwMsgChannelAccept *msg; | 402 struct mwMsgChannelAccept *msg; |
403 struct mwCipherInstance *ci; | |
404 | |
377 int ret; | 405 int ret; |
378 | 406 |
379 g_return_val_if_fail(chan != NULL, -1); | 407 g_return_val_if_fail(chan != NULL, -1); |
380 g_return_val_if_fail(mwChannel_isIncoming(chan), -1); | 408 g_return_val_if_fail(mwChannel_isIncoming(chan), -1); |
381 g_return_val_if_fail(chan->state == mwChannel_WAIT, -1); | 409 g_return_val_if_fail(chan->state == mwChannel_WAIT, -1); |
390 msg->service = chan->service; | 418 msg->service = chan->service; |
391 msg->proto_type = chan->proto_type; | 419 msg->proto_type = chan->proto_type; |
392 msg->proto_ver = chan->proto_ver; | 420 msg->proto_ver = chan->proto_ver; |
393 mwOpaque_clone(&msg->addtl, &chan->addtl_accept); | 421 mwOpaque_clone(&msg->addtl, &chan->addtl_accept); |
394 | 422 |
395 /* if nobody selected a cipher, we'll just pick the first that comes | 423 ci = chan->cipher; |
396 handy */ | 424 |
397 if(chan->supported) { | 425 if(! ci) { |
398 GList *l = mwChannel_getSupportedCipherInstances(chan); | 426 /* automatically select a cipher if one hasn't been already */ |
399 if(l) { | 427 |
400 mwChannel_selectCipherInstance(chan, l->data); | 428 switch(chan->offered_policy) { |
401 g_list_free(l); | 429 case mwEncrypt_NONE: |
402 } else { | |
403 mwChannel_selectCipherInstance(chan, NULL); | 430 mwChannel_selectCipherInstance(chan, NULL); |
431 break; | |
432 | |
433 case mwEncrypt_RC2_40: | |
434 ci = get_supported(chan, mwCipher_RC2_40); | |
435 mwChannel_selectCipherInstance(chan, ci); | |
436 break; | |
437 | |
438 case mwEncrypt_RC2_128: | |
439 ci = get_supported(chan, mwCipher_RC2_128); | |
440 mwChannel_selectCipherInstance(chan, ci); | |
441 break; | |
442 | |
443 case mwEncrypt_WHATEVER: | |
444 case mwEncrypt_ALL: | |
445 default: | |
446 { | |
447 GList *l, *ll; | |
448 | |
449 l = mwChannel_getSupportedCipherInstances(chan); | |
450 if(l) { | |
451 /* nobody selected a cipher, so we'll just pick the last in | |
452 the list of available ones */ | |
453 for(ll = l; ll->next; ll = ll->next); | |
454 ci = ll->data; | |
455 g_list_free(l); | |
456 | |
457 mwChannel_selectCipherInstance(chan, ci); | |
458 | |
459 } else { | |
460 /* this may cause breakage, but there's really nothing else | |
461 we can do. They want something we can't provide. If they | |
462 don't like it, then they'll error the channel out */ | |
463 mwChannel_selectCipherInstance(chan, NULL); | |
464 } | |
465 } | |
404 } | 466 } |
405 } | 467 } |
406 | 468 |
469 msg->encrypt.mode = chan->policy; /* set in selectCipherInstance */ | |
470 msg->encrypt.extra = chan->offered_policy; | |
471 | |
407 if(chan->cipher) { | 472 if(chan->cipher) { |
408 mwCipherInstance_accept(chan->cipher); | 473 msg->encrypt.item = mwCipherInstance_accept(chan->cipher); |
409 | |
410 msg->encrypt.item = mwCipherInstance_newItem(chan->cipher); | |
411 | |
412 /** @todo figure out encrypt modes */ | |
413 msg->encrypt.mode = 0x1000; | |
414 msg->encrypt.extra = 0x1000; | |
415 } | 474 } |
416 | 475 |
417 ret = mwSession_send(session, MW_MESSAGE(msg)); | 476 ret = mwSession_send(session, MW_MESSAGE(msg)); |
418 mwMessage_free(MW_MESSAGE(msg)); | 477 mwMessage_free(MW_MESSAGE(msg)); |
419 | 478 |
420 if(ret) { | 479 if(ret) { |
421 state(chan, mwChannel_ERROR); | 480 state(chan, mwChannel_ERROR, ret); |
422 } else { | 481 } else { |
423 channel_open(chan); | 482 channel_open(chan); |
424 } | 483 } |
425 | 484 |
426 return ret; | 485 return ret; |
482 int ret; | 541 int ret; |
483 | 542 |
484 /* may make this not a warning in the future */ | 543 /* may make this not a warning in the future */ |
485 g_return_val_if_fail(chan != NULL, 0); | 544 g_return_val_if_fail(chan != NULL, 0); |
486 | 545 |
487 state(chan, reason? mwChannel_ERROR: mwChannel_DESTROY); | 546 state(chan, reason? mwChannel_ERROR: mwChannel_DESTROY, reason); |
488 | 547 |
489 session = chan->session; | 548 session = chan->session; |
490 g_return_val_if_fail(session != NULL, -1); | 549 g_return_val_if_fail(session != NULL, -1); |
491 | 550 |
492 cs = mwSession_getChannels(session); | 551 cs = mwSession_getChannels(session); |
688 if(mwChannel_isOutgoing(chan)) { | 747 if(mwChannel_isOutgoing(chan)) { |
689 g_warning("channel 0x%08x not an incoming channel", chan->id); | 748 g_warning("channel 0x%08x not an incoming channel", chan->id); |
690 mwChannel_destroy(chan, ERR_REQUEST_INVALID, NULL); | 749 mwChannel_destroy(chan, ERR_REQUEST_INVALID, NULL); |
691 return; | 750 return; |
692 } | 751 } |
752 | |
753 chan->offered_policy = msg->encrypt.mode; | |
754 g_message("channel offered with encrypt policy 0x%04x", chan->policy); | |
693 | 755 |
694 for(list = msg->encrypt.items; list; list = list->next) { | 756 for(list = msg->encrypt.items; list; list = list->next) { |
695 struct mwEncryptItem *ei = list->data; | 757 struct mwEncryptItem *ei = list->data; |
696 struct mwCipher *cipher; | 758 struct mwCipher *cipher; |
697 struct mwCipherInstance *ci; | 759 struct mwCipherInstance *ci; |
752 g_warning("no service: 0x%08x", chan->service); | 814 g_warning("no service: 0x%08x", chan->service); |
753 mwChannel_destroy(chan, ERR_SERVICE_NO_SUPPORT, NULL); | 815 mwChannel_destroy(chan, ERR_SERVICE_NO_SUPPORT, NULL); |
754 return; | 816 return; |
755 } | 817 } |
756 | 818 |
819 chan->policy = msg->encrypt.mode; | |
820 g_message("channel accepted with encrypt policy 0x%04x", chan->policy); | |
821 | |
757 if(! msg->encrypt.mode || ! msg->encrypt.item) { | 822 if(! msg->encrypt.mode || ! msg->encrypt.item) { |
823 /* no mode or no item means no encryption */ | |
758 mwChannel_selectCipherInstance(chan, NULL); | 824 mwChannel_selectCipherInstance(chan, NULL); |
759 | 825 |
760 } else { | 826 } else { |
761 guint16 cid = msg->encrypt.item->id; | 827 guint16 cid = msg->encrypt.item->id; |
762 struct mwCipherInstance *ci = get_supported(chan, cid); | 828 struct mwCipherInstance *ci = get_supported(chan, cid); |
770 mwCipherInstance_accepted(ci, msg->encrypt.item); | 836 mwCipherInstance_accepted(ci, msg->encrypt.item); |
771 mwChannel_selectCipherInstance(chan, ci); | 837 mwChannel_selectCipherInstance(chan, ci); |
772 } | 838 } |
773 | 839 |
774 /* mark it as open for the service */ | 840 /* mark it as open for the service */ |
775 state(chan, mwChannel_OPEN); | 841 state(chan, mwChannel_OPEN, 0); |
776 | 842 |
777 /* let the service know */ | 843 /* let the service know */ |
778 mwService_recvAccept(srvc, chan, msg); | 844 mwService_recvAccept(srvc, chan, msg); |
779 | 845 |
780 /* flush it if the service didn't just immediately close it */ | 846 /* flush it if the service didn't just immediately close it */ |
792 | 858 |
793 g_return_if_fail(chan != NULL); | 859 g_return_if_fail(chan != NULL); |
794 g_return_if_fail(msg != NULL); | 860 g_return_if_fail(msg != NULL); |
795 g_return_if_fail(chan->id == msg->head.channel); | 861 g_return_if_fail(chan->id == msg->head.channel); |
796 | 862 |
797 state(chan, msg->reason? mwChannel_ERROR: mwChannel_DESTROY); | 863 state(chan, msg->reason? mwChannel_ERROR: mwChannel_DESTROY, msg->reason); |
798 | 864 |
799 srvc = mwChannel_getService(chan); | 865 srvc = mwChannel_getService(chan); |
800 if(srvc) mwService_recvDestroy(srvc, chan, msg); | 866 if(srvc) mwService_recvDestroy(srvc, chan, msg); |
801 | 867 |
802 cs = mwSession_getChannels(chan->session); | 868 cs = mwSession_getChannels(chan->session); |
863 c = mwCipherInstance_getCipher(ci); | 929 c = mwCipherInstance_getCipher(ci); |
864 cid = mwCipher_getType(c); | 930 cid = mwCipher_getType(c); |
865 | 931 |
866 g_hash_table_steal(chan->supported, GUINT_TO_POINTER(cid)); | 932 g_hash_table_steal(chan->supported, GUINT_TO_POINTER(cid)); |
867 | 933 |
934 switch(mwCipher_getType(c)) { | |
935 case mwCipher_RC2_40: | |
936 chan->policy = mwEncrypt_RC2_40; | |
937 break; | |
938 | |
939 case mwCipher_RC2_128: | |
940 chan->policy = mwEncrypt_RC2_128; | |
941 break; | |
942 | |
943 default: | |
944 /* unsure if this is bad */ | |
945 chan->policy = mwEncrypt_WHATEVER; | |
946 } | |
947 | |
868 g_message("channel 0x%08x selected cipher %s", | 948 g_message("channel 0x%08x selected cipher %s", |
869 chan->id, NSTR(mwCipher_getName(c))); | 949 chan->id, NSTR(mwCipher_getName(c))); |
950 | |
870 } else { | 951 } else { |
952 | |
953 chan->policy = mwEncrypt_NONE; | |
871 g_message("channel 0x%08x selected no cipher", chan->id); | 954 g_message("channel 0x%08x selected no cipher", chan->id); |
872 } | 955 } |
873 | 956 |
874 g_hash_table_destroy(chan->supported); | 957 g_hash_table_destroy(chan->supported); |
875 chan->supported = NULL; | 958 chan->supported = NULL; |