aboutsummaryrefslogtreecommitdiff
path: root/src/DirectConnection.cpp
blob: 12ae761dec0838907c7b45a5f48ac2fe52b6186b (plain)
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include "../include/DirectConnection.hpp"
#include <cstdio>
#include <cstring>

#ifndef WIN32
   #include <arpa/inet.h>
   #include <netdb.h>
#else
   #include <winsock2.h>
   #include <ws2tcpip.h>
#endif
#include <udt/udt.h>

namespace sibs
{
    Ipv4::Ipv4(const char *ip, u16 port)
    {        
        struct addrinfo hints = {};
        hints.ai_flags = AI_PASSIVE;
        hints.ai_family = AF_INET;
        hints.ai_socktype = SOCK_STREAM;
        
        char portStr[6];
        sprintf(portStr, "%d", port);
        int addrInfoResult = getaddrinfo(ip, portStr, &hints, &address);
        if(addrInfoResult != 0)
        {
            std::string errMsg = "Ip ";
            errMsg += ip;
            errMsg += " is not a valid ip";
            throw InvalidAddressException(errMsg);
        }
    }
    
    Ipv4::~Ipv4()
    {
        freeaddrinfo(address);
    }
    
    DirectConnections::DirectConnections() : 
        mySocket(0)
    {
        try
        {
            init();
        }
        catch(...)
        {
            cleanup();
        }
    }
    
    DirectConnections::~DirectConnections()
    {
        cleanup();
    }
    
    void DirectConnections::init()
    {
        UDT::startup();
        eid = UDT::epoll_create();
        mySocket = UDT::socket(AI_PASSIVE, AF_INET, SOCK_STREAM);
        bool rendezvous = true;
        UDT::setsockopt(mySocket, 0, UDT_RENDEZVOUS, &rendezvous, sizeof(bool));
        bool reuseAddr = true;
        UDT::setsockopt(mySocket, 0, UDT_REUSEADDR, &reuseAddr, sizeof(bool));
        
        // Windows UDP issue
        // For better performance, modify HKLM\System\CurrentControlSet\Services\Afd\Parameters\FastSendDatagramThreshold
        #ifdef WIN32
        int mss = 1052;
        UDT::setsockopt(socket, 0, UDT_MSS, &mss, sizeof(mss));
        #endif
        
        sockaddr_in myAddr = {};
        myAddr.sin_family = AF_INET;
        myAddr.sin_port = htons(9000);
        myAddr.sin_addr.s_addr = INADDR_ANY;
        memset(&myAddr.sin_zero, '\0', 8);

        if(UDT::bind(mySocket, (sockaddr*)&myAddr, sizeof(myAddr)) == UDT::ERROR)
        {
            // TODO: Add ip and port to error
            std::string errMsg = "UDT: Failed to bind, error: ";
            errMsg += UDT::getlasterror().getErrorMessage();
            throw ConnectionException(errMsg);
        }
    }
    
    void DirectConnections::cleanup()
    {
        UDT::epoll_release(eid);
        
        if(mySocket != 0)
            UDT::close(mySocket);
        
        UDT::cleanup();
    }
    
    void DirectConnections::connect(const Ipv4 &address)
    {
        if(UDT::connect(mySocket, address.address->ai_addr, address.address->ai_addrlen) == UDT::ERROR)
        {
            // TODO: Add ip and port to error
            std::string errMsg = "UDT: Failed to connect, error: ";
            errMsg += UDT::getlasterror().getErrorMessage();
            throw ConnectionException(errMsg);
        }
        
        //UDT::epoll_add_usock(eid, 2);
    } 
}