Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(164)

Side by Side Diff: net/base/tcp_client_socket_libevent.cc

Issue 4049: Port SSLClientSocket to Linux (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 12 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/base/tcp_client_socket.h ('k') | net/base/x509_certificate_nss.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/base/tcp_client_socket.h" 5 #include "net/base/tcp_client_socket.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #include <netdb.h> 9 #include <netdb.h>
10 #include <sys/socket.h> 10 #include <sys/socket.h>
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
60 return ERR_FAILED; 60 return ERR_FAILED;
61 } 61 }
62 } 62 }
63 63
64 //----------------------------------------------------------------------------- 64 //-----------------------------------------------------------------------------
65 65
66 TCPClientSocket::TCPClientSocket(const AddressList& addresses) 66 TCPClientSocket::TCPClientSocket(const AddressList& addresses)
67 : socket_(kInvalidSocket), 67 : socket_(kInvalidSocket),
68 addresses_(addresses), 68 addresses_(addresses),
69 current_ai_(addresses_.head()), 69 current_ai_(addresses_.head()),
70 wait_state_(NOT_WAITING), 70 waiting_connect_(false),
71 event_(new event) { 71 event_(new event),
72 write_callback_(NULL),
73 callback_(NULL) {
72 } 74 }
73 75
74 TCPClientSocket::~TCPClientSocket() { 76 TCPClientSocket::~TCPClientSocket() {
75 Disconnect(); 77 Disconnect();
76 } 78 }
77 79
78 int TCPClientSocket::Connect(CompletionCallback* callback) { 80 int TCPClientSocket::Connect(CompletionCallback* callback) {
79 // If already connected, then just return OK. 81 // If already connected, then just return OK.
80 if (socket_ != kInvalidSocket) 82 if (socket_ != kInvalidSocket)
81 return OK; 83 return OK;
82 84
83 DCHECK(wait_state_ == NOT_WAITING); 85 DCHECK(!waiting_connect_);
84 86
85 const addrinfo* ai = current_ai_; 87 const addrinfo* ai = current_ai_;
86 DCHECK(ai); 88 DCHECK(ai);
87 89
88 int rv = CreateSocket(ai); 90 int rv = CreateSocket(ai);
89 if (rv != OK) 91 if (rv != OK)
90 return rv; 92 return rv;
91 93
92 if (!connect(socket_, ai->ai_addr, static_cast<int>(ai->ai_addrlen))) { 94 if (!connect(socket_, ai->ai_addr, static_cast<int>(ai->ai_addrlen))) {
93 // Connected without waiting! 95 // Connected without waiting!
94 return OK; 96 return OK;
95 } 97 }
96 98
97 // Synchronous operation not supported 99 // Synchronous operation not supported
98 DCHECK(callback); 100 DCHECK(callback);
99 101
100 if (errno != EINPROGRESS) { 102 if (errno != EINPROGRESS) {
101 LOG(ERROR) << "connect failed: " << errno; 103 DLOG(INFO) << "connect failed: " << errno;
102 return MapPosixError(errno); 104 return MapPosixError(errno);
103 } 105 }
104 106
105 // Initialize event_ and link it to our MessagePump. 107 // Initialize event_ and link it to our MessagePump.
106 // POLLOUT is set if the connection is established. 108 // POLLOUT is set if the connection is established.
107 // POLLIN is set if the connection fails, 109 // POLLIN is set if the connection fails,
108 // so select for both read and write. 110 // so select for both read and write.
109 MessageLoopForIO::current()->WatchSocket( 111 MessageLoopForIO::current()->WatchSocket(
110 socket_, EV_READ|EV_WRITE|EV_PERSIST, event_.get(), this); 112 socket_, EV_READ|EV_WRITE|EV_PERSIST, event_.get(), this);
111 113
112 wait_state_ = WAITING_CONNECT; 114 waiting_connect_ = true;
113 callback_ = callback; 115 callback_ = callback;
114 return ERR_IO_PENDING; 116 return ERR_IO_PENDING;
115 } 117 }
116 118
117 int TCPClientSocket::ReconnectIgnoringLastError(CompletionCallback* callback) { 119 int TCPClientSocket::ReconnectIgnoringLastError(CompletionCallback* callback) {
118 // No ignorable errors! 120 // No ignorable errors!
119 return ERR_UNEXPECTED; 121 return ERR_UNEXPECTED;
120 } 122 }
121 123
122 void TCPClientSocket::Disconnect() { 124 void TCPClientSocket::Disconnect() {
123 if (socket_ == kInvalidSocket) 125 if (socket_ == kInvalidSocket)
124 return; 126 return;
125 127
126 MessageLoopForIO::current()->UnwatchSocket(event_.get()); 128 MessageLoopForIO::current()->UnwatchSocket(event_.get());
127 close(socket_); 129 close(socket_);
128 socket_ = kInvalidSocket; 130 socket_ = kInvalidSocket;
131 waiting_connect_ = false;
129 132
130 // Reset for next time. 133 // Reset for next time.
131 current_ai_ = addresses_.head(); 134 current_ai_ = addresses_.head();
132 } 135 }
133 136
134 bool TCPClientSocket::IsConnected() const { 137 bool TCPClientSocket::IsConnected() const {
135 if (socket_ == kInvalidSocket || wait_state_ == WAITING_CONNECT) 138 if (socket_ == kInvalidSocket || waiting_connect_)
136 return false; 139 return false;
137 140
138 // Check if connection is alive. 141 // Check if connection is alive.
139 char c; 142 char c;
140 int rv = recv(socket_, &c, 1, MSG_PEEK); 143 int rv = recv(socket_, &c, 1, MSG_PEEK);
141 if (rv == 0) 144 if (rv == 0)
142 return false; 145 return false;
143 if (rv == -1 && errno != EAGAIN && errno != EWOULDBLOCK) 146 if (rv == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
144 return false; 147 return false;
145 148
146 return true; 149 return true;
147 } 150 }
148 151
149 int TCPClientSocket::Read(char* buf, 152 int TCPClientSocket::Read(char* buf,
150 int buf_len, 153 int buf_len,
151 CompletionCallback* callback) { 154 CompletionCallback* callback) {
152 DCHECK(socket_ != kInvalidSocket); 155 DCHECK(socket_ != kInvalidSocket);
153 DCHECK(wait_state_ == NOT_WAITING); 156 DCHECK(!waiting_connect_);
154 DCHECK(!callback_); 157 DCHECK(!callback_);
155 // Synchronous operation not supported 158 // Synchronous operation not supported
156 DCHECK(callback); 159 DCHECK(callback);
157 DCHECK(buf_len > 0); 160 DCHECK(buf_len > 0);
158 161
159 int nread = read(socket_, buf, buf_len); 162 int nread = read(socket_, buf, buf_len);
160 if (nread >= 0) { 163 if (nread >= 0) {
161 return nread; 164 return nread;
162 } 165 }
163 if (errno != EAGAIN && errno != EWOULDBLOCK) 166 if (errno != EAGAIN && errno != EWOULDBLOCK) {
167 DLOG(INFO) << "read failed, errno " << errno;
164 return MapPosixError(errno); 168 return MapPosixError(errno);
169 }
165 170
166 MessageLoopForIO::current()->WatchSocket( 171 MessageLoopForIO::current()->WatchSocket(
167 socket_, EV_READ|EV_PERSIST, event_.get(), this); 172 socket_, EV_READ|EV_PERSIST, event_.get(), this);
168 173
169 buf_ = buf; 174 buf_ = buf;
170 buf_len_ = buf_len; 175 buf_len_ = buf_len;
171 wait_state_ = WAITING_READ;
172 callback_ = callback; 176 callback_ = callback;
173 return ERR_IO_PENDING; 177 return ERR_IO_PENDING;
174 } 178 }
175 179
176 int TCPClientSocket::Write(const char* buf, 180 int TCPClientSocket::Write(const char* buf,
177 int buf_len, 181 int buf_len,
178 CompletionCallback* callback) { 182 CompletionCallback* callback) {
179 DCHECK(socket_ != kInvalidSocket); 183 DCHECK(socket_ != kInvalidSocket);
180 DCHECK(wait_state_ == NOT_WAITING); 184 DCHECK(!waiting_connect_);
181 DCHECK(!callback_); 185 DCHECK(!write_callback_);
182 // Synchronous operation not supported 186 // Synchronous operation not supported
183 DCHECK(callback); 187 DCHECK(callback);
184 DCHECK(buf_len > 0); 188 DCHECK(buf_len > 0);
185 189
186 int nwrite = write(socket_, buf, buf_len); 190 int nwrite = write(socket_, buf, buf_len);
187 if (nwrite >= 0) { 191 if (nwrite >= 0) {
188 return nwrite; 192 return nwrite;
189 } 193 }
190 if (errno != EAGAIN && errno != EWOULDBLOCK) 194 if (errno != EAGAIN && errno != EWOULDBLOCK)
191 return MapPosixError(errno); 195 return MapPosixError(errno);
192 196
193 MessageLoopForIO::current()->WatchSocket( 197 MessageLoopForIO::current()->WatchSocket(
194 socket_, EV_WRITE|EV_PERSIST, event_.get(), this); 198 socket_, EV_WRITE|EV_PERSIST, event_.get(), this);
195 199
196 buf_ = const_cast<char*>(buf); 200 write_buf_ = buf;
197 buf_len_ = buf_len; 201 write_buf_len_ = buf_len;
198 wait_state_ = WAITING_WRITE; 202 write_callback_ = callback;
199 callback_ = callback;
200 return ERR_IO_PENDING; 203 return ERR_IO_PENDING;
201 } 204 }
202 205
203 int TCPClientSocket::CreateSocket(const addrinfo* ai) { 206 int TCPClientSocket::CreateSocket(const addrinfo* ai) {
204 socket_ = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); 207 socket_ = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
205 if (socket_ == kInvalidSocket) 208 if (socket_ == kInvalidSocket)
206 return MapPosixError(errno); 209 return MapPosixError(errno);
207 210
208 // All our socket I/O is nonblocking 211 // All our socket I/O is nonblocking
209 if (SetNonBlocking(socket_)) 212 if (SetNonBlocking(socket_))
210 return MapPosixError(errno); 213 return MapPosixError(errno);
211 214
212 return OK; 215 return OK;
213 } 216 }
214 217
215 void TCPClientSocket::DoCallback(int rv) { 218 void TCPClientSocket::DoCallback(int rv) {
216 DCHECK(rv != ERR_IO_PENDING); 219 DCHECK(rv != ERR_IO_PENDING);
217 DCHECK(callback_); 220 DCHECK(callback_);
218 221
219 // since Run may result in Read being called, clear callback_ up front. 222 // since Run may result in Read being called, clear callback_ up front.
220 CompletionCallback* c = callback_; 223 CompletionCallback* c = callback_;
221 callback_ = NULL; 224 callback_ = NULL;
222 c->Run(rv); 225 c->Run(rv);
223 } 226 }
224 227
228 void TCPClientSocket::DoWriteCallback(int rv) {
229 DCHECK(rv != ERR_IO_PENDING);
230 DCHECK(write_callback_);
231
232 // since Run may result in Write being called, clear write_callback_ up front.
233 CompletionCallback* c = write_callback_;
234 write_callback_ = NULL;
235 c->Run(rv);
236 }
237
225 void TCPClientSocket::DidCompleteConnect() { 238 void TCPClientSocket::DidCompleteConnect() {
226 int result = ERR_UNEXPECTED; 239 int result = ERR_UNEXPECTED;
227 240
228 wait_state_ = NOT_WAITING;
229
230 // Check to see if connect succeeded 241 // Check to see if connect succeeded
231 int error_code = 0; 242 int error_code = 0;
232 socklen_t len = sizeof(error_code); 243 socklen_t len = sizeof(error_code);
233 if (getsockopt(socket_, SOL_SOCKET, SO_ERROR, &error_code, &len) < 0) 244 if (getsockopt(socket_, SOL_SOCKET, SO_ERROR, &error_code, &len) < 0)
234 error_code = errno; 245 error_code = errno;
235 246
236 if (error_code == EINPROGRESS || error_code == EALREADY) { 247 if (error_code == EINPROGRESS || error_code == EALREADY) {
237 NOTREACHED(); // This indicates a bug in libevent or our code. 248 NOTREACHED(); // This indicates a bug in libevent or our code.
238 result = ERR_IO_PENDING; 249 result = ERR_IO_PENDING;
239 wait_state_ = WAITING_CONNECT; // And await next callback.
240 } else if (current_ai_->ai_next && ( 250 } else if (current_ai_->ai_next && (
241 error_code == EADDRNOTAVAIL || 251 error_code == EADDRNOTAVAIL ||
242 error_code == EAFNOSUPPORT || 252 error_code == EAFNOSUPPORT ||
243 error_code == ECONNREFUSED || 253 error_code == ECONNREFUSED ||
244 error_code == ENETUNREACH || 254 error_code == ENETUNREACH ||
245 error_code == EHOSTUNREACH || 255 error_code == EHOSTUNREACH ||
246 error_code == ETIMEDOUT)) { 256 error_code == ETIMEDOUT)) {
247 // This address failed, try next one in list. 257 // This address failed, try next one in list.
248 const addrinfo* next = current_ai_->ai_next; 258 const addrinfo* next = current_ai_->ai_next;
249 Disconnect(); 259 Disconnect();
250 current_ai_ = next; 260 current_ai_ = next;
251 result = Connect(callback_); 261 result = Connect(callback_);
252 } else { 262 } else {
253 result = MapPosixError(error_code); 263 result = MapPosixError(error_code);
254 MessageLoopForIO::current()->UnwatchSocket(event_.get()); 264 MessageLoopForIO::current()->UnwatchSocket(event_.get());
265 waiting_connect_ = false;
255 } 266 }
256 267
257 if (result != ERR_IO_PENDING) 268 if (result != ERR_IO_PENDING)
258 DoCallback(result); 269 DoCallback(result);
259 } 270 }
260 271
261 void TCPClientSocket::DidCompleteIO() { 272 void TCPClientSocket::DidCompleteRead() {
262 int bytes_transferred; 273 int bytes_transferred;
263 switch (wait_state_) { 274 bytes_transferred = read(socket_, buf_, buf_len_);
264 case WAITING_READ:
265 bytes_transferred = read(socket_, buf_, buf_len_);
266 break;
267 case WAITING_WRITE:
268 bytes_transferred = write(socket_, buf_, buf_len_);
269 break;
270 default:
271 NOTREACHED();
272 return;
273 }
274 275
275 int result; 276 int result;
276 if (bytes_transferred >= 0) { 277 if (bytes_transferred >= 0) {
277 result = bytes_transferred; 278 result = bytes_transferred;
278 } else { 279 } else {
279 result = MapPosixError(errno); 280 result = MapPosixError(errno);
280 } 281 }
281 282
282 if (result != ERR_IO_PENDING) { 283 if (result != ERR_IO_PENDING) {
283 wait_state_ = NOT_WAITING; 284 buf_ = NULL;
285 buf_len_ = 0;
284 MessageLoopForIO::current()->UnwatchSocket(event_.get()); 286 MessageLoopForIO::current()->UnwatchSocket(event_.get());
285 DoCallback(result); 287 DoCallback(result);
286 } 288 }
287 } 289 }
288 290
291 void TCPClientSocket::DidCompleteWrite() {
292 int bytes_transferred;
293 bytes_transferred = write(socket_, write_buf_, write_buf_len_);
294
295 int result;
296 if (bytes_transferred >= 0) {
297 result = bytes_transferred;
298 } else {
299 result = MapPosixError(errno);
300 }
301
302 if (result != ERR_IO_PENDING) {
303 write_buf_ = NULL;
304 write_buf_len_ = 0;
305 MessageLoopForIO::current()->UnwatchSocket(event_.get());
306 DoWriteCallback(result);
307 }
308 }
309
289 void TCPClientSocket::OnSocketReady(short flags) { 310 void TCPClientSocket::OnSocketReady(short flags) {
290 switch (wait_state_) { 311 // the only used bits of flags are EV_READ and EV_WRITE
291 case WAITING_CONNECT: 312
292 DidCompleteConnect(); 313 if (waiting_connect_) {
293 break; 314 DidCompleteConnect();
294 case WAITING_READ: 315 } else {
295 case WAITING_WRITE: 316 if ((flags & EV_WRITE) && write_callback_)
296 DidCompleteIO(); 317 DidCompleteWrite();
297 break; 318 if ((flags & EV_READ) && callback_)
298 default: 319 DidCompleteRead();
299 NOTREACHED();
300 break;
301 } 320 }
302 } 321 }
303 322
323 int TCPClientSocket::GetPeerName(struct sockaddr *name, socklen_t *namelen) {
324 return ::getpeername(socket_, name, namelen);
325 }
326
304 } // namespace net 327 } // namespace net
305 328
OLDNEW
« no previous file with comments | « net/base/tcp_client_socket.h ('k') | net/base/x509_certificate_nss.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698