OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include <arpa/inet.h> | 5 #include <arpa/inet.h> |
6 #include <errno.h> | 6 #include <errno.h> |
7 #include <netdb.h> | 7 #include <netdb.h> |
8 #include <stdio.h> | 8 #include <stdio.h> |
9 #include <stdlib.h> | 9 #include <stdlib.h> |
10 #include <string.h> | 10 #include <string.h> |
11 #include <sys/socket.h> | 11 #include <sys/socket.h> |
12 #include <unistd.h> | 12 #include <unistd.h> |
13 | 13 |
14 #include "bin/fdutils.h" | 14 #include "bin/fdutils.h" |
15 #include "bin/socket.h" | 15 #include "bin/socket.h" |
16 | 16 |
17 | 17 |
18 bool Socket::Initialize() { | 18 bool Socket::Initialize() { |
19 // Nothing to do on Mac OS. | 19 // Nothing to do on Mac OS. |
20 return true; | 20 return true; |
21 } | 21 } |
22 | 22 |
23 | 23 |
24 intptr_t Socket::CreateConnect(const char* host, const intptr_t port) { | 24 intptr_t Socket::CreateConnect(const char* host, const intptr_t port) { |
25 intptr_t fd; | 25 intptr_t fd; |
26 struct hostent* server; | 26 struct hostent* server; |
27 struct sockaddr_in server_address; | 27 struct sockaddr_in server_address; |
28 | 28 |
29 fd = socket(AF_INET, SOCK_STREAM, 0); | 29 fd = TEMP_FAILURE_RETRY(socket(AF_INET, SOCK_STREAM, 0)); |
30 if (fd < 0) { | 30 if (fd < 0) { |
31 fprintf(stderr, "Error CreateConnect: %s\n", strerror(errno)); | 31 fprintf(stderr, "Error CreateConnect: %s\n", strerror(errno)); |
32 return -1; | 32 return -1; |
33 } | 33 } |
34 | 34 |
35 FDUtils::SetNonBlocking(fd); | 35 FDUtils::SetNonBlocking(fd); |
36 | 36 |
37 server = gethostbyname(host); | 37 server = gethostbyname(host); |
38 if (server == NULL) { | 38 if (server == NULL) { |
39 close(fd); | 39 TEMP_FAILURE_RETRY(close(fd)); |
40 fprintf(stderr, "Error CreateConnect: %s\n", strerror(errno)); | 40 fprintf(stderr, "Error CreateConnect: %s\n", strerror(errno)); |
41 return -1; | 41 return -1; |
42 } | 42 } |
43 | 43 |
44 server_address.sin_family = AF_INET; | 44 server_address.sin_family = AF_INET; |
45 server_address.sin_port = htons(port); | 45 server_address.sin_port = htons(port); |
46 bcopy(server->h_addr, &server_address.sin_addr.s_addr, server->h_length); | 46 bcopy(server->h_addr, &server_address.sin_addr.s_addr, server->h_length); |
47 memset(&server_address.sin_zero, 0, sizeof(server_address.sin_zero)); | 47 memset(&server_address.sin_zero, 0, sizeof(server_address.sin_zero)); |
48 intptr_t result = connect(fd, | 48 intptr_t result = TEMP_FAILURE_RETRY( |
49 reinterpret_cast<struct sockaddr *>(&server_address), | 49 connect(fd, |
50 sizeof(server_address)); | 50 reinterpret_cast<struct sockaddr *>(&server_address), |
| 51 sizeof(server_address))); |
51 if (result == 0 || errno == EINPROGRESS) { | 52 if (result == 0 || errno == EINPROGRESS) { |
52 return fd; | 53 return fd; |
53 } | 54 } |
54 return -1; | 55 return -1; |
55 } | 56 } |
56 | 57 |
57 | 58 |
58 intptr_t Socket::Available(intptr_t fd) { | 59 intptr_t Socket::Available(intptr_t fd) { |
59 return FDUtils::AvailableBytes(fd); | 60 return FDUtils::AvailableBytes(fd); |
60 } | 61 } |
61 | 62 |
62 | 63 |
63 int Socket::Read(intptr_t fd, void* buffer, intptr_t num_bytes) { | 64 int Socket::Read(intptr_t fd, void* buffer, intptr_t num_bytes) { |
64 ASSERT(fd >= 0); | 65 ASSERT(fd >= 0); |
65 ssize_t read_bytes = read(fd, buffer, num_bytes); | 66 ssize_t read_bytes = TEMP_FAILURE_RETRY(read(fd, buffer, num_bytes)); |
66 if (read_bytes == -1 && | 67 ASSERT(EAGAIN == EWOULDBLOCK); |
67 (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)) { | 68 if (read_bytes == -1 && errno == EWOULDBLOCK) { |
68 // If the read was interrupted or the read would block we need | 69 // If the read would block we need to retry and therefore return 0 |
69 // to retry and therefore return 0 as the number of bytes written. | 70 // as the number of bytes written. |
70 read_bytes = 0; | 71 read_bytes = 0; |
71 } | 72 } |
72 return read_bytes; | 73 return read_bytes; |
73 } | 74 } |
74 | 75 |
75 | 76 |
76 int Socket::Write(intptr_t fd, const void* buffer, intptr_t num_bytes) { | 77 int Socket::Write(intptr_t fd, const void* buffer, intptr_t num_bytes) { |
77 ASSERT(fd >= 0); | 78 ASSERT(fd >= 0); |
78 ssize_t written_bytes = write(fd, buffer, num_bytes); | 79 ssize_t written_bytes = TEMP_FAILURE_RETRY(write(fd, buffer, num_bytes)); |
79 if (written_bytes == -1 && | 80 ASSERT(EAGAIN == EWOULDBLOCK); |
80 (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)) { | 81 if (written_bytes == -1 && errno == EWOULDBLOCK) { |
81 // If the write was interrupted or the write would block we need | 82 // If the would block we need to retry and therefore return 0 as |
82 // to retry and therefore return 0 as the number of bytes written. | 83 // the number of bytes written. |
83 written_bytes = 0; | 84 written_bytes = 0; |
84 } | 85 } |
85 return written_bytes; | 86 return written_bytes; |
86 } | 87 } |
87 | 88 |
88 | 89 |
89 intptr_t Socket::GetPort(intptr_t fd) { | 90 intptr_t Socket::GetPort(intptr_t fd) { |
90 ASSERT(fd >= 0); | 91 ASSERT(fd >= 0); |
91 struct sockaddr_in socket_address; | 92 struct sockaddr_in socket_address; |
92 socklen_t size = sizeof(socket_address); | 93 socklen_t size = sizeof(socket_address); |
93 if (getsockname(fd, reinterpret_cast<struct sockaddr *>(&socket_address), | 94 if (TEMP_FAILURE_RETRY( |
94 &size)) { | 95 getsockname(fd, |
| 96 reinterpret_cast<struct sockaddr *>(&socket_address), |
| 97 &size))) { |
95 fprintf(stderr, "Error getsockname: %s\n", strerror(errno)); | 98 fprintf(stderr, "Error getsockname: %s\n", strerror(errno)); |
96 return 0; | 99 return 0; |
97 } | 100 } |
98 return ntohs(socket_address.sin_port); | 101 return ntohs(socket_address.sin_port); |
99 } | 102 } |
100 | 103 |
101 | 104 |
102 intptr_t Socket::GetStdioHandle(int num) { | 105 intptr_t Socket::GetStdioHandle(int num) { |
103 return static_cast<intptr_t>(num); | 106 return static_cast<intptr_t>(num); |
104 } | 107 } |
105 | 108 |
106 | 109 |
107 intptr_t ServerSocket::CreateBindListen(const char* host, | 110 intptr_t ServerSocket::CreateBindListen(const char* host, |
108 intptr_t port, | 111 intptr_t port, |
109 intptr_t backlog) { | 112 intptr_t backlog) { |
110 intptr_t fd; | 113 intptr_t fd; |
111 struct sockaddr_in server_address; | 114 struct sockaddr_in server_address; |
112 | 115 |
113 fd = socket(AF_INET, SOCK_STREAM, 0); | 116 fd = TEMP_FAILURE_RETRY(socket(AF_INET, SOCK_STREAM, 0)); |
114 if (fd < 0) { | 117 if (fd < 0) { |
115 fprintf(stderr, "Error CreateBind: %s\n", strerror(errno)); | 118 fprintf(stderr, "Error CreateBind: %s\n", strerror(errno)); |
116 return -1; | 119 return -1; |
117 } | 120 } |
118 | 121 |
119 int optval = 1; | 122 int optval = 1; |
120 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); | 123 TEMP_FAILURE_RETRY( |
| 124 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))); |
121 | 125 |
122 server_address.sin_family = AF_INET; | 126 server_address.sin_family = AF_INET; |
123 server_address.sin_port = htons(port); | 127 server_address.sin_port = htons(port); |
124 server_address.sin_addr.s_addr = inet_addr(host); | 128 server_address.sin_addr.s_addr = inet_addr(host); |
125 memset(&server_address.sin_zero, 0, sizeof(server_address.sin_zero)); | 129 memset(&server_address.sin_zero, 0, sizeof(server_address.sin_zero)); |
126 | 130 |
127 if (bind(fd, reinterpret_cast<struct sockaddr *>(&server_address), | 131 if (TEMP_FAILURE_RETRY( |
128 sizeof(server_address)) < 0) { | 132 bind(fd, |
129 close(fd); | 133 reinterpret_cast<struct sockaddr *>(&server_address), |
| 134 sizeof(server_address))) < 0) { |
| 135 TEMP_FAILURE_RETRY(close(fd)); |
130 fprintf(stderr, "Error Bind: %s\n", strerror(errno)); | 136 fprintf(stderr, "Error Bind: %s\n", strerror(errno)); |
131 return -1; | 137 return -1; |
132 } | 138 } |
133 | 139 |
134 if (listen(fd, backlog) != 0) { | 140 if (TEMP_FAILURE_RETRY(listen(fd, backlog)) != 0) { |
135 fprintf(stderr, "Error Listen: %s\n", strerror(errno)); | 141 fprintf(stderr, "Error Listen: %s\n", strerror(errno)); |
136 return -1; | 142 return -1; |
137 } | 143 } |
138 | 144 |
139 FDUtils::SetNonBlocking(fd); | 145 FDUtils::SetNonBlocking(fd); |
140 return fd; | 146 return fd; |
141 } | 147 } |
142 | 148 |
143 intptr_t ServerSocket::Accept(intptr_t fd) { | 149 intptr_t ServerSocket::Accept(intptr_t fd) { |
144 intptr_t socket; | 150 intptr_t socket; |
145 struct sockaddr clientaddr; | 151 struct sockaddr clientaddr; |
146 socklen_t addrlen = sizeof(clientaddr); | 152 socklen_t addrlen = sizeof(clientaddr); |
147 socket = accept(fd, &clientaddr, &addrlen); | 153 socket = TEMP_FAILURE_RETRY(accept(fd, &clientaddr, &addrlen)); |
148 if (socket < 0) { | 154 if (socket < 0) { |
149 fprintf(stderr, "Error Accept: %s\n", strerror(errno)); | 155 fprintf(stderr, "Error Accept: %s\n", strerror(errno)); |
150 } else { | 156 } else { |
151 FDUtils::SetNonBlocking(socket); | 157 FDUtils::SetNonBlocking(socket); |
152 } | 158 } |
153 return socket; | 159 return socket; |
154 } | 160 } |
OLD | NEW |