libpurple/protocols/gg/lib/dcc7.c

branch
release-2.x.y
changeset 35617
c9069e0e3c36
parent 33709
84fb3f1d401b
child 35620
fb20cfee648a
child 35627
fd11790cc4d6
equal deleted inserted replaced
35602:ba59da68fb79 35617:c9069e0e3c36
1 /* $Id: dcc7.c 1087 2011-04-14 20:53:25Z wojtekka $ */ 1 /* $Id$ */
2 2
3 /* 3 /*
4 * (C) Copyright 2001-2010 Wojtek Kaniewski <wojtekka@irc.pl> 4 * (C) Copyright 2001-2010 Wojtek Kaniewski <wojtekka@irc.pl>
5 * Tomasz Chiliński <chilek@chilan.com> 5 * Tomasz Chiliński <chilek@chilan.com>
6 * Adam Wysocki <gophi@ekg.chmurka.net> 6 * Adam Wysocki <gophi@ekg.chmurka.net>
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)
515 return dcc; 507 return dcc;
516 508
517 fail: 509 fail:
518 if (fd != -1) { 510 if (fd != -1) {
519 int errsv = errno; 511 int errsv = errno;
520 close(fd); 512 gg_file_close(fd);
521 errno = errsv; 513 errno = errsv;
522 } 514 }
523 515
524 free(dcc); 516 free(dcc);
525 return NULL; 517 return NULL;
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;
881 881
882 e->type = GG_EVENT_DCC7_REJECT; 882 e->type = GG_EVENT_DCC7_REJECT;
883 e->event.dcc7_reject.dcc7 = dcc; 883 e->event.dcc7_reject.dcc7 = dcc;
884 e->event.dcc7_reject.reason = gg_fix32(p->reason); 884 e->event.dcc7_reject.reason = gg_fix32(p->reason);
885 885
886 // XXX ustawić state na rejected? 886 /* XXX ustawić state na rejected? */
887 887
888 return 0; 888 return 0;
889 } 889 }
890 890
891 /** 891 /**
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
1527 1537
1528 if (dcc->fd != -1) 1538 if (dcc->fd != -1)
1529 close(dcc->fd); 1539 close(dcc->fd);
1530 1540
1531 if (dcc->file_fd != -1) 1541 if (dcc->file_fd != -1)
1532 close(dcc->file_fd); 1542 gg_file_close(dcc->file_fd);
1533 1543
1534 if (dcc->sess) 1544 if (dcc->sess)
1535 gg_dcc7_session_remove(dcc->sess, dcc); 1545 gg_dcc7_session_remove(dcc->sess, dcc);
1536 1546
1537 free(dcc->relay_list); 1547 free(dcc->relay_list);

mercurial