Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / native_client_sdk / src / tests / nacl_io_socket_test / echo_server.cc
blob7a0a65cced15a028e53381c78a438617faf99735
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 <stdio.h>
8 #include <string.h>
9 #include <sstream>
11 #include "ppapi/c/pp_errors.h"
12 #include "ppapi/cpp/var.h"
13 #include "ppapi/utility/completion_callback_factory.h"
15 #ifdef WIN32
16 #undef PostMessage
17 #endif
19 // Number of connections to queue up on the listening
20 // socket before new ones get "Connection Refused"
21 static const int kBacklog = 10;
23 // Implement htons locally. Even though this is provided by
24 // nacl_io we don't want to include nacl_io in this simple
25 // example.
26 static uint16_t Htons(uint16_t hostshort) {
27 uint8_t result_bytes[2];
28 result_bytes[0] = (uint8_t) ((hostshort >> 8) & 0xFF);
29 result_bytes[1] = (uint8_t) (hostshort & 0xFF);
31 uint16_t result;
32 memcpy(&result, result_bytes, 2);
33 return result;
36 void EchoServer::Start(uint16_t port) {
37 if (!pp::TCPSocket::IsAvailable()) {
38 Log("TCPSocket not available");
39 return;
42 listening_socket_ = pp::TCPSocket(instance_);
43 if (listening_socket_.is_null()) {
44 Log("Error creating TCPSocket.");
45 return;
48 std::ostringstream status;
49 status << "Starting server on port: " << port;
50 Log(status.str().c_str());
52 // Attempt to listen on all interfaces (0.0.0.0)
53 // on the given port number.
54 PP_NetAddress_IPv4 ipv4_addr = { Htons(port), { 0 } };
55 pp::NetAddress addr(instance_, ipv4_addr);
56 pp::CompletionCallback callback =
57 callback_factory_.NewCallback(&EchoServer::OnBindCompletion);
58 int32_t rtn = listening_socket_.Bind(addr, callback);
59 if (rtn != PP_OK_COMPLETIONPENDING) {
60 Log("Error binding listening socket.");
61 return;
65 void EchoServer::OnBindCompletion(int32_t result) {
66 if (result != PP_OK) {
67 std::ostringstream status;
68 status << "server: Bind failed with: " << result;
69 Log(status.str().c_str());
70 return;
73 pp::CompletionCallback callback =
74 callback_factory_.NewCallback(&EchoServer::OnListenCompletion);
76 int32_t rtn = listening_socket_.Listen(kBacklog, callback);
77 if (rtn != PP_OK_COMPLETIONPENDING) {
78 Log("server: Error listening on server socket.");
79 return;
83 void EchoServer::OnListenCompletion(int32_t result) {
84 std::ostringstream status;
85 if (result != PP_OK) {
86 status << "server: Listen failed with: " << result;
87 Log(status.str().c_str());
88 return;
91 pp::NetAddress addr = listening_socket_.GetLocalAddress();
92 status << "server: Listening on: " << addr.DescribeAsString(true).AsString();
93 Log(status.str().c_str());
95 ready_ = true;
96 if (ready_cond_) {
97 pthread_mutex_lock(ready_lock_);
98 pthread_cond_signal(ready_cond_);
99 pthread_mutex_unlock(ready_lock_);
102 TryAccept();
105 void EchoServer::OnAcceptCompletion(int32_t result, pp::TCPSocket socket) {
106 std::ostringstream status;
108 if (result != PP_OK) {
109 status << "server: Accept failed: " << result;
110 Log(status.str().c_str());
111 return;
114 pp::NetAddress addr = socket.GetLocalAddress();
115 status << "server: New connection from: ";
116 status << addr.DescribeAsString(true).AsString();
117 Log(status.str().c_str());
118 incoming_socket_ = socket;
120 TryRead();
123 void EchoServer::OnReadCompletion(int32_t result) {
124 std::ostringstream status;
125 if (result <= 0) {
126 if (result == 0)
127 status << "server: client disconnected";
128 else
129 status << "server: Read failed: " << result;
130 Log(status.str().c_str());
132 // Remove the current incoming socket and try
133 // to accept the next one.
134 incoming_socket_.Close();
135 incoming_socket_ = pp::TCPSocket();
136 TryAccept();
137 return;
140 status << "server: Read " << result << " bytes";
141 Log(status.str().c_str());
143 // Echo the bytes back to the client
144 pp::CompletionCallback callback =
145 callback_factory_.NewCallback(&EchoServer::OnWriteCompletion);
146 result = incoming_socket_.Write(receive_buffer_, result, callback);
147 if (result != PP_OK_COMPLETIONPENDING) {
148 status << "server: Write failed: " << result;
149 Log(status.str().c_str());
153 void EchoServer::OnWriteCompletion(int32_t result) {
154 std::ostringstream status;
155 if (result < 0) {
156 status << "server: Write failed: " << result;
157 Log(status.str().c_str());
158 return;
161 status << "server: Wrote " << result << " bytes";
162 Log(status.str().c_str());
164 // Try and read more bytes from the client
165 TryRead();
168 void EchoServer::TryRead() {
169 pp::CompletionCallback callback =
170 callback_factory_.NewCallback(&EchoServer::OnReadCompletion);
171 incoming_socket_.Read(receive_buffer_, kBufferSize, callback);
174 void EchoServer::TryAccept() {
175 pp::CompletionCallbackWithOutput<pp::TCPSocket> callback =
176 callback_factory_.NewCallbackWithOutput(
177 &EchoServer::OnAcceptCompletion);
178 listening_socket_.Accept(callback);