"Fossies" - the Fresh Open Source Software Archive 
Member "HTTPing-2.9/tcp.c" (29 Oct 2022, 5148 Bytes) of package /linux/www/HTTPing-2.9.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "tcp.c" see the
Fossies "Dox" file reference documentation.
1 /* Released under AGPL v3 with exception for the OpenSSL library. See license.txt */
2
3 #include <sys/types.h>
4 #include <sys/time.h>
5 #include <sys/socket.h>
6 #include <netinet/in.h>
7 #include <netinet/tcp.h>
8 #include <arpa/inet.h>
9 #include <libintl.h>
10 #include <netdb.h>
11 #include <errno.h>
12 #include <stdio.h>
13 #include <string.h>
14 #include <unistd.h>
15
16 #include "error.h"
17 #include "gen.h"
18 #include "io.h"
19 #include "main.h"
20 #include "tcp.h"
21
22 void failure_close(int fd)
23 {
24 struct linger sl;
25
26 sl.l_onoff = 1;
27 sl.l_linger = 0;
28
29 if (setsockopt(fd, SOL_SOCKET, SO_LINGER, &sl, sizeof sl) == -1)
30 set_error(gettext("could not set TCP_NODELAY on socket (%s)"), strerror(errno));
31
32 close(fd);
33 }
34
35 int set_no_delay(int fd)
36 {
37 int flag = 1;
38
39 if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int)) == -1)
40 {
41 set_error(gettext("could not set TCP_NODELAY on socket (%s)"), strerror(errno));
42 return -1;
43 }
44
45 return 0;
46 }
47
48 int create_socket(struct sockaddr *bind_to, struct addrinfo *ai, int recv_buffer_size, int tx_buffer_size, int max_mtu, char use_no_delay, int priority, int tos)
49 {
50 int fd = -1;
51
52 /* create socket */
53 fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
54 if (fd == -1)
55 {
56 set_error(gettext("problem creating socket (%s)"), strerror(errno));
57 return RC_INVAL;
58 }
59
60 /* go through a specific interface? */
61 if (bind_to)
62 {
63 int set = 1;
64
65 /* set reuse flags */
66 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &set, sizeof set) == -1)
67 {
68 set_error(gettext("error setting sockopt to interface (%s)"), strerror(errno));
69 close(fd);
70 return RC_INVAL;
71 }
72
73 if (bind(fd, bind_to, sizeof *bind_to) == -1)
74 {
75 set_error(gettext("error binding to interface (%s)"), strerror(errno));
76 close(fd);
77 return RC_INVAL;
78 }
79 }
80
81 if (max_mtu >= 0)
82 {
83 if (setsockopt(fd, IPPROTO_TCP, TCP_MAXSEG, &max_mtu, sizeof max_mtu) == -1)
84 {
85 set_error(gettext("error setting MTU size (%s)"), strerror(errno));
86 close(fd);
87 return RC_INVAL;
88 }
89 }
90
91 if (use_no_delay)
92 {
93 int rc = -1;
94
95 if ((rc = set_no_delay(fd)) != 0)
96 return rc;
97 }
98
99 if (tx_buffer_size > 0)
100 {
101 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *)&tx_buffer_size, sizeof tx_buffer_size) == -1)
102 {
103 set_error(gettext("error setting transmit buffer size (%s)"), strerror(errno));
104 close(fd);
105 return RC_INVAL;
106 }
107 }
108
109 if (recv_buffer_size > 0)
110 {
111 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&recv_buffer_size, sizeof recv_buffer_size) == -1)
112 {
113 set_error(gettext("error setting receive buffer size (%s)"), strerror(errno));
114 close(fd);
115 return RC_INVAL;
116 }
117 }
118
119 #ifdef linux
120 if (priority >= 0)
121 {
122 if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, (char *)&priority, sizeof priority) == -1)
123 {
124 set_error(gettext("error setting priority (%s)"), strerror(errno));
125 close(fd);
126 return RC_INVAL;
127 }
128 }
129 #endif
130
131 if (tos >= 0)
132 {
133 if (setsockopt(fd, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof tos) == -1)
134 {
135 set_error(gettext("failed to set TOS info"));
136 close(fd);
137 return RC_INVAL;
138 }
139 }
140
141 return fd;
142 }
143
144 int connect_to(int fd, struct addrinfo *ai, double timeout, char *tfo, char *msg, int msg_len, char *msg_accepted)
145 {
146 int rc = -1;
147 struct timeval to;
148 fd_set wfds;
149
150 /* make fd nonblocking */
151 if (set_fd_nonblocking(fd) == -1)
152 return RC_INVAL;
153
154 /* wait for connection */
155 FD_ZERO(&wfds);
156 FD_SET(fd, &wfds);
157
158 to.tv_sec = (long)(timeout / 1000.0);
159 to.tv_usec = (long)(timeout * 1000.0) % 1000000;
160
161 /* connect to peer */
162 #ifdef TCP_TFO
163 if (tfo && *tfo)
164 {
165 rc = sendto(fd, msg, msg_len, MSG_FASTOPEN, ai -> ai_addr, ai -> ai_addrlen);
166
167 if(rc == msg_len)
168 *msg_accepted = 1;
169 if(errno == 0)
170 return RC_OK;
171 if(errno == ENOTSUP)
172 {
173 printf(gettext("TCP TFO Not Supported. Please check if \"/proc/sys/net/ipv4/tcp_fastopen\" is 1. Disabling TFO for now.\n"));
174 *tfo = 0;
175 goto old_connect;
176 }
177 }
178
179 else
180 #else
181 (void)tfo;
182 (void)msg;
183 (void)msg_len;
184 (void)msg_accepted;
185 #endif
186 {
187 int rc = -1;
188
189 old_connect:
190 rc = connect(fd, ai -> ai_addr, ai -> ai_addrlen);
191
192 if (rc == 0)
193 {
194 /* connection made, return */
195 return RC_OK;
196 }
197
198 if (rc == -1)
199 {
200 /* problem connecting */
201 if (errno != EINPROGRESS)
202 {
203 set_error(gettext("problem connecting to host: %s"), strerror(errno));
204 return RC_INVAL;
205 }
206 }
207 }
208
209 if (stop)
210 return RC_CTRLC;
211
212 /* wait for connection */
213 rc = select(fd + 1, NULL, &wfds, NULL, &to);
214 if (rc == 0)
215 {
216 set_error(gettext("connect time out"));
217 return RC_TIMEOUT; /* timeout */
218 }
219 else if (rc == -1)
220 {
221 if (errno == EINTR)
222 return RC_CTRLC;/* ^C pressed */
223
224 set_error(gettext("select() failed: %s"), strerror(errno));
225
226 return RC_INVAL; /* error */
227 }
228 else
229 {
230 int optval=0;
231 socklen_t optvallen = sizeof optval;
232
233 /* see if the connect succeeded or failed */
234 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &optval, &optvallen) == -1)
235 {
236 set_error(gettext("getsockopt failed (%s)"), strerror(errno));
237 return RC_INVAL;
238 }
239
240 /* no error? */
241 if (optval == 0)
242 return RC_OK;
243
244 /* don't ask */
245 errno = optval;
246 }
247
248 set_error(gettext("could not connect (%s)"), strerror(errno));
249
250 return RC_INVAL;
251 }