1 // Copyright 2010-2018, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 // Session Server
31
32 #include "session/session_server.h"
33
34 #include <memory>
35 #include <string>
36
37 #include "base/logging.h"
38 #include "base/port.h"
39 #include "base/scheduler.h"
40 #include "engine/engine_factory.h"
41 #include "ipc/ipc.h"
42 #include "ipc/named_event.h"
43 #include "protocol/commands.pb.h"
44 #include "session/session_handler.h"
45 #include "session/session_usage_observer.h"
46 #include "usage_stats/usage_stats_uploader.h"
47
48 namespace {
49
50 #ifdef OS_WIN
51 // On Windows, multiple processes can create named pipe objects whose names are
52 // the same. To reduce the potential risk of DOS, we limit the maximum number
53 // of pipe instances to 1 here.
54 const int kNumConnections = 1;
55 #else
56 const int kNumConnections = 10;
57 #endif // OS_WIN
58
59 const int kTimeOut = 5000; // 5000msec
60 const char kSessionName[] = "session";
61 const char kEventName[] = "session";
62
63 } // namespace
64
65 namespace mozc {
66
SessionServer()67 SessionServer::SessionServer()
68 : IPCServer(kSessionName, kNumConnections, kTimeOut),
69 usage_observer_(new session::SessionUsageObserver()),
70 session_handler_(new SessionHandler(
71 std::unique_ptr<Engine>(EngineFactory::Create()))) {
72 using usage_stats::UsageStatsUploader;
73 // start session watch dog timer
74 session_handler_->StartWatchDog();
75 session_handler_->AddObserver(usage_observer_.get());
76
77 // start usage stats timer
78 // send usage stats within 6 min later
79 Scheduler::AddJob(Scheduler::JobSetting(
80 "UsageStatsTimer",
81 UsageStatsUploader::kDefaultScheduleInterval,
82 UsageStatsUploader::kDefaultScheduleMaxInterval,
83 UsageStatsUploader::kDefaultSchedulerDelay,
84 UsageStatsUploader::kDefaultSchedulerRandomDelay,
85 &UsageStatsUploader::Send,
86 nullptr));
87
88 // Send a notification event to the UI.
89 NamedEventNotifier notifier(kEventName);
90 if (!notifier.Notify()) {
91 LOG(WARNING) << "NamedEvent " << kEventName << " is not found";
92 }
93 }
94
95 SessionServer::~SessionServer() = default;
96
Connected() const97 bool SessionServer::Connected() const {
98 return (session_handler_ &&
99 session_handler_->IsAvailable() &&
100 IPCServer::Connected());
101 }
102
Process(const char * request,size_t request_size,char * response,size_t * response_size)103 bool SessionServer::Process(const char *request,
104 size_t request_size,
105 char *response,
106 size_t *response_size) {
107 if (!session_handler_) {
108 LOG(WARNING) << "handler is not available";
109 return false; // shutdown the server if handler doesn't exist
110 }
111
112 commands::Command command; // can define as a private member?
113 if (!command.mutable_input()->ParseFromArray(request, request_size)) {
114 LOG(WARNING) << "Invalid request";
115 *response_size = 0;
116 return true;
117 }
118
119 if (!session_handler_->EvalCommand(&command)) {
120 LOG(WARNING) << "EvalCommand() returned false. Exiting the loop.";
121 *response_size = 0;
122 return false;
123 }
124
125 string output;
126 if (!command.output().SerializeToString(&output)) {
127 LOG(WARNING) << "SerializeToString() failed";
128 *response_size = 0;
129 return true;
130 }
131
132 // TODO(taku) automatically increase the buffer.
133 // Needs to fix IPCServer as well
134 if (*response_size < output.size()) {
135 LOG(WARNING) << "response size < output.size";
136 *response_size = 0;
137 return true;
138 }
139
140 ::memcpy(response, output.data(), output.size());
141 *response_size = output.size();
142
143 // debug message
144 VLOG(2) << command.DebugString();
145
146 return true;
147 }
148 } // namespace mozc
149