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 113 114
|
#include "address.h"
#include <cstring>
#include <stdio.h>
#include <cstdlib>
#include <netdb.h>
#include <sys/socket.h>
typedef char *PCHAR;
address::address(const char *addr, unsigned short default_port)
{
unsigned short port = default_port;
char *addr_copy = strdup(addr);
int len = strlen(addr);
m_count = 1;
int i;
for(i = 0; i < len; i++)
{
if(addr_copy[i] == ',')
m_count++;
}
char **names = (char **)malloc(m_count * sizeof(char *));
int ind = 0;
for(i = 0; i < m_count; i++)
{
names[i] = &addr_copy[ind];
while(addr_copy[ind] && addr_copy[ind] != ',')
ind++;
addr_copy[ind] = '\0';
ind++;
}
m_rr_dns = (bool *)malloc(m_count * sizeof(bool));
m_addr = (sockaddr_in *)malloc(m_count * sizeof(sockaddr_in));
m_hostname = (char **)malloc(m_count * sizeof(char *));
for(i = 0; i < m_count; i++)
{
char *hostname = names[i];
if(hostname[0] == '+')
{
m_rr_dns[i] = true;
hostname++;
}
else
{
m_rr_dns[i] = false;
}
if(hostname[0] == '[')
{
hostname++;
int j;
for(j = 0; hostname[j] && hostname[j] != ']'; j++)
{}
if(!hostname[j])
{
fprintf(stderr, "Bad address: %s\n", addr);
exit(1);
}
hostname[j] = '\0';
port = atoi(&hostname[j + 1]);
}
m_hostname[i] = strdup(hostname);
m_addr[i].sin_family = AF_INET;
m_addr[i].sin_port = htons(port);
if(!m_rr_dns[i])
{
if(resolve_name(i))
exit(1);
}
}
free(names);
free(addr_copy);
}
address::~address()
{
for(int i = 0; i < m_count; i++)
free(m_hostname[i]);
free(m_hostname);
free(m_rr_dns);
free(m_addr);
}
int address::resolve_name(int ind)
{
hostent *he = gethostbyname(m_hostname[ind]);
if(!he)
{
fprintf(stderr, "Bad address \"%s\" for server.\n", m_hostname[ind]);
return 1;
}
m_addr[ind].sin_addr.s_addr = *((unsigned int *)he->h_addr_list[0]);
return 0;
}
sockaddr *address::get_rand_addr()
{
int ind = 0;
if(m_count > 1)
ind = rand() % m_count;
return get_addr(ind);
}
sockaddr *address::get_addr(int ind)
{
if(ind < 0 || ind > m_count)
return get_rand_addr();
if(m_rr_dns[ind])
{
if(resolve_name(ind))
return NULL;
}
return (sockaddr *)&m_addr[ind];
}
|