This source file includes following definitions.
- Htons
 
- Start
 
- OnBindCompletion
 
- OnListenCompletion
 
- OnAcceptCompletion
 
- OnReadCompletion
 
- OnWriteCompletion
 
- TryRead
 
- TryAccept
 
#include "echo_server.h"
#include <stdio.h>
#include <string.h>
#include <sstream>
#include "ppapi/c/pp_errors.h"
#include "ppapi/cpp/var.h"
#include "ppapi/utility/completion_callback_factory.h"
#ifdef WIN32
#undef PostMessage
#endif
static const int kBacklog = 10;
static uint16_t Htons(uint16_t hostshort) {
  uint8_t result_bytes[2];
  result_bytes[0] = (uint8_t) ((hostshort >> 8) & 0xFF);
  result_bytes[1] = (uint8_t) (hostshort & 0xFF);
  uint16_t result;
  memcpy(&result, result_bytes, 2);
  return result;
}
void EchoServer::Start(uint16_t port) {
  if (!pp::TCPSocket::IsAvailable()) {
    Log("TCPSocket not available");
    return;
  }
  listening_socket_ = pp::TCPSocket(instance_);
  if (listening_socket_.is_null()) {
    Log("Error creating TCPSocket.");
    return;
  }
  std::ostringstream status;
  status << "Starting server on port: " << port;
  Log(status.str().c_str());
  
  
  PP_NetAddress_IPv4 ipv4_addr = { Htons(port), { 0 } };
  pp::NetAddress addr(instance_, ipv4_addr);
  pp::CompletionCallback callback =
      callback_factory_.NewCallback(&EchoServer::OnBindCompletion);
  int32_t rtn = listening_socket_.Bind(addr, callback);
  if (rtn != PP_OK_COMPLETIONPENDING) {
    Log("Error binding listening socket.");
    return;
  }
}
void EchoServer::OnBindCompletion(int32_t result) {
  if (result != PP_OK) {
    std::ostringstream status;
    status << "server: Bind failed with: " << result;
    Log(status.str().c_str());
    return;
  }
  pp::CompletionCallback callback =
      callback_factory_.NewCallback(&EchoServer::OnListenCompletion);
  int32_t rtn = listening_socket_.Listen(kBacklog, callback);
  if (rtn != PP_OK_COMPLETIONPENDING) {
    Log("server: Error listening on server socket.");
    return;
  }
}
void EchoServer::OnListenCompletion(int32_t result) {
  std::ostringstream status;
  if (result != PP_OK) {
    status << "server: Listen failed with: " << result;
    Log(status.str().c_str());
    return;
  }
  pp::NetAddress addr = listening_socket_.GetLocalAddress();
  status << "server: Listening on: " << addr.DescribeAsString(true).AsString();
  Log(status.str().c_str());
  ready_ = true;
  if (ready_cond_) {
    pthread_mutex_lock(ready_lock_);
    pthread_cond_signal(ready_cond_);
    pthread_mutex_unlock(ready_lock_);
  }
  TryAccept();
}
void EchoServer::OnAcceptCompletion(int32_t result, pp::TCPSocket socket) {
  std::ostringstream status;
  if (result != PP_OK) {
    status << "server: Accept failed: " << result;
    Log(status.str().c_str());
    return;
  }
  pp::NetAddress addr = socket.GetLocalAddress();
  status << "server: New connection from: ";
  status << addr.DescribeAsString(true).AsString();
  Log(status.str().c_str());
  incoming_socket_ = socket;
  TryRead();
}
void EchoServer::OnReadCompletion(int32_t result) {
  std::ostringstream status;
  if (result <= 0) {
    if (result == 0)
      status << "server: client disconnected";
    else
      status << "server: Read failed: " << result;
    Log(status.str().c_str());
    
    
    incoming_socket_.Close();
    incoming_socket_ = pp::TCPSocket();
    TryAccept();
    return;
  }
  status << "server: Read " << result << " bytes";
  Log(status.str().c_str());
  
  pp::CompletionCallback callback =
      callback_factory_.NewCallback(&EchoServer::OnWriteCompletion);
  result = incoming_socket_.Write(receive_buffer_, result, callback);
  if (result != PP_OK_COMPLETIONPENDING) {
    status << "server: Write failed: " << result;
    Log(status.str().c_str());
  }
}
void EchoServer::OnWriteCompletion(int32_t result) {
  std::ostringstream status;
  if (result < 0) {
    status << "server: Write failed: " << result;
    Log(status.str().c_str());
    return;
  }
  status << "server: Wrote " << result << " bytes";
  Log(status.str().c_str());
  
  TryRead();
}
void EchoServer::TryRead() {
  pp::CompletionCallback callback =
      callback_factory_.NewCallback(&EchoServer::OnReadCompletion);
  incoming_socket_.Read(receive_buffer_, kBufferSize, callback);
}
void EchoServer::TryAccept() {
  pp::CompletionCallbackWithOutput<pp::TCPSocket> callback =
      callback_factory_.NewCallbackWithOutput(
          &EchoServer::OnAcceptCompletion);
  listening_socket_.Accept(callback);
}