Index: net/web2socket_proxy/web2socket_conn.h |
diff --git a/net/web2socket_proxy/web2socket_conn.h b/net/web2socket_proxy/web2socket_conn.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..5a677f7275ee307c6626ba90f9081136273284f4 |
--- /dev/null |
+++ b/net/web2socket_proxy/web2socket_conn.h |
@@ -0,0 +1,142 @@ |
+// Copyright (c) 2010 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#ifndef NET_WEB2SOCKET_PROXY_WEB2SOCKET_CONN_H_ |
+#define NET_WEB2SOCKET_PROXY_WEB2SOCKET_CONN_H_ |
+ |
+#include <sys/socket.h> |
+ |
+#include "base/md5.h" |
+#include "net/web2socket_proxy/web2socket_serv.h" |
+#include "third_party/libevent/event.h" |
+ |
+class Conn { |
+ public: |
+ enum Phase { |
+ // Initial stage of connection. |
+ PHASE_WAIT_HANDSHAKE, |
+ PHASE_WAIT_DESTFRAME, |
+ PHASE_WAIT_DESTCONNECT, |
+ |
+ // Operational stage of connection. |
+ PHASE_OUTSIDE_FRAME, |
+ PHASE_INSIDE_FRAME_BASE64, |
+ PHASE_INSIDE_FRAME_SKIP, |
+ |
+ // Terminal stage of connection. |
+ PHASE_SHUT, // Closing handshake was emitted, buffers may pending. |
+ PHASE_DEFUNCT // Connection was nuked. |
+ }; |
+ |
+ // Channel structure. |
+ struct Chan { |
+ int sock; |
+ struct bufferevent* bev; |
+ |
+ Chan() : sock(-1), bev(NULL) {} |
+ |
+ ~Chan() { |
+ if (bev) { |
+ bufferevent_disable(bev, EV_READ | EV_WRITE); |
+ bufferevent_free(bev); |
+ bev = NULL; |
+ } |
+ if (sock >= 0) { |
+ shutdown(sock, SHUT_RDWR); |
+ close(sock); |
+ sock = -1; |
+ } |
+ } |
+ }; |
+ |
+ // Status of processing incoming data. |
+ enum Status { |
+ STATUS_OK, |
+ STATUS_INCOMPLETE, // Not all required data is present in buffer yet. |
+ STATUS_SKIP, |
+ STATUS_ABORT // Data is invalid. We must shut connection. |
+ }; |
+ |
+ // Unfortunately evdns callbacks are uncancellable, |
+ // so potentially we can receive callback for a deleted Conn. |
+ // Even worse, storage of deleted Conn may be reused |
+ // for a new connection and new connection can receive callback |
+ // destined for deleted Conn. |
+ // Conn::Token is introduced in order to prevent that. |
+ typedef void* Token; |
+ typedef std::map<Token, Conn*> TokenMap; |
+ |
+ explicit Conn(Web2SocketServ* master); |
+ ~Conn(); |
+ |
+ static Conn* Get(Token token); |
+ |
+ void Shut(); |
+ |
+ Status ConsumeHeader(struct evbuffer*); |
+ Status ConsumeDestframe(struct evbuffer*); |
+ Status ConsumeFrameHeader(struct evbuffer*); |
+ Status ProcessFrameData(struct evbuffer*); |
+ |
+ // Returns true on success. |
+ bool EmitHandshake(struct bufferevent*); |
+ |
+ // Attempts to establish second connection (to remote TCP service). |
+ // Returns true on success. |
+ bool TryConnectDest(const struct sockaddr*, socklen_t); |
+ |
+ // Used as libevent callbacks. |
+ static void OnDestConnectTimeout(int, short, Token); |
+ static void OnPrimchanRead(struct bufferevent*, Token); |
+ static void OnPrimchanWrite(struct bufferevent*, Token); |
+ static void OnPrimchanError(struct bufferevent*, short what, Token); |
+ static void OnDestResolutionIPv4(int result, char type, int count, |
+ int ttl, void* addr_list, Token); |
+ static void OnDestResolutionIPv6(int result, char type, int count, |
+ int ttl, void* addr_list, Token); |
+ static void OnDestchanRead(struct bufferevent*, Token); |
+ static void OnDestchanWrite(struct bufferevent*, Token); |
+ static void OnDestchanError(struct bufferevent*, short what, Token); |
+ |
+ Chan& primchan() { return primchan_; } |
+ Token token() const { return token_; } |
+ |
+ private: |
+ Web2SocketServ* master_; |
+ Phase phase_; |
+ |
+ // We maintain two channels per Conn: |
+ // primary channel is websocket connection. |
+ Chan primchan_; |
+ // Destination channel is a proxied connection. |
+ Chan destchan_; |
+ |
+ Token token_; |
+ |
+ // Header fields supplied by client at initial websocket handshake. |
+ std::map<std::string, std::string> header_fields_; |
+ |
+ // Cryptohashed answer for websocket handshake. |
+ MD5Digest handshake_response_; |
+ |
+ // Hostname and port of destination socket. |
+ // Websocket client supplies them in first data frame (destframe). |
+ std::string destname_; |
+ uint32_t destport_; |
+ |
+ // We try to DNS resolve hostname in both IPv4 and IPv6 domains. |
+ // Track resolution failures here. |
+ bool destresolution_ipv4_failed_; |
+ bool destresolution_ipv6_failed_; |
+ |
+ // Used to schedule a timeout for an initial phase of connection. |
+ struct event destconnect_timeout_event_; |
+ |
+ static TokenMap token_map_; |
+ static Token last_token_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(Conn); |
+}; |
+ |
+#endif // NET_WEB2SOCKET_PROXY_WEB2SOCKET_CONN_H_ |