| 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 |