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
|
/*
* Copyright (C) 2015 Canonical Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Authored by: James Henstridge <james.henstridge@canonical.com>
*/
#include "artserver.h"
#include <testsetup.h>
#include <internal/env_vars.h>
#include <internal/raii.h>
#include <QDebug>
#include <stdexcept>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
ArtServer::ArtServer()
: socket_(-1, unity::thumbnailer::internal::do_close)
{
server_.setStandardInputFile(QProcess::nullDevice());
server_.setProcessChannelMode(QProcess::ForwardedErrorChannel);
server_.start(FAKE_ART_SERVER, QStringList());
if (!server_.waitForStarted())
{
throw std::runtime_error("ArtServer::ArtServer(): wait for server start failed");
}
if (!server_.waitForReadyRead())
{
throw std::runtime_error("ArtServer::ArtServer(): wait for read from server failed");
}
auto port = QString::fromUtf8(server_.readAllStandardOutput()).trimmed();
server_url_ = "http://127.0.0.1:" + port.toStdString();
// Create a bound TCP socket with no listen queue. Attempts to
// connect to this port can not succeed. And as long as we hold
// the socket open, no other socket can reuse the port number.
socket_.reset(socket(AF_INET, SOCK_STREAM, 0));
if (socket_.get() < 0)
{
throw std::runtime_error("ArtServer::ArtServer(): Could not create socket");
}
struct sockaddr_in addr;
memset(&addr, 0, sizeof(struct sockaddr_in));
if (bind(socket_.get(), reinterpret_cast<struct sockaddr*>(&addr),
sizeof(struct sockaddr_in)) < 0)
{
throw std::runtime_error("ArtServer::ArtServer(): Could not bind socket");
}
socklen_t length = sizeof(struct sockaddr_in);
if (getsockname(socket_.get(), reinterpret_cast<struct sockaddr*>(&addr),
&length) < 0 || length > sizeof(struct sockaddr_in))
{
throw std::runtime_error("ArtServer::ArtServer(): Could not get socket name");
}
blocked_server_url_ = "http://127.0.0.1:" + std::to_string(addr.sin_port);
update_env();
}
ArtServer::~ArtServer()
{
server_.terminate();
if (!server_.waitForFinished())
{
qCritical() << "Failed to terminate fake art server";
}
unsetenv(unity::thumbnailer::internal::EnvVars::UBUNTU_SERVER_URL);
}
std::string const& ArtServer::server_url() const
{
if (blocked_)
{
return blocked_server_url_;
}
else
{
return server_url_;
}
}
void ArtServer::block_access()
{
blocked_ = true;
update_env();
}
void ArtServer::unblock_access()
{
blocked_ = false;
update_env();
}
void ArtServer::update_env()
{
setenv(unity::thumbnailer::internal::EnvVars::UBUNTU_SERVER_URL, server_url().c_str(), true);
}
|