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

Side by Side Diff: net/web2socket_proxy/web2socket_serv.cc

Issue 5484001: Web2socket proxy. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix for signed/unsigned confusion + cosmetic Created 9 years, 11 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/web2socket_proxy/web2socket_serv.h ('k') | third_party/libevent/chromium.patch » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2010 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 "web2socket_serv.h"
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10
11 #include <vector>
12
13 #include <arpa/inet.h>
14 #include <fcntl.h>
15 #include <netinet/in.h>
16 #include <signal.h>
17 #include <sys/types.h>
18 #include <sys/wait.h>
19
20 #include "base/logging.h"
21 #include "net/web2socket_proxy/web2socket_conn.h"
22 #include "third_party/libevent/evdns.h"
23
24 Web2SocketServ::Web2SocketServ(const std::string& origin,
25 struct sockaddr* addr,
26 int addr_len)
27 : origin_(origin),
28 addr_(addr),
29 addr_len_(addr_len),
30 evbase_(NULL),
31 listening_sock_(-1) {}
32
33 Web2SocketServ::~Web2SocketServ() {
34 while (!conn_pool_.empty())
35 ZapConn(conn_pool_.back());
36 if (listening_sock_ >= 0) {
37 shutdown(listening_sock_, SHUT_RDWR);
38 close(listening_sock_);
39 }
40 if (evbase_)
41 event_base_free(evbase_);
42 }
43
44 void Web2SocketServ::Run() {
45 if (evbase_) {
46 // One run at a time is all we do.
47 return;
48 }
49
50 evbase_ = event_init();
51 if (!evbase_) {
52 perror("Couldn't create libevent base");
53 return;
54 }
55
56 listening_sock_ = socket(AF_INET, SOCK_STREAM, 0);
57 if (listening_sock_ < 0) {
58 perror("Failed to create socket");
59 return;
60 }
61 if (bind(listening_sock_, addr_, addr_len_)) {
62 perror("Failed to bind server socket");
63 return;
64 }
65 if (listen(listening_sock_, 12)) {
66 perror("Failed to listen server socket");
67 return;
68 }
69 {
70 int on = 1;
71 setsockopt(listening_sock_, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
72 }
73 if (!SetNonBlock(listening_sock_)) {
74 perror("Failed to go non block");
75 return;
76 }
77 {
78 struct event listen_event;
79 event_set(&listen_event, listening_sock_, EV_READ | EV_PERSIST,
80 &OnConnect, this);
81 event_base_set(evbase_, &listen_event);
82 if (event_add(&listen_event, NULL)) {
83 perror("Failed to add listening event");
84 return;
85 }
86 }
87 if (evdns_init()) {
88 perror("Failed to initialize evDNS");
89 return;
90 }
91 if (!IgnoreSigPipe())
92 return;
93 fprintf(stderr, "Starting event dispatch loop, accepting connections..\n");
94 event_base_dispatch(evbase_);
95 perror("Event dispatch loop terminated");
96 }
97
98 void Web2SocketServ::ZapConn(Conn* cs) {
99 RevMap::iterator rit = rev_map_.find(cs);
100 if (rit != rev_map_.end()) {
101 conn_pool_.erase(rit->second);
102 rev_map_.erase(rit);
103 delete cs;
104 }
105 }
106
107 void Web2SocketServ::MarkConnImportance(Conn* cs,
108 bool important) {
109 if (conn_pool_.size() < kConnPoolLimit / 4) {
110 // Fast common path.
111 return;
112 }
113 RevMap::iterator rit = rev_map_.find(cs);
114 if (rit != rev_map_.end()) {
115 ConnPool::iterator it = rit->second;
116 CHECK(*it == cs);
117 if (important && it == conn_pool_.begin()) {
118 // Already at the top. Shortcut.
119 return;
120 }
121 conn_pool_.erase(it);
122 }
123 if (important) {
124 conn_pool_.push_front(cs);
125 rev_map_[cs] = conn_pool_.begin();
126 } else {
127 conn_pool_.push_back(cs);
128 rev_map_[cs] = conn_pool_.end();
129 --rev_map_[cs];
130 }
131 }
132
133 Conn* Web2SocketServ::GetFreshConn() {
134 if (conn_pool_.size() > kConnPoolLimit) {
135 // Connections overflow. Shut those oldest not active.
136 ConnPool::iterator it = conn_pool_.end();
137 --it;
138 for (int i = conn_pool_.size() - kConnPoolLimit; i-- > 0;) {
139 // Shut may invalidate an iterator; hence postdecrement.
140 (*it--)->Shut();
141 }
142 if (conn_pool_.size() > kConnPoolLimit + 12) {
143 // Connections overflow. Zap the oldest not active.
144 ZapConn(conn_pool_.back());
145 }
146 }
147 Conn* cs = new Conn(this);
148 conn_pool_.push_front(cs);
149 rev_map_[cs] = conn_pool_.begin();
150 return cs;
151 }
152
153 bool Web2SocketServ::IsConnSane(Conn* cs) {
154 return rev_map_.find(cs) != rev_map_.end();
155 }
156
157 void Web2SocketServ::OnConnect(int listening_sock,
158 short event, void* ctx) {
159 Web2SocketServ* self = static_cast<Web2SocketServ*>(ctx);
160 Conn* cs = self->GetFreshConn();
161 cs->primchan().sock = accept(listening_sock, NULL, NULL);
162 if (cs->primchan().sock < 0
163 || !SetNonBlock(cs->primchan().sock)) {
164 self->ZapConn(cs);
165 // Read readiness was triggered on listening socket
166 // yet we failed to accept a connection; definitely weird.
167 sleep(1);
168 return;
169 }
170
171 cs->primchan().bev = bufferevent_new(cs->primchan().sock,
172 &Conn::OnPrimchanRead,
173 &Conn::OnPrimchanWrite,
174 &Conn::OnPrimchanError,
175 cs->token());
176 if (cs->primchan().bev == NULL) {
177 self->ZapConn(cs);
178 return;
179 }
180 bufferevent_base_set(self->evbase_, cs->primchan().bev);
181 bufferevent_setwatermark(cs->primchan().bev, EV_READ, 0, kReadBufferLimit);
182 if (bufferevent_enable(cs->primchan().bev, EV_READ | EV_WRITE)) {
183 self->ZapConn(cs);
184 return;
185 }
186 }
187
188 bool Web2SocketServ::SetNonBlock(int fd) {
189 int flags = fcntl(fd, F_GETFL, 0);
190 return flags >= 0 && fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0;
191 }
192
193 bool Web2SocketServ::IgnoreSigPipe() {
194 struct sigaction sa;
195 sa.sa_handler = SIG_IGN;
196 sa.sa_flags = 0;
197 if (sigemptyset(&sa.sa_mask) ||
198 sigaction(SIGPIPE, &sa, 0)) {
199 perror("Failed to disable sigpipe");
200 return false;
201 }
202 return true;
203 }
204
OLDNEW
« no previous file with comments | « net/web2socket_proxy/web2socket_serv.h ('k') | third_party/libevent/chromium.patch » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698