| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/chromeos/web_socket_proxy.h" | |
| 6 | |
| 7 #include <stdio.h> | |
| 8 #include <stdlib.h> | |
| 9 #include <string.h> | |
| 10 | |
| 11 #include <algorithm> | |
| 12 #include <limits> | |
| 13 #include <list> | |
| 14 #include <map> | |
| 15 #include <vector> | |
| 16 | |
| 17 #include <errno.h> | |
| 18 #include <fcntl.h> | |
| 19 #include <netinet/in.h> | |
| 20 #include <signal.h> | |
| 21 #include <sys/socket.h> | |
| 22 #include <sys/types.h> | |
| 23 #include <sys/wait.h> | |
| 24 | |
| 25 #include "base/base64.h" | |
| 26 #include "base/basictypes.h" | |
| 27 #include "base/bind.h" | |
| 28 #include "base/bind_helpers.h" | |
| 29 #include "base/lazy_instance.h" | |
| 30 #include "base/logging.h" | |
| 31 #include "base/memory/ref_counted.h" | |
| 32 #include "base/memory/scoped_ptr.h" | |
| 33 #include "base/memory/weak_ptr.h" | |
| 34 #include "base/message_loop/message_loop.h" | |
| 35 #include "base/sequenced_task_runner_helpers.h" | |
| 36 #include "base/sha1.h" | |
| 37 #include "base/stl_util.h" | |
| 38 #include "base/strings/string_number_conversions.h" | |
| 39 #include "base/strings/string_util.h" | |
| 40 #include "base/sys_byteorder.h" | |
| 41 #include "chrome/browser/chrome_notification_types.h" | |
| 42 #include "chrome/browser/chromeos/web_socket_proxy_helper.h" | |
| 43 #include "chrome/browser/internal_auth.h" | |
| 44 #include "content/public/browser/browser_thread.h" | |
| 45 #include "content/public/browser/notification_details.h" | |
| 46 #include "content/public/browser/notification_service.h" | |
| 47 #include "content/public/browser/notification_types.h" | |
| 48 #include "content/public/common/url_constants.h" | |
| 49 #include "extensions/common/constants.h" | |
| 50 #include "net/base/address_list.h" | |
| 51 #include "net/base/host_port_pair.h" | |
| 52 #include "net/base/io_buffer.h" | |
| 53 #include "net/base/net_errors.h" | |
| 54 #include "net/cert/cert_verifier.h" | |
| 55 #include "net/http/transport_security_state.h" | |
| 56 #include "net/socket/client_socket_factory.h" | |
| 57 #include "net/socket/client_socket_handle.h" | |
| 58 #include "net/socket/ssl_client_socket.h" | |
| 59 #include "net/socket/stream_socket.h" | |
| 60 #include "net/ssl/ssl_config_service.h" | |
| 61 #include "third_party/libevent/evdns.h" | |
| 62 #include "third_party/libevent/event.h" | |
| 63 #include "url/gurl.h" | |
| 64 #include "url/url_parse.h" | |
| 65 | |
| 66 using content::BrowserThread; | |
| 67 | |
| 68 namespace chromeos { | |
| 69 | |
| 70 namespace { | |
| 71 | |
| 72 const uint8 kCRLF[] = "\r\n"; | |
| 73 const uint8 kCRLFCRLF[] = "\r\n\r\n"; | |
| 74 | |
| 75 // Not a constant but preprocessor definition for easy concatenation. | |
| 76 #define kProxyPath "/tcpproxy" | |
| 77 | |
| 78 enum WebSocketStatusCode { | |
| 79 WS_CLOSE_NORMAL = 1000, | |
| 80 WS_CLOSE_GOING_AWAY = 1001, | |
| 81 WS_CLOSE_PROTOCOL_ERROR = 1002, | |
| 82 WS_CLOSE_UNACCEPTABLE_DATA = 1003, | |
| 83 | |
| 84 WS_CLOSE_DESTINATION_ERROR = 4000, | |
| 85 WS_CLOSE_LIMIT_VIOLATION = 4001, | |
| 86 WS_CLOSE_RESOLUTION_FAILED = 4002, | |
| 87 WS_CLOSE_UNEXPECTED = 4003 | |
| 88 }; | |
| 89 | |
| 90 enum WebSocketFrameOpcode { | |
| 91 WS_OPCODE_TEXT = 1, | |
| 92 WS_OPCODE_CLOSE = 8 | |
| 93 }; | |
| 94 | |
| 95 // Fixed-size (one-byte) messages communicated via control pipe. | |
| 96 const char kControlMessageShutdown[] = { '.' }; | |
| 97 const char kControlMessageNetworkChange[] = { ':' }; | |
| 98 | |
| 99 // Returns true on success. | |
| 100 bool SetNonBlock(int fd) { | |
| 101 int flags = fcntl(fd, F_GETFL, 0); | |
| 102 return flags >= 0 && fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0; | |
| 103 } | |
| 104 | |
| 105 // Returns true on success. | |
| 106 bool IgnoreSigPipe() { | |
| 107 struct sigaction sa; | |
| 108 sa.sa_handler = SIG_IGN; | |
| 109 sa.sa_flags = 0; | |
| 110 if (sigemptyset(&sa.sa_mask) || sigaction(SIGPIPE, &sa, 0)) { | |
| 111 LOG(ERROR) << "WebSocketProxy: Failed to disable sigpipe"; | |
| 112 return false; | |
| 113 } | |
| 114 return true; | |
| 115 } | |
| 116 | |
| 117 uint64 ReadNetworkInteger(uint8* buf, int num_bytes) { | |
| 118 uint64 rv = 0; | |
| 119 DCHECK_GE(num_bytes, 0); | |
| 120 DCHECK_LE(num_bytes, 8); | |
| 121 while (num_bytes--) { | |
| 122 rv <<= 8; | |
| 123 rv += *buf++; | |
| 124 } | |
| 125 return rv; | |
| 126 } | |
| 127 | |
| 128 void WriteNetworkInteger(int64 n, uint8* buf, int num_bytes) { | |
| 129 DCHECK_GE(num_bytes, 0); | |
| 130 DCHECK_LE(num_bytes, 8); | |
| 131 while (num_bytes--) { | |
| 132 buf[num_bytes] = n % (1 << 8); | |
| 133 n >>= 8; | |
| 134 } | |
| 135 } | |
| 136 | |
| 137 typedef uint8 (*AsciiFilter)(uint8); | |
| 138 | |
| 139 uint8 AsciiFilterVerbatim(uint8 c) { | |
| 140 return c; | |
| 141 } | |
| 142 | |
| 143 uint8 AsciiFilterLower(uint8 c) { | |
| 144 return base::ToLowerASCII(c); | |
| 145 } | |
| 146 | |
| 147 std::string FetchAsciiSnippet(uint8* begin, uint8* end, AsciiFilter filter) { | |
| 148 std::string rv; | |
| 149 for (; begin < end; ++begin) { | |
| 150 if (!isascii(*begin)) | |
| 151 return rv; | |
| 152 rv += filter(*begin); | |
| 153 } | |
| 154 return rv; | |
| 155 } | |
| 156 | |
| 157 std::string FetchExtensionIdFromOrigin(const std::string &origin) { | |
| 158 GURL url(origin); | |
| 159 if (url.SchemeIs(extensions::kExtensionScheme)) | |
| 160 return url.host(); | |
| 161 else | |
| 162 return std::string(); | |
| 163 } | |
| 164 | |
| 165 inline size_t strlen(const void* s) { | |
| 166 return ::strlen(static_cast<const char*>(s)); | |
| 167 } | |
| 168 | |
| 169 void SendNotification(int port) { | |
| 170 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 171 content::NotificationService::current()->Notify( | |
| 172 chrome::NOTIFICATION_WEB_SOCKET_PROXY_STARTED, | |
| 173 content::NotificationService::AllSources(), content::Details<int>(&port)); | |
| 174 } | |
| 175 | |
| 176 class Conn; | |
| 177 | |
| 178 // Websocket to TCP proxy server. | |
| 179 class Serv { | |
| 180 public: | |
| 181 Serv(); | |
| 182 ~Serv(); | |
| 183 | |
| 184 // Do not call it twice. | |
| 185 void Run(); | |
| 186 | |
| 187 // Terminates running server (should be called on a different thread). | |
| 188 void Shutdown(); | |
| 189 // Called on network change. Reinitializes DNS resolution service. | |
| 190 void OnNetworkChange(); | |
| 191 | |
| 192 void ZapConn(Conn*); | |
| 193 void MarkConnImportance(Conn*, bool important); | |
| 194 Conn* GetFreshConn(); | |
| 195 bool IsConnSane(Conn*); | |
| 196 void CloseAll(); | |
| 197 | |
| 198 static void OnConnect(int listening_sock, short event, void*); | |
| 199 static void OnControlRequest(int fd, short event, void*); | |
| 200 | |
| 201 struct event_base* evbase() { return evbase_; } | |
| 202 | |
| 203 // Libevent base. | |
| 204 struct event_base* evbase_; | |
| 205 | |
| 206 // Socket to listen incoming websocket connections. | |
| 207 int listening_sock_; | |
| 208 | |
| 209 // TODO(dilmah): remove this extra socket as soon as obsolete | |
| 210 // getPassportForTCP function is removed from webSocketProxyPrivate API. | |
| 211 // Additional socket to listen incoming connections on fixed port 10101. | |
| 212 int extra_listening_sock_; | |
| 213 | |
| 214 // Used to communicate control requests: either shutdown request or network | |
| 215 // change notification. | |
| 216 int control_descriptor_[2]; | |
| 217 | |
| 218 // Flag whether shutdown has been requested. | |
| 219 bool shutdown_requested_; | |
| 220 | |
| 221 // List of pending connections; We are trying to keep size of this list | |
| 222 // below kConnPoolLimit in LRU fashion. | |
| 223 typedef std::list<Conn*> ConnPool; | |
| 224 ConnPool conn_pool_; | |
| 225 | |
| 226 // Reverse map to look up a connection in a conn_pool. | |
| 227 typedef std::map<Conn*, ConnPool::iterator> RevMap; | |
| 228 RevMap rev_map_; | |
| 229 | |
| 230 scoped_ptr<struct event> connection_event_; | |
| 231 scoped_ptr<struct event> control_event_; | |
| 232 // TODO(dilmah): remove this extra event as soon as obsolete | |
| 233 // getPassportForTCP function is removed from webSocketProxyPrivate API. | |
| 234 scoped_ptr<struct event> extra_connection_event_; | |
| 235 | |
| 236 DISALLOW_COPY_AND_ASSIGN(Serv); | |
| 237 }; | |
| 238 | |
| 239 // Connection (amalgamates both channels between proxy and javascript and | |
| 240 // between proxy and destination). | |
| 241 class Conn { | |
| 242 public: | |
| 243 enum Phase { | |
| 244 // Initial stage of connection. | |
| 245 PHASE_WAIT_HANDSHAKE, | |
| 246 PHASE_WAIT_DESTFRAME, | |
| 247 PHASE_WAIT_DESTCONNECT, | |
| 248 | |
| 249 // Operational stage of connection. | |
| 250 PHASE_OUTSIDE_FRAME, | |
| 251 PHASE_INSIDE_FRAME_BASE64, | |
| 252 PHASE_INSIDE_FRAME_SKIP, | |
| 253 | |
| 254 // Terminal stage of connection. | |
| 255 PHASE_SHUT, // Closing handshake was emitted, buffers may be pending. | |
| 256 PHASE_DEFUNCT // Connection was nuked. | |
| 257 }; | |
| 258 | |
| 259 // Channel structure (either proxy<->browser or proxy<->destination). | |
| 260 class Chan { | |
| 261 public: | |
| 262 explicit Chan(Conn* master) | |
| 263 : master_(master), | |
| 264 write_pending_(false), | |
| 265 read_bev_(NULL), | |
| 266 write_bev_(NULL), | |
| 267 read_fd_(-1), | |
| 268 write_fd_(-1) { | |
| 269 } | |
| 270 | |
| 271 ~Chan() { | |
| 272 Zap(); | |
| 273 } | |
| 274 | |
| 275 // Returns true on success. | |
| 276 bool Write(const void* data, size_t size) { | |
| 277 if (write_bev_ == NULL) | |
| 278 return false; | |
| 279 write_pending_ = true; | |
| 280 return (0 == bufferevent_write(write_bev_, data, size)); | |
| 281 } | |
| 282 | |
| 283 void Zap() { | |
| 284 if (read_bev_) { | |
| 285 bufferevent_disable(read_bev_, EV_READ); | |
| 286 bufferevent_free(read_bev_); | |
| 287 } | |
| 288 if (write_bev_ && write_bev_ != read_bev_) { | |
| 289 bufferevent_disable(write_bev_, EV_READ); | |
| 290 bufferevent_free(write_bev_); | |
| 291 } | |
| 292 read_bev_ = NULL; | |
| 293 write_bev_ = NULL; | |
| 294 if (write_fd_ && read_fd_ == write_fd_) | |
| 295 shutdown(write_fd_, SHUT_RDWR); | |
| 296 if (write_fd_ >= 0) { | |
| 297 close(write_fd_); | |
| 298 DCHECK_GE(read_fd_, 0); | |
| 299 } | |
| 300 if (read_fd_ && read_fd_ != write_fd_) | |
| 301 close(read_fd_); | |
| 302 read_fd_ = -1; | |
| 303 write_fd_ = -1; | |
| 304 write_pending_ = false; | |
| 305 master_->ConsiderSuicide(); | |
| 306 } | |
| 307 | |
| 308 void Shut() { | |
| 309 if (!write_pending_) | |
| 310 Zap(); | |
| 311 } | |
| 312 | |
| 313 int read_fd() const { return read_fd_; } | |
| 314 void set_read_fd(int fd) { read_fd_ = fd; } | |
| 315 int write_fd() const { return write_fd_; } | |
| 316 void set_write_fd(int fd) { write_fd_ = fd; } | |
| 317 bool write_pending() const { return write_pending_; } | |
| 318 void set_write_pending(bool pending) { write_pending_ = pending; } | |
| 319 struct bufferevent* read_bev() const { return read_bev_; } | |
| 320 void set_read_bev(struct bufferevent* bev) { read_bev_ = bev; } | |
| 321 struct bufferevent* write_bev() const { return write_bev_; } | |
| 322 void set_write_bev(struct bufferevent* bev) { write_bev_ = bev; } | |
| 323 | |
| 324 private: | |
| 325 Conn* master_; | |
| 326 bool write_pending_; // Whether write buffer is not flushed yet. | |
| 327 struct bufferevent* read_bev_; | |
| 328 struct bufferevent* write_bev_; | |
| 329 // UNIX descriptors. | |
| 330 int read_fd_; | |
| 331 int write_fd_; | |
| 332 | |
| 333 DISALLOW_COPY_AND_ASSIGN(Chan); | |
| 334 }; | |
| 335 | |
| 336 // Status of processing incoming data. | |
| 337 enum Status { | |
| 338 STATUS_OK, | |
| 339 STATUS_INCOMPLETE, // Not all required data is present in buffer yet. | |
| 340 STATUS_SKIP, | |
| 341 STATUS_ABORT // Data is invalid. We must shut connection. | |
| 342 }; | |
| 343 | |
| 344 // Unfortunately evdns callbacks are uncancellable, | |
| 345 // so potentially we can receive callback for a deleted Conn. | |
| 346 // Even worse, storage of deleted Conn may be reused | |
| 347 // for a new connection and new connection can receive callback | |
| 348 // destined for deleted Conn. | |
| 349 // EventKey is introduced in order to prevent that. | |
| 350 typedef void* EventKey; | |
| 351 typedef std::map<EventKey, Conn*> EventKeyMap; | |
| 352 | |
| 353 explicit Conn(Serv* master); | |
| 354 ~Conn(); | |
| 355 | |
| 356 static Conn* Get(EventKey evkey); | |
| 357 | |
| 358 void Shut(int status, const void* reason); | |
| 359 | |
| 360 void ConsiderSuicide(); | |
| 361 | |
| 362 Status ConsumeHeader(struct evbuffer*); | |
| 363 Status ConsumeDestframe(struct evbuffer*); | |
| 364 Status ConsumeFrameHeader(struct evbuffer*); | |
| 365 Status ProcessFrameData(struct evbuffer*); | |
| 366 | |
| 367 // Return true on success. | |
| 368 bool EmitHandshake(Chan*); | |
| 369 bool EmitFrame( | |
| 370 Chan*, WebSocketFrameOpcode opcode, const void* buf, size_t size); | |
| 371 | |
| 372 // Attempts to establish second connection (to remote TCP service). | |
| 373 // Returns true on success. | |
| 374 bool TryConnectDest(const struct sockaddr*, socklen_t); | |
| 375 | |
| 376 // Return security origin associated with this connection. | |
| 377 const std::string& GetOrigin(); | |
| 378 | |
| 379 // Used as libevent callbacks. | |
| 380 static void OnDestConnectTimeout(int, short, EventKey); | |
| 381 static void OnPrimchanRead(struct bufferevent*, EventKey); | |
| 382 static void OnPrimchanWrite(struct bufferevent*, EventKey); | |
| 383 static void OnPrimchanError(struct bufferevent*, short what, EventKey); | |
| 384 static void OnDestResolutionIPv4(int result, char type, int count, | |
| 385 int ttl, void* addr_list, EventKey); | |
| 386 static void OnDestResolutionIPv6(int result, char type, int count, | |
| 387 int ttl, void* addr_list, EventKey); | |
| 388 static void OnDestchanRead(struct bufferevent*, EventKey); | |
| 389 static void OnDestchanWrite(struct bufferevent*, EventKey); | |
| 390 static void OnDestchanError(struct bufferevent*, short what, EventKey); | |
| 391 | |
| 392 Chan& primchan() { return primchan_; } | |
| 393 EventKey evkey() const { return evkey_; } | |
| 394 | |
| 395 private: | |
| 396 Serv* master_; | |
| 397 Phase phase_; | |
| 398 uint64 frame_bytes_remaining_; | |
| 399 uint8 frame_mask_[4]; | |
| 400 int frame_mask_index_; | |
| 401 | |
| 402 // We maintain two channels per Conn: | |
| 403 // primary channel is websocket connection. | |
| 404 Chan primchan_; | |
| 405 // Destination channel is a proxied connection. | |
| 406 Chan destchan_; | |
| 407 | |
| 408 EventKey evkey_; | |
| 409 | |
| 410 // Header fields supplied by client at initial websocket handshake. | |
| 411 std::map<std::string, std::string> header_fields_; | |
| 412 | |
| 413 // Parameters requested via query component of GET resource. | |
| 414 std::map<std::string, std::string> requested_parameters_; | |
| 415 | |
| 416 // Hostname and port of destination socket. | |
| 417 // Websocket client supplies them in first data frame (destframe). | |
| 418 std::string destname_; | |
| 419 int destport_; | |
| 420 | |
| 421 // Preresolved |destname_| (empty if not pre-resolved). | |
| 422 std::string destaddr_; | |
| 423 | |
| 424 // Whether TLS over TCP requested. | |
| 425 bool do_tls_; | |
| 426 | |
| 427 // We try to DNS resolve hostname in both IPv4 and IPv6 domains. | |
| 428 // Track resolution failures here. | |
| 429 bool destresolution_ipv4_failed_; | |
| 430 bool destresolution_ipv6_failed_; | |
| 431 | |
| 432 // Used to schedule a timeout for initial phase of connection. | |
| 433 scoped_ptr<struct event> destconnect_timeout_event_; | |
| 434 | |
| 435 static base::LazyInstance<EventKeyMap>::Leaky evkey_map_; | |
| 436 static EventKey last_evkey_; | |
| 437 | |
| 438 DISALLOW_COPY_AND_ASSIGN(Conn); | |
| 439 }; | |
| 440 | |
| 441 class SSLChan : public base::MessageLoopForIO::Watcher { | |
| 442 public: | |
| 443 static void Start(const net::AddressList& address_list, | |
| 444 const net::HostPortPair& host_port_pair, | |
| 445 int read_pipe, | |
| 446 int write_pipe) { | |
| 447 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 448 SSLChan* ALLOW_UNUSED chan = new SSLChan( | |
| 449 address_list, host_port_pair, read_pipe, write_pipe); | |
| 450 } | |
| 451 | |
| 452 private: | |
| 453 enum Phase { | |
| 454 PHASE_CONNECTING, | |
| 455 PHASE_RUNNING, | |
| 456 PHASE_CLOSING, | |
| 457 PHASE_CLOSED | |
| 458 }; | |
| 459 | |
| 460 class DerivedIOBufferWithSize : public net::IOBufferWithSize { | |
| 461 public: | |
| 462 DerivedIOBufferWithSize(net::IOBuffer* host, int size) | |
| 463 : IOBufferWithSize(host->data(), size), host_(host) { | |
| 464 DCHECK(host_.get()); | |
| 465 DCHECK(host_->data()); | |
| 466 } | |
| 467 | |
| 468 protected: | |
| 469 virtual ~DerivedIOBufferWithSize() { | |
| 470 data_ = NULL; // We do not own memory, bypass base class destructor. | |
| 471 } | |
| 472 | |
| 473 scoped_refptr<net::IOBuffer> host_; | |
| 474 }; | |
| 475 | |
| 476 // Provides queue of data represented as IOBuffers. | |
| 477 class IOBufferQueue { | |
| 478 public: | |
| 479 // We do not allocate all capacity at once but lazily in |buf_size_| chunks. | |
| 480 explicit IOBufferQueue(int capacity) | |
| 481 : buf_size_(1 + capacity / kNumBuffersLimit) { | |
| 482 } | |
| 483 | |
| 484 // Obtains IOBuffer to add new data to back. | |
| 485 net::IOBufferWithSize* GetIOBufferToFill() { | |
| 486 if (back_.get() == NULL) { | |
| 487 if (storage_.size() >= kNumBuffersLimit) | |
| 488 return NULL; | |
| 489 storage_.push_back(new net::IOBufferWithSize(buf_size_)); | |
| 490 back_ = new net::DrainableIOBuffer(storage_.back().get(), buf_size_); | |
| 491 } | |
| 492 return new DerivedIOBufferWithSize( | |
| 493 back_.get(), back_->BytesRemaining()); | |
| 494 } | |
| 495 | |
| 496 // Obtains IOBuffer with some data from front. | |
| 497 net::IOBufferWithSize* GetIOBufferToProcess() { | |
| 498 if (front_.get() == NULL) { | |
| 499 if (storage_.empty()) | |
| 500 return NULL; | |
| 501 front_ = new net::DrainableIOBuffer(storage_.front().get(), buf_size_); | |
| 502 } | |
| 503 int front_capacity = | |
| 504 (storage_.size() == 1 && back_.get()) ? back_->BytesConsumed() | |
| 505 : buf_size_; | |
| 506 return new DerivedIOBufferWithSize( | |
| 507 front_.get(), front_capacity - front_->BytesConsumed()); | |
| 508 } | |
| 509 | |
| 510 // Records number of bytes as added to back. | |
| 511 void DidFill(int bytes) { | |
| 512 DCHECK(back_.get()); | |
| 513 back_->DidConsume(bytes); | |
| 514 if (back_->BytesRemaining() == 0) | |
| 515 back_ = NULL; | |
| 516 } | |
| 517 | |
| 518 // Pops number of bytes from front. | |
| 519 void DidProcess(int bytes) { | |
| 520 DCHECK(front_.get()); | |
| 521 front_->DidConsume(bytes); | |
| 522 if (front_->BytesRemaining() == 0) { | |
| 523 storage_.pop_front(); | |
| 524 front_ = NULL; | |
| 525 } | |
| 526 } | |
| 527 | |
| 528 void Clear() { | |
| 529 front_ = NULL; | |
| 530 back_ = NULL; | |
| 531 storage_.clear(); | |
| 532 } | |
| 533 | |
| 534 private: | |
| 535 static const unsigned kNumBuffersLimit = 12; | |
| 536 const int buf_size_; | |
| 537 std::list< scoped_refptr<net::IOBufferWithSize> > storage_; | |
| 538 scoped_refptr<net::DrainableIOBuffer> front_; | |
| 539 scoped_refptr<net::DrainableIOBuffer> back_; | |
| 540 | |
| 541 DISALLOW_COPY_AND_ASSIGN(IOBufferQueue); | |
| 542 }; | |
| 543 | |
| 544 SSLChan(const net::AddressList address_list, | |
| 545 const net::HostPortPair host_port_pair, | |
| 546 int read_pipe, | |
| 547 int write_pipe) | |
| 548 : phase_(PHASE_CONNECTING), | |
| 549 host_port_pair_(host_port_pair), | |
| 550 inbound_stream_(WebSocketProxy::kBufferLimit), | |
| 551 outbound_stream_(WebSocketProxy::kBufferLimit), | |
| 552 read_pipe_(read_pipe), | |
| 553 write_pipe_(write_pipe), | |
| 554 weak_factory_(this) { | |
| 555 if (!SetNonBlock(read_pipe_) || !SetNonBlock(write_pipe_)) { | |
| 556 Shut(net::ERR_UNEXPECTED); | |
| 557 return; | |
| 558 } | |
| 559 net::ClientSocketFactory* factory = | |
| 560 net::ClientSocketFactory::GetDefaultFactory(); | |
| 561 socket_.reset(factory->CreateTransportClientSocket( | |
| 562 address_list, NULL, net::NetLog::Source())); | |
| 563 if (socket_ == NULL) { | |
| 564 Shut(net::ERR_FAILED); | |
| 565 return; | |
| 566 } | |
| 567 int result = socket_->Connect(base::Bind(&SSLChan::OnSocketConnect, | |
| 568 base::Unretained(this))); | |
| 569 if (result != net::ERR_IO_PENDING) | |
| 570 OnSocketConnect(result); | |
| 571 } | |
| 572 | |
| 573 virtual ~SSLChan() { | |
| 574 phase_ = PHASE_CLOSED; | |
| 575 write_pipe_controller_.StopWatchingFileDescriptor(); | |
| 576 read_pipe_controller_.StopWatchingFileDescriptor(); | |
| 577 close(write_pipe_); | |
| 578 close(read_pipe_); | |
| 579 } | |
| 580 | |
| 581 void Shut(int ALLOW_UNUSED net_error_code) { | |
| 582 if (phase_ != PHASE_CLOSED) { | |
| 583 phase_ = PHASE_CLOSING; | |
| 584 scoped_refptr<net::IOBufferWithSize> buf[] = { | |
| 585 outbound_stream_.GetIOBufferToProcess(), | |
| 586 inbound_stream_.GetIOBufferToProcess() | |
| 587 }; | |
| 588 for (int i = arraysize(buf); i--;) { | |
| 589 if (buf[i].get() && buf[i]->size() > 0) { | |
| 590 base::MessageLoop::current()->PostTask( | |
| 591 FROM_HERE, | |
| 592 base::Bind(&SSLChan::Proceed, weak_factory_.GetWeakPtr())); | |
| 593 return; | |
| 594 } | |
| 595 } | |
| 596 phase_ = PHASE_CLOSED; | |
| 597 if (socket_ != NULL) { | |
| 598 socket_->Disconnect(); | |
| 599 socket_.reset(); | |
| 600 } | |
| 601 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); | |
| 602 } | |
| 603 } | |
| 604 | |
| 605 void OnSocketConnect(int result) { | |
| 606 if (phase_ != PHASE_CONNECTING) { | |
| 607 NOTREACHED(); | |
| 608 return; | |
| 609 } | |
| 610 if (result) { | |
| 611 Shut(result); | |
| 612 return; | |
| 613 } | |
| 614 net::ClientSocketHandle* handle = new net::ClientSocketHandle(); | |
| 615 handle->set_socket(socket_.release()); | |
| 616 net::ClientSocketFactory* factory = | |
| 617 net::ClientSocketFactory::GetDefaultFactory(); | |
| 618 net::SSLClientSocketContext ssl_context; | |
| 619 if (!cert_verifier_.get()) | |
| 620 cert_verifier_.reset(net::CertVerifier::CreateDefault()); | |
| 621 ssl_context.cert_verifier = cert_verifier_.get(); | |
| 622 if (!transport_security_state_.get()) | |
| 623 transport_security_state_.reset(new net::TransportSecurityState); | |
| 624 ssl_context.transport_security_state = transport_security_state_.get(); | |
| 625 socket_.reset(factory->CreateSSLClientSocket( | |
| 626 handle, host_port_pair_, ssl_config_, ssl_context)); | |
| 627 if (!socket_.get()) { | |
| 628 LOG(WARNING) << "Failed to create an SSL client socket."; | |
| 629 OnSSLHandshakeCompleted(net::ERR_UNEXPECTED); | |
| 630 return; | |
| 631 } | |
| 632 result = socket_->Connect(base::Bind(&SSLChan::OnSSLHandshakeCompleted, | |
| 633 base::Unretained(this))); | |
| 634 if (result != net::ERR_IO_PENDING) | |
| 635 OnSSLHandshakeCompleted(result); | |
| 636 } | |
| 637 | |
| 638 void OnSSLHandshakeCompleted(int result) { | |
| 639 if (result) { | |
| 640 Shut(result); | |
| 641 return; | |
| 642 } | |
| 643 is_socket_read_pending_ = false; | |
| 644 is_socket_write_pending_ = false; | |
| 645 is_read_pipe_blocked_ = false; | |
| 646 is_write_pipe_blocked_ = false; | |
| 647 base::MessageLoopForIO::current()->WatchFileDescriptor( | |
| 648 read_pipe_, false, base::MessageLoopForIO::WATCH_READ, | |
| 649 &read_pipe_controller_, this); | |
| 650 base::MessageLoopForIO::current()->WatchFileDescriptor( | |
| 651 write_pipe_, false, base::MessageLoopForIO::WATCH_WRITE, | |
| 652 &write_pipe_controller_, this); | |
| 653 phase_ = PHASE_RUNNING; | |
| 654 Proceed(); | |
| 655 } | |
| 656 | |
| 657 void OnSocketRead(int result) { | |
| 658 DCHECK(is_socket_read_pending_); | |
| 659 is_socket_read_pending_ = false; | |
| 660 if (result <= 0) { | |
| 661 Shut(result); | |
| 662 return; | |
| 663 } | |
| 664 inbound_stream_.DidFill(result); | |
| 665 Proceed(); | |
| 666 } | |
| 667 | |
| 668 void OnSocketWrite(int result) { | |
| 669 DCHECK(is_socket_write_pending_); | |
| 670 is_socket_write_pending_ = false; | |
| 671 if (result < 0) { | |
| 672 outbound_stream_.Clear(); | |
| 673 Shut(result); | |
| 674 return; | |
| 675 } | |
| 676 outbound_stream_.DidProcess(result); | |
| 677 Proceed(); | |
| 678 } | |
| 679 | |
| 680 // MessageLoopForIO::Watcher overrides. | |
| 681 virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE { | |
| 682 if (fd != read_pipe_) { | |
| 683 NOTREACHED(); | |
| 684 return; | |
| 685 } | |
| 686 is_read_pipe_blocked_ = false; | |
| 687 Proceed(); | |
| 688 } | |
| 689 | |
| 690 virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE { | |
| 691 if (fd != write_pipe_) { | |
| 692 NOTREACHED(); | |
| 693 return; | |
| 694 } | |
| 695 is_write_pipe_blocked_ = false; | |
| 696 Proceed(); | |
| 697 } | |
| 698 | |
| 699 private: | |
| 700 void Proceed() { | |
| 701 if (phase_ != PHASE_RUNNING && phase_ != PHASE_CLOSING) | |
| 702 return; | |
| 703 for (bool proceed = true; proceed;) { | |
| 704 proceed = false; | |
| 705 if (!is_read_pipe_blocked_ && phase_ == PHASE_RUNNING) { | |
| 706 scoped_refptr<net::IOBufferWithSize> buf = | |
| 707 outbound_stream_.GetIOBufferToFill(); | |
| 708 if (buf.get() && buf->size() > 0) { | |
| 709 int rv = read(read_pipe_, buf->data(), buf->size()); | |
| 710 if (rv > 0) { | |
| 711 outbound_stream_.DidFill(rv); | |
| 712 proceed = true; | |
| 713 } else if (rv == -1 && errno == EAGAIN) { | |
| 714 is_read_pipe_blocked_ = true; | |
| 715 base::MessageLoopForIO::current()->WatchFileDescriptor( | |
| 716 read_pipe_, false, base::MessageLoopForIO::WATCH_READ, | |
| 717 &read_pipe_controller_, this); | |
| 718 } else if (rv == 0) { | |
| 719 Shut(0); | |
| 720 } else { | |
| 721 DCHECK_LT(rv, 0); | |
| 722 Shut(net::ERR_UNEXPECTED); | |
| 723 return; | |
| 724 } | |
| 725 } | |
| 726 } | |
| 727 if (!is_socket_read_pending_ && phase_ == PHASE_RUNNING) { | |
| 728 scoped_refptr<net::IOBufferWithSize> buf = | |
| 729 inbound_stream_.GetIOBufferToFill(); | |
| 730 if (buf.get() && buf->size() > 0) { | |
| 731 int rv = socket_->Read( | |
| 732 buf.get(), | |
| 733 buf->size(), | |
| 734 base::Bind(&SSLChan::OnSocketRead, base::Unretained(this))); | |
| 735 is_socket_read_pending_ = true; | |
| 736 if (rv != net::ERR_IO_PENDING) { | |
| 737 base::MessageLoop::current()->PostTask( | |
| 738 FROM_HERE, base::Bind(&SSLChan::OnSocketRead, | |
| 739 weak_factory_.GetWeakPtr(), rv)); | |
| 740 } | |
| 741 } | |
| 742 } | |
| 743 if (!is_socket_write_pending_) { | |
| 744 scoped_refptr<net::IOBufferWithSize> buf = | |
| 745 outbound_stream_.GetIOBufferToProcess(); | |
| 746 if (buf.get() && buf->size() > 0) { | |
| 747 int rv = socket_->Write( | |
| 748 buf.get(), | |
| 749 buf->size(), | |
| 750 base::Bind(&SSLChan::OnSocketWrite, base::Unretained(this))); | |
| 751 is_socket_write_pending_ = true; | |
| 752 if (rv != net::ERR_IO_PENDING) { | |
| 753 base::MessageLoop::current()->PostTask( | |
| 754 FROM_HERE, base::Bind(&SSLChan::OnSocketWrite, | |
| 755 weak_factory_.GetWeakPtr(), rv)); | |
| 756 } | |
| 757 } else if (phase_ == PHASE_CLOSING) { | |
| 758 Shut(0); | |
| 759 } | |
| 760 } | |
| 761 if (!is_write_pipe_blocked_) { | |
| 762 scoped_refptr<net::IOBufferWithSize> buf = | |
| 763 inbound_stream_.GetIOBufferToProcess(); | |
| 764 if (buf.get() && buf->size() > 0) { | |
| 765 int rv = write(write_pipe_, buf->data(), buf->size()); | |
| 766 if (rv > 0) { | |
| 767 inbound_stream_.DidProcess(rv); | |
| 768 proceed = true; | |
| 769 } else if (rv == -1 && errno == EAGAIN) { | |
| 770 is_write_pipe_blocked_ = true; | |
| 771 base::MessageLoopForIO::current()->WatchFileDescriptor( | |
| 772 write_pipe_, false, base::MessageLoopForIO::WATCH_WRITE, | |
| 773 &write_pipe_controller_, this); | |
| 774 } else { | |
| 775 DCHECK_LE(rv, 0); | |
| 776 inbound_stream_.Clear(); | |
| 777 Shut(net::ERR_UNEXPECTED); | |
| 778 return; | |
| 779 } | |
| 780 } else if (phase_ == PHASE_CLOSING) { | |
| 781 Shut(0); | |
| 782 } | |
| 783 } | |
| 784 } | |
| 785 } | |
| 786 | |
| 787 Phase phase_; | |
| 788 scoped_ptr<net::StreamSocket> socket_; | |
| 789 net::HostPortPair host_port_pair_; | |
| 790 scoped_ptr<net::CertVerifier> cert_verifier_; | |
| 791 scoped_ptr<net::TransportSecurityState> transport_security_state_; | |
| 792 net::SSLConfig ssl_config_; | |
| 793 IOBufferQueue inbound_stream_; | |
| 794 IOBufferQueue outbound_stream_; | |
| 795 int read_pipe_; | |
| 796 int write_pipe_; | |
| 797 bool is_socket_read_pending_; | |
| 798 bool is_socket_write_pending_; | |
| 799 bool is_read_pipe_blocked_; | |
| 800 bool is_write_pipe_blocked_; | |
| 801 base::WeakPtrFactory<SSLChan> weak_factory_; | |
| 802 base::MessageLoopForIO::FileDescriptorWatcher read_pipe_controller_; | |
| 803 base::MessageLoopForIO::FileDescriptorWatcher write_pipe_controller_; | |
| 804 | |
| 805 friend class base::DeleteHelper<SSLChan>; | |
| 806 DISALLOW_COPY_AND_ASSIGN(SSLChan); | |
| 807 }; | |
| 808 | |
| 809 Serv::Serv() | |
| 810 : evbase_(NULL), | |
| 811 listening_sock_(-1), | |
| 812 extra_listening_sock_(-1), | |
| 813 shutdown_requested_(false) { | |
| 814 control_descriptor_[0] = -1; | |
| 815 control_descriptor_[1] = -1; | |
| 816 } | |
| 817 | |
| 818 Serv::~Serv() { | |
| 819 CloseAll(); | |
| 820 } | |
| 821 | |
| 822 void Serv::Run() { | |
| 823 if (evbase_ || shutdown_requested_) | |
| 824 return; | |
| 825 | |
| 826 evbase_ = event_init(); | |
| 827 if (!evbase_) { | |
| 828 LOG(ERROR) << "WebSocketProxy: Couldn't create libevent base"; | |
| 829 return; | |
| 830 } | |
| 831 | |
| 832 if (pipe(control_descriptor_) || | |
| 833 !SetNonBlock(control_descriptor_[0]) || | |
| 834 !SetNonBlock(control_descriptor_[1])) { | |
| 835 LOG(ERROR) << "WebSocketProxy: Failed to create control pipe"; | |
| 836 return; | |
| 837 } | |
| 838 | |
| 839 listening_sock_ = socket(AF_INET, SOCK_STREAM, 0); | |
| 840 if (listening_sock_ < 0) { | |
| 841 LOG(ERROR) << "WebSocketProxy: Failed to create socket"; | |
| 842 return; | |
| 843 } | |
| 844 { | |
| 845 int on = 1; | |
| 846 setsockopt(listening_sock_, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); | |
| 847 } | |
| 848 | |
| 849 struct sockaddr_in addr; | |
| 850 memset(&addr, 0, sizeof(addr)); | |
| 851 addr.sin_family = AF_INET; | |
| 852 // Let the OS allocate a port number. | |
| 853 addr.sin_port = base::HostToNet16(0); | |
| 854 addr.sin_addr.s_addr = base::HostToNet32(INADDR_LOOPBACK); | |
| 855 if (bind(listening_sock_, | |
| 856 reinterpret_cast<struct sockaddr*>(&addr), | |
| 857 sizeof(addr))) { | |
| 858 LOG(ERROR) << "WebSocketProxy: Failed to bind server socket"; | |
| 859 return; | |
| 860 } | |
| 861 if (listen(listening_sock_, 12)) { | |
| 862 LOG(ERROR) << "WebSocketProxy: Failed to listen server socket"; | |
| 863 return; | |
| 864 } | |
| 865 if (!SetNonBlock(listening_sock_)) { | |
| 866 LOG(ERROR) << "WebSocketProxy: Failed to go non block"; | |
| 867 return; | |
| 868 } | |
| 869 | |
| 870 connection_event_.reset(new struct event); | |
| 871 event_set(connection_event_.get(), listening_sock_, EV_READ | EV_PERSIST, | |
| 872 &OnConnect, this); | |
| 873 event_base_set(evbase_, connection_event_.get()); | |
| 874 if (event_add(connection_event_.get(), NULL)) { | |
| 875 LOG(ERROR) << "WebSocketProxy: Failed to add listening event"; | |
| 876 return; | |
| 877 } | |
| 878 | |
| 879 { | |
| 880 // TODO(dilmah): remove this control block as soon as obsolete | |
| 881 // getPassportForTCP function is removed from webSocketProxyPrivate API. | |
| 882 // Following block adds extra listening socket on fixed port 10101. | |
| 883 extra_listening_sock_ = socket(AF_INET, SOCK_STREAM, 0); | |
| 884 if (extra_listening_sock_ < 0) { | |
| 885 LOG(ERROR) << "WebSocketProxy: Failed to create socket"; | |
| 886 return; | |
| 887 } | |
| 888 { | |
| 889 int on = 1; | |
| 890 setsockopt(listening_sock_, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); | |
| 891 } | |
| 892 const int kPort = 10101; | |
| 893 memset(&addr, 0, sizeof(addr)); | |
| 894 addr.sin_family = AF_INET; | |
| 895 addr.sin_port = base::HostToNet16(kPort); | |
| 896 addr.sin_addr.s_addr = base::HostToNet32(INADDR_LOOPBACK); | |
| 897 if (bind(extra_listening_sock_, | |
| 898 reinterpret_cast<struct sockaddr*>(&addr), | |
| 899 sizeof(addr))) { | |
| 900 LOG(ERROR) << "WebSocketProxy: Failed to bind server socket"; | |
| 901 return; | |
| 902 } | |
| 903 if (listen(extra_listening_sock_, 12)) { | |
| 904 LOG(ERROR) << "WebSocketProxy: Failed to listen server socket"; | |
| 905 return; | |
| 906 } | |
| 907 if (!SetNonBlock(extra_listening_sock_)) { | |
| 908 LOG(ERROR) << "WebSocketProxy: Failed to go non block"; | |
| 909 return; | |
| 910 } | |
| 911 extra_connection_event_.reset(new struct event); | |
| 912 event_set(extra_connection_event_.get(), extra_listening_sock_, | |
| 913 EV_READ | EV_PERSIST, &OnConnect, this); | |
| 914 event_base_set(evbase_, extra_connection_event_.get()); | |
| 915 if (event_add(extra_connection_event_.get(), NULL)) { | |
| 916 LOG(ERROR) << "WebSocketProxy: Failed to add listening event"; | |
| 917 return; | |
| 918 } | |
| 919 } | |
| 920 | |
| 921 control_event_.reset(new struct event); | |
| 922 event_set(control_event_.get(), control_descriptor_[0], EV_READ | EV_PERSIST, | |
| 923 &OnControlRequest, this); | |
| 924 event_base_set(evbase_, control_event_.get()); | |
| 925 if (event_add(control_event_.get(), NULL)) { | |
| 926 LOG(ERROR) << "WebSocketProxy: Failed to add control event"; | |
| 927 return; | |
| 928 } | |
| 929 | |
| 930 if (evdns_init()) | |
| 931 LOG(WARNING) << "WebSocketProxy: Failed to initialize evDNS"; | |
| 932 if (!IgnoreSigPipe()) { | |
| 933 LOG(ERROR) << "WebSocketProxy: Failed to ignore SIGPIPE"; | |
| 934 return; | |
| 935 } | |
| 936 | |
| 937 memset(&addr, 0, sizeof(addr)); | |
| 938 socklen_t addr_len = sizeof(addr); | |
| 939 if (getsockname( | |
| 940 listening_sock_, reinterpret_cast<struct sockaddr*>(&addr), &addr_len)) { | |
| 941 LOG(ERROR) << "Failed to determine listening port"; | |
| 942 return; | |
| 943 } | |
| 944 BrowserThread::PostTask( | |
| 945 BrowserThread::UI, FROM_HERE, | |
| 946 base::Bind(&SendNotification, base::NetToHost16(addr.sin_port))); | |
| 947 | |
| 948 LOG(INFO) << "WebSocketProxy: Starting event dispatch loop."; | |
| 949 event_base_dispatch(evbase_); | |
| 950 if (shutdown_requested_) | |
| 951 LOG(INFO) << "WebSocketProxy: Event dispatch loop terminated upon request"; | |
| 952 else | |
| 953 LOG(ERROR) << "WebSocketProxy: Event dispatch loop terminated unexpectedly"; | |
| 954 CloseAll(); | |
| 955 } | |
| 956 | |
| 957 void Serv::Shutdown() { | |
| 958 int r ALLOW_UNUSED = | |
| 959 write(control_descriptor_[1], kControlMessageShutdown, 1); | |
| 960 } | |
| 961 | |
| 962 void Serv::OnNetworkChange() { | |
| 963 int r ALLOW_UNUSED = | |
| 964 write(control_descriptor_[1], kControlMessageNetworkChange, 1); | |
| 965 } | |
| 966 | |
| 967 void Serv::CloseAll() { | |
| 968 while (!conn_pool_.empty()) | |
| 969 ZapConn(conn_pool_.back()); | |
| 970 if (listening_sock_ >= 0) { | |
| 971 shutdown(listening_sock_, SHUT_RDWR); | |
| 972 close(listening_sock_); | |
| 973 } | |
| 974 for (int i = 0; i < 2; ++i) { | |
| 975 if (control_descriptor_[i] >= 0) { | |
| 976 control_descriptor_[i] = -1; | |
| 977 close(control_descriptor_[i]); | |
| 978 } | |
| 979 } | |
| 980 if (control_event_.get()) { | |
| 981 event_del(control_event_.get()); | |
| 982 control_event_.reset(); | |
| 983 } | |
| 984 if (extra_connection_event_.get()) { | |
| 985 event_del(extra_connection_event_.get()); | |
| 986 extra_connection_event_.reset(); | |
| 987 } | |
| 988 if (connection_event_.get()) { | |
| 989 event_del(connection_event_.get()); | |
| 990 connection_event_.reset(); | |
| 991 } | |
| 992 if (evbase_) { | |
| 993 event_base_free(evbase_); | |
| 994 evbase_ = NULL; | |
| 995 } | |
| 996 } | |
| 997 | |
| 998 void Serv::ZapConn(Conn* cs) { | |
| 999 RevMap::iterator rit = rev_map_.find(cs); | |
| 1000 if (rit != rev_map_.end()) { | |
| 1001 conn_pool_.erase(rit->second); | |
| 1002 rev_map_.erase(rit); | |
| 1003 delete cs; | |
| 1004 } | |
| 1005 } | |
| 1006 | |
| 1007 void Serv::MarkConnImportance(Conn* cs, bool important) { | |
| 1008 if (conn_pool_.size() < WebSocketProxy::kConnPoolLimit / 4) { | |
| 1009 // Fast common path. | |
| 1010 return; | |
| 1011 } | |
| 1012 RevMap::iterator rit = rev_map_.find(cs); | |
| 1013 if (rit != rev_map_.end()) { | |
| 1014 ConnPool::iterator it = rit->second; | |
| 1015 CHECK(*it == cs); | |
| 1016 if (important && it == conn_pool_.begin()) { | |
| 1017 // Already at the top. Shortcut. | |
| 1018 return; | |
| 1019 } | |
| 1020 conn_pool_.erase(it); | |
| 1021 } | |
| 1022 if (important) { | |
| 1023 conn_pool_.push_front(cs); | |
| 1024 rev_map_[cs] = conn_pool_.begin(); | |
| 1025 } else { | |
| 1026 conn_pool_.push_back(cs); | |
| 1027 rev_map_[cs] = conn_pool_.end(); | |
| 1028 --rev_map_[cs]; | |
| 1029 } | |
| 1030 } | |
| 1031 | |
| 1032 Conn* Serv::GetFreshConn() { | |
| 1033 if (conn_pool_.size() > WebSocketProxy::kConnPoolLimit) { | |
| 1034 // Connections overflow. Shut those oldest not active. | |
| 1035 ConnPool::iterator it = conn_pool_.end(); | |
| 1036 --it; | |
| 1037 for (int i = conn_pool_.size() - WebSocketProxy::kConnPoolLimit; i-- > 0;) { | |
| 1038 // Shut may invalidate an iterator; hence postdecrement. | |
| 1039 (*it--)->Shut(WS_CLOSE_GOING_AWAY, | |
| 1040 "Flood of new connections, getting rid of old ones"); | |
| 1041 } | |
| 1042 if (conn_pool_.size() > WebSocketProxy::kConnPoolLimit + 12) { | |
| 1043 // Connections overflow. Zap the oldest not active. | |
| 1044 ZapConn(conn_pool_.back()); | |
| 1045 } | |
| 1046 } | |
| 1047 Conn* cs = new Conn(this); | |
| 1048 conn_pool_.push_front(cs); | |
| 1049 rev_map_[cs] = conn_pool_.begin(); | |
| 1050 return cs; | |
| 1051 } | |
| 1052 | |
| 1053 bool Serv::IsConnSane(Conn* cs) { | |
| 1054 return rev_map_.find(cs) != rev_map_.end(); | |
| 1055 } | |
| 1056 | |
| 1057 // static | |
| 1058 void Serv::OnConnect(int listening_sock, short event, void* ctx) { | |
| 1059 Serv* self = static_cast<Serv*>(ctx); | |
| 1060 Conn* cs = self->GetFreshConn(); | |
| 1061 int sock = accept(listening_sock, NULL, NULL); | |
| 1062 if (sock < 0 || !SetNonBlock(sock)) { | |
| 1063 // Read readiness was triggered on listening socket | |
| 1064 // yet we failed to accept a connection; definitely weird. | |
| 1065 NOTREACHED(); | |
| 1066 self->ZapConn(cs); | |
| 1067 return; | |
| 1068 } | |
| 1069 cs->primchan().set_read_fd(sock); | |
| 1070 cs->primchan().set_write_fd(sock); | |
| 1071 | |
| 1072 struct bufferevent* bev = bufferevent_new( | |
| 1073 sock, | |
| 1074 &Conn::OnPrimchanRead, &Conn::OnPrimchanWrite, &Conn::OnPrimchanError, | |
| 1075 cs->evkey()); | |
| 1076 if (bev == NULL) { | |
| 1077 self->ZapConn(cs); | |
| 1078 return; | |
| 1079 } | |
| 1080 cs->primchan().set_read_bev(bev); | |
| 1081 cs->primchan().set_write_bev(bev); | |
| 1082 bufferevent_base_set(self->evbase_, bev); | |
| 1083 bufferevent_setwatermark(bev, EV_READ, 0, WebSocketProxy::kBufferLimit); | |
| 1084 if (bufferevent_enable(bev, EV_READ | EV_WRITE)) { | |
| 1085 self->ZapConn(cs); | |
| 1086 return; | |
| 1087 } | |
| 1088 } | |
| 1089 | |
| 1090 // static | |
| 1091 void Serv::OnControlRequest(int fd, short event, void* ctx) { | |
| 1092 Serv* self = static_cast<Serv*>(ctx); | |
| 1093 | |
| 1094 char c; | |
| 1095 if (1 == read(fd, &c, 1) && c == *kControlMessageNetworkChange) { | |
| 1096 // OnNetworkChange request. | |
| 1097 evdns_clear_nameservers_and_suspend(); | |
| 1098 evdns_init(); | |
| 1099 evdns_resume(); | |
| 1100 } else if (c == *kControlMessageShutdown) { | |
| 1101 self->shutdown_requested_ = true; | |
| 1102 event_base_loopbreak(self->evbase_); | |
| 1103 } | |
| 1104 } | |
| 1105 | |
| 1106 Conn::Conn(Serv* master) | |
| 1107 : master_(master), | |
| 1108 phase_(PHASE_WAIT_HANDSHAKE), | |
| 1109 frame_bytes_remaining_(0), | |
| 1110 frame_mask_index_(0), | |
| 1111 primchan_(this), | |
| 1112 destchan_(this), | |
| 1113 do_tls_(false), | |
| 1114 destresolution_ipv4_failed_(false), | |
| 1115 destresolution_ipv6_failed_(false) { | |
| 1116 while (evkey_map_.Get().find(last_evkey_) != evkey_map_.Get().end()) { | |
| 1117 last_evkey_ = reinterpret_cast<EventKey>(reinterpret_cast<size_t>( | |
| 1118 last_evkey_) + 1); | |
| 1119 } | |
| 1120 evkey_ = last_evkey_; | |
| 1121 evkey_map_.Get()[evkey_] = this; | |
| 1122 // Schedule timeout for initial phase of connection. | |
| 1123 destconnect_timeout_event_.reset(new struct event); | |
| 1124 evtimer_set(destconnect_timeout_event_.get(), | |
| 1125 &OnDestConnectTimeout, evkey_); | |
| 1126 event_base_set(master_->evbase(), | |
| 1127 destconnect_timeout_event_.get()); | |
| 1128 | |
| 1129 struct timeval tv; | |
| 1130 tv.tv_sec = 20; | |
| 1131 tv.tv_usec = 0; | |
| 1132 evtimer_add(destconnect_timeout_event_.get(), &tv); | |
| 1133 } | |
| 1134 | |
| 1135 Conn::~Conn() { | |
| 1136 phase_ = PHASE_DEFUNCT; | |
| 1137 event_del(destconnect_timeout_event_.get()); | |
| 1138 if (evkey_map_.Get()[evkey_] == this) | |
| 1139 evkey_map_.Get().erase(evkey_); | |
| 1140 else | |
| 1141 NOTREACHED(); | |
| 1142 } | |
| 1143 | |
| 1144 Conn* Conn::Get(EventKey evkey) { | |
| 1145 EventKeyMap::iterator it = evkey_map_.Get().find(evkey); | |
| 1146 if (it == evkey_map_.Get().end()) | |
| 1147 return NULL; | |
| 1148 Conn* cs = it->second; | |
| 1149 if (cs == NULL || | |
| 1150 cs->evkey_ != evkey || | |
| 1151 cs->master_ == NULL || | |
| 1152 cs->phase_ < 0 || | |
| 1153 cs->phase_ > PHASE_SHUT || | |
| 1154 !cs->master_->IsConnSane(cs)) { | |
| 1155 return NULL; | |
| 1156 } | |
| 1157 return cs; | |
| 1158 } | |
| 1159 | |
| 1160 void Conn::Shut(int status, const void* reason) { | |
| 1161 if (phase_ >= PHASE_SHUT) | |
| 1162 return; | |
| 1163 master_->MarkConnImportance(this, false); | |
| 1164 | |
| 1165 std::vector<uint8> payload(2 + strlen(reason)); | |
| 1166 WriteNetworkInteger(status, vector_as_array(&payload), 2); | |
| 1167 memcpy(vector_as_array(&payload) + 2, reason, strlen(reason)); | |
| 1168 | |
| 1169 EmitFrame( | |
| 1170 &primchan_, WS_OPCODE_CLOSE, vector_as_array(&payload), payload.size()); | |
| 1171 primchan_.Shut(); | |
| 1172 destchan_.Shut(); | |
| 1173 phase_ = PHASE_SHUT; | |
| 1174 } | |
| 1175 | |
| 1176 void Conn::ConsiderSuicide() { | |
| 1177 if (!primchan_.write_pending() && !destchan_.write_pending()) | |
| 1178 master_->ZapConn(this); | |
| 1179 } | |
| 1180 | |
| 1181 Conn::Status Conn::ConsumeHeader(struct evbuffer* evb) { | |
| 1182 uint8* buf = EVBUFFER_DATA(evb); | |
| 1183 size_t buf_size = EVBUFFER_LENGTH(evb); | |
| 1184 | |
| 1185 static const uint8 kGetPrefix[] = "GET " kProxyPath; | |
| 1186 static const uint8 kKeyValueDelimiter[] = ": "; | |
| 1187 | |
| 1188 if (buf_size <= 0) | |
| 1189 return STATUS_INCOMPLETE; | |
| 1190 if (!buf) | |
| 1191 return STATUS_ABORT; | |
| 1192 if (!std::equal(buf, buf + std::min(buf_size, strlen(kGetPrefix)), | |
| 1193 kGetPrefix)) { | |
| 1194 // Data head does not match what is expected. | |
| 1195 return STATUS_ABORT; | |
| 1196 } | |
| 1197 | |
| 1198 if (buf_size >= WebSocketProxy::kHeaderLimit) | |
| 1199 return STATUS_ABORT; | |
| 1200 uint8* buf_end = buf + buf_size; | |
| 1201 // Handshake request must end with double CRLF. | |
| 1202 uint8* term_pos = std::search(buf, buf_end, kCRLFCRLF, | |
| 1203 kCRLFCRLF + strlen(kCRLFCRLF)); | |
| 1204 if (term_pos == buf_end) | |
| 1205 return STATUS_INCOMPLETE; | |
| 1206 term_pos += strlen(kCRLFCRLF); | |
| 1207 // First line is "GET path?query protocol" line. If query is empty then we | |
| 1208 // fall back to (obsolete) way of obtaining parameters from first websocket | |
| 1209 // frame. Otherwise query contains all required parameters (host, port etc). | |
| 1210 uint8* get_request_end = std::search( | |
| 1211 buf, term_pos, kCRLF, kCRLF + strlen(kCRLF)); | |
| 1212 DCHECK(get_request_end != term_pos); | |
| 1213 uint8* resource_end = std::find( | |
| 1214 buf + strlen(kGetPrefix), get_request_end, ' '); | |
| 1215 if (*resource_end != ' ') | |
| 1216 return STATUS_ABORT; | |
| 1217 if (resource_end != buf + strlen(kGetPrefix)) { | |
| 1218 char* piece = reinterpret_cast<char*>(buf) + strlen(kGetPrefix) + 1; | |
| 1219 url_parse::Component query( | |
| 1220 0, resource_end - reinterpret_cast<uint8*>(piece)); | |
| 1221 for (url_parse::Component key, value; | |
| 1222 url_parse::ExtractQueryKeyValue(piece, &query, &key, &value);) { | |
| 1223 if (key.len > 0) { | |
| 1224 requested_parameters_[std::string(piece + key.begin, key.len)] = | |
| 1225 net::UnescapeURLComponent(std::string(piece + value.begin, | |
| 1226 value.len), net::UnescapeRule::URL_SPECIAL_CHARS); | |
| 1227 } | |
| 1228 } | |
| 1229 } | |
| 1230 for (uint8* pos = get_request_end;;) { | |
| 1231 pos += strlen(kCRLF); | |
| 1232 if (term_pos - pos < static_cast<ptrdiff_t>(strlen(kCRLF))) | |
| 1233 return STATUS_ABORT; | |
| 1234 if (term_pos - pos == static_cast<ptrdiff_t>(strlen(kCRLF))) | |
| 1235 break; | |
| 1236 uint8* npos = std::search(pos, term_pos, kKeyValueDelimiter, | |
| 1237 kKeyValueDelimiter + strlen(kKeyValueDelimiter)); | |
| 1238 if (npos == term_pos) | |
| 1239 return STATUS_ABORT; | |
| 1240 std::string key = FetchAsciiSnippet(pos, npos, AsciiFilterLower); | |
| 1241 pos = std::search(npos += strlen(kKeyValueDelimiter), term_pos, | |
| 1242 kCRLF, kCRLF + strlen(kCRLF)); | |
| 1243 if (pos == term_pos) | |
| 1244 return STATUS_ABORT; | |
| 1245 if (!key.empty()) { | |
| 1246 header_fields_[key] = FetchAsciiSnippet(npos, pos, | |
| 1247 key == "sec-websocket-key" ? AsciiFilterVerbatim : AsciiFilterLower); | |
| 1248 } | |
| 1249 } | |
| 1250 | |
| 1251 // Values of Upgrade and Connection fields are hardcoded in the protocol. | |
| 1252 if (header_fields_["upgrade"] != "websocket" || | |
| 1253 header_fields_["connection"] != "upgrade" || | |
| 1254 header_fields_["sec-websocket-key"].size() != 24) { | |
| 1255 return STATUS_ABORT; | |
| 1256 } | |
| 1257 if (header_fields_["sec-websocket-version"] != "8" && | |
| 1258 header_fields_["sec-websocket-version"] != "13") { | |
| 1259 return STATUS_ABORT; | |
| 1260 } | |
| 1261 // Normalize origin (e.g. leading slash). | |
| 1262 GURL origin = GURL(GetOrigin()).GetOrigin(); | |
| 1263 if (!origin.is_valid()) | |
| 1264 return STATUS_ABORT; | |
| 1265 | |
| 1266 if (!requested_parameters_.empty()) { | |
| 1267 destname_ = requested_parameters_["hostname"]; | |
| 1268 int port; | |
| 1269 if (!base::StringToInt(requested_parameters_["port"], &port) || | |
| 1270 port < 0 || port >= 1 << 16) { | |
| 1271 return STATUS_ABORT; | |
| 1272 } | |
| 1273 destport_ = port; | |
| 1274 destaddr_ = requested_parameters_["addr"]; | |
| 1275 do_tls_ = (requested_parameters_["tls"] == "true"); | |
| 1276 | |
| 1277 requested_parameters_["extension_id"] = | |
| 1278 FetchExtensionIdFromOrigin(GetOrigin()); | |
| 1279 std::string passport(requested_parameters_["passport"]); | |
| 1280 requested_parameters_.erase("passport"); | |
| 1281 if (!chrome::InternalAuthVerification::VerifyPassport( | |
| 1282 passport, "web_socket_proxy", requested_parameters_)) { | |
| 1283 return STATUS_ABORT; | |
| 1284 } | |
| 1285 } | |
| 1286 | |
| 1287 evbuffer_drain(evb, term_pos - buf); | |
| 1288 return STATUS_OK; | |
| 1289 } | |
| 1290 | |
| 1291 bool Conn::EmitHandshake(Chan* chan) { | |
| 1292 std::vector<std::string> boilerplate; | |
| 1293 boilerplate.push_back("HTTP/1.1 101 WebSocket Protocol Handshake"); | |
| 1294 boilerplate.push_back("Upgrade: websocket"); | |
| 1295 boilerplate.push_back("Connection: Upgrade"); | |
| 1296 | |
| 1297 { | |
| 1298 // Take care of Accept field. | |
| 1299 std::string word = header_fields_["sec-websocket-key"]; | |
| 1300 word += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; | |
| 1301 std::string accept_token; | |
| 1302 base::Base64Encode(base::SHA1HashString(word), &accept_token); | |
| 1303 boilerplate.push_back("Sec-WebSocket-Accept: " + accept_token); | |
| 1304 } | |
| 1305 | |
| 1306 boilerplate.push_back(""); | |
| 1307 for (size_t i = 0; i < boilerplate.size(); ++i) { | |
| 1308 if (!chan->Write(boilerplate[i].c_str(), boilerplate[i].size()) || | |
| 1309 !chan->Write(kCRLF, strlen(kCRLF))) { | |
| 1310 return false; | |
| 1311 } | |
| 1312 } | |
| 1313 return true; | |
| 1314 } | |
| 1315 | |
| 1316 bool Conn::EmitFrame( | |
| 1317 Chan* chan, WebSocketFrameOpcode opcode, const void* buf, size_t size) { | |
| 1318 uint8 header[10]; | |
| 1319 int header_size = 2; | |
| 1320 DCHECK(chan); | |
| 1321 DCHECK(opcode >= 0 && static_cast<int>(opcode) < 16); | |
| 1322 header[0] = opcode | 0x80; // FIN bit set. | |
| 1323 if (size < 126) { | |
| 1324 header[1] = size; | |
| 1325 } else if (size < (1 << 16)) { | |
| 1326 header[1] = 126; | |
| 1327 WriteNetworkInteger(size, header + 2, 2); | |
| 1328 header_size += 2; | |
| 1329 } else { | |
| 1330 header[1] = 127; | |
| 1331 WriteNetworkInteger(size, header + 2, 8); | |
| 1332 header_size += 8; | |
| 1333 } | |
| 1334 return chan->Write(header, header_size) && chan->Write(buf, size); | |
| 1335 } | |
| 1336 | |
| 1337 Conn::Status Conn::ConsumeDestframe(struct evbuffer* evb) { | |
| 1338 if (!requested_parameters_.empty()) { | |
| 1339 // Parameters were already provided (and verified) in query component of | |
| 1340 // websocket URL. | |
| 1341 return STATUS_OK; | |
| 1342 } | |
| 1343 if (frame_bytes_remaining_ == 0) { | |
| 1344 Conn::Status rv = ConsumeFrameHeader(evb); | |
| 1345 if (rv != STATUS_OK) | |
| 1346 return rv; | |
| 1347 if (frame_bytes_remaining_ == 0 || | |
| 1348 frame_bytes_remaining_ >= WebSocketProxy::kHeaderLimit) { | |
| 1349 return STATUS_ABORT; | |
| 1350 } | |
| 1351 } | |
| 1352 | |
| 1353 uint8* buf = EVBUFFER_DATA(evb); | |
| 1354 size_t buf_size = EVBUFFER_LENGTH(evb); | |
| 1355 if (buf_size < frame_bytes_remaining_) | |
| 1356 return STATUS_INCOMPLETE; | |
| 1357 for (size_t i = 0; i < buf_size; ++i) { | |
| 1358 buf[i] ^= frame_mask_[frame_mask_index_]; | |
| 1359 frame_mask_index_ = (frame_mask_index_ + 1) % 4; | |
| 1360 } | |
| 1361 std::string passport; | |
| 1362 if (!WebSocketProxyHelper::FetchPassportAddrNamePort( | |
| 1363 buf, buf + frame_bytes_remaining_, | |
| 1364 &passport, &destaddr_, &destname_, &destport_)) { | |
| 1365 return STATUS_ABORT; | |
| 1366 } | |
| 1367 std::map<std::string, std::string> map; | |
| 1368 map["hostname"] = destname_; | |
| 1369 map["port"] = base::IntToString(destport_); | |
| 1370 map["extension_id"] = FetchExtensionIdFromOrigin(GetOrigin()); | |
| 1371 if (!destaddr_.empty()) | |
| 1372 map["addr"] = destaddr_; | |
| 1373 if (!chrome::InternalAuthVerification::VerifyPassport( | |
| 1374 passport, "web_socket_proxy", map)) { | |
| 1375 return STATUS_ABORT; | |
| 1376 } | |
| 1377 | |
| 1378 evbuffer_drain(evb, frame_bytes_remaining_); | |
| 1379 frame_bytes_remaining_ = 0; | |
| 1380 return STATUS_OK; | |
| 1381 } | |
| 1382 | |
| 1383 Conn::Status Conn::ConsumeFrameHeader(struct evbuffer* evb) { | |
| 1384 uint8* buf = EVBUFFER_DATA(evb); | |
| 1385 size_t buf_size = EVBUFFER_LENGTH(evb); | |
| 1386 size_t header_size = 2; | |
| 1387 | |
| 1388 if (buf_size < header_size) | |
| 1389 return STATUS_INCOMPLETE; | |
| 1390 if (buf[0] & 0x70) { | |
| 1391 // We are not able to handle non-zero reserved bits. | |
| 1392 NOTIMPLEMENTED(); | |
| 1393 return STATUS_ABORT; | |
| 1394 } | |
| 1395 bool fin_flag = buf[0] & 0x80; | |
| 1396 if (!fin_flag) { | |
| 1397 NOTIMPLEMENTED(); | |
| 1398 return STATUS_ABORT; | |
| 1399 } | |
| 1400 int opcode = buf[0] & 0x0f; | |
| 1401 switch (opcode) { | |
| 1402 case WS_OPCODE_TEXT: | |
| 1403 break; | |
| 1404 case WS_OPCODE_CLOSE: | |
| 1405 return STATUS_ABORT; | |
| 1406 default: | |
| 1407 NOTIMPLEMENTED(); | |
| 1408 return STATUS_ABORT; | |
| 1409 } | |
| 1410 | |
| 1411 bool mask_flag = buf[1] & 0x80; | |
| 1412 if (!mask_flag) { | |
| 1413 // Client-to-server frames must be masked. | |
| 1414 return STATUS_ABORT; | |
| 1415 } | |
| 1416 frame_bytes_remaining_ = buf[1] & 0x7f; | |
| 1417 int extra_size = 0; | |
| 1418 if (frame_bytes_remaining_ == 126) | |
| 1419 extra_size = 2; | |
| 1420 else if (frame_bytes_remaining_ == 127) | |
| 1421 extra_size = 8; | |
| 1422 if (buf_size < header_size + extra_size + sizeof(frame_mask_)) | |
| 1423 return STATUS_INCOMPLETE; | |
| 1424 if (extra_size) | |
| 1425 frame_bytes_remaining_ = ReadNetworkInteger(buf + header_size, extra_size); | |
| 1426 header_size += extra_size; | |
| 1427 memcpy(frame_mask_, buf + header_size, sizeof(frame_mask_)); | |
| 1428 header_size += sizeof(frame_mask_); | |
| 1429 frame_mask_index_ = 0; | |
| 1430 evbuffer_drain(evb, header_size); | |
| 1431 return STATUS_OK; | |
| 1432 } | |
| 1433 | |
| 1434 Conn::Status Conn::ProcessFrameData(struct evbuffer* evb) { | |
| 1435 uint8* buf = EVBUFFER_DATA(evb); | |
| 1436 size_t buf_size = EVBUFFER_LENGTH(evb); | |
| 1437 | |
| 1438 DCHECK_GE(frame_bytes_remaining_, 1u); | |
| 1439 if (frame_bytes_remaining_ < buf_size) | |
| 1440 buf_size = frame_bytes_remaining_; | |
| 1441 // base64 is encoded in chunks of 4 bytes. | |
| 1442 buf_size = buf_size / 4 * 4; | |
| 1443 if (buf_size < 1) | |
| 1444 return STATUS_INCOMPLETE; | |
| 1445 switch (phase_) { | |
| 1446 case PHASE_INSIDE_FRAME_BASE64: { | |
| 1447 for (size_t i = 0; i < buf_size; ++i) { | |
| 1448 buf[i] ^= frame_mask_[frame_mask_index_]; | |
| 1449 frame_mask_index_ = (frame_mask_index_ + 1) % 4; | |
| 1450 } | |
| 1451 std::string out_bytes; | |
| 1452 base::Base64Decode(std::string(buf, buf + buf_size), &out_bytes); | |
| 1453 evbuffer_drain(evb, buf_size); | |
| 1454 DCHECK(destchan_.write_bev()); | |
| 1455 if (!destchan_.Write(out_bytes.c_str(), out_bytes.size())) | |
| 1456 return STATUS_ABORT; | |
| 1457 break; | |
| 1458 } | |
| 1459 case PHASE_INSIDE_FRAME_SKIP: { | |
| 1460 evbuffer_drain(evb, buf_size); | |
| 1461 break; | |
| 1462 } | |
| 1463 default: { | |
| 1464 return STATUS_ABORT; | |
| 1465 } | |
| 1466 } | |
| 1467 frame_bytes_remaining_ -= buf_size; | |
| 1468 return frame_bytes_remaining_ ? STATUS_INCOMPLETE : STATUS_OK; | |
| 1469 } | |
| 1470 | |
| 1471 bool Conn::TryConnectDest(const struct sockaddr* addr, socklen_t addrlen) { | |
| 1472 if (destchan_.read_fd() >= 0 || destchan_.read_bev() != NULL) | |
| 1473 return false; | |
| 1474 if (do_tls_) { | |
| 1475 int fd[4]; | |
| 1476 if (pipe(fd) || pipe(fd + 2)) | |
| 1477 return false; | |
| 1478 destchan_.set_read_fd(fd[0]); | |
| 1479 destchan_.set_write_fd(fd[3]); | |
| 1480 for (int i = arraysize(fd); i--;) { | |
| 1481 if (!SetNonBlock(fd[i])) | |
| 1482 return false; | |
| 1483 } | |
| 1484 destchan_.set_read_bev(bufferevent_new( | |
| 1485 destchan_.read_fd(), | |
| 1486 &OnDestchanRead, NULL, &OnDestchanError, | |
| 1487 evkey_)); | |
| 1488 destchan_.set_write_bev(bufferevent_new( | |
| 1489 destchan_.write_fd(), | |
| 1490 NULL, &OnDestchanWrite, &OnDestchanError, | |
| 1491 evkey_)); | |
| 1492 net::IPEndPoint endpoint; | |
| 1493 if (!endpoint.FromSockAddr(addr, addrlen)) | |
| 1494 return false; | |
| 1495 net::AddressList addrlist(endpoint); | |
| 1496 net::HostPortPair host_port_pair(destname_, destport_); | |
| 1497 BrowserThread::PostTask( | |
| 1498 BrowserThread::IO, FROM_HERE, base::Bind( | |
| 1499 &SSLChan::Start, addrlist, host_port_pair, fd[2], fd[1])); | |
| 1500 } else { | |
| 1501 int sock = socket(addr->sa_family, SOCK_STREAM, 0); | |
| 1502 if (sock < 0) | |
| 1503 return false; | |
| 1504 destchan_.set_read_fd(sock); | |
| 1505 destchan_.set_write_fd(sock); | |
| 1506 if (!SetNonBlock(sock)) | |
| 1507 return false; | |
| 1508 if (connect(sock, addr, addrlen)) { | |
| 1509 if (errno != EINPROGRESS) | |
| 1510 return false; | |
| 1511 } | |
| 1512 destchan_.set_read_bev(bufferevent_new( | |
| 1513 sock, | |
| 1514 &OnDestchanRead, &OnDestchanWrite, &OnDestchanError, | |
| 1515 evkey_)); | |
| 1516 destchan_.set_write_bev(destchan_.read_bev()); | |
| 1517 } | |
| 1518 if (destchan_.read_bev() == NULL || destchan_.write_bev() == NULL) | |
| 1519 return false; | |
| 1520 if (bufferevent_base_set(master_->evbase(), destchan_.read_bev()) || | |
| 1521 bufferevent_base_set(master_->evbase(), destchan_.write_bev())) { | |
| 1522 return false; | |
| 1523 } | |
| 1524 bufferevent_setwatermark( | |
| 1525 destchan_.read_bev(), EV_READ, 0, WebSocketProxy::kBufferLimit); | |
| 1526 if (bufferevent_enable(destchan_.read_bev(), EV_READ) || | |
| 1527 bufferevent_enable(destchan_.write_bev(), EV_WRITE)) { | |
| 1528 return false; | |
| 1529 } | |
| 1530 return true; | |
| 1531 } | |
| 1532 | |
| 1533 const std::string& Conn::GetOrigin() { | |
| 1534 return header_fields_[header_fields_["sec-websocket-version"] == "8" ? | |
| 1535 "sec-websocket-origin" : "origin"]; | |
| 1536 } | |
| 1537 | |
| 1538 // static | |
| 1539 void Conn::OnPrimchanRead(struct bufferevent* bev, EventKey evkey) { | |
| 1540 Conn* cs = Conn::Get(evkey); | |
| 1541 if (bev == NULL || | |
| 1542 cs == NULL || | |
| 1543 bev != cs->primchan_.read_bev()) { | |
| 1544 NOTREACHED(); | |
| 1545 return; | |
| 1546 } | |
| 1547 if (EVBUFFER_LENGTH(EVBUFFER_INPUT(bev)) <= 0) | |
| 1548 return; | |
| 1549 cs->master_->MarkConnImportance(cs, true); | |
| 1550 for (;;) { | |
| 1551 switch (cs->phase_) { | |
| 1552 case PHASE_WAIT_HANDSHAKE: { | |
| 1553 switch (cs->ConsumeHeader(EVBUFFER_INPUT(bev))) { | |
| 1554 case STATUS_OK: { | |
| 1555 break; | |
| 1556 } | |
| 1557 case STATUS_INCOMPLETE: { | |
| 1558 return; | |
| 1559 } | |
| 1560 case STATUS_ABORT: | |
| 1561 default: { | |
| 1562 cs->master_->ZapConn(cs); | |
| 1563 return; | |
| 1564 } | |
| 1565 } | |
| 1566 // Header consumed OK. Do respond. | |
| 1567 if (!cs->EmitHandshake(&cs->primchan_)) { | |
| 1568 cs->master_->ZapConn(cs); | |
| 1569 return; | |
| 1570 } | |
| 1571 cs->phase_ = PHASE_WAIT_DESTFRAME; | |
| 1572 } | |
| 1573 case PHASE_WAIT_DESTFRAME: { | |
| 1574 switch (cs->ConsumeDestframe(EVBUFFER_INPUT(bev))) { | |
| 1575 case STATUS_OK: { | |
| 1576 { | |
| 1577 // Unfortunately libevent as of 1.4 does not look into /etc/hosts. | |
| 1578 // There seems to be no easy API to perform only "local" part of | |
| 1579 // getaddrinfo resolution. Hence this hack for "localhost". | |
| 1580 if (cs->destname_ == "localhost") | |
| 1581 cs->destname_ = "127.0.0.1"; | |
| 1582 } | |
| 1583 if (cs->destaddr_.empty()) | |
| 1584 cs->destaddr_ = cs->destname_; | |
| 1585 { | |
| 1586 struct sockaddr_in sa; | |
| 1587 memset(&sa, 0, sizeof(sa)); | |
| 1588 sa.sin_port = base::HostToNet16(cs->destport_); | |
| 1589 if (inet_pton(sa.sin_family = AF_INET, | |
| 1590 cs->destaddr_.c_str(), | |
| 1591 &sa.sin_addr) == 1) { | |
| 1592 // valid IPv4 address supplied. | |
| 1593 if (cs->TryConnectDest((struct sockaddr*)&sa, sizeof(sa))) { | |
| 1594 cs->phase_ = PHASE_WAIT_DESTCONNECT; | |
| 1595 return; | |
| 1596 } | |
| 1597 } | |
| 1598 } | |
| 1599 { | |
| 1600 if (cs->destaddr_.size() >= 2 && | |
| 1601 cs->destaddr_[0] == '[' && | |
| 1602 cs->destaddr_[cs->destaddr_.size() - 1] == ']') { | |
| 1603 // Literal IPv6 address in brackets. | |
| 1604 cs->destaddr_ = | |
| 1605 cs->destaddr_.substr(1, cs->destaddr_.size() - 2); | |
| 1606 } | |
| 1607 struct sockaddr_in6 sa; | |
| 1608 memset(&sa, 0, sizeof(sa)); | |
| 1609 sa.sin6_port = base::HostToNet16(cs->destport_); | |
| 1610 if (inet_pton(sa.sin6_family = AF_INET6, | |
| 1611 cs->destaddr_.c_str(), | |
| 1612 &sa.sin6_addr) == 1) { | |
| 1613 // valid IPv6 address supplied. | |
| 1614 if (cs->TryConnectDest((struct sockaddr*)&sa, sizeof(sa))) { | |
| 1615 cs->phase_ = PHASE_WAIT_DESTCONNECT; | |
| 1616 return; | |
| 1617 } | |
| 1618 } | |
| 1619 } | |
| 1620 // Asynchronous DNS resolution. | |
| 1621 if (evdns_count_nameservers() < 1) { | |
| 1622 evdns_clear_nameservers_and_suspend(); | |
| 1623 evdns_init(); | |
| 1624 evdns_resume(); | |
| 1625 } | |
| 1626 evdns_resolve_ipv4(cs->destname_.c_str(), 0, | |
| 1627 &OnDestResolutionIPv4, evkey); | |
| 1628 evdns_resolve_ipv6(cs->destname_.c_str(), 0, | |
| 1629 &OnDestResolutionIPv6, evkey); | |
| 1630 cs->phase_ = PHASE_WAIT_DESTCONNECT; | |
| 1631 return; | |
| 1632 } | |
| 1633 case STATUS_INCOMPLETE: { | |
| 1634 return; | |
| 1635 } | |
| 1636 case STATUS_ABORT: | |
| 1637 default: { | |
| 1638 cs->Shut(WS_CLOSE_DESTINATION_ERROR, | |
| 1639 "Incorrect destination specification in first frame"); | |
| 1640 return; | |
| 1641 } | |
| 1642 } | |
| 1643 } | |
| 1644 case PHASE_WAIT_DESTCONNECT: { | |
| 1645 if (EVBUFFER_LENGTH(EVBUFFER_INPUT(bev)) >= | |
| 1646 WebSocketProxy::kBufferLimit) { | |
| 1647 cs->Shut(WS_CLOSE_LIMIT_VIOLATION, "Read buffer overflow"); | |
| 1648 } | |
| 1649 return; | |
| 1650 } | |
| 1651 case PHASE_OUTSIDE_FRAME: { | |
| 1652 switch (cs->ConsumeFrameHeader(EVBUFFER_INPUT(bev))) { | |
| 1653 case STATUS_OK: { | |
| 1654 if (cs->frame_bytes_remaining_ % 4) { | |
| 1655 // We expect base64 encoded data (encoded in 4-bytes chunks). | |
| 1656 cs->Shut(WS_CLOSE_UNACCEPTABLE_DATA, | |
| 1657 "Frame payload size is not multiple of 4"); | |
| 1658 return; | |
| 1659 } | |
| 1660 cs->phase_ = PHASE_INSIDE_FRAME_BASE64; | |
| 1661 // Process remaining data if any. | |
| 1662 break; | |
| 1663 } | |
| 1664 case STATUS_SKIP: { | |
| 1665 cs->phase_ = PHASE_INSIDE_FRAME_SKIP; | |
| 1666 // Process remaining data if any. | |
| 1667 break; | |
| 1668 } | |
| 1669 case STATUS_INCOMPLETE: { | |
| 1670 return; | |
| 1671 } | |
| 1672 case STATUS_ABORT: | |
| 1673 default: { | |
| 1674 cs->Shut(WS_CLOSE_PROTOCOL_ERROR, "Invalid frame header"); | |
| 1675 return; | |
| 1676 } | |
| 1677 } | |
| 1678 break; | |
| 1679 } | |
| 1680 case PHASE_INSIDE_FRAME_BASE64: | |
| 1681 case PHASE_INSIDE_FRAME_SKIP: { | |
| 1682 switch (cs->ProcessFrameData(EVBUFFER_INPUT(bev))) { | |
| 1683 case STATUS_OK: { | |
| 1684 cs->phase_ = PHASE_OUTSIDE_FRAME; | |
| 1685 // Handle remaining data if any. | |
| 1686 break; | |
| 1687 } | |
| 1688 case STATUS_INCOMPLETE: { | |
| 1689 return; | |
| 1690 } | |
| 1691 case STATUS_ABORT: | |
| 1692 default: { | |
| 1693 cs->Shut(WS_CLOSE_UNACCEPTABLE_DATA, "Invalid frame data"); | |
| 1694 return; | |
| 1695 } | |
| 1696 } | |
| 1697 break; | |
| 1698 } | |
| 1699 case PHASE_SHUT: { | |
| 1700 evbuffer_drain(EVBUFFER_INPUT(bev), | |
| 1701 EVBUFFER_LENGTH(EVBUFFER_INPUT(bev))); | |
| 1702 return; | |
| 1703 } | |
| 1704 case PHASE_DEFUNCT: | |
| 1705 default: { | |
| 1706 NOTREACHED(); | |
| 1707 cs->master_->ZapConn(cs); | |
| 1708 return; | |
| 1709 } | |
| 1710 } | |
| 1711 } | |
| 1712 } | |
| 1713 | |
| 1714 // static | |
| 1715 void Conn::OnPrimchanWrite(struct bufferevent* bev, EventKey evkey) { | |
| 1716 Conn* cs = Conn::Get(evkey); | |
| 1717 if (bev == NULL || | |
| 1718 cs == NULL || | |
| 1719 bev != cs->primchan_.write_bev()) { | |
| 1720 NOTREACHED(); | |
| 1721 return; | |
| 1722 } | |
| 1723 // Write callback is called when low watermark is reached, 0 by default. | |
| 1724 cs->primchan_.set_write_pending(false); | |
| 1725 if (cs->phase_ >= PHASE_SHUT) { | |
| 1726 cs->master_->ZapConn(cs); | |
| 1727 return; | |
| 1728 } | |
| 1729 if (cs->phase_ > PHASE_WAIT_DESTCONNECT) | |
| 1730 OnDestchanRead(cs->destchan_.read_bev(), evkey); | |
| 1731 if (cs->phase_ >= PHASE_SHUT) | |
| 1732 cs->primchan_.Zap(); | |
| 1733 } | |
| 1734 | |
| 1735 // static | |
| 1736 void Conn::OnPrimchanError(struct bufferevent* bev, | |
| 1737 short what, EventKey evkey) { | |
| 1738 Conn* cs = Conn::Get(evkey); | |
| 1739 if (bev == NULL || | |
| 1740 cs == NULL || | |
| 1741 (bev != cs->primchan_.read_bev() && bev != cs->primchan_.write_bev())) { | |
| 1742 return; | |
| 1743 } | |
| 1744 cs->primchan_.set_write_pending(false); | |
| 1745 if (cs->phase_ >= PHASE_SHUT) | |
| 1746 cs->master_->ZapConn(cs); | |
| 1747 else | |
| 1748 cs->Shut(WS_CLOSE_NORMAL, "Error reported on websocket channel"); | |
| 1749 } | |
| 1750 | |
| 1751 // static | |
| 1752 void Conn::OnDestResolutionIPv4(int result, char type, | |
| 1753 int count, int ttl, | |
| 1754 void* addr_list, EventKey evkey) { | |
| 1755 Conn* cs = Conn::Get(evkey); | |
| 1756 if (cs == NULL) | |
| 1757 return; | |
| 1758 if (cs->phase_ != PHASE_WAIT_DESTCONNECT) | |
| 1759 return; | |
| 1760 if (result == DNS_ERR_NONE && | |
| 1761 count >= 1 && | |
| 1762 addr_list != NULL && | |
| 1763 type == DNS_IPv4_A) { | |
| 1764 for (int i = 0; i < count; ++i) { | |
| 1765 struct sockaddr_in sa; | |
| 1766 memset(&sa, 0, sizeof(sa)); | |
| 1767 sa.sin_family = AF_INET; | |
| 1768 sa.sin_port = base::HostToNet16(cs->destport_); | |
| 1769 DCHECK(sizeof(sa.sin_addr) == sizeof(struct in_addr)); | |
| 1770 memcpy(&sa.sin_addr, | |
| 1771 static_cast<struct in_addr*>(addr_list) + i, | |
| 1772 sizeof(sa.sin_addr)); | |
| 1773 if (cs->TryConnectDest((struct sockaddr*)&sa, sizeof(sa))) | |
| 1774 return; | |
| 1775 } | |
| 1776 } | |
| 1777 cs->destresolution_ipv4_failed_ = true; | |
| 1778 if (cs->destresolution_ipv4_failed_ && cs->destresolution_ipv6_failed_) | |
| 1779 cs->Shut(WS_CLOSE_RESOLUTION_FAILED, "DNS resolution failed"); | |
| 1780 } | |
| 1781 | |
| 1782 // static | |
| 1783 void Conn::OnDestResolutionIPv6(int result, char type, | |
| 1784 int count, int ttl, | |
| 1785 void* addr_list, EventKey evkey) { | |
| 1786 Conn* cs = Conn::Get(evkey); | |
| 1787 if (cs == NULL) | |
| 1788 return; | |
| 1789 if (cs->phase_ != PHASE_WAIT_DESTCONNECT) | |
| 1790 return; | |
| 1791 if (result == DNS_ERR_NONE && | |
| 1792 count >= 1 && | |
| 1793 addr_list != NULL && | |
| 1794 type == DNS_IPv6_AAAA) { | |
| 1795 for (int i = 0; i < count; ++i) { | |
| 1796 struct sockaddr_in6 sa; | |
| 1797 memset(&sa, 0, sizeof(sa)); | |
| 1798 sa.sin6_family = AF_INET6; | |
| 1799 sa.sin6_port = base::HostToNet16(cs->destport_); | |
| 1800 DCHECK(sizeof(sa.sin6_addr) == sizeof(struct in6_addr)); | |
| 1801 memcpy(&sa.sin6_addr, | |
| 1802 static_cast<struct in6_addr*>(addr_list) + i, | |
| 1803 sizeof(sa.sin6_addr)); | |
| 1804 if (cs->TryConnectDest((struct sockaddr*)&sa, sizeof(sa))) | |
| 1805 return; | |
| 1806 } | |
| 1807 } | |
| 1808 cs->destresolution_ipv6_failed_ = true; | |
| 1809 if (cs->destresolution_ipv4_failed_ && cs->destresolution_ipv6_failed_) | |
| 1810 cs->Shut(WS_CLOSE_RESOLUTION_FAILED, "DNS resolution failed"); | |
| 1811 } | |
| 1812 | |
| 1813 // static | |
| 1814 void Conn::OnDestConnectTimeout(int, short, EventKey evkey) { | |
| 1815 Conn* cs = Conn::Get(evkey); | |
| 1816 if (cs == NULL) | |
| 1817 return; | |
| 1818 if (cs->phase_ > PHASE_WAIT_DESTCONNECT) | |
| 1819 return; | |
| 1820 cs->Shut(WS_CLOSE_RESOLUTION_FAILED, "DNS resolution timeout"); | |
| 1821 } | |
| 1822 | |
| 1823 // static | |
| 1824 void Conn::OnDestchanRead(struct bufferevent* bev, EventKey evkey) { | |
| 1825 Conn* cs = Conn::Get(evkey); | |
| 1826 if (bev == NULL || | |
| 1827 cs == NULL || | |
| 1828 bev != cs->destchan_.read_bev()) { | |
| 1829 NOTREACHED(); | |
| 1830 return; | |
| 1831 } | |
| 1832 if (EVBUFFER_LENGTH(EVBUFFER_INPUT(bev)) <= 0) | |
| 1833 return; | |
| 1834 if (cs->primchan_.write_bev() == NULL) { | |
| 1835 cs->master_->ZapConn(cs); | |
| 1836 return; | |
| 1837 } | |
| 1838 cs->master_->MarkConnImportance(cs, true); | |
| 1839 std::string out_bytes; | |
| 1840 base::Base64Encode( | |
| 1841 std::string( | |
| 1842 static_cast<const char*>(static_cast<void*>( | |
| 1843 EVBUFFER_DATA(EVBUFFER_INPUT(bev)))), | |
| 1844 EVBUFFER_LENGTH(EVBUFFER_INPUT(bev))), | |
| 1845 &out_bytes); | |
| 1846 evbuffer_drain(EVBUFFER_INPUT(bev), EVBUFFER_LENGTH(EVBUFFER_INPUT(bev))); | |
| 1847 if (!cs->EmitFrame(&cs->primchan_, WS_OPCODE_TEXT, | |
| 1848 out_bytes.c_str(), out_bytes.size())) { | |
| 1849 cs->Shut(WS_CLOSE_UNEXPECTED, "Failed to write websocket frame"); | |
| 1850 } | |
| 1851 } | |
| 1852 | |
| 1853 // static | |
| 1854 void Conn::OnDestchanWrite(struct bufferevent* bev, EventKey evkey) { | |
| 1855 Conn* cs = Conn::Get(evkey); | |
| 1856 if (bev == NULL || | |
| 1857 cs == NULL || | |
| 1858 bev != cs->destchan_.write_bev()) { | |
| 1859 NOTREACHED(); | |
| 1860 return; | |
| 1861 } | |
| 1862 // Write callback is called when low watermark is reached, 0 by default. | |
| 1863 cs->destchan_.set_write_pending(false); | |
| 1864 if (cs->phase_ == PHASE_WAIT_DESTCONNECT) | |
| 1865 cs->phase_ = PHASE_OUTSIDE_FRAME; | |
| 1866 if (cs->phase_ < PHASE_SHUT) | |
| 1867 OnPrimchanRead(cs->primchan_.read_bev(), evkey); | |
| 1868 else | |
| 1869 cs->destchan_.Zap(); | |
| 1870 } | |
| 1871 | |
| 1872 // static | |
| 1873 void Conn::OnDestchanError(struct bufferevent* bev, | |
| 1874 short what, EventKey evkey) { | |
| 1875 Conn* cs = Conn::Get(evkey); | |
| 1876 if (bev == NULL || | |
| 1877 cs == NULL || | |
| 1878 (bev != cs->destchan_.read_bev() && bev != cs->destchan_.write_bev())) { | |
| 1879 return; | |
| 1880 } | |
| 1881 cs->destchan_.set_write_pending(false); | |
| 1882 if (cs->phase_ >= PHASE_SHUT) | |
| 1883 cs->master_->ZapConn(cs); | |
| 1884 else | |
| 1885 cs->Shut(WS_CLOSE_DESTINATION_ERROR, | |
| 1886 "Failure reported on destination channel"); | |
| 1887 } | |
| 1888 | |
| 1889 // static | |
| 1890 Conn::EventKey Conn::last_evkey_ = 0; | |
| 1891 | |
| 1892 // static | |
| 1893 base::LazyInstance<Conn::EventKeyMap>::Leaky | |
| 1894 Conn::evkey_map_ = LAZY_INSTANCE_INITIALIZER; | |
| 1895 | |
| 1896 } // namespace | |
| 1897 | |
| 1898 WebSocketProxy::WebSocketProxy() : impl_(new Serv()) { | |
| 1899 } | |
| 1900 | |
| 1901 WebSocketProxy::~WebSocketProxy() { | |
| 1902 delete static_cast<Serv*>(impl_); | |
| 1903 impl_ = NULL; | |
| 1904 } | |
| 1905 | |
| 1906 void WebSocketProxy::Run() { | |
| 1907 static_cast<Serv*>(impl_)->Run(); | |
| 1908 } | |
| 1909 | |
| 1910 void WebSocketProxy::Shutdown() { | |
| 1911 static_cast<Serv*>(impl_)->Shutdown(); | |
| 1912 } | |
| 1913 | |
| 1914 void WebSocketProxy::OnNetworkChange() { | |
| 1915 static_cast<Serv*>(impl_)->OnNetworkChange(); | |
| 1916 } | |
| 1917 | |
| 1918 } // namespace chromeos | |
| OLD | NEW |