aboutsummaryrefslogtreecommitdiff
path: root/mcnetwork.c
blob: 2d350c86c309bf610787f42d6e373fc7247acdbc (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
83
84
#include "mcnetwork.h"

#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>

#include "mctypes.h"

void send_ping_handshake(int socket, int protocol, char* address,
    unsigned short port, int next_state)
{
    void* raw_handshake;
    size_t handshake_size;
    handshake hs = { to_varint(protocol),
        { to_varint(strlen(address)), address }, port, to_varint(next_state) };
    handshake_size = serialize_handshake(hs, &raw_handshake);
    send_ping_packet(socket, 0x0, handshake_size, raw_handshake);
    free_handshake(hs);
}

void send_ping_packet(int socket, int packet_id, size_t raw_size, void* payload)
{
    void* raw_packet;
    size_t p_size;
    packet p = { to_varint(raw_size + size_varint(to_varint(packet_id))),
        to_varint(packet_id), payload };
    p_size = serialize_packet(p, &raw_packet);
    free_packet(p);

    if (send(socket, raw_packet, p_size, 0) < 0)
        perror("packet failed");
}

void connect_mc_server(int socket, char* address, unsigned short port, int protocol)
{
    struct addrinfo* mc_info = malloc(sizeof(struct addrinfo));
    memset(mc_info, 0, sizeof(struct addrinfo));
    struct addrinfo hints;
    memset(&hints, 0, sizeof(struct addrinfo));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = protocol;

    if (getaddrinfo(address, "80", &hints, &mc_info) != 0)
		exit(1);

    struct sockaddr_in mc_sock;
    mc_sock.sin_family = AF_INET;
    mc_sock.sin_port = htons(port);
    memcpy(&mc_sock.sin_addr, mc_info->ai_addr->sa_data + 2,
        mc_info->ai_addrlen); // stupidity

    freeaddrinfo(mc_info);

    if (connect(socket, (struct sockaddr*)&mc_sock, sizeof(mc_sock)) < 0)
		exit(1);
}

varint recv_varint(int s)
{
    unsigned long i = 0;
    varint v = NULL;
    do {
        v = reallocarray(v, i, sizeof(u_int8_t));
        recv(s, v + i, 1, 0);
        i++;
    } while ((v[i - 1] & 0x80) != 0);
    return v;
}

packet recv_packet(int socket)
{
    packet p;
    size_t data_size;
    p.length = recv_varint(socket);
    p.id = recv_varint(socket);
    data_size = from_varint(p.length) - size_varint(p.id);
    p.data = malloc(data_size);
    recv(socket, p.data, data_size, MSG_WAITALL);
    return p;
}