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

Side by Side Diff: mojo/examples/http_server/http_server.cc

Issue 657113002: Add basic TCP socket mojo implementation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 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
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 <stdio.h> 5 #include <stdio.h>
6 #include <arpa/inet.h>
6 7
7 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/memory/weak_ptr.h"
10 #include "mojo/common/handle_watcher.h"
8 #include "mojo/public/c/system/main.h" 11 #include "mojo/public/c/system/main.h"
9 #include "mojo/public/cpp/application/application_delegate.h" 12 #include "mojo/public/cpp/application/application_delegate.h"
10 #include "mojo/public/cpp/application/application_impl.h" 13 #include "mojo/public/cpp/application/application_impl.h"
11 #include "mojo/public/cpp/application/application_runner.h" 14 #include "mojo/public/cpp/application/application_runner.h"
15 #include "mojo/public/cpp/system/data_pipe.h"
12 #include "mojo/services/public/interfaces/network/network_service.mojom.h" 16 #include "mojo/services/public/interfaces/network/network_service.mojom.h"
13 17
14 namespace mojo { 18 namespace mojo {
15 namespace examples { 19 namespace examples {
16 20
21 // The canned response that this server replies to each request with.
22 const char kResponse[] =
23 "HTTP/1.0 200 OK\n"
24 "Content-Type: text/html; charset=utf-8\n"
25 "\n"
26 "Hello, world\n";
27
28 // Represents one connection to a client. This connection will manage its own
29 // lifetime and will delete itself when the connection is closed.
30 class Connection {
31 public:
32 Connection(TCPConnectedSocketPtr conn,
33 ScopedDataPipeProducerHandle sender,
34 ScopedDataPipeConsumerHandle receiver)
35 : connection_(conn.Pass()),
36 sender_(sender.Pass()),
37 receiver_(receiver.Pass()),
38 weak_ptr_factory_(this),
39 response_(kResponse),
40 response_offset_(0) {
41 WriteMore();
42 }
43
44 ~Connection() {
45 }
46
47 private:
48 void OnSenderReady(MojoResult result) {
49 WriteMore();
50 }
51
52 void WriteMore() {
53 uint32_t num_bytes =
54 static_cast<uint32_t>(response_.size() - response_offset_);
55 // TODO(brettw) write chunks (ideally capped at some small size to
56 // illustrate how it works even in the presence of our relatively small
57 // reply) rather than specifying ALL_OR_NONE. See below.
58 MojoResult result = WriteDataRaw(
59 sender_.get(), &response_[response_offset_], &num_bytes,
60 MOJO_WRITE_DATA_FLAG_ALL_OR_NONE);
61 if (result == MOJO_RESULT_SHOULD_WAIT) {
62 num_bytes = 0;
63 } else if (result != MOJO_RESULT_OK) {
64 printf("Error writing to pipe.\n");
65 delete this;
66 return;
67 }
68
69 response_offset_ += num_bytes;
70
71 if (response_offset_ == response_.size()) {
72 // Connection complete.
73 delete this;
74 return;
75 }
76
77 // Wait for sender to be writable.
78 // TODO(brettw) we won't actually get here since we ALL_OR_NONE was
79 // specified above. This call won't work because the message loop is not a
yzshen1 2014/10/15 21:07:44 You could use Environment::GetDefaultAsyncWaiter()
80 // Chromium message loop. Figure out how to do handle watching outside the
81 // context of a chromium message loop implementation, remove the
82 // ALL_OR_NONE flag, and this should start working.
83 sender_watcher_.Start(
84 sender_.get(),
85 MOJO_HANDLE_SIGNAL_WRITABLE, MOJO_DEADLINE_INDEFINITE,
86 base::Bind(&Connection::OnSenderReady, weak_ptr_factory_.GetWeakPtr()));
87 }
88
89 TCPConnectedSocketPtr connection_;
90 ScopedDataPipeProducerHandle sender_;
91 ScopedDataPipeConsumerHandle receiver_;
92
93 base::WeakPtrFactory<Connection> weak_ptr_factory_;
94 common::HandleWatcher sender_watcher_;
95
96 std::string response_;
97 size_t response_offset_;
98 };
99
17 class HttpServerApp : public ApplicationDelegate { 100 class HttpServerApp : public ApplicationDelegate {
18 public: 101 public:
19 virtual void Initialize(ApplicationImpl* app) override { 102 virtual void Initialize(ApplicationImpl* app) override {
20 app->ConnectToService("mojo:mojo_network_service", &network_service_); 103 app->ConnectToService("mojo:mojo_network_service", &network_service_);
21 Start(); 104 Start();
22 } 105 }
23 106
24 private: 107 private:
25 void OnListeningStarted(NetworkErrorPtr err) {
26 }
27
28 void OnSocketBound(NetworkErrorPtr err, NetAddressPtr bound_address) { 108 void OnSocketBound(NetworkErrorPtr err, NetAddressPtr bound_address) {
29 if (err->code != 0) { 109 if (err->code != 0) {
30 printf("Bound err = %d\n", err->code); 110 printf("Bound err = %d\n", err->code);
31 return; 111 return;
32 } 112 }
33 113
34 printf("Got address = %d.%d.%d.%d:%d\n", 114 printf("Got address %d.%d.%d.%d:%d\n",
35 (int)bound_address->ipv4->addr[0], 115 (int)bound_address->ipv4->addr[0],
36 (int)bound_address->ipv4->addr[1], 116 (int)bound_address->ipv4->addr[1],
37 (int)bound_address->ipv4->addr[2], 117 (int)bound_address->ipv4->addr[2],
38 (int)bound_address->ipv4->addr[3], 118 (int)bound_address->ipv4->addr[3],
39 (int)bound_address->ipv4->port); 119 (int)bound_address->ipv4->port);
120 }
40 121
41 bound_socket_->StartListening( 122 void OnSocketListening(NetworkErrorPtr err) {
42 GetProxy(&server_socket_), 123 if (err->code != 0) {
43 base::Bind(&HttpServerApp::OnListeningStarted, 124 printf("Listen err = %d\n", err->code);
44 base::Unretained(this))); 125 return;
126 }
127 printf("Waiting for incoming connections...\n");
128 }
129
130 void OnConnectionAccepted(NetworkErrorPtr err, NetAddressPtr remote_address) {
131 if (err->code != 0) {
132 printf("Accepted socket error = %d\n", err->code);
133 return;
134 }
135
136 new Connection(pending_connected_socket_.Pass(),
137 pending_send_handle_.Pass(),
138 pending_receive_handle_.Pass());
139
140 // Ready for another connection.
141 WaitForNextConnection();
142 }
143
144 void WaitForNextConnection() {
145 // Need two pipes (one for each direction).
146 ScopedDataPipeConsumerHandle send_consumer_handle;
147 MojoResult result = CreateDataPipe(
148 nullptr, &pending_send_handle_, &send_consumer_handle);
149 assert(result == MOJO_RESULT_OK);
150
151 ScopedDataPipeProducerHandle receive_producer_handle;
152 result = CreateDataPipe(
153 nullptr, &receive_producer_handle, &pending_receive_handle_);
154 assert(result == MOJO_RESULT_OK);
155
156 server_socket_->Accept(send_consumer_handle.Pass(),
157 receive_producer_handle.Pass(),
158 GetProxy(&pending_connected_socket_),
159 base::Bind(&HttpServerApp::OnConnectionAccepted,
160 base::Unretained(this)));
45 } 161 }
46 162
47 void Start() { 163 void Start() {
48 NetAddressPtr net_address(NetAddress::New()); 164 NetAddressPtr net_address(NetAddress::New());
49 net_address->family = NET_ADDRESS_FAMILY_IPV4; 165 net_address->family = NET_ADDRESS_FAMILY_IPV4;
50 net_address->ipv4 = NetAddressIPv4::New(); 166 net_address->ipv4 = NetAddressIPv4::New();
51 net_address->ipv4->addr.resize(4); 167 net_address->ipv4->addr.resize(4);
52 net_address->ipv4->addr[0] = 0; 168 net_address->ipv4->addr[0] = 127;
53 net_address->ipv4->addr[1] = 0; 169 net_address->ipv4->addr[1] = 0;
54 net_address->ipv4->addr[2] = 0; 170 net_address->ipv4->addr[2] = 0;
55 net_address->ipv4->addr[3] = 0; 171 net_address->ipv4->addr[3] = 1;
172 net_address->ipv4->port = 0;
56 173
174 // Note that we can start using the proxies right away even thought the
175 // callbacks have not been called yet. If a previous step fails, they'll
176 // all fail.
57 network_service_->CreateTCPBoundSocket( 177 network_service_->CreateTCPBoundSocket(
58 net_address.Pass(), 178 net_address.Pass(),
59 GetProxy(&bound_socket_), 179 GetProxy(&bound_socket_),
60 base::Bind(&HttpServerApp::OnSocketBound, base::Unretained(this))); 180 base::Bind(&HttpServerApp::OnSocketBound, base::Unretained(this)));
181 bound_socket_->StartListening(GetProxy(
182 &server_socket_),
183 base::Bind(&HttpServerApp::OnSocketListening, base::Unretained(this)));
184 WaitForNextConnection();
61 } 185 }
62 186
63 NetworkServicePtr network_service_; 187 NetworkServicePtr network_service_;
64 TCPBoundSocketPtr bound_socket_; 188 TCPBoundSocketPtr bound_socket_;
65 TCPServerSocketPtr server_socket_; 189 TCPServerSocketPtr server_socket_;
190
191 ScopedDataPipeProducerHandle pending_send_handle_;
192 ScopedDataPipeConsumerHandle pending_receive_handle_;
193 TCPConnectedSocketPtr pending_connected_socket_;
66 }; 194 };
67 195
68 } // namespace examples 196 } // namespace examples
69 } // namespace mojo 197 } // namespace mojo
70 198
71 MojoResult MojoMain(MojoHandle shell_handle) { 199 MojoResult MojoMain(MojoHandle shell_handle) {
72 mojo::ApplicationRunner runner(new mojo::examples::HttpServerApp); 200 mojo::ApplicationRunner runner(new mojo::examples::HttpServerApp);
73 return runner.Run(shell_handle); 201 return runner.Run(shell_handle);
74 } 202 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698