summaryrefslogtreecommitdiffstats
path: root/src/tcp.c
blob: dc73d558e0d522f0685035acddbab61fb8f1f7be (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <sys/utsname.h>
void disconnection (struct torrent * t) {
	fprintf(stderr, "disconnecting from peer ");
	peer_print(stderr, t->dl);
	fprintf(stderr, " nfds=%ld, pollfds=%zu\n", *t->dht->nfds, *t->dht->pollfds_size);
	for (size_t i = 0; i < *t->dht->nfds; i++) {
		if ((*t->dht->pollfds)[i].fd == t->socket) {
			if (i != (*t->dht->nfds)--)
				(*t->dht->pollfds)[i] = (*t->dht->pollfds)[*t->dht->nfds];
			break;
		}
	}
	if (t->dl->flags & goodmeta) {
		char buf[128];
		bin2hex(buf, t->hash, 20);
		strcpy(buf+40, ".torrent");
		FILE * f = fopen(buf, "w+b");
		if (!f) {
			L(user, t->dht, "fopen(%s, \"w+b\"): %s", buf, strerror(errno));
			return;
		}
		char remote[INET6_ADDRSTRLEN + 64];
		if (!inet_ntop(t->dl->addr.sin6_family, t->dl->addr.sin6_addr.s6_addr, remote, INET6_ADDRSTRLEN+7))
			snprintf(remote, sizeof remote,  "(inet_ntop: %s)", strerror(errno));
		sprintf(remote+strlen(remote), "/%d", ntohs(t->dl->addr.sin6_port));
		char createdby[1024];
		char unam[512];
		char * machinetext = unam;
		struct utsname utsname;
		if (uname(&utsname) == -1)
			snprintf(unam, 512, "uname(&utsname) == -1, errno == %d (%s)", errno, strerror(errno));
		else
			snprintf(unam, 512, "%s %s %s %s %s"
#ifdef _GNU_SOURCE
				" %s"
#endif
				, utsname.sysname, utsname.nodename, utsname.release, utsname.version, utsname.machine
#ifdef _GNU_SOURCE
				, utsname.domainname
#endif
				);
		if (getenv("CREATED_BY"))
			machinetext = getenv("CREATED_BY");
		snprintf(createdby, 1024, "http://ni.šijanec.eu/sijanec/travnik mailto:tk@sijanec.eu %s", machinetext);
		fprintf(f, "d10:created by%zu:%s13:creation datei%lde8:encoding5:UTF-84:info", strlen(createdby), createdby, time(NULL));
		fwrite(t->metadata, 1, t->size, f); // i don't expect any errors here
		fprintf(f, "6:sourced2:ip%zu:%s", strlen(remote), remote);
		if (t->software)
			fprintf(f, "1:v%zu:%s", strlen(t->software), t->software);
		fputs("ee", f);
		if (fclose(f) == EOF)
			L(user, t->dht, "fclose(%s): %s", buf, strerror(errno));
	}
#ifdef DISCONNECTION_MIXIN_BOTTOM
	DISCONNECTION_MIXIN_BOTTOM
#endif
}
void intentions (struct torrent * t) {
	for (size_t i = 0; i < *t->dht->nfds; i++)
		if ((*t->dht->pollfds)[i].fd == t->socket) {
			(*t->dht->pollfds)[i].events &= ~(POLLIN | POLLOUT);
			if (t->state & incoming)
				(*t->dht->pollfds)[i].events |= POLLIN;
			if (t->state & outgoing)
				(*t->dht->pollfds)[i].events |= POLLOUT;
		}
	fprintf(stderr, "tcp intentions: ");
	peer_print(stderr, t->dl);
	fprintf(stderr, " nfds=%ld, pollfds=%zu%s%s\n", *t->dht->nfds, *t->dht->pollfds_size, (t->state & incoming) ? " reading" : "", (t->state & outgoing) ? " writing" : "");
}
void connection (struct dht * d, struct torrent * t) {
	if (*d->pollfds_size <= *d->nfds)
		*d->pollfds = reallocarray(*d->pollfds, (*d->pollfds_size *= 2), sizeof **d->pollfds);
	(*d->pollfds)[*d->nfds].events = POLLIN | POLLOUT;
	(*d->pollfds)[(*d->nfds)++].fd = t->socket;
	fprintf(stderr, "attempting to connect to peer ");
	peer_print(stderr, t->dl);
	fprintf(stderr, " nfds=%ld, pollfds=%zu\n", *d->nfds, *d->pollfds_size);
	t->disconnection = disconnection;
	t->dht = d;
	t->intentions = intentions;
}