14e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
24e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
34e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// found in the LICENSE file.
44e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
54e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#ifndef ECHO_SERVER_H_
64e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#define ECHO_SERVER_H_
74e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
84e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ppapi/cpp/instance.h"
94e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ppapi/cpp/tcp_socket.h"
104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ppapi/utility/completion_callback_factory.h"
114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)static const int kBufferSize = 1024;
134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Simple "echo" server based on a listening pp::TCPSocket.
154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// This server handles just one connection at a time and will
164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// echo back whatever bytes get sent to it.
174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)class EchoServer {
184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) typedef void (*LogFunction)(const char*);
194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public:
214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EchoServer(pp::Instance* instance,
224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)             uint16_t port,
234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)             LogFunction log_function=NULL,
244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)             pthread_cond_t* ready_cond=NULL,
254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)             pthread_mutex_t* ready_lock=NULL)
264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    : instance_(instance),
274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      callback_factory_(this),
284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      ready_(false),
294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      ready_cond_(ready_cond),
304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      ready_lock_(ready_lock),
314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      log_function_(log_function) {
324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    Start(port);
334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) protected:
364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void Start(uint16_t port);
374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Callback functions
394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void OnBindCompletion(int32_t result);
404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void OnListenCompletion(int32_t result);
414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void OnAcceptCompletion(int32_t result, pp::TCPSocket socket);
424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void OnReadCompletion(int32_t result);
434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void OnWriteCompletion(int32_t result);
444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void TryRead();
464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void TryAccept();
474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void Log(const char* msg) {
494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (log_function_)
504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      log_function_(msg);
514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  pp::Instance* instance_;
544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  pp::CompletionCallbackFactory<EchoServer> callback_factory_;
554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  pp::TCPSocket listening_socket_;
564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  pp::TCPSocket incoming_socket_;
574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  char receive_buffer_[kBufferSize];
594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  bool ready_;
604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  pthread_cond_t* ready_cond_;
614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  pthread_mutex_t* ready_lock_;
624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  LogFunction log_function_;
634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#endif  // ECHO_SERVER_H_
66