Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / native_client_sdk / src / examples / api / socket / echo_server.cc
bloba88a82ef7fd6c20ae3b5e673cb08ea881c0a6458
1 // Copyright (c) 2013 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.
5 #include "echo_server.h"
7 #include <string.h>
8 #include <sstream>
10 #include "ppapi/c/pp_errors.h"
11 #include "ppapi/cpp/var.h"
12 #include "ppapi/utility/completion_callback_factory.h"
14 #ifdef WIN32
15 #undef PostMessage
16 #endif
18 // Number of connections to queue up on the listening
19 // socket before new ones get "Connection Refused"
20 static const int kBacklog = 10;
22 // Implement htons locally. Even though this is provided by
23 // nacl_io we don't want to include nacl_io in this simple
24 // example.
25 static uint16_t Htons(uint16_t hostshort) {
26 uint8_t result_bytes[2];
27 result_bytes[0] = (uint8_t) ((hostshort >> 8) & 0xFF);
28 result_bytes[1] = (uint8_t) (hostshort & 0xFF);
30 uint16_t result;
31 memcpy(&result, result_bytes, 2);
32 return result;
35 void EchoServer::Start(uint16_t port) {
36 if (!pp::TCPSocket::IsAvailable()) {
37 instance_->PostMessage("TCPSocket not available");
38 return;
41 listening_socket_ = pp::TCPSocket(instance_);
42 if (listening_socket_.is_null()) {
43 instance_->PostMessage("Error creating TCPSocket.");
44 return;
47 std::ostringstream status;
48 status << "Starting server on port: " << port;
49 instance_->PostMessage(status.str());
51 // Attempt to listen on all interfaces (0.0.0.0)
52 // on the given port number.
53 PP_NetAddress_IPv4 ipv4_addr = { Htons(port), { 0 } };
54 pp::NetAddress addr(instance_, ipv4_addr);
55 pp::CompletionCallback callback =
56 callback_factory_.NewCallback(&EchoServer::OnBindCompletion);
57 int32_t rtn = listening_socket_.Bind(addr, callback);
58 if (rtn != PP_OK_COMPLETIONPENDING) {
59 instance_->PostMessage("Error binding listening socket.");
60 return;
64 void EchoServer::OnBindCompletion(int32_t result) {
65 if (result != PP_OK) {
66 std::ostringstream status;
67 status << "server: Bind failed with: " << result;
68 instance_->PostMessage(status.str());
69 return;
72 pp::CompletionCallback callback =
73 callback_factory_.NewCallback(&EchoServer::OnListenCompletion);
75 int32_t rtn = listening_socket_.Listen(kBacklog, callback);
76 if (rtn != PP_OK_COMPLETIONPENDING) {
77 instance_->PostMessage("server: Error listening on server socket.");
78 return;
82 void EchoServer::OnListenCompletion(int32_t result) {
83 std::ostringstream status;
84 if (result != PP_OK) {
85 status << "server: Listen failed with: " << result;
86 instance_->PostMessage(status.str());
87 return;
90 pp::NetAddress addr = listening_socket_.GetLocalAddress();
91 status << "server: Listening on: " << addr.DescribeAsString(true).AsString();
92 instance_->PostMessage(status.str());
94 TryAccept();
97 void EchoServer::OnAcceptCompletion(int32_t result, pp::TCPSocket socket) {
98 std::ostringstream status;
100 if (result != PP_OK) {
101 status << "server: Accept failed: " << result;
102 instance_->PostMessage(status.str());
103 return;
106 pp::NetAddress addr = socket.GetLocalAddress();
107 status << "server: New connection from: ";
108 status << addr.DescribeAsString(true).AsString();
109 instance_->PostMessage(status.str());
110 incoming_socket_ = socket;
112 TryRead();
115 void EchoServer::OnReadCompletion(int32_t result) {
116 std::ostringstream status;
117 if (result <= 0) {
118 if (result == 0)
119 status << "server: client disconnected";
120 else
121 status << "server: Read failed: " << result;
122 instance_->PostMessage(status.str());
124 // Remove the current incoming socket and try
125 // to accept the next one.
126 incoming_socket_.Close();
127 incoming_socket_ = pp::TCPSocket();
128 TryAccept();
129 return;
132 status << "server: Read " << result << " bytes";
133 instance_->PostMessage(status.str());
135 // Echo the bytes back to the client
136 pp::CompletionCallback callback =
137 callback_factory_.NewCallback(&EchoServer::OnWriteCompletion);
138 result = incoming_socket_.Write(receive_buffer_, result, callback);
139 if (result != PP_OK_COMPLETIONPENDING) {
140 status << "server: Write failed: " << result;
141 instance_->PostMessage(status.str());
145 void EchoServer::OnWriteCompletion(int32_t result) {
146 std::ostringstream status;
147 if (result < 0) {
148 status << "server: Write failed: " << result;
149 instance_->PostMessage(status.str());
150 return;
153 status << "server: Wrote " << result << " bytes";
154 instance_->PostMessage(status.str());
156 // Try and read more bytes from the client
157 TryRead();
160 void EchoServer::TryRead() {
161 pp::CompletionCallback callback =
162 callback_factory_.NewCallback(&EchoServer::OnReadCompletion);
163 incoming_socket_.Read(receive_buffer_, kBufferSize, callback);
166 void EchoServer::TryAccept() {
167 pp::CompletionCallbackWithOutput<pp::TCPSocket> callback =
168 callback_factory_.NewCallbackWithOutput(
169 &EchoServer::OnAcceptCompletion);
170 listening_socket_.Accept(callback);