From 3a8c091da4c77d51ad26c3822d706d83d8658d41 Mon Sep 17 00:00:00 2001 From: mykola2312 <49044616+mykola2312@users.noreply.github.com> Date: Tue, 29 Mar 2022 13:31:53 +0300 Subject: [PATCH] initial commit --- .gitignore | 6 +++ CMakeLists.txt | 8 +++ udptracker.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 udptracker.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..31b56fc --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.vscode +CMakeFiles +CMakeCache.txt +Makefile +*.cmake +udptracker \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..f227e42 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.10) +project(udptracker) + +set(SOURCES + udptracker.c +) + +add_executable(udptracker ${SOURCES}) \ No newline at end of file diff --git a/udptracker.c b/udptracker.c new file mode 100644 index 0000000..8eccfd9 --- /dev/null +++ b/udptracker.c @@ -0,0 +1,142 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define INIT_CONNECTION_ID 0x41727101980ULL +#define ACTION_CONNECT 0 +#define ACTION_ANNOUNCE 1 +#define ANNOUNCE_NUMWANT -1 + +struct connect_request_s { + uint64_t connection_id; + uint32_t action; + uint32_t transaction_id; +} __attribute__((packed)); + +struct connect_response_s { + uint32_t action; + uint32_t transaction_id; + uint64_t connection_id; +} __attribute__((packed)); + +struct announce_request_s { + uint64_t connection_id; + uint32_t action; + uint32_t transaction_id; + uint8_t info_hash[20]; + uint8_t peer_id[20]; + uint64_t downloaded; + uint64_t left; + uint64_t uploaded; + uint32_t event; + uint32_t ip_address; + uint32_t key; + int32_t numwant; + uint16_t port; +} __attribute__((packed)); + +struct announce_response_s { + uint32_t action; + uint32_t transaction_id; + uint32_t interval; + uint32_t leechers; + uint32_t seeders; +} __attribute__((packed)); + +struct peer_s { + uint32_t ip_address; + uint16_t port; +} __attribute__((packed)); + +static void _sendto(int sockfd, const void* data, size_t size, + const struct sockaddr* paddr, socklen_t socklen) +{ + ssize_t sent = sendto(sockfd, data, size, 0, paddr, socklen); + if (sent == -1) + { + fprintf(stderr, "sendto errno %d error %s\n", + errno, strerror(errno)); + } +} + +static ssize_t _recvfrom(int sockfd, void* data, size_t size, + struct sockaddr* paddr, socklen_t* socklen) +{ + ssize_t read = recvfrom(sockfd, data, size, 0, paddr, socklen); + if (read == -1) + { + fprintf(stderr, "recvfrom errno %d error %s\n", + errno, strerror(errno)); + } + + return read; +} + +int main(int argc, char** argv) +{ + if (argc < 3) + { + fprintf(stderr, "%s \n", argv[0]); + return 1; + } + + struct hostent* host = gethostbyname(argv[1]); + if (!host) + { + fprintf(stderr, "Host not found: %d\n", errno); + return 1; + } + + if (host->h_addrtype == AF_INET6) + { + char buf[48] = {0}; + fprintf(stderr, "IPv6 not supported yet: %s\n", + inet_ntop(AF_INET6, host->h_addr_list[0], buf, 48)); + return 1; + } + + struct sockaddr_in addr = {0}; + struct sockaddr* paddr = (struct sockaddr*)&addr; + socklen_t addrlen = sizeof(addr); + addr.sin_family = host->h_addrtype; + memcpy(&addr.sin_addr, host->h_addr_list[0], addrlen); + addr.sin_port = htons(atoi(argv[2])); + + printf("%s\t%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); + + int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + + srand(time(NULL)); + uint64_t connection_id = INIT_CONNECTION_ID; + uint32_t transaction_id = rand(); + printf("connect\ttransaction\t%u\n", transaction_id); + { + struct connect_request_s req = { + .connection_id = __bswap_64(INIT_CONNECTION_ID), + .action = __bswap_32(ACTION_CONNECT), + .transaction_id = transaction_id + }; + _sendto(sockfd, &req, sizeof(req), paddr, addrlen); + + struct connect_response_s res = {0}; + _recvfrom(sockfd, &res, sizeof(res), paddr, &addrlen); + res.action = __bswap_32(res.action); + res.transaction_id = __bswap_32(res.transaction_id); + res.connection_id = __bswap_64(res.connection_id); + printf("%u\t%u\t%lu\n", res.action, + res.transaction_id, res.connection_id); + + connection_id = res.connection_id; + } + + close(sockfd); + + return 0; +} \ No newline at end of file