@@ -2,6 +2,7 @@ | |||
#define BTPD_H | |||
#include <sys/types.h> | |||
#include <sys/socket.h> | |||
#include <sys/time.h> | |||
#include <assert.h> | |||
@@ -872,12 +872,11 @@ net_shake_read(struct peer *p, unsigned long rmax) | |||
if (in->buf_off < 68) | |||
break; | |||
else { | |||
if (!hs->incoming && bcmp(in->buf + 48, p->id, 20) != 0) | |||
goto bad_shake; | |||
else if (hs->incoming && torrent_has_peer(p->tp, in->buf + 48)) | |||
goto bad_shake; // Not really, but we are already connected | |||
if (hs->incoming) | |||
bcopy(in->buf + 48, p->id, 20); | |||
if (torrent_has_peer(p->tp, in->buf + 48)) | |||
goto bad_shake; // Not really, but we're already connected. | |||
else if (bcmp(in->buf + 48, btpd.peer_id, 20) == 0) | |||
goto bad_shake; // Connection from myself. | |||
bcopy(in->buf + 48, p->id, 20); | |||
hs->state = SHAKE_ID; | |||
} | |||
default: | |||
@@ -922,6 +921,22 @@ net_handshake(struct peer *p, int incoming) | |||
net_send_shake(p); | |||
} | |||
int | |||
net_connect2(struct sockaddr *sa, socklen_t salen, int *sd) | |||
{ | |||
if ((*sd = socket(PF_INET, SOCK_STREAM, 0)) == -1) | |||
return errno; | |||
set_nonblocking(*sd); | |||
if (connect(*sd, sa, salen) == -1 && errno != EINPROGRESS) { | |||
btpd_log(BTPD_L_CONN, "Botched connection %s.", strerror(errno)); | |||
close(*sd); | |||
return errno; | |||
} | |||
return 0; | |||
} | |||
int | |||
net_connect(const char *ip, int port, int *sd) | |||
{ | |||
@@ -939,25 +954,14 @@ net_connect(const char *ip, int port, int *sd) | |||
if (getaddrinfo(ip, portstr, &hints, &res) != 0) | |||
return errno; | |||
if (res) { | |||
if ((*sd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { | |||
btpd_log(BTPD_L_CONN, "Botched connection %s.", strerror(errno)); | |||
freeaddrinfo(res); | |||
return errno; | |||
} | |||
set_nonblocking(*sd); | |||
if (connect(*sd, res->ai_addr, res->ai_addrlen) == -1 && | |||
errno != EINPROGRESS) { | |||
btpd_log(BTPD_L_CONN, "Botched connection %s.", strerror(errno)); | |||
close(*sd); | |||
freeaddrinfo(res); | |||
return errno; | |||
} | |||
} | |||
int error = net_connect2(res->ai_addr, res->ai_addrlen, sd); | |||
freeaddrinfo(res); | |||
btpd.npeers++; | |||
return 0; | |||
if (error == 0) | |||
btpd.npeers++; | |||
return error; | |||
} | |||
void | |||
@@ -99,6 +99,7 @@ void net_handshake(struct peer *p, int incoming); | |||
void net_read_cb(int sd, short type, void *arg); | |||
void net_write_cb(int sd, short type, void *arg); | |||
int net_connect2(struct sockaddr *sa, socklen_t salen, int *sd); | |||
int net_connect(const char *ip, int port, int *sd); | |||
void net_unsend_piece(struct peer *p, struct piece_req *req); | |||
@@ -1,4 +1,6 @@ | |||
#include <sys/types.h> | |||
#include <sys/socket.h> | |||
#include <netinet/in.h> | |||
#include <string.h> | |||
#include <unistd.h> | |||
@@ -173,6 +175,25 @@ peer_create_out(struct torrent *tp, | |||
p = peer_create_common(sd); | |||
p->tp = tp; | |||
bcopy(id, p->id, 20); | |||
//bcopy(id, p->id, 20); | |||
net_handshake(p, 0); | |||
} | |||
void | |||
peer_create_out_compact(struct torrent *tp, const char *compact) | |||
{ | |||
int sd; | |||
struct peer *p; | |||
struct sockaddr_in addr; | |||
addr.sin_family = AF_INET; | |||
addr.sin_addr.s_addr = *(long *)compact; | |||
addr.sin_port = *(short *)(compact + 4); | |||
if (net_connect2((struct sockaddr *)&addr, sizeof(addr), &sd) != 0) | |||
return; | |||
p = peer_create_common(sd); | |||
p->tp = tp; | |||
net_handshake(p, 0); | |||
} |
@@ -58,7 +58,7 @@ unsigned long peer_get_rate(unsigned long *rates); | |||
void peer_create_in(int sd); | |||
void peer_create_out(struct torrent *tp, const uint8_t *id, | |||
const char *ip, int port); | |||
void peer_create_out_compact(struct torrent *tp, const char *compact); | |||
void peer_kill(struct peer *p); | |||
#endif |
@@ -21,7 +21,7 @@ | |||
#define PRIu64 "llu" | |||
#endif | |||
#define REQ_SIZE (getpagesize() * 2) | |||
#define REQ_SIZE (1024 + 6 * 50) | |||
struct tracker_req { | |||
enum tr_event tr_event; | |||
@@ -102,16 +102,29 @@ tracker_done(struct child *child) | |||
tp->tracker_time = btpd.seconds + interval; | |||
if ((benc_dget_lst(req->res->buf, "peers", &peers)) != 0) { | |||
btpd_log(BTPD_L_TRACKER, "Bad data from tracker.\n"); | |||
failed = 1; | |||
goto out; | |||
int error = 0; | |||
size_t length; | |||
if ((error = benc_dget_lst(req->res->buf, "peers", &peers)) == 0) { | |||
for (peers = benc_first(peers); | |||
peers != NULL && btpd.npeers < btpd.maxpeers; | |||
peers = benc_next(peers)) | |||
maybe_connect_to(tp, peers); | |||
} | |||
for (peers = benc_first(peers); | |||
peers != NULL && btpd.npeers < btpd.maxpeers; | |||
peers = benc_next(peers)) | |||
maybe_connect_to(tp, peers); | |||
if (error == EINVAL) { | |||
error = benc_dget_str(req->res->buf, "peers", &peers, &length); | |||
if (error == 0 && length % 6 == 0) { | |||
for (size_t i = 0; i < length; i += 6) | |||
peer_create_out_compact(tp, peers + i * 6); | |||
} | |||
} | |||
if (error != 0) { | |||
btpd_log(BTPD_L_ERROR, "Bad data from tracker.\n"); | |||
failed = 1; | |||
goto out; | |||
} | |||
out: | |||
if (failed) { | |||
@@ -165,10 +178,13 @@ create_url(struct tracker_req *req, struct torrent *tp, char **url) | |||
left = torrent_bytes_left(tp); | |||
i = asprintf(url, "%s%cinfo_hash=%s&peer_id=%s&port=%d" | |||
i = asprintf(url, "%s%cinfo_hash=%s" | |||
"&peer_id=%s" | |||
"&port=%d" | |||
"&uploaded=%" PRIu64 | |||
"&downloaded=%" PRIu64 | |||
"&left=%" PRIu64 | |||
"&compact=1" | |||
"%s%s", | |||
tp->meta.announce, qc, e_hash, e_id, btpd.port, | |||
tp->uploaded, tp->downloaded, left, | |||