_gnutls_strdatum_to_buf() will account for NULL input.
[gnutls.git] / src / socket.c
blob20c366f788cd32bd2d28c48fec13774f3c7419ee
1 /*
2 * Copyright (C) 2000-2012 Free Software Foundation, Inc.
4 * This file is part of GnuTLS.
6 * GnuTLS is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuTLS is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <config.h>
22 #if HAVE_SYS_SOCKET_H
23 # include <sys/socket.h>
24 #elif HAVE_WS2TCPIP_H
25 # include <ws2tcpip.h>
26 #endif
27 #include <netdb.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <sys/select.h>
31 #include <sys/types.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #ifndef _WIN32
36 # include <signal.h>
37 #endif
38 #include <socket.h>
39 #include "sockets.h"
41 #define MAX_BUF 4096
43 extern unsigned int verbose;
44 /* Functions to manipulate sockets
47 ssize_t
48 socket_recv (const socket_st * socket, void *buffer, int buffer_size)
50 int ret;
52 if (socket->secure)
56 ret = gnutls_record_recv (socket->session, buffer, buffer_size);
57 if (ret == GNUTLS_E_HEARTBEAT_PING_RECEIVED)
58 gnutls_heartbeat_pong(socket->session, 0);
60 while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_HEARTBEAT_PING_RECEIVED);
63 else
66 ret = recv (socket->fd, buffer, buffer_size, 0);
68 while (ret == -1 && errno == EINTR);
70 return ret;
73 ssize_t
74 socket_send (const socket_st * socket, const void *buffer, int buffer_size)
76 int ret;
78 if (socket->secure)
81 ret = gnutls_record_send (socket->session, buffer, buffer_size);
83 while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
84 else
87 ret = send (socket->fd, buffer, buffer_size, 0);
89 while (ret == -1 && errno == EINTR);
91 if (ret > 0 && ret != buffer_size && verbose)
92 fprintf (stderr,
93 "*** Only sent %d bytes instead of %d.\n", ret, buffer_size);
95 return ret;
98 void
99 socket_bye (socket_st * socket)
101 int ret;
102 if (socket->secure)
105 ret = gnutls_bye (socket->session, GNUTLS_SHUT_WR);
106 while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
107 if (ret < 0)
108 fprintf (stderr, "*** gnutls_bye() error: %s\n",
109 gnutls_strerror (ret));
110 gnutls_deinit (socket->session);
111 socket->session = NULL;
114 freeaddrinfo (socket->addr_info);
115 socket->addr_info = socket->ptr = NULL;
117 free (socket->ip);
118 free (socket->hostname);
119 free (socket->service);
121 shutdown (socket->fd, SHUT_RDWR); /* no more receptions */
122 close (socket->fd);
124 socket->fd = -1;
125 socket->secure = 0;
128 void
129 socket_open (socket_st * hd, const char *hostname, const char *service, int udp)
131 struct addrinfo hints, *res, *ptr;
132 int sd, err;
133 char buffer[MAX_BUF + 1];
134 char portname[16] = { 0 };
136 printf ("Resolving '%s'...\n", hostname);
137 /* get server name */
138 memset (&hints, 0, sizeof (hints));
139 hints.ai_socktype = udp ? SOCK_DGRAM : SOCK_STREAM;
140 if ((err = getaddrinfo (hostname, service, &hints, &res)))
142 fprintf (stderr, "Cannot resolve %s:%s: %s\n", hostname, service,
143 gai_strerror (err));
144 exit (1);
147 sd = -1;
148 for (ptr = res; ptr != NULL; ptr = ptr->ai_next)
150 sd = socket (ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
151 if (sd == -1)
152 continue;
154 if ((err = getnameinfo (ptr->ai_addr, ptr->ai_addrlen, buffer, MAX_BUF,
155 portname, sizeof (portname),
156 NI_NUMERICHOST | NI_NUMERICSERV)) != 0)
158 fprintf (stderr, "getnameinfo(): %s\n", gai_strerror (err));
159 continue;
162 if (hints.ai_socktype == SOCK_DGRAM)
164 #if defined(IP_DONTFRAG)
165 int yes = 1;
166 if (setsockopt (sd, IPPROTO_IP, IP_DONTFRAG,
167 (const void *) &yes, sizeof (yes)) < 0)
168 perror ("setsockopt(IP_DF) failed");
169 #elif defined(IP_MTU_DISCOVER)
170 int yes = IP_PMTUDISC_DO;
171 if (setsockopt(sd, IPPROTO_IP, IP_MTU_DISCOVER,
172 (const void*) &yes, sizeof (yes)) < 0)
173 perror ("setsockopt(IP_DF) failed");
174 #endif
178 printf ("Connecting to '%s:%s'...\n", buffer, portname);
180 err = connect (sd, ptr->ai_addr, ptr->ai_addrlen);
181 if (err < 0)
183 fprintf (stderr, "Cannot connect to %s:%s: %s\n", buffer,
184 portname, strerror (errno));
185 continue;
187 break;
190 if (err != 0)
191 exit(1);
193 if (sd == -1)
195 fprintf (stderr, "Could not find a supported socket\n");
196 exit (1);
199 hd->secure = 0;
200 hd->fd = sd;
201 hd->hostname = strdup (hostname);
202 hd->ip = strdup (buffer);
203 hd->service = strdup (portname);
204 hd->ptr = ptr;
205 hd->addr_info = res;
207 return;
210 void
211 sockets_init (void)
213 #ifdef _WIN32
214 WORD wVersionRequested;
215 WSADATA wsaData;
217 wVersionRequested = MAKEWORD (1, 1);
218 if (WSAStartup (wVersionRequested, &wsaData) != 0)
220 perror ("WSA_STARTUP_ERROR");
222 #else
223 signal (SIGPIPE, SIG_IGN);
224 #endif