Mercurial > pidgin
comparison libpurple/protocols/bonjour/jabber.c @ 21667:919338d399ae
merge of '2fcb5d2cb35c5ba692592e22bc442c3d62000f85'
and '61c8d242483046a3b3b43cd1afbb794af35a08c9'
author | Ethan Blanton <elb@pidgin.im> |
---|---|
date | Tue, 27 Nov 2007 15:57:08 +0000 |
parents | 4fe9acb6b514 9736ee1ca29e |
children | fded60f269bc |
comparison
equal
deleted
inserted
replaced
21438:4fe9acb6b514 | 21667:919338d399ae |
---|---|
89 return "12"; | 89 return "12"; |
90 } | 90 } |
91 #endif | 91 #endif |
92 | 92 |
93 static BonjourJabberConversation * | 93 static BonjourJabberConversation * |
94 bonjour_jabber_conv_new() { | 94 bonjour_jabber_conv_new(PurpleBuddy *pb) { |
95 | 95 |
96 BonjourJabberConversation *bconv = g_new0(BonjourJabberConversation, 1); | 96 BonjourJabberConversation *bconv = g_new0(BonjourJabberConversation, 1); |
97 bconv->socket = -1; | 97 bconv->socket = -1; |
98 bconv->tx_buf = purple_circ_buffer_new(512); | 98 bconv->tx_buf = purple_circ_buffer_new(512); |
99 bconv->tx_handler = 0; | 99 bconv->tx_handler = 0; |
100 bconv->rx_handler = 0; | 100 bconv->rx_handler = 0; |
101 bconv->pb = pb; | |
101 | 102 |
102 return bconv; | 103 return bconv; |
103 } | 104 } |
104 | 105 |
105 | 106 |
326 | 327 |
327 return ret; | 328 return ret; |
328 } | 329 } |
329 | 330 |
330 void bonjour_jabber_process_packet(PurpleBuddy *pb, xmlnode *packet) { | 331 void bonjour_jabber_process_packet(PurpleBuddy *pb, xmlnode *packet) { |
332 | |
333 g_return_if_fail(packet != NULL); | |
334 | |
331 if (!strcmp(packet->name, "message")) | 335 if (!strcmp(packet->name, "message")) |
332 _jabber_parse_and_write_message_to_ui(packet, pb); | 336 _jabber_parse_and_write_message_to_ui(packet, pb); |
333 else if(!strcmp(packet->name, "iq")) | 337 else if(!strcmp(packet->name, "iq")) |
334 xep_iq_parse(packet, NULL, pb); | 338 xep_iq_parse(packet, NULL, pb); |
335 else | 339 else |
336 purple_debug_warning("bonjour", "Unknown packet: %s\n", | 340 purple_debug_warning("bonjour", "Unknown packet: %s\n", packet->name ? packet->name : "(null)"); |
337 packet->name); | |
338 } | 341 } |
339 | 342 |
340 | 343 |
341 static void | 344 static void |
342 _client_socket_handler(gpointer data, gint socket, PurpleInputCondition condition) | 345 _client_socket_handler(gpointer data, gint socket, PurpleInputCondition condition) |
350 /* Read the data from the socket */ | 353 /* Read the data from the socket */ |
351 if ((len = recv(socket, message, sizeof(message) - 1, 0)) == -1) { | 354 if ((len = recv(socket, message, sizeof(message) - 1, 0)) == -1) { |
352 /* There have been an error reading from the socket */ | 355 /* There have been an error reading from the socket */ |
353 if (errno != EAGAIN) { | 356 if (errno != EAGAIN) { |
354 BonjourBuddy *bb = pb->proto_data; | 357 BonjourBuddy *bb = pb->proto_data; |
355 | 358 const char *err = g_strerror(errno); |
356 purple_debug_warning("bonjour", "receive error: %s\n", g_strerror(errno)); | 359 |
360 purple_debug_warning("bonjour", "receive error: %s\n", err ? err : "(null)"); | |
357 | 361 |
358 bonjour_jabber_close_conversation(bb->conversation); | 362 bonjour_jabber_close_conversation(bb->conversation); |
359 bb->conversation = NULL; | 363 bb->conversation = NULL; |
360 | 364 |
361 /* I guess we really don't need to notify the user. | 365 /* I guess we really don't need to notify the user. |
362 * If they try to send another message it'll reconnect */ | 366 * If they try to send another message it'll reconnect */ |
363 } | 367 } |
364 return; | 368 return; |
365 } else if (len == 0) { /* The other end has closed the socket */ | 369 } else if (len == 0) { /* The other end has closed the socket */ |
366 purple_debug_warning("bonjour", "Connection closed (without stream end) by %s.\n", pb->name); | 370 purple_debug_warning("bonjour", "Connection closed (without stream end) by %s.\n", pb->name ? pb->name : "(null)"); |
367 bonjour_jabber_stream_ended(pb); | 371 bonjour_jabber_stream_ended(pb); |
368 return; | 372 return; |
369 } else { | 373 } else { |
370 message_length = len; | 374 message_length = len; |
371 message[message_length] = '\0'; | 375 message[message_length] = '\0'; |
401 #endif | 405 #endif |
402 /* Close the socket, clear the watcher and free memory */ | 406 /* Close the socket, clear the watcher and free memory */ |
403 bonjour_jabber_close_conversation(bb->conversation); | 407 bonjour_jabber_close_conversation(bb->conversation); |
404 bb->conversation = NULL; | 408 bb->conversation = NULL; |
405 } | 409 } |
406 | |
407 } | 410 } |
408 | 411 |
409 void bonjour_jabber_stream_started(PurpleBuddy *pb) { | 412 void bonjour_jabber_stream_started(PurpleBuddy *pb) { |
410 BonjourBuddy *bb = pb->proto_data; | 413 BonjourBuddy *bb = pb->proto_data; |
411 BonjourJabberConversation *bconv = bb->conversation; | 414 BonjourJabberConversation *bconv = bb->conversation; |
573 bb = pb->proto_data; | 576 bb = pb->proto_data; |
574 | 577 |
575 /* Check if the conversation has been previously started */ | 578 /* Check if the conversation has been previously started */ |
576 if (bb->conversation == NULL) | 579 if (bb->conversation == NULL) |
577 { | 580 { |
578 bb->conversation = bonjour_jabber_conv_new(); | 581 bb->conversation = bonjour_jabber_conv_new(pb); |
579 | 582 |
580 if (!bonjour_jabber_stream_init(pb, client_socket)) { | 583 if (!bonjour_jabber_stream_init(pb, client_socket)) { |
581 close(client_socket); | 584 close(client_socket); |
582 return; | 585 return; |
583 } | 586 } |
711 bb->conversation = NULL; | 714 bb->conversation = NULL; |
712 return; | 715 return; |
713 } | 716 } |
714 } | 717 } |
715 | 718 |
716 int | 719 static PurpleBuddy * |
717 bonjour_jabber_send_message(BonjourJabber *data, const gchar *to, const gchar *body) | 720 _find_or_start_conversation(BonjourJabber *data, const gchar *to) |
718 { | 721 { |
719 xmlnode *message_node, *node, *node2; | 722 PurpleBuddy *pb = NULL; |
720 gchar *message; | 723 BonjourBuddy *bb = NULL; |
721 PurpleBuddy *pb; | 724 |
722 BonjourBuddy *bb; | 725 g_return_val_if_fail(data != NULL, NULL); |
723 int ret; | 726 g_return_val_if_fail(to != NULL, NULL); |
724 | 727 |
725 pb = purple_find_buddy(data->account, to); | 728 pb = purple_find_buddy(data->account, to); |
726 if (pb == NULL) { | 729 if (pb == NULL || pb->proto_data == NULL) |
727 purple_debug_info("bonjour", "Can't send a message to an offline buddy (%s).\n", to); | |
728 /* You can not send a message to an offline buddy */ | 730 /* You can not send a message to an offline buddy */ |
729 return -10000; | 731 return NULL; |
730 } | 732 |
731 | 733 bb = (BonjourBuddy *) pb->proto_data; |
732 bb = pb->proto_data; | |
733 | 734 |
734 /* Check if there is a previously open conversation */ | 735 /* Check if there is a previously open conversation */ |
735 if (bb->conversation == NULL) | 736 if (bb->conversation == NULL) |
736 { | 737 { |
737 PurpleProxyConnectData *connect_data; | 738 PurpleProxyConnectData *connect_data; |
738 PurpleProxyInfo *proxy_info; | 739 PurpleProxyInfo *proxy_info; |
740 | |
741 purple_debug_info("bonjour", "Starting conversation with %s\n", to); | |
739 | 742 |
740 /* Make sure that the account always has a proxy of "none". | 743 /* Make sure that the account always has a proxy of "none". |
741 * This is kind of dirty, but proxy_connect_none() isn't exposed. */ | 744 * This is kind of dirty, but proxy_connect_none() isn't exposed. */ |
742 proxy_info = purple_account_get_proxy_info(data->account); | 745 proxy_info = purple_account_get_proxy_info(data->account); |
743 if (proxy_info == NULL) { | 746 if (proxy_info == NULL) { |
744 proxy_info = purple_proxy_info_new(); | 747 proxy_info = purple_proxy_info_new(); |
745 purple_account_set_proxy_info(data->account, proxy_info); | 748 purple_account_set_proxy_info(data->account, proxy_info); |
746 } | 749 } |
747 purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_NONE); | 750 purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_NONE); |
748 | 751 |
749 connect_data = | 752 connect_data = purple_proxy_connect(data->account->gc, data->account, |
750 purple_proxy_connect(data->account->gc, data->account, bb->ip, | 753 bb->ip, bb->port_p2pj, _connected_to_buddy, pb); |
751 bb->port_p2pj, _connected_to_buddy, pb); | |
752 | 754 |
753 if (connect_data == NULL) { | 755 if (connect_data == NULL) { |
754 purple_debug_error("bonjour", "Unable to connect to buddy (%s).\n", to); | 756 purple_debug_error("bonjour", "Unable to connect to buddy (%s).\n", to); |
755 return -10001; | 757 return NULL; |
756 } | 758 } |
757 | 759 |
758 bb->conversation = bonjour_jabber_conv_new(); | 760 bb->conversation = bonjour_jabber_conv_new(pb); |
759 bb->conversation->connect_data = connect_data; | 761 bb->conversation->connect_data = connect_data; |
760 /* We don't want _send_data() to register the tx_handler; | 762 /* We don't want _send_data() to register the tx_handler; |
761 * that neeeds to wait until we're actually connected. */ | 763 * that neeeds to wait until we're actually connected. */ |
762 bb->conversation->tx_handler = 0; | 764 bb->conversation->tx_handler = 0; |
763 } | 765 } |
766 return pb; | |
767 } | |
768 | |
769 int | |
770 bonjour_jabber_send_message(BonjourJabber *data, const gchar *to, const gchar *body) | |
771 { | |
772 xmlnode *message_node, *node, *node2; | |
773 gchar *message; | |
774 PurpleBuddy *pb; | |
775 BonjourBuddy *bb; | |
776 int ret; | |
777 | |
778 pb = _find_or_start_conversation(data, to); | |
779 if (pb == NULL) { | |
780 purple_debug_info("bonjour", "Can't send a message to an offline buddy (%s).\n", to); | |
781 /* You can not send a message to an offline buddy */ | |
782 return -10000; | |
783 } | |
784 | |
785 bb = pb->proto_data; | |
764 | 786 |
765 message_node = xmlnode_new("message"); | 787 message_node = xmlnode_new("message"); |
766 xmlnode_set_attrib(message_node, "to", bb->name); | 788 xmlnode_set_attrib(message_node, "to", bb->name); |
767 xmlnode_set_attrib(message_node, "from", purple_account_get_username(data->account)); | 789 xmlnode_set_attrib(message_node, "from", purple_account_get_username(data->account)); |
768 xmlnode_set_attrib(message_node, "type", "chat"); | 790 xmlnode_set_attrib(message_node, "type", "chat"); |
797 } | 819 } |
798 | 820 |
799 void | 821 void |
800 bonjour_jabber_close_conversation(BonjourJabberConversation *bconv) | 822 bonjour_jabber_close_conversation(BonjourJabberConversation *bconv) |
801 { | 823 { |
802 if (bconv != NULL) | 824 if (bconv != NULL) { |
803 { | 825 GList *xfers, *tmp_next; |
826 BonjourData *bd = bconv->pb->account->gc->proto_data; | |
827 | |
828 /* Cancel any file transfers that are waiting to begin */ | |
829 xfers = bd->xfer_lists; | |
830 while(xfers != NULL) { | |
831 PurpleXfer *xfer = xfers->data; | |
832 tmp_next = xfers->next; | |
833 /* We only need to cancel this if it hasn't actually started transferring. */ | |
834 /* This will change if we ever support IBB transfers. */ | |
835 if (strcmp(xfer->who, bconv->pb->name) == 0 | |
836 && (purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_NOT_STARTED | |
837 || purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_UNKNOWN)) { | |
838 purple_xfer_cancel_remote(xfer); | |
839 } | |
840 xfers = tmp_next; | |
841 } | |
842 | |
804 /* Close the socket and remove the watcher */ | 843 /* Close the socket and remove the watcher */ |
805 if (bconv->socket >= 0) { | 844 if (bconv->socket >= 0) { |
806 /* Send the end of the stream to the other end of the conversation */ | 845 /* Send the end of the stream to the other end of the conversation */ |
807 if (bconv->sent_stream_start) | 846 if (bconv->sent_stream_start) |
808 send(bconv->socket, STREAM_END, strlen(STREAM_END), 0); | 847 send(bconv->socket, STREAM_END, strlen(STREAM_END), 0); |
853 } | 892 } |
854 | 893 |
855 g_slist_free(buddies); | 894 g_slist_free(buddies); |
856 } | 895 } |
857 } | 896 } |
858 static PurpleBuddy * | |
859 _start_conversation(BonjourJabber *data, const gchar *to) | |
860 { | |
861 PurpleBuddy *pb = NULL; | |
862 BonjourBuddy *bb = NULL; | |
863 | |
864 if(data == NULL || to == NULL) | |
865 return NULL; | |
866 | |
867 purple_debug_info("Bonjour", "start-conversation with %s - \n", to); | |
868 | |
869 pb = purple_find_buddy(data->account, to); | |
870 if (pb == NULL) | |
871 /* You can not send a message to an offline buddy */ | |
872 return NULL; | |
873 | |
874 bb = (BonjourBuddy *) pb->proto_data; | |
875 if(bb == NULL) | |
876 return NULL; | |
877 | |
878 /* Check if there is a previously open conversation */ | |
879 if (bb->conversation == NULL) | |
880 { | |
881 PurpleProxyConnectData *connect_data; | |
882 PurpleProxyInfo *proxy_info; | |
883 | |
884 /* Make sure that the account always has a proxy of "none". | |
885 * This is kind of dirty, but proxy_connect_none() isn't exposed. */ | |
886 proxy_info = purple_account_get_proxy_info(data->account); | |
887 if (proxy_info == NULL) { | |
888 proxy_info = purple_proxy_info_new(); | |
889 purple_account_set_proxy_info(data->account, proxy_info); | |
890 } | |
891 purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_NONE); | |
892 | |
893 connect_data = purple_proxy_connect(data->account->gc, data->account, | |
894 bb->ip, bb->port_p2pj, _connected_to_buddy, pb); | |
895 | |
896 if (connect_data == NULL) { | |
897 purple_debug_error("bonjour", "Unable to connect to buddy (%s).\n", to); | |
898 return NULL; | |
899 } | |
900 | |
901 bb->conversation = bonjour_jabber_conv_new(); | |
902 bb->conversation->connect_data = connect_data; | |
903 /* We don't want _send_data() to register the tx_handler; | |
904 * that neeeds to wait until we're actually connected. */ | |
905 bb->conversation->tx_handler = 0; | |
906 } | |
907 return pb; | |
908 } | |
909 | 897 |
910 XepIq * | 898 XepIq * |
911 xep_iq_new(void *data, XepIqType type, const gchar *to, const gchar *id) | 899 xep_iq_new(void *data, XepIqType type, const char *to, const char *from, const char *id) |
912 { | 900 { |
913 xmlnode *iq_node = NULL; | 901 xmlnode *iq_node = NULL; |
914 XepIq *iq = NULL; | 902 XepIq *iq = NULL; |
915 | 903 |
916 if(data == NULL || to == NULL || id == NULL) | 904 g_return_val_if_fail(data != NULL, NULL); |
917 return NULL; | 905 g_return_val_if_fail(to != NULL, NULL); |
918 iq = g_new0(XepIq, 1); | 906 g_return_val_if_fail(id != NULL, NULL); |
919 if(iq == NULL) | |
920 return NULL; | |
921 | 907 |
922 iq_node = xmlnode_new("iq"); | 908 iq_node = xmlnode_new("iq"); |
923 if(iq_node == NULL) { | |
924 g_free(iq); | |
925 return NULL; | |
926 } | |
927 | 909 |
928 xmlnode_set_attrib(iq_node, "to", to); | 910 xmlnode_set_attrib(iq_node, "to", to); |
911 xmlnode_set_attrib(iq_node, "from", from); | |
929 xmlnode_set_attrib(iq_node, "id", id); | 912 xmlnode_set_attrib(iq_node, "id", id); |
930 switch (type) { | 913 switch (type) { |
931 case XEP_IQ_SET: | 914 case XEP_IQ_SET: |
932 xmlnode_set_attrib(iq_node, "type", "set"); | 915 xmlnode_set_attrib(iq_node, "type", "set"); |
933 break; | 916 break; |
944 default: | 927 default: |
945 xmlnode_set_attrib(iq_node, "type", "none"); | 928 xmlnode_set_attrib(iq_node, "type", "none"); |
946 break; | 929 break; |
947 } | 930 } |
948 | 931 |
932 iq = g_new0(XepIq, 1); | |
949 iq->node = iq_node; | 933 iq->node = iq_node; |
950 iq->type = type; | 934 iq->type = type; |
951 iq->data = ((BonjourData*)data)->jabber_data; | 935 iq->data = ((BonjourData*)data)->jabber_data; |
952 iq->to = (char*)to; | 936 iq->to = (char*)to; |
937 | |
953 return iq; | 938 return iq; |
954 } | 939 } |
955 | 940 |
956 static gboolean | 941 static gboolean |
957 check_if_blocked(PurpleBuddy *pb) | 942 check_if_blocked(PurpleBuddy *pb) |
965 | 950 |
966 acc = pb->account; | 951 acc = pb->account; |
967 | 952 |
968 for(l = acc->deny; l != NULL; l = l->next) { | 953 for(l = acc->deny; l != NULL; l = l->next) { |
969 if(!purple_utf8_strcasecmp(pb->name, (char *)l->data)) { | 954 if(!purple_utf8_strcasecmp(pb->name, (char *)l->data)) { |
970 purple_debug_info("Bonjour", "%s has been blocked.\n", pb->name, acc->username); | 955 purple_debug_info("bonjour", "%s has been blocked.\n", pb->name, acc->username); |
971 blocked = TRUE; | 956 blocked = TRUE; |
972 break; | 957 break; |
973 } | 958 } |
974 } | 959 } |
975 return blocked; | 960 return blocked; |
989 } | 974 } |
990 | 975 |
991 if(check_if_blocked(pb)) | 976 if(check_if_blocked(pb)) |
992 return; | 977 return; |
993 | 978 |
994 if ((child = xmlnode_get_child(packet, "si")) || (child = xmlnode_get_child(packet, "si"))) | 979 if ((child = xmlnode_get_child(packet, "si")) || (child = xmlnode_get_child(packet, "error"))) |
995 xep_si_parse(connection, packet, pb); | 980 xep_si_parse(connection, packet, pb); |
996 else | 981 else |
997 xep_bytestreams_parse(connection, packet, pb); | 982 xep_bytestreams_parse(connection, packet, pb); |
998 } | 983 } |
999 | 984 |
1000 int | 985 int |
1001 xep_iq_send(XepIq *iq) | 986 xep_iq_send_and_free(XepIq *iq) |
1002 { | 987 { |
1003 char *msg = NULL; | |
1004 gint msg_len = 0; | |
1005 int ret = -1; | 988 int ret = -1; |
1006 PurpleBuddy *pb = NULL; | 989 PurpleBuddy *pb = NULL; |
1007 /* Convert xml node into stream */ | 990 |
1008 msg = xmlnode_to_str(iq->node, &msg_len); | 991 /* start the talk, reuse the message socket */ |
992 pb = _find_or_start_conversation ((BonjourJabber*)iq->data, iq->to); | |
993 /* Send the message */ | |
994 if (pb != NULL) { | |
995 /* Convert xml node into stream */ | |
996 gchar *msg = xmlnode_to_str(iq->node, NULL); | |
997 ret = _send_data(pb, msg); | |
998 g_free(msg); | |
999 } | |
1000 | |
1009 xmlnode_free(iq->node); | 1001 xmlnode_free(iq->node); |
1010 /* start the talk, reuse the message socket */ | 1002 iq->node = NULL; |
1011 pb = _start_conversation ((BonjourJabber*)iq->data, iq->to); | 1003 g_free(iq); |
1012 /* Send the message */ | 1004 |
1013 if (pb != NULL) | 1005 return (ret >= 0) ? 0 : -1; |
1014 ret = _send_data(pb, msg); | 1006 } |
1015 g_free(msg); | 1007 |
1016 if (ret == -1) | 1008 /* This returns a ';' delimited string containing all non-localhost IPs */ |
1017 return -1; | 1009 const char * |
1018 return 0; | |
1019 } | |
1020 | |
1021 char * | |
1022 purple_network_get_my_ip_ext2(int fd) | 1010 purple_network_get_my_ip_ext2(int fd) |
1023 { | 1011 { |
1024 char buffer[1024]; | 1012 char buffer[1024]; |
1025 static char ip_ext[17 * 10]; | 1013 static char ip_ext[17 * 10]; |
1026 char *tmp; | 1014 char *tmp; |
1029 struct ifreq *ifr; | 1017 struct ifreq *ifr; |
1030 struct sockaddr_in *sinptr; | 1018 struct sockaddr_in *sinptr; |
1031 guint32 lhost = htonl(127 * 256 * 256 * 256 + 1); | 1019 guint32 lhost = htonl(127 * 256 * 256 * 256 + 1); |
1032 long unsigned int add; | 1020 long unsigned int add; |
1033 int source = fd; | 1021 int source = fd; |
1034 int len; | 1022 int len, count = 0; |
1035 | 1023 |
1036 if (fd < 0) | 1024 if (fd < 0) |
1037 source = socket(PF_INET, SOCK_STREAM, 0); | 1025 source = socket(PF_INET, SOCK_STREAM, 0); |
1038 | 1026 |
1039 ifc.ifc_len = sizeof(buffer); | 1027 ifc.ifc_len = sizeof(buffer); |
1040 ifc.ifc_req = (struct ifreq *)buffer; | 1028 ifc.ifc_req = (struct ifreq *)buffer; |
1041 ioctl(source, SIOCGIFCONF, &ifc); | 1029 ioctl(source, SIOCGIFCONF, &ifc); |
1042 | 1030 |
1043 if (fd < 0) | 1031 if (fd < 0) |
1044 close(source); | 1032 close(source); |
1045 memset(ip_ext, 0, 17 * 10); | 1033 |
1034 memset(ip_ext, 0, sizeof(ip_ext)); | |
1046 memcpy(ip_ext, "0.0.0.0", 7); | 1035 memcpy(ip_ext, "0.0.0.0", 7); |
1047 tmp = buffer; | 1036 tmp = buffer; |
1048 tip = ip_ext; | 1037 tip = ip_ext; |
1049 while (tmp < buffer + ifc.ifc_len) | 1038 while (tmp < buffer + ifc.ifc_len && count < 10) |
1050 { | 1039 { |
1051 ifr = (struct ifreq *)tmp; | 1040 ifr = (struct ifreq *)tmp; |
1052 tmp += HX_SIZE_OF_IFREQ(*ifr); | 1041 tmp += HX_SIZE_OF_IFREQ(*ifr); |
1053 | 1042 |
1054 if (ifr->ifr_addr.sa_family == AF_INET) | 1043 if (ifr->ifr_addr.sa_family == AF_INET) |
1060 len = g_snprintf(tip, 17, "%lu.%lu.%lu.%lu;", | 1049 len = g_snprintf(tip, 17, "%lu.%lu.%lu.%lu;", |
1061 ((add >> 24) & 255), | 1050 ((add >> 24) & 255), |
1062 ((add >> 16) & 255), | 1051 ((add >> 16) & 255), |
1063 ((add >> 8) & 255), | 1052 ((add >> 8) & 255), |
1064 add & 255); | 1053 add & 255); |
1065 tip = (char*) ((int) tip + len); | 1054 tip = &tip[len]; |
1055 count++; | |
1066 continue; | 1056 continue; |
1067 } | 1057 } |
1068 } | 1058 } |
1069 } | 1059 } |
1070 | 1060 |