blob: e0031ba0a79ebba9da7bbd5ce323858bcf01957c [file] [log] [blame]
Mark Salyzyn12717162014-04-29 15:49:14 -07001/*
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08002** Copyright 2006, The Android Open Source Project
3**
4** Licensed under the Apache License, Version 2.0 (the "License");
5** you may not use this file except in compliance with the License.
6** You may obtain a copy of the License at
7**
8** http://www.apache.org/licenses/LICENSE-2.0
9**
10** Unless required by applicable law or agreed to in writing, software
11** distributed under the License is distributed on an "AS IS" BASIS,
12** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13** See the License for the specific language governing permissions and
14** limitations under the License.
15*/
16
Mark Salyzyn12717162014-04-29 15:49:14 -070017#include <errno.h>
Ken Liermanaecc6a62013-06-20 09:27:13 -070018#include <fcntl.h>
Mark Salyzyn12717162014-04-29 15:49:14 -070019#include <stddef.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080020#include <stdlib.h>
21#include <string.h>
22#include <unistd.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080023
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080024#include <sys/socket.h>
25#include <sys/select.h>
26#include <sys/types.h>
27#include <netinet/in.h>
28#include <netdb.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080029
Mark Salyzyn12717162014-04-29 15:49:14 -070030#include <cutils/sockets.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080031
32/* Connect to port on the IP interface. type is
33 * SOCK_STREAM or SOCK_DGRAM.
34 * return is a file descriptor or -1 on error
35 */
36int socket_network_client(const char *host, int port, int type)
37{
Ken Liermanaecc6a62013-06-20 09:27:13 -070038 return socket_network_client_timeout(host, port, type, 0);
39}
40
41/* Connect to port on the IP interface. type is SOCK_STREAM or SOCK_DGRAM.
42 * timeout in seconds return is a file descriptor or -1 on error
43 */
44int socket_network_client_timeout(const char *host, int port, int type, int timeout)
45{
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080046 struct hostent *hp;
47 struct sockaddr_in addr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080048 int s;
Ken Liermanaecc6a62013-06-20 09:27:13 -070049 int flags = 0, error = 0, ret = 0;
50 fd_set rset, wset;
51 socklen_t len = sizeof(error);
52 struct timeval ts;
53
54 ts.tv_sec = timeout;
55 ts.tv_usec = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080056
57 hp = gethostbyname(host);
Ken Liermanaecc6a62013-06-20 09:27:13 -070058 if (hp == 0) return -1;
59
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080060 memset(&addr, 0, sizeof(addr));
61 addr.sin_family = hp->h_addrtype;
62 addr.sin_port = htons(port);
63 memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
64
65 s = socket(hp->h_addrtype, type, 0);
Ken Liermanaecc6a62013-06-20 09:27:13 -070066 if (s < 0) return -1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080067
Ken Liermanaecc6a62013-06-20 09:27:13 -070068 if ((flags = fcntl(s, F_GETFL, 0)) < 0) {
69 close(s);
70 return -1;
71 }
72
73 if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) {
74 close(s);
75 return -1;
76 }
77
78 if ((ret = connect(s, (struct sockaddr *) &addr, sizeof(addr))) < 0) {
79 if (errno != EINPROGRESS) {
80 close(s);
81 return -1;
82 }
83 }
84
85 if (ret == 0)
86 goto done;
87
88 FD_ZERO(&rset);
89 FD_SET(s, &rset);
90 wset = rset;
91
92 if ((ret = select(s + 1, &rset, &wset, NULL, (timeout) ? &ts : NULL)) < 0) {
93 close(s);
94 return -1;
95 }
96 if (ret == 0) { // we had a timeout
97 errno = ETIMEDOUT;
98 close(s);
99 return -1;
100 }
101
102 if (FD_ISSET(s, &rset) || FD_ISSET(s, &wset)) {
103 if (getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
104 close(s);
105 return -1;
106 }
107 } else {
108 close(s);
109 return -1;
110 }
111
112 if (error) { // check if we had a socket error
113 errno = error;
114 close(s);
115 return -1;
116 }
117
118done:
119 if (fcntl(s, F_SETFL, flags) < 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800120 close(s);
121 return -1;
122 }
123
124 return s;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800125}