You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
111 lines
2.8 KiB
111 lines
2.8 KiB
/**
|
|
* \file
|
|
*
|
|
* \author Georg Hopp
|
|
*
|
|
* \copyright
|
|
* Copyright © 2014 Georg Hopp
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#define _POSIX_SOURCE 1
|
|
|
|
#include <stdlib.h> // for atoi() and exit()
|
|
#include <errno.h> // for errno
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <netdb.h>
|
|
|
|
#include "tr/socket.h"
|
|
#include "tr/logger.h"
|
|
|
|
int
|
|
TR_socketInit(TR_Socket this, TR_socketAction_fptr action)
|
|
{
|
|
struct addrinfo hint;
|
|
struct addrinfo * info, * current_info;
|
|
char port_str[6];
|
|
int code;
|
|
|
|
hint.ai_socktype = this->type;
|
|
hint.ai_flags = this->flags;
|
|
hint.ai_family = AF_UNSPEC;
|
|
hint.ai_protocol = 0;
|
|
hint.ai_addrlen = 0;
|
|
hint.ai_canonname = NULL;
|
|
hint.ai_addr = NULL;
|
|
hint.ai_next = NULL;
|
|
|
|
sprintf(port_str, "%u", this->port);
|
|
code = getaddrinfo(this->host, port_str, &hint, &info);
|
|
if (0 != code) {
|
|
// TODO error handling...
|
|
puts(gai_strerror(code));
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
current_info = info;
|
|
for (
|
|
current_info = info;
|
|
current_info;
|
|
current_info = current_info->ai_next)
|
|
{
|
|
this->handle = socket(
|
|
current_info->ai_family,
|
|
current_info->ai_socktype,
|
|
current_info->ai_protocol);
|
|
|
|
if (-1 == this->handle) {
|
|
continue;
|
|
}
|
|
|
|
this->addrlen = current_info->ai_addrlen;
|
|
memcpy(&(this->addr), current_info->ai_addr, this->addrlen);
|
|
|
|
if (0 == action(this)) {
|
|
break; // success / open and bind or open and connect...
|
|
}
|
|
|
|
close(this->handle);
|
|
this->handle = -1;
|
|
}
|
|
|
|
if (NULL != current_info) {
|
|
int reUse = 1; //! \todo make this configurable
|
|
//int flags = fcntl(this->handle, F_GETFL, 0);
|
|
|
|
//fcntl(this->handle, F_SETFL, flags | O_NONBLOCK);
|
|
if (current_info->ai_canonname) {
|
|
this->cname[TR_MAX_CNAME-1] = 0;
|
|
strncpy(this->cname, current_info->ai_canonname, TR_MAX_CNAME-1);
|
|
}
|
|
this->fin_state = TR_FIN_NO;
|
|
|
|
//! Make the socket REUSE a TIME_WAIT socket
|
|
setsockopt(this->handle, SOL_SOCKET, SO_REUSEADDR, &reUse, sizeof(reUse));
|
|
}
|
|
|
|
freeaddrinfo(info);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// vim: set ts=4 sw=4:
|