| 27 * \file dcc7.c |
27 * \file dcc7.c |
| 28 * |
28 * |
| 29 * \brief Obsługa połączeń bezpośrednich od wersji Gadu-Gadu 7.x |
29 * \brief Obsługa połączeń bezpośrednich od wersji Gadu-Gadu 7.x |
| 30 */ |
30 */ |
| 31 |
31 |
| 32 #include <sys/types.h> |
32 #include "fileio.h" |
| 33 #include <sys/stat.h> |
33 #include "network.h" |
| 34 #ifndef _WIN32 |
34 #include "strman.h" |
| 35 # include <sys/ioctl.h> |
|
| 36 # include <sys/socket.h> |
|
| 37 # include <netinet/in.h> |
|
| 38 # include <arpa/inet.h> |
|
| 39 # ifdef sun |
|
| 40 # include <sys/filio.h> |
|
| 41 # endif |
|
| 42 #endif |
|
| 43 #include <time.h> |
|
| 44 |
35 |
| 45 #include <ctype.h> |
36 #include <ctype.h> |
| 46 #include <errno.h> |
37 #include <errno.h> |
| 47 #include <fcntl.h> |
|
| 48 #include <stdarg.h> |
|
| 49 #include <string.h> |
38 #include <string.h> |
| 50 #include <stdio.h> |
|
| 51 #include <stdlib.h> |
39 #include <stdlib.h> |
| 52 #include <unistd.h> |
40 #include <time.h> |
| 53 |
41 |
| 54 #include "compat.h" |
|
| 55 #include "libgadu.h" |
42 #include "libgadu.h" |
| 56 #include "protocol.h" |
43 #include "protocol.h" |
| 57 #include "resolver.h" |
44 #include "resolver.h" |
| 58 #include "libgadu-internal.h" |
45 #include "internal.h" |
| 59 #include "libgadu-debug.h" |
46 #include "debug.h" |
| 60 |
47 |
| 61 #define gg_debug_dcc(dcc, level, fmt...) \ |
48 #ifdef _MSC_VER |
| |
49 # define gg_debug_dcc(dcc, level, fmt, ...) \ |
| |
50 gg_debug_session(((dcc) != NULL) ? (dcc)->sess : NULL, level, fmt, __VA_ARGS__) |
| |
51 #else |
| |
52 # define gg_debug_dcc(dcc, level, fmt...) \ |
| 62 gg_debug_session(((dcc) != NULL) ? (dcc)->sess : NULL, level, fmt) |
53 gg_debug_session(((dcc) != NULL) ? (dcc)->sess : NULL, level, fmt) |
| |
54 #endif |
| 63 |
55 |
| 64 #define gg_debug_dump_dcc(dcc, level, buf, len) \ |
56 #define gg_debug_dump_dcc(dcc, level, buf, len) \ |
| 65 gg_debug_dump(((dcc) != NULL) ? (dcc)->sess : NULL, level, buf, len) |
57 gg_debug_dump(((dcc) != NULL) ? (dcc)->sess : NULL, level, buf, len) |
| 66 |
58 |
| 67 /** |
59 /** |
| 144 |
136 |
| 145 empty = !memcmp(&id, "\0\0\0\0\0\0\0\0", 8); |
137 empty = !memcmp(&id, "\0\0\0\0\0\0\0\0", 8); |
| 146 |
138 |
| 147 for (tmp = sess->dcc7_list; tmp; tmp = tmp->next) { |
139 for (tmp = sess->dcc7_list; tmp; tmp = tmp->next) { |
| 148 if (empty) { |
140 if (empty) { |
| 149 if (tmp->peer_uin == uin /*&& tmp->state != GG_STATE_WAITING_FOR_ACCEPT*/) |
141 if (tmp->peer_uin == uin && tmp->state == GG_STATE_WAITING_FOR_ACCEPT) |
| 150 return tmp; |
142 return tmp; |
| 151 } else { |
143 } else { |
| 152 if (!memcmp(&tmp->cid, &id, sizeof(id))) |
144 if (!memcmp(&tmp->cid, &id, sizeof(id))) |
| 153 return tmp; |
145 return tmp; |
| 154 } |
146 } |
| 434 dcc->peer_uin = rcpt; |
426 dcc->peer_uin = rcpt; |
| 435 dcc->file_fd = fd; |
427 dcc->file_fd = fd; |
| 436 dcc->size = size; |
428 dcc->size = size; |
| 437 dcc->seek = seek; |
429 dcc->seek = seek; |
| 438 |
430 |
| 439 strncpy((char*) dcc->filename, filename1250, GG_DCC7_FILENAME_LEN - 1); |
431 strncpy((char*) dcc->filename, filename1250, GG_DCC7_FILENAME_LEN); |
| 440 dcc->filename[GG_DCC7_FILENAME_LEN] = 0; |
432 dcc->filename[GG_DCC7_FILENAME_LEN] = 0; |
| 441 |
433 |
| 442 memcpy(dcc->hash, hash, GG_DCC7_HASH_LEN); |
434 memcpy(dcc->hash, hash, GG_DCC7_HASH_LEN); |
| 443 |
435 |
| 444 if (gg_dcc7_session_add(sess, dcc) == -1) |
436 if (gg_dcc7_session_add(sess, dcc) == -1) |
| 637 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_handle_id(%p, %p, %p, %d)\n", sess, e, payload, len); |
629 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_handle_id(%p, %p, %p, %d)\n", sess, e, payload, len); |
| 638 |
630 |
| 639 for (tmp = sess->dcc7_list; tmp; tmp = tmp->next) { |
631 for (tmp = sess->dcc7_list; tmp; tmp = tmp->next) { |
| 640 gg_debug_session(sess, GG_DEBUG_MISC, "// checking dcc %p, state %d, type %d\n", tmp, tmp->state, tmp->dcc_type); |
632 gg_debug_session(sess, GG_DEBUG_MISC, "// checking dcc %p, state %d, type %d\n", tmp, tmp->state, tmp->dcc_type); |
| 641 |
633 |
| 642 if (tmp->state != GG_STATE_REQUESTING_ID || tmp->dcc_type != gg_fix32(p->type)) |
634 if (tmp->state != GG_STATE_REQUESTING_ID || tmp->dcc_type != (int) gg_fix32(p->type)) |
| 643 continue; |
635 continue; |
| 644 |
636 |
| 645 tmp->cid = p->id; |
637 tmp->cid = p->id; |
| 646 |
638 |
| 647 switch (tmp->dcc_type) { |
639 switch (tmp->dcc_type) { |
| 654 s.type = gg_fix32(GG_DCC7_TYPE_FILE); |
646 s.type = gg_fix32(GG_DCC7_TYPE_FILE); |
| 655 s.uin_from = gg_fix32(tmp->uin); |
647 s.uin_from = gg_fix32(tmp->uin); |
| 656 s.uin_to = gg_fix32(tmp->peer_uin); |
648 s.uin_to = gg_fix32(tmp->peer_uin); |
| 657 s.size = gg_fix32(tmp->size); |
649 s.size = gg_fix32(tmp->size); |
| 658 |
650 |
| 659 memcpy((char*) s.filename, (char*) tmp->filename, GG_DCC7_FILENAME_LEN); |
651 /* Uwaga: To nie jest ciąg kończony zerem. |
| |
652 * Note: This is not a null-terminated string. */ |
| |
653 strncpy((char*) s.filename, (char*) tmp->filename, sizeof(s.filename)); |
| 660 |
654 |
| 661 tmp->state = GG_STATE_WAITING_FOR_ACCEPT; |
655 tmp->state = GG_STATE_WAITING_FOR_ACCEPT; |
| 662 tmp->timeout = GG_DCC7_TIMEOUT_FILE_ACK; |
656 tmp->timeout = GG_DCC7_TIMEOUT_FILE_ACK; |
| 663 |
657 |
| 664 return gg_send_packet(sess, GG_DCC7_NEW, &s, sizeof(s), NULL); |
658 return gg_send_packet(sess, GG_DCC7_NEW, &s, sizeof(s), NULL); |
| 686 |
680 |
| 687 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_handle_accept(%p, %p, %p, %d)\n", sess, e, payload, len); |
681 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_handle_accept(%p, %p, %p, %d)\n", sess, e, payload, len); |
| 688 |
682 |
| 689 if (!(dcc = gg_dcc7_session_find(sess, p->id, gg_fix32(p->uin)))) { |
683 if (!(dcc = gg_dcc7_session_find(sess, p->id, gg_fix32(p->uin)))) { |
| 690 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_accept() unknown dcc session\n"); |
684 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_accept() unknown dcc session\n"); |
| 691 // XXX wysłać reject? |
685 /* XXX wysłać reject? */ |
| 692 e->type = GG_EVENT_DCC7_ERROR; |
686 e->type = GG_EVENT_DCC7_ERROR; |
| 693 e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE; |
687 e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE; |
| 694 return 0; |
688 return 0; |
| 695 } |
689 } |
| 696 |
690 |
| 699 e->type = GG_EVENT_DCC7_ERROR; |
693 e->type = GG_EVENT_DCC7_ERROR; |
| 700 e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE; |
694 e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE; |
| 701 return 0; |
695 return 0; |
| 702 } |
696 } |
| 703 |
697 |
| 704 // XXX czy dla odwrotnego połączenia powinniśmy wywołać już zdarzenie GG_DCC7_ACCEPT? |
698 /* XXX czy dla odwrotnego połączenia powinniśmy wywołać już zdarzenie GG_DCC7_ACCEPT? */ |
| 705 |
699 |
| 706 dcc->offset = gg_fix32(p->offset); |
700 dcc->offset = gg_fix32(p->offset); |
| 707 dcc->state = GG_STATE_WAITING_FOR_INFO; |
701 dcc->state = GG_STATE_WAITING_FOR_INFO; |
| 708 |
702 |
| 709 return 0; |
703 return 0; |
| 771 e->type = GG_EVENT_DCC7_ERROR; |
765 e->type = GG_EVENT_DCC7_ERROR; |
| 772 e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE; |
766 e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE; |
| 773 return 0; |
767 return 0; |
| 774 } |
768 } |
| 775 |
769 |
| 776 #if defined(HAVE_UINT64_T) && defined(HAVE_STRTOULL) |
770 #if defined(HAVE__STRTOUI64) || defined(HAVE_STRTOULL) |
| 777 { |
771 { |
| 778 uint64_t cid; |
772 uint64_t cid; |
| 779 |
773 |
| |
774 # ifdef HAVE__STRTOUI64 |
| |
775 cid = _strtoui64(tmp + 2, NULL, 0); |
| |
776 # else |
| 780 cid = strtoull(tmp + 2, NULL, 0); |
777 cid = strtoull(tmp + 2, NULL, 0); |
| |
778 # endif |
| 781 |
779 |
| 782 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() info.str=%s, info.id=%llu, sess.id=%llu\n", tmp + 2, cid, *((unsigned long long*) &dcc->cid)); |
780 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() info.str=%s, info.id=%llu, sess.id=%llu\n", tmp + 2, cid, *((unsigned long long*) &dcc->cid)); |
| 783 |
781 |
| 784 cid = gg_fix64(cid); |
782 cid = gg_fix64(cid); |
| 785 |
783 |
| 797 e->type = GG_EVENT_DCC7_ERROR; |
795 e->type = GG_EVENT_DCC7_ERROR; |
| 798 e->event.dcc7_error = GG_ERROR_DCC7_RELAY; |
796 e->event.dcc7_error = GG_ERROR_DCC7_RELAY; |
| 799 return 0; |
797 return 0; |
| 800 } |
798 } |
| 801 |
799 |
| 802 // XXX wysyłać dopiero jeśli uda się połączyć z serwerem? |
800 /* XXX wysyłać dopiero jeśli uda się połączyć z serwerem? */ |
| 803 |
801 |
| 804 gg_send_packet(dcc->sess, GG_DCC7_INFO, payload, len, NULL); |
802 gg_send_packet(dcc->sess, GG_DCC7_INFO, payload, len, NULL); |
| 805 |
803 |
| 806 return 0; |
804 return 0; |
| 807 |
805 |
| 810 e->type = GG_EVENT_DCC7_ERROR; |
808 e->type = GG_EVENT_DCC7_ERROR; |
| 811 e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE; |
809 e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE; |
| 812 return 0; |
810 return 0; |
| 813 } |
811 } |
| 814 |
812 |
| 815 // jeśli nadal czekamy na połączenie przychodzące, a druga strona nie |
813 #if 0 |
| 816 // daje rady i oferuje namiary na siebie, bierzemy co dają. |
814 /* jeśli nadal czekamy na połączenie przychodzące, a druga strona nie |
| 817 |
815 * daje rady i oferuje namiary na siebie, bierzemy co dają. |
| 818 // if (dcc->state != GG_STATE_WAITING_FOR_INFO && (dcc->state != GG_STATE_LISTENING || dcc->reverse)) { |
816 */ |
| 819 // gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() invalid state\n"); |
817 if (dcc->state != GG_STATE_WAITING_FOR_INFO && (dcc->state != GG_STATE_LISTENING || dcc->reverse)) { |
| 820 // e->type = GG_EVENT_DCC7_ERROR; |
818 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() invalid state\n"); |
| 821 // e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE; |
819 e->type = GG_EVENT_DCC7_ERROR; |
| 822 // return 0; |
820 e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE; |
| 823 // } |
821 return 0; |
| |
822 } |
| |
823 #endif |
| 824 |
824 |
| 825 if (dcc->state == GG_STATE_LISTENING) { |
825 if (dcc->state == GG_STATE_LISTENING) { |
| 826 close(dcc->fd); |
826 close(dcc->fd); |
| 827 dcc->fd = -1; |
827 dcc->fd = -1; |
| 828 dcc->reverse = 1; |
828 dcc->reverse = 1; |
| 927 gg_dcc7_free(dcc); |
927 gg_dcc7_free(dcc); |
| 928 return -1; |
928 return -1; |
| 929 } |
929 } |
| 930 |
930 |
| 931 dcc->size = gg_fix32(p->size); |
931 dcc->size = gg_fix32(p->size); |
| 932 strncpy((char*) dcc->filename, (char*) p->filename, GG_DCC7_FILENAME_LEN - 1); |
932 strncpy((char*) dcc->filename, (char*) p->filename, GG_DCC7_FILENAME_LEN); |
| 933 dcc->filename[GG_DCC7_FILENAME_LEN] = 0; |
933 dcc->filename[GG_DCC7_FILENAME_LEN] = 0; |
| 934 memcpy(dcc->hash, p->hash, GG_DCC7_HASH_LEN); |
934 memcpy(dcc->hash, p->hash, GG_DCC7_HASH_LEN); |
| 935 |
935 |
| 936 e->type = GG_EVENT_DCC7_NEW; |
936 e->type = GG_EVENT_DCC7_NEW; |
| 937 e->event.dcc7_new = dcc; |
937 e->event.dcc7_new = dcc; |
| 1050 |
1050 |
| 1051 switch (dcc->state) { |
1051 switch (dcc->state) { |
| 1052 case GG_STATE_LISTENING: |
1052 case GG_STATE_LISTENING: |
| 1053 { |
1053 { |
| 1054 struct sockaddr_in sin; |
1054 struct sockaddr_in sin; |
| 1055 int fd, one = 1; |
1055 int fd; |
| |
1056 #ifdef FIONBIO |
| |
1057 int one = 1; |
| |
1058 #endif |
| 1056 socklen_t sin_len = sizeof(sin); |
1059 socklen_t sin_len = sizeof(sin); |
| 1057 |
1060 |
| 1058 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_LISTENING\n"); |
1061 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_LISTENING\n"); |
| 1059 |
1062 |
| 1060 if ((fd = accept(dcc->fd, (struct sockaddr*) &sin, &sin_len)) == -1) { |
1063 if ((fd = accept(dcc->fd, (struct sockaddr*) &sin, &sin_len)) == -1) { |
| 1094 } |
1097 } |
| 1095 |
1098 |
| 1096 case GG_STATE_CONNECTING: |
1099 case GG_STATE_CONNECTING: |
| 1097 { |
1100 { |
| 1098 int res = 0, error = 0; |
1101 int res = 0, error = 0; |
| 1099 unsigned int error_size = sizeof(error); |
1102 socklen_t error_size = sizeof(error); |
| 1100 |
1103 |
| 1101 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_CONNECTING\n"); |
1104 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_CONNECTING\n"); |
| 1102 |
1105 |
| 1103 dcc->soft_timeout = 0; |
1106 dcc->soft_timeout = 0; |
| 1104 |
1107 |
| 1116 if (gg_dcc7_connect(dcc) == 0) |
1119 if (gg_dcc7_connect(dcc) == 0) |
| 1117 break; |
1120 break; |
| 1118 } |
1121 } |
| 1119 |
1122 |
| 1120 if (dcc->relay_index >= dcc->relay_count) { |
1123 if (dcc->relay_index >= dcc->relay_count) { |
| 1121 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() no relay available"); |
1124 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() no relay available\n"); |
| 1122 e->type = GG_EVENT_DCC7_ERROR; |
1125 e->type = GG_EVENT_DCC7_ERROR; |
| 1123 e->event.dcc_error = GG_ERROR_DCC7_RELAY; |
1126 e->event.dcc_error = GG_ERROR_DCC7_RELAY; |
| 1124 return e; |
1127 return e; |
| 1125 } |
1128 } |
| 1126 } else { |
1129 } else { |
| 1154 |
1157 |
| 1155 if (!dcc->relay) { |
1158 if (!dcc->relay) { |
| 1156 struct gg_dcc7_welcome_p2p welcome, welcome_ok; |
1159 struct gg_dcc7_welcome_p2p welcome, welcome_ok; |
| 1157 welcome_ok.id = dcc->cid; |
1160 welcome_ok.id = dcc->cid; |
| 1158 |
1161 |
| 1159 if ((res = read(dcc->fd, &welcome, sizeof(welcome))) != sizeof(welcome)) { |
1162 if ((res = recv(dcc->fd, &welcome, sizeof(welcome), 0)) != sizeof(welcome)) { |
| 1160 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() read() failed (%d, %s)\n", res, strerror(errno)); |
1163 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() recv() failed (%d, %s)\n", res, strerror(errno)); |
| 1161 e->type = GG_EVENT_DCC7_ERROR; |
1164 e->type = GG_EVENT_DCC7_ERROR; |
| 1162 e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE; |
1165 e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE; |
| 1163 return e; |
1166 return e; |
| 1164 } |
1167 } |
| 1165 |
1168 |
| 1172 } else { |
1175 } else { |
| 1173 struct gg_dcc7_welcome_server welcome, welcome_ok; |
1176 struct gg_dcc7_welcome_server welcome, welcome_ok; |
| 1174 welcome_ok.magic = GG_DCC7_WELCOME_SERVER; |
1177 welcome_ok.magic = GG_DCC7_WELCOME_SERVER; |
| 1175 welcome_ok.id = dcc->cid; |
1178 welcome_ok.id = dcc->cid; |
| 1176 |
1179 |
| 1177 if ((res = read(dcc->fd, &welcome, sizeof(welcome))) != sizeof(welcome)) { |
1180 if ((res = recv(dcc->fd, &welcome, sizeof(welcome), 0)) != sizeof(welcome)) { |
| 1178 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() read() failed (%d, %s)\n", res, strerror(errno)); |
1181 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() recv() failed (%d, %s)\n", res, strerror(errno)); |
| 1179 e->type = GG_EVENT_DCC7_ERROR; |
1182 e->type = GG_EVENT_DCC7_ERROR; |
| 1180 e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE; |
1183 e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE; |
| 1181 return e; |
1184 return e; |
| 1182 } |
1185 } |
| 1183 |
1186 |
| 1210 if (!dcc->relay) { |
1213 if (!dcc->relay) { |
| 1211 struct gg_dcc7_welcome_p2p welcome; |
1214 struct gg_dcc7_welcome_p2p welcome; |
| 1212 |
1215 |
| 1213 welcome.id = dcc->cid; |
1216 welcome.id = dcc->cid; |
| 1214 |
1217 |
| 1215 if ((res = write(dcc->fd, &welcome, sizeof(welcome))) != sizeof(welcome)) { |
1218 if ((res = send(dcc->fd, &welcome, sizeof(welcome), 0)) != sizeof(welcome)) { |
| 1216 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() write() failed (%d, %s)\n", res, strerror(errno)); |
1219 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() send() failed (%d, %s)\n", res, strerror(errno)); |
| 1217 e->type = GG_EVENT_DCC7_ERROR; |
1220 e->type = GG_EVENT_DCC7_ERROR; |
| 1218 e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE; |
1221 e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE; |
| 1219 return e; |
1222 return e; |
| 1220 } |
1223 } |
| 1221 } else { |
1224 } else { |
| 1222 struct gg_dcc7_welcome_server welcome; |
1225 struct gg_dcc7_welcome_server welcome; |
| 1223 |
1226 |
| 1224 welcome.magic = gg_fix32(GG_DCC7_WELCOME_SERVER); |
1227 welcome.magic = gg_fix32(GG_DCC7_WELCOME_SERVER); |
| 1225 welcome.id = dcc->cid; |
1228 welcome.id = dcc->cid; |
| 1226 |
1229 |
| 1227 if ((res = write(dcc->fd, &welcome, sizeof(welcome))) != sizeof(welcome)) { |
1230 if ((res = send(dcc->fd, &welcome, sizeof(welcome), 0)) != sizeof(welcome)) { |
| 1228 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() write() failed (%d, %s)\n", res, strerror(errno)); |
1231 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() send() failed (%d, %s)\n", res, strerror(errno)); |
| 1229 e->type = GG_EVENT_DCC7_ERROR; |
1232 e->type = GG_EVENT_DCC7_ERROR; |
| 1230 e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE; |
1233 e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE; |
| 1231 return e; |
1234 return e; |
| 1232 } |
1235 } |
| 1233 } |
1236 } |
| 1245 } |
1248 } |
| 1246 |
1249 |
| 1247 case GG_STATE_SENDING_FILE: |
1250 case GG_STATE_SENDING_FILE: |
| 1248 { |
1251 { |
| 1249 char buf[1024]; |
1252 char buf[1024]; |
| 1250 int chunk, res; |
1253 size_t chunk; |
| |
1254 int res; |
| 1251 |
1255 |
| 1252 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_SENDING_FILE (offset=%d, size=%d)\n", dcc->offset, dcc->size); |
1256 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_SENDING_FILE (offset=%d, size=%d)\n", dcc->offset, dcc->size); |
| 1253 |
1257 |
| 1254 if (dcc->offset >= dcc->size) { |
1258 if (dcc->offset >= dcc->size) { |
| 1255 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() offset >= size, finished\n"); |
1259 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() offset >= size, finished\n"); |
| 1273 e->type = GG_EVENT_DCC7_ERROR; |
1277 e->type = GG_EVENT_DCC7_ERROR; |
| 1274 e->event.dcc_error = (res == -1) ? GG_ERROR_DCC7_FILE : GG_ERROR_DCC7_EOF; |
1278 e->event.dcc_error = (res == -1) ? GG_ERROR_DCC7_FILE : GG_ERROR_DCC7_EOF; |
| 1275 return e; |
1279 return e; |
| 1276 } |
1280 } |
| 1277 |
1281 |
| 1278 if ((res = write(dcc->fd, buf, res)) == -1) { |
1282 if ((res = send(dcc->fd, buf, res, 0)) == -1) { |
| 1279 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() write() failed (%s)\n", strerror(errno)); |
1283 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() send() failed (%s)\n", strerror(errno)); |
| 1280 e->type = GG_EVENT_DCC7_ERROR; |
1284 e->type = GG_EVENT_DCC7_ERROR; |
| 1281 e->event.dcc_error = GG_ERROR_DCC7_NET; |
1285 e->event.dcc_error = GG_ERROR_DCC7_NET; |
| 1282 return e; |
1286 return e; |
| 1283 } |
1287 } |
| 1284 |
1288 |
| 1310 e->type = GG_EVENT_DCC7_DONE; |
1314 e->type = GG_EVENT_DCC7_DONE; |
| 1311 e->event.dcc7_done.dcc7 = dcc; |
1315 e->event.dcc7_done.dcc7 = dcc; |
| 1312 return e; |
1316 return e; |
| 1313 } |
1317 } |
| 1314 |
1318 |
| 1315 if ((res = read(dcc->fd, buf, sizeof(buf))) < 1) { |
1319 if ((res = recv(dcc->fd, buf, sizeof(buf), 0)) < 1) { |
| 1316 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() read() failed (fd=%d, res=%d, %s)\n", dcc->fd, res, strerror(errno)); |
1320 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() recv() failed (fd=%d, res=%d, %s)\n", dcc->fd, res, strerror(errno)); |
| 1317 e->type = GG_EVENT_DCC7_ERROR; |
1321 e->type = GG_EVENT_DCC7_ERROR; |
| 1318 e->event.dcc_error = (res == -1) ? GG_ERROR_DCC7_NET : GG_ERROR_DCC7_EOF; |
1322 e->event.dcc_error = (res == -1) ? GG_ERROR_DCC7_NET : GG_ERROR_DCC7_EOF; |
| 1319 return e; |
1323 return e; |
| 1320 } |
1324 } |
| 1321 |
1325 |
| 1322 // XXX zapisywać do skutku? |
1326 /* XXX zapisywać do skutku? */ |
| 1323 |
1327 |
| 1324 if ((wres = write(dcc->file_fd, buf, res)) < res) { |
1328 if ((wres = write(dcc->file_fd, buf, res)) < res) { |
| 1325 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() write() failed (fd=%d, res=%d, %s)\n", dcc->file_fd, wres, strerror(errno)); |
1329 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() write() failed (fd=%d, res=%d, %s)\n", dcc->file_fd, wres, strerror(errno)); |
| 1326 e->type = GG_EVENT_DCC7_ERROR; |
1330 e->type = GG_EVENT_DCC7_ERROR; |
| 1327 e->event.dcc_error = GG_ERROR_DCC7_FILE; |
1331 e->event.dcc_error = GG_ERROR_DCC7_FILE; |
| 1345 } |
1349 } |
| 1346 |
1350 |
| 1347 case GG_STATE_RESOLVING_RELAY: |
1351 case GG_STATE_RESOLVING_RELAY: |
| 1348 { |
1352 { |
| 1349 struct in_addr addr; |
1353 struct in_addr addr; |
| |
1354 int res; |
| 1350 |
1355 |
| 1351 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_RESOLVING_RELAY\n"); |
1356 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_RESOLVING_RELAY\n"); |
| 1352 |
1357 |
| 1353 if (read(dcc->fd, &addr, sizeof(addr)) < sizeof(addr) || addr.s_addr == INADDR_NONE) { |
1358 do { |
| |
1359 res = gg_resolver_recv(dcc->fd, &addr, sizeof(addr)); |
| |
1360 } while (res == -1 && errno == EINTR); |
| |
1361 |
| |
1362 dcc->sess->resolver_cleanup(&dcc->resolver, 0); |
| |
1363 |
| |
1364 if (res != sizeof(addr) || addr.s_addr == INADDR_NONE) { |
| 1354 int errno_save = errno; |
1365 int errno_save = errno; |
| 1355 |
1366 |
| 1356 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() resolving failed\n"); |
1367 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() resolving failed\n"); |
| 1357 close(dcc->fd); |
1368 close(dcc->fd); |
| 1358 dcc->fd = -1; |
1369 dcc->fd = -1; |
| 1359 dcc->sess->resolver_cleanup(&dcc->resolver, 0); |
|
| 1360 errno = errno_save; |
1370 errno = errno_save; |
| 1361 e->type = GG_EVENT_DCC7_ERROR; |
1371 e->type = GG_EVENT_DCC7_ERROR; |
| 1362 e->event.dcc_error = GG_ERROR_DCC7_RELAY; |
1372 e->event.dcc_error = GG_ERROR_DCC7_RELAY; |
| 1363 return e; |
1373 return e; |
| 1364 } |
1374 } |
| 1383 } |
1393 } |
| 1384 |
1394 |
| 1385 case GG_STATE_CONNECTING_RELAY: |
1395 case GG_STATE_CONNECTING_RELAY: |
| 1386 { |
1396 { |
| 1387 int res; |
1397 int res; |
| 1388 unsigned int res_size = sizeof(res); |
1398 socklen_t res_size = sizeof(res); |
| 1389 struct gg_dcc7_relay_req pkt; |
1399 struct gg_dcc7_relay_req pkt; |
| 1390 |
1400 |
| 1391 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_CONNECTING_RELAY\n"); |
1401 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_CONNECTING_RELAY\n"); |
| 1392 |
1402 |
| 1393 if (getsockopt(dcc->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) != 0 || res != 0) { |
1403 if (getsockopt(dcc->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) != 0 || res != 0) { |
| 1405 pkt.dunno1 = gg_fix16(GG_DCC7_RELAY_DUNNO1); |
1415 pkt.dunno1 = gg_fix16(GG_DCC7_RELAY_DUNNO1); |
| 1406 |
1416 |
| 1407 gg_debug_dcc(dcc, GG_DEBUG_DUMP, "// gg_dcc7_watch_fd() send pkt(0x%.2x)\n", gg_fix32(pkt.magic)); |
1417 gg_debug_dcc(dcc, GG_DEBUG_DUMP, "// gg_dcc7_watch_fd() send pkt(0x%.2x)\n", gg_fix32(pkt.magic)); |
| 1408 gg_debug_dump_dcc(dcc, GG_DEBUG_DUMP, (const char*) &pkt, sizeof(pkt)); |
1418 gg_debug_dump_dcc(dcc, GG_DEBUG_DUMP, (const char*) &pkt, sizeof(pkt)); |
| 1409 |
1419 |
| 1410 if ((res = write(dcc->fd, &pkt, sizeof(pkt))) != sizeof(pkt)) { |
1420 if ((res = send(dcc->fd, &pkt, sizeof(pkt), 0)) != sizeof(pkt)) { |
| 1411 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() sending failed\n"); |
1421 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() sending failed\n"); |
| 1412 e->type = GG_EVENT_DCC7_ERROR; |
1422 e->type = GG_EVENT_DCC7_ERROR; |
| 1413 e->event.dcc_error = GG_ERROR_DCC7_RELAY; |
1423 e->event.dcc_error = GG_ERROR_DCC7_RELAY; |
| 1414 return e; |
1424 return e; |
| 1415 } |
1425 } |
| 1429 int res; |
1439 int res; |
| 1430 int i; |
1440 int i; |
| 1431 |
1441 |
| 1432 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_READING_RELAY\n"); |
1442 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_READING_RELAY\n"); |
| 1433 |
1443 |
| 1434 if ((res = read(dcc->fd, buf, sizeof(buf))) < sizeof(*pkt)) { |
1444 if ((res = recv(dcc->fd, buf, sizeof(buf), 0)) < (int) sizeof(*pkt)) { |
| 1435 if (res == 0) |
1445 if (res == 0) |
| 1436 errno = ECONNRESET; |
1446 errno = ECONNRESET; |
| 1437 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() read() failed (%d, %s)\n", res, strerror(errno)); |
1447 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() recv() failed (%d, %s)\n", res, strerror(errno)); |
| 1438 e->type = GG_EVENT_DCC7_ERROR; |
1448 e->type = GG_EVENT_DCC7_ERROR; |
| 1439 e->event.dcc_error = GG_ERROR_DCC7_RELAY; |
1449 e->event.dcc_error = GG_ERROR_DCC7_RELAY; |
| 1440 return e; |
1450 return e; |
| 1441 } |
1451 } |
| 1442 |
1452 |
| 1458 dcc->relay_index = 0; |
1468 dcc->relay_index = 0; |
| 1459 dcc->relay_count = gg_fix32(pkt->rcount); |
1469 dcc->relay_count = gg_fix32(pkt->rcount); |
| 1460 dcc->relay_list = malloc(dcc->relay_count * sizeof(gg_dcc7_relay_t)); |
1470 dcc->relay_list = malloc(dcc->relay_count * sizeof(gg_dcc7_relay_t)); |
| 1461 |
1471 |
| 1462 if (dcc->relay_list == NULL) { |
1472 if (dcc->relay_list == NULL) { |
| 1463 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() not enough memory"); |
1473 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() not enough memory\n"); |
| 1464 dcc->relay_count = 0; |
1474 dcc->relay_count = 0; |
| 1465 free(e); |
1475 free(e); |
| 1466 return NULL; |
1476 return NULL; |
| 1467 } |
1477 } |
| 1468 |
1478 |
| 1487 if (gg_dcc7_connect(dcc) == 0) |
1497 if (gg_dcc7_connect(dcc) == 0) |
| 1488 break; |
1498 break; |
| 1489 } |
1499 } |
| 1490 |
1500 |
| 1491 if (dcc->relay_index >= dcc->relay_count) { |
1501 if (dcc->relay_index >= dcc->relay_count) { |
| 1492 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() no relay available"); |
1502 gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() no relay available\n"); |
| 1493 e->type = GG_EVENT_DCC7_ERROR; |
1503 e->type = GG_EVENT_DCC7_ERROR; |
| 1494 e->event.dcc_error = GG_ERROR_DCC7_RELAY; |
1504 e->event.dcc_error = GG_ERROR_DCC7_RELAY; |
| 1495 return e; |
1505 return e; |
| 1496 } |
1506 } |
| 1497 |
1507 |