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;