summaryrefslogtreecommitdiffstats
path: root/mojo/services/network/http_server_impl.cc
blob: cc1422164e3f94ba51b760f5cfbd5ab09356fcf5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "mojo/services/network/http_server_impl.h"

#include <utility>

#include "base/logging.h"
#include "mojo/services/network/http_connection_impl.h"
#include "mojo/services/network/net_adapters.h"
#include "mojo/services/network/net_address_type_converters.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/log/net_log.h"
#include "net/socket/tcp_server_socket.h"

namespace mojo {

namespace {

const int kBackLog = 10;

}  // namespace

// static
void HttpServerImpl::Create(
    NetAddressPtr local_address,
    HttpServerDelegatePtr delegate,
    scoped_ptr<mojo::AppRefCount> app_refcount,
    const Callback<void(NetworkErrorPtr, NetAddressPtr)>& callback) {
  HttpServerImpl* http_server =
      new HttpServerImpl(std::move(delegate), std::move(app_refcount));

  int net_error = http_server->Start(std::move(local_address));
  if (net_error != net::OK) {
    callback.Run(MakeNetworkError(net_error), nullptr);
    delete http_server;
    return;
  }
  callback.Run(MakeNetworkError(net::OK), http_server->GetLocalAddress());
}

HttpServerImpl::HttpServerImpl(HttpServerDelegatePtr delegate,
                               scoped_ptr<mojo::AppRefCount> app_refcount)
    : delegate_(std::move(delegate)), app_refcount_(std::move(app_refcount)) {
  DCHECK(delegate_);
  delegate_.set_connection_error_handler([this]() { delete this; });
}

HttpServerImpl::~HttpServerImpl() {}

int HttpServerImpl::Start(NetAddressPtr local_address) {
  DCHECK(local_address);

  scoped_ptr<net::ServerSocket> socket(
      new net::TCPServerSocket(nullptr, net::NetLog::Source()));
  int net_result = socket->Listen(local_address.To<net::IPEndPoint>(),
                                  kBackLog);
  if (net_result != net::OK)
    return net_result;

  server_.reset(new net::HttpServer(std::move(socket), this));

  return net::OK;
}

NetAddressPtr HttpServerImpl::GetLocalAddress() const {
  if (!server_)
    return nullptr;

  net::IPEndPoint address;
  int net_result = server_->GetLocalAddress(&address);
  if (net_result != net::OK)
    return nullptr;

  return NetAddress::From(address);
}

void HttpServerImpl::OnConnect(int connection_id) {
  DCHECK(connections_.find(connection_id) == connections_.end());

  HttpConnectionPtr connection;
  HttpConnectionDelegatePtr connection_delegate;
  InterfaceRequest<HttpConnectionDelegate> delegate_request =
      GetProxy(&connection_delegate);
  linked_ptr<HttpConnectionImpl> connection_impl(new HttpConnectionImpl(
      connection_id, this, std::move(connection_delegate), &connection));

  connections_[connection_id] = connection_impl;

  delegate_->OnConnected(std::move(connection), std::move(delegate_request));
}

void HttpServerImpl::OnHttpRequest(int connection_id,
                                   const net::HttpServerRequestInfo& info) {
  DCHECK(connections_.find(connection_id) != connections_.end());
  connections_[connection_id]->OnReceivedHttpRequest(info);
}

void HttpServerImpl::OnWebSocketRequest(
    int connection_id,
    const net::HttpServerRequestInfo& info) {
  DCHECK(connections_.find(connection_id) != connections_.end());
  connections_[connection_id]->OnReceivedWebSocketRequest(info);
}

void HttpServerImpl::OnWebSocketMessage(int connection_id,
                                        const std::string& data) {
  DCHECK(connections_.find(connection_id) != connections_.end());
  connections_[connection_id]->OnReceivedWebSocketMessage(data);
}

void HttpServerImpl::OnClose(int connection_id) {
  DCHECK(connections_.find(connection_id) != connections_.end());
  connections_.erase(connection_id);
}

}  // namespace mojo