From: Thadeu Lima de Souza Cascardo Date: Sun, 6 Apr 2008 17:50:59 +0000 (-0300) Subject: Makes a TCP connection to given service at server. X-Git-Url: http://git.cascardo.info/?p=cascardo%2Fchat.git;a=commitdiff_plain;h=68aad407c269e1ccea8ccba21101ab6f93470890 Makes a TCP connection to given service at server. This is a synchronous/blocking implementation of a TCP connection. Given a domain name and service, uses SRV to get server name and port, orders it, and tries to get server address for each name, trying IPv6 before IPv4. --- diff --git a/tcp_connect.c b/tcp_connect.c new file mode 100644 index 0000000..54ea3fd --- /dev/null +++ b/tcp_connect.c @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2008 Thadeu Lima de Souza Cascardo + * + * 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 2 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 . + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include "sort_udns.h" + +int tcp_connect_a4 (struct in_addr addr, int port) +{ + int fd; + struct sockaddr_in in4; + fd = socket (PF_INET, SOCK_STREAM, 0); + if (fd < 0) + return -1; + in4.sin_family = AF_INET; + in4.sin_port = htons (port); + in4.sin_addr = addr; + if (connect (fd, (struct sockaddr *) &in4, sizeof (in4)) < 0) + { + close (fd); + return -1; + } + return fd; +} + +int +tcp_connect_a6 (struct in6_addr addr, int port) +{ + int fd; + struct sockaddr_in6 in6; + fd = socket (PF_INET6, SOCK_STREAM, 0); + if (fd < 0) + return -1; + memset (&in6, sizeof (in6), 0); + in6.sin6_family = AF_INET6; + in6.sin6_port = htons (port); + in6.sin6_addr = addr; + if (connect (fd, (struct sockaddr *) &in6, sizeof (in6)) < 0) + { + close (fd); + return -1; + } + return fd; +} + +int +tcp_connect4 (struct dns_srv srv) +{ + struct dns_rr_a4 *a4; + int i; + int fd; + a4 = dns_resolve_a4 (NULL, srv.name, 0); + if (a4 == NULL) + return -1; + for (i = 0; i < a4->dnsa4_nrr; i++) + { + fd = tcp_connect_a4 (a4->dnsa4_addr[i], srv.port); + if (fd >= 0) + { + free (a4); + return fd; + } + } + free (a4); + return -1; +} + +int +tcp_connect6 (struct dns_srv srv) +{ + struct dns_rr_a6 *a6; + int i; + int fd; + a6 = dns_resolve_a6 (NULL, srv.name, 0); + if (a6 == NULL) + return -1; + for (i = 0; i < a6->dnsa6_nrr; i++) + { + fd = tcp_connect_a6 (a6->dnsa6_addr[i], srv.port); + if (fd >= 0) + { + free (a6); + return fd; + } + } + free (a6); + return -1; +} + +int +tcp_connect (char *server, char *service) +{ + struct dns_rr_srv *srv; + int i; + int fd; + srv = dns_resolve_srv (NULL, server, service, "tcp", 0); + if (srv == NULL) + return -1; + dns_srv_sort (srv->dnssrv_srv, srv->dnssrv_nrr); + for (i = 0; i < srv->dnssrv_nrr; i++) + { + fd = tcp_connect6 (srv->dnssrv_srv[i]); + if (fd < 0) + fd = tcp_connect4 (srv->dnssrv_srv[i]); + if (fd >= 0) + { + free (srv); + return fd; + } + } + free (srv); + return -1; +} + +#ifdef TEST +int +main (int argc, char **argv) +{ + char *server; + char *service; + int fd; + dns_init (NULL, 1); + server = (argc >= 2) ? argv[1] : "holoscopio.com"; + service = (argc >= 3) ? argv[2] : "xmpp-client"; + fd = tcp_connect (server, service); + if (fd > 0) + close (fd); + return 0; +} +#endif diff --git a/tcp_connect.h b/tcp_connect.h new file mode 100644 index 0000000..1d62037 --- /dev/null +++ b/tcp_connect.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2008 Thadeu Lima de Souza Cascardo + * + * 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 2 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 . + * + */ + +#ifndef SORT_UDNS_H +#define SORT_UDNS_H + +int tcp_connect (char *, char*); + +#endif