mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2026-08-12 20:53:48 +00:00
Remove tunneling support
It's depending on an unmaintained package (slirp), and I don't think anyone uses that code. It's not tested upstream nor in fedora, so let's remove it.
This commit is contained in:
parent
1b6ced7dda
commit
ef9a8bf053
1
README
1
README
@ -44,7 +44,6 @@ functionality
|
||||
XRandR >= 1.2 (X11 support)
|
||||
Xinerama >= 1.0 (X11 support)
|
||||
libcacard >= 0.1.2 (Smartcard support)
|
||||
Slirp (Tunnelling support)
|
||||
|
||||
Communication
|
||||
-------------
|
||||
|
||||
@ -155,13 +155,6 @@ else
|
||||
PLATFORM_INCLUDES=-I$(top_srcdir)/client/x11
|
||||
endif
|
||||
|
||||
if SUPPORT_TUNNEL
|
||||
spicec_SOURCES += \
|
||||
tunnel_channel.cpp \
|
||||
tunnel_channel.h \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
if SUPPORT_GUI
|
||||
spicec_SOURCES += \
|
||||
gui/gui.cpp \
|
||||
|
||||
@ -43,9 +43,6 @@
|
||||
#include "red_gl_canvas.h"
|
||||
#endif
|
||||
#include "cmd_line_parser.h"
|
||||
#ifdef USE_TUNNEL
|
||||
#include "tunnel_channel.h"
|
||||
#endif
|
||||
#ifdef USE_GUI
|
||||
#include "gui/gui.h"
|
||||
#endif
|
||||
@ -1960,9 +1957,6 @@ bool Application::set_channels_security(CmdLineParser& parser, bool on, char *va
|
||||
channels_names["cursor"] = SPICE_CHANNEL_CURSOR;
|
||||
channels_names["playback"] = SPICE_CHANNEL_PLAYBACK;
|
||||
channels_names["record"] = SPICE_CHANNEL_RECORD;
|
||||
#ifdef USE_TUNNEL
|
||||
channels_names["tunnel"] = SPICE_CHANNEL_TUNNEL;
|
||||
#endif
|
||||
#ifdef USE_SMARTCARD
|
||||
channels_names["smartcard"] = SPICE_CHANNEL_SMARTCARD;
|
||||
#endif
|
||||
@ -2133,9 +2127,6 @@ bool Application::set_enable_channels(CmdLineParser& parser, bool enable, char *
|
||||
channels_names["cursor"] = SPICE_CHANNEL_CURSOR;
|
||||
channels_names["playback"] = SPICE_CHANNEL_PLAYBACK;
|
||||
channels_names["record"] = SPICE_CHANNEL_RECORD;
|
||||
#ifdef USE_TUNNEL
|
||||
channels_names["tunnel"] = SPICE_CHANNEL_TUNNEL;
|
||||
#endif
|
||||
#ifdef USE_SMARTCARD
|
||||
channels_names["smartcard"] = SPICE_CHANNEL_SMARTCARD;
|
||||
#endif
|
||||
@ -2224,11 +2215,6 @@ void Application::register_channels()
|
||||
_client.register_channel_factory(RecordChannel::Factory());
|
||||
}
|
||||
|
||||
#ifdef USE_TUNNEL
|
||||
if (_enabled_channels[SPICE_CHANNEL_TUNNEL]) {
|
||||
_client.register_channel_factory(TunnelChannel::Factory());
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SMARTCARD
|
||||
if (_enabled_channels[SPICE_CHANNEL_SMARTCARD] && _smartcard_options->enable) {
|
||||
smartcard_init(_smartcard_options); // throws Exception
|
||||
|
||||
@ -1,852 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2009 Red Hat, Inc.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
Author:
|
||||
yhalperi@redhat.com
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
#include "tunnel_channel.h"
|
||||
#include <spice/protocol.h>
|
||||
|
||||
#define SOCKET_WINDOW_SIZE 60
|
||||
#define SOCKET_TOKENS_TO_SEND 20
|
||||
|
||||
/* classes for tunneling msgs without reallocations and memcpy */
|
||||
|
||||
class InSocketMessage;
|
||||
class OutSocketMessage;
|
||||
|
||||
class InSocketMessage: public ClientNetSocket::SendBuffer {
|
||||
public:
|
||||
InSocketMessage(RedChannel::CompoundInMessage& full_msg);
|
||||
|
||||
const uint8_t* data();
|
||||
uint32_t size();
|
||||
ClientNetSocket::SendBuffer* ref();
|
||||
void unref();
|
||||
|
||||
protected:
|
||||
virtual ~InSocketMessage() {}
|
||||
|
||||
private:
|
||||
int _refs;
|
||||
RedChannel::CompoundInMessage& _full_msg;
|
||||
SpiceMsgTunnelSocketData* _sckt_msg;
|
||||
uint32_t _buf_size;
|
||||
};
|
||||
|
||||
InSocketMessage::InSocketMessage(RedChannel::CompoundInMessage& full_msg)
|
||||
: _refs (1)
|
||||
, _full_msg (full_msg)
|
||||
{
|
||||
ASSERT(full_msg.type() == SPICE_MSG_TUNNEL_SOCKET_DATA);
|
||||
_full_msg.ref();
|
||||
_sckt_msg = (SpiceMsgTunnelSocketData*)(_full_msg.data());
|
||||
_buf_size = _full_msg.size() - sizeof(SpiceMsgTunnelSocketData);
|
||||
}
|
||||
|
||||
const uint8_t* InSocketMessage::data()
|
||||
{
|
||||
return _sckt_msg->data;
|
||||
}
|
||||
|
||||
uint32_t InSocketMessage::size()
|
||||
{
|
||||
return _buf_size;
|
||||
}
|
||||
|
||||
ClientNetSocket::SendBuffer* InSocketMessage::ref()
|
||||
{
|
||||
_full_msg.ref();
|
||||
_refs++;
|
||||
return this;
|
||||
}
|
||||
|
||||
void InSocketMessage::unref()
|
||||
{
|
||||
_full_msg.unref();
|
||||
if (!--_refs) {
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
class OutSocketMessage: public RedPeer::OutMessage,
|
||||
public RedChannel::OutMessage,
|
||||
public ClientNetSocket::ReceiveBuffer {
|
||||
public:
|
||||
|
||||
virtual RedPeer::OutMessage& peer_message() { return *this;}
|
||||
virtual void release();
|
||||
|
||||
virtual uint8_t* buf() { return _the_buf; };
|
||||
virtual uint32_t buf_max_size() {return _max_data_size;}
|
||||
virtual void set_buf_size(uint32_t size);
|
||||
virtual void release_buf();
|
||||
|
||||
static void init(uint32_t max_data_size);
|
||||
static OutSocketMessage& alloc_message(uint16_t id, SpiceMessageMarshallers *marshallers);
|
||||
|
||||
static void clear_free_messages();
|
||||
|
||||
protected:
|
||||
OutSocketMessage();
|
||||
virtual ~OutSocketMessage() {}
|
||||
|
||||
private:
|
||||
static std::list<OutSocketMessage*> _free_messages;
|
||||
static uint32_t _max_data_size;
|
||||
uint8_t *_the_buf;
|
||||
};
|
||||
|
||||
std::list<OutSocketMessage*> OutSocketMessage::_free_messages;
|
||||
uint32_t OutSocketMessage::_max_data_size;
|
||||
|
||||
OutSocketMessage::OutSocketMessage()
|
||||
: RedPeer::OutMessage(SPICE_MSGC_TUNNEL_SOCKET_DATA)
|
||||
, RedChannel::OutMessage()
|
||||
, ClientNetSocket::ReceiveBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
void OutSocketMessage::set_buf_size(uint32_t size)
|
||||
{
|
||||
spice_marshaller_unreserve_space(_marshaller, _max_data_size - size);
|
||||
}
|
||||
|
||||
void OutSocketMessage::release()
|
||||
{
|
||||
OutSocketMessage::_free_messages.push_front(this);
|
||||
}
|
||||
|
||||
void OutSocketMessage::release_buf()
|
||||
{
|
||||
release();
|
||||
}
|
||||
|
||||
void OutSocketMessage::init(uint32_t max_data_size)
|
||||
{
|
||||
_max_data_size = max_data_size;
|
||||
}
|
||||
|
||||
OutSocketMessage& OutSocketMessage::alloc_message(uint16_t id, SpiceMessageMarshallers *marshallers)
|
||||
{
|
||||
OutSocketMessage* ret;
|
||||
if (!_free_messages.empty()) {
|
||||
ret = _free_messages.front();
|
||||
_free_messages.pop_front();
|
||||
spice_marshaller_reset(ret->marshaller());
|
||||
} else {
|
||||
ret = new OutSocketMessage();
|
||||
}
|
||||
|
||||
SpiceMsgcTunnelSocketData data;
|
||||
data.connection_id = id;
|
||||
marshallers->msgc_tunnel_socket_data(ret->marshaller(), &data);
|
||||
ret->_the_buf = spice_marshaller_reserve_space(ret->marshaller(), _max_data_size);
|
||||
|
||||
return *ret;
|
||||
}
|
||||
|
||||
void OutSocketMessage::clear_free_messages()
|
||||
{
|
||||
while (!_free_messages.empty()) {
|
||||
OutSocketMessage* message = _free_messages.front();
|
||||
_free_messages.pop_front();
|
||||
delete message;
|
||||
}
|
||||
}
|
||||
|
||||
struct TunnelService {
|
||||
uint32_t type;
|
||||
uint32_t id;
|
||||
uint32_t group;
|
||||
struct in_addr ip;
|
||||
uint32_t port;
|
||||
std::string name;
|
||||
std::string description;
|
||||
|
||||
struct in_addr virtual_ip;
|
||||
#ifdef TUNNEL_CONFIG
|
||||
TunnelConfigConnectionIfc* service_src;
|
||||
#endif
|
||||
};
|
||||
|
||||
class TunnelChannel::TunnelSocket: public ClientNetSocket {
|
||||
public:
|
||||
TunnelSocket(uint16_t id, TunnelService& dst_service, ProcessLoop& process_loop,
|
||||
EventHandler & event_handler, SpiceMessageMarshallers *marshallers);
|
||||
virtual ~TunnelSocket() {}
|
||||
|
||||
void set_num_tokens(uint32_t tokens) {_num_tokens = tokens;}
|
||||
void set_server_num_tokens(uint32_t tokens) {_server_num_tokens = tokens;}
|
||||
void set_guest_closed() {_guest_closed = true;}
|
||||
|
||||
uint32_t get_num_tokens() {return _num_tokens;}
|
||||
uint32_t get_server_num_tokens() {return _server_num_tokens;}
|
||||
bool get_guest_closed() {return _guest_closed;}
|
||||
|
||||
protected:
|
||||
virtual ReceiveBuffer& alloc_receive_buffer() {return OutSocketMessage::alloc_message(id(), _marshallers);}
|
||||
|
||||
private:
|
||||
uint32_t _num_tokens;
|
||||
uint32_t _server_num_tokens;
|
||||
uint32_t _service_id;
|
||||
bool _guest_closed;
|
||||
SpiceMessageMarshallers *_marshallers;
|
||||
};
|
||||
|
||||
TunnelChannel::TunnelSocket::TunnelSocket(uint16_t id, TunnelService& dst_service,
|
||||
ProcessLoop& process_loop,
|
||||
ClientNetSocket::EventHandler& event_handler,
|
||||
SpiceMessageMarshallers *marshallers)
|
||||
: ClientNetSocket(id, dst_service.ip, htons((uint16_t)dst_service.port),
|
||||
process_loop, event_handler)
|
||||
, _num_tokens (0)
|
||||
, _server_num_tokens (0)
|
||||
, _service_id (dst_service.id)
|
||||
, _guest_closed (false)
|
||||
, _marshallers(marshallers)
|
||||
{
|
||||
}
|
||||
|
||||
class TunnelHandler: public MessageHandlerImp<TunnelChannel, SPICE_CHANNEL_TUNNEL> {
|
||||
public:
|
||||
TunnelHandler(TunnelChannel& channel)
|
||||
: MessageHandlerImp<TunnelChannel, SPICE_CHANNEL_TUNNEL>(channel) {}
|
||||
};
|
||||
|
||||
TunnelChannel::TunnelChannel(RedClient& client, uint32_t id)
|
||||
: RedChannel(client, SPICE_CHANNEL_TUNNEL, id, new TunnelHandler(*this))
|
||||
, _max_socket_data_size(0)
|
||||
, _service_id(0)
|
||||
, _service_group(0)
|
||||
#ifdef TUNNEL_CONFIG
|
||||
, _config_listener (NULL)
|
||||
#endif
|
||||
{
|
||||
TunnelHandler* handler = static_cast<TunnelHandler*>(get_message_handler());
|
||||
|
||||
handler->set_handler(SPICE_MSG_MIGRATE, &TunnelChannel::handle_migrate);
|
||||
handler->set_handler(SPICE_MSG_SET_ACK, &TunnelChannel::handle_set_ack);
|
||||
handler->set_handler(SPICE_MSG_PING, &TunnelChannel::handle_ping);
|
||||
handler->set_handler(SPICE_MSG_WAIT_FOR_CHANNELS, &TunnelChannel::handle_wait_for_channels);
|
||||
|
||||
handler->set_handler(SPICE_MSG_TUNNEL_INIT,
|
||||
&TunnelChannel::handle_init);
|
||||
handler->set_handler(SPICE_MSG_TUNNEL_SERVICE_IP_MAP,
|
||||
&TunnelChannel::handle_service_ip_map);
|
||||
handler->set_handler(SPICE_MSG_TUNNEL_SOCKET_OPEN,
|
||||
&TunnelChannel::handle_socket_open);
|
||||
handler->set_handler(SPICE_MSG_TUNNEL_SOCKET_CLOSE,
|
||||
&TunnelChannel::handle_socket_close);
|
||||
handler->set_handler(SPICE_MSG_TUNNEL_SOCKET_FIN,
|
||||
&TunnelChannel::handle_socket_fin);
|
||||
handler->set_handler(SPICE_MSG_TUNNEL_SOCKET_TOKEN,
|
||||
&TunnelChannel::handle_socket_token);
|
||||
handler->set_handler(SPICE_MSG_TUNNEL_SOCKET_CLOSED_ACK,
|
||||
&TunnelChannel::handle_socket_closed_ack);
|
||||
handler->set_handler(SPICE_MSG_TUNNEL_SOCKET_DATA,
|
||||
&TunnelChannel::handle_socket_data);
|
||||
}
|
||||
|
||||
TunnelChannel::~TunnelChannel()
|
||||
{
|
||||
destroy_sockets();
|
||||
OutSocketMessage::clear_free_messages();
|
||||
}
|
||||
|
||||
void TunnelChannel::handle_init(RedPeer::InMessage* message)
|
||||
{
|
||||
SpiceMsgTunnelInit* init_msg = (SpiceMsgTunnelInit*)message->data();
|
||||
_max_socket_data_size = init_msg->max_socket_data_size;
|
||||
OutSocketMessage::init(_max_socket_data_size);
|
||||
_sockets.resize(init_msg->max_num_of_sockets);
|
||||
}
|
||||
|
||||
void TunnelChannel::send_service(TunnelService& service)
|
||||
{
|
||||
if (service.type != SPICE_TUNNEL_SERVICE_TYPE_IPP &&
|
||||
service.type == SPICE_TUNNEL_SERVICE_TYPE_GENERIC) {
|
||||
THROW("%s: invalid service type", __FUNCTION__);
|
||||
}
|
||||
|
||||
Message* service_msg = new Message(SPICE_MSGC_TUNNEL_SERVICE_ADD);
|
||||
SpiceMsgcTunnelAddGenericService add;
|
||||
SpiceMarshaller *name_out, *description_out;
|
||||
add.id = service.id;
|
||||
add.group = service.group;
|
||||
add.type = service.type;
|
||||
add.port = service.port;
|
||||
|
||||
if (service.type == SPICE_TUNNEL_SERVICE_TYPE_IPP) {
|
||||
add.u.ip.type = SPICE_TUNNEL_IP_TYPE_IPv4;
|
||||
}
|
||||
|
||||
_marshallers->msgc_tunnel_service_add(service_msg->marshaller(), &add,
|
||||
&name_out, &description_out);
|
||||
|
||||
spice_marshaller_add(name_out, (uint8_t *)service.name.c_str(), service.name.length() + 1);
|
||||
spice_marshaller_add(description_out, (uint8_t *)service.description.c_str(), service.description.length() + 1);
|
||||
|
||||
post_message(service_msg);
|
||||
}
|
||||
|
||||
void TunnelChannel::handle_service_ip_map(RedPeer::InMessage* message)
|
||||
{
|
||||
SpiceMsgTunnelServiceIpMap* service_ip_msg = (SpiceMsgTunnelServiceIpMap*)message->data();
|
||||
TunnelService* service = find_service(service_ip_msg->service_id);
|
||||
if (!service) {
|
||||
THROW("%s: attempt to map non-existing service id=%d", __FUNCTION__,
|
||||
service_ip_msg->service_id);
|
||||
}
|
||||
|
||||
if (service_ip_msg->virtual_ip.type == SPICE_TUNNEL_IP_TYPE_IPv4) {
|
||||
memcpy(&service->virtual_ip.s_addr, service_ip_msg->virtual_ip.data,
|
||||
sizeof(SpiceTunnelIPv4));
|
||||
} else {
|
||||
THROW("unexpected ip type %d", service_ip_msg->virtual_ip.type);
|
||||
}
|
||||
DBG(0, "service_id=%d (%s), virtual_ip=%s", service->id, service->name.c_str(),
|
||||
inet_ntoa(service->virtual_ip));
|
||||
#ifdef TUNNEL_CONFIG
|
||||
service->service_src->send_virtual_ip(service->virtual_ip);
|
||||
#endif
|
||||
}
|
||||
|
||||
void TunnelChannel::handle_socket_open(RedPeer::InMessage* message)
|
||||
{
|
||||
SpiceMsgTunnelSocketOpen* open_msg = (SpiceMsgTunnelSocketOpen*)message->data();
|
||||
TunnelSocket* sckt;
|
||||
Message* out_msg;
|
||||
|
||||
if (_sockets[open_msg->connection_id]) {
|
||||
THROW("%s: attempt to open an already opened connection id=%d", __FUNCTION__,
|
||||
open_msg->connection_id);
|
||||
}
|
||||
|
||||
TunnelService* service = find_service(open_msg->service_id);
|
||||
if (!service) {
|
||||
THROW("%s: attempt to access non-existing service id=%d", __FUNCTION__,
|
||||
open_msg->service_id);
|
||||
}
|
||||
|
||||
sckt = new TunnelSocket(open_msg->connection_id, *service, get_process_loop(), *this, _marshallers);
|
||||
|
||||
if (sckt->connect(open_msg->tokens)) {
|
||||
_sockets[open_msg->connection_id] = sckt;
|
||||
out_msg = new Message(SPICE_MSGC_TUNNEL_SOCKET_OPEN_ACK);
|
||||
sckt->set_num_tokens(0);
|
||||
sckt->set_server_num_tokens(SOCKET_WINDOW_SIZE);
|
||||
SpiceMsgcTunnelSocketOpenAck ack;
|
||||
ack.connection_id = open_msg->connection_id;
|
||||
ack.tokens = SOCKET_WINDOW_SIZE;
|
||||
_marshallers->msgc_tunnel_socket_open_ack(out_msg->marshaller(), &ack);
|
||||
} else {
|
||||
out_msg = new Message(SPICE_MSGC_TUNNEL_SOCKET_OPEN_NACK);
|
||||
SpiceMsgcTunnelSocketOpenNack nack;
|
||||
nack.connection_id = open_msg->connection_id;
|
||||
_marshallers->msgc_tunnel_socket_open_nack(out_msg->marshaller(), &nack);
|
||||
delete sckt;
|
||||
}
|
||||
|
||||
post_message(out_msg);
|
||||
}
|
||||
|
||||
void TunnelChannel::handle_socket_fin(RedPeer::InMessage* message)
|
||||
{
|
||||
SpiceMsgTunnelSocketFin* fin_msg = (SpiceMsgTunnelSocketFin*)message->data();
|
||||
TunnelSocket* sckt = _sockets[fin_msg->connection_id];
|
||||
|
||||
if (!sckt) {
|
||||
THROW("%s: fin connection that doesn't exist id=%d", __FUNCTION__, fin_msg->connection_id);
|
||||
}
|
||||
|
||||
DBG(0, "guest fin connection_id=%d", fin_msg->connection_id);
|
||||
if (sckt->is_connected()) {
|
||||
sckt->push_fin();
|
||||
}
|
||||
}
|
||||
|
||||
void TunnelChannel::handle_socket_close(RedPeer::InMessage* message)
|
||||
{
|
||||
SpiceMsgTunnelSocketClose* close_msg = (SpiceMsgTunnelSocketClose*)message->data();
|
||||
TunnelSocket* sckt = _sockets[close_msg->connection_id];
|
||||
|
||||
if (!sckt) {
|
||||
THROW("%s: closing connection that doesn't exist id=%d", __FUNCTION__,
|
||||
close_msg->connection_id);
|
||||
}
|
||||
DBG(0, "guest closed connection_id=%d", close_msg->connection_id);
|
||||
|
||||
sckt->set_guest_closed();
|
||||
|
||||
if (sckt->is_connected()) {
|
||||
sckt->push_disconnect();
|
||||
} else {
|
||||
// close happened in the server side before it received the client
|
||||
// close msg. we should ack the server and free the socket
|
||||
on_socket_disconnect(*sckt);
|
||||
}
|
||||
}
|
||||
|
||||
void TunnelChannel::handle_socket_closed_ack(RedPeer::InMessage* message)
|
||||
{
|
||||
SpiceMsgTunnelSocketClosedAck* close_ack_msg = (SpiceMsgTunnelSocketClosedAck*)message->data();
|
||||
TunnelSocket* sckt = _sockets[close_ack_msg->connection_id];
|
||||
if (!sckt) {
|
||||
THROW("%s: close ack to connection that doesn't exist id=%d", __FUNCTION__,
|
||||
close_ack_msg->connection_id);
|
||||
}
|
||||
|
||||
if (sckt->is_connected()) {
|
||||
THROW("%s: close ack to connection that is not closed id=%d",
|
||||
__FUNCTION__, close_ack_msg->connection_id);
|
||||
}
|
||||
_sockets[sckt->id()] = NULL;
|
||||
DBG(0, "guest Acked closed connection_id=%d", close_ack_msg->connection_id);
|
||||
delete sckt;
|
||||
}
|
||||
|
||||
void TunnelChannel::handle_socket_data(RedPeer::InMessage* message)
|
||||
{
|
||||
SpiceMsgTunnelSocketData* send_msg = (SpiceMsgTunnelSocketData*)message->data();
|
||||
TunnelSocket* sckt = _sockets[send_msg->connection_id];
|
||||
|
||||
if (!sckt) {
|
||||
THROW("%s: sending data to connection that doesn't exist id=%d", __FUNCTION__,
|
||||
send_msg->connection_id);
|
||||
}
|
||||
|
||||
if (!sckt->get_server_num_tokens()) {
|
||||
THROW("%s: token violation connectio_id=%d", __FUNCTION__, sckt->id());
|
||||
}
|
||||
|
||||
sckt->set_server_num_tokens(sckt->get_server_num_tokens() - 1);
|
||||
|
||||
if (!sckt->is_connected()) {
|
||||
// server hasn't handled the close msg yet
|
||||
return;
|
||||
}
|
||||
|
||||
InSocketMessage* sckt_msg = new InSocketMessage(*(
|
||||
static_cast<RedChannel::CompoundInMessage*>(message)));
|
||||
if (sckt_msg->size() > _max_socket_data_size) {
|
||||
THROW("%s: socket data exceeds size limit %d > %d connection_id=%d", __FUNCTION__,
|
||||
sckt_msg->size(), _max_socket_data_size, sckt->id());
|
||||
}
|
||||
sckt->push_send(*sckt_msg);
|
||||
sckt_msg->unref();
|
||||
}
|
||||
|
||||
void TunnelChannel::handle_socket_token(RedPeer::InMessage* message)
|
||||
{
|
||||
SpiceMsgTunnelSocketTokens* token_msg = (SpiceMsgTunnelSocketTokens*)message->data();
|
||||
TunnelSocket* sckt = _sockets[token_msg->connection_id];
|
||||
|
||||
if (!sckt) {
|
||||
THROW("%s: ack connection that doesn't exist id=%d", __FUNCTION__,
|
||||
token_msg->connection_id);
|
||||
}
|
||||
if (!sckt->is_connected()) {
|
||||
return;
|
||||
}
|
||||
sckt->add_recv_tokens(token_msg->num_tokens);
|
||||
}
|
||||
|
||||
void TunnelChannel::on_socket_message_recv_done(ClientNetSocket& sckt,
|
||||
ClientNetSocket::ReceiveBuffer& buf)
|
||||
{
|
||||
OutSocketMessage* out_msg = static_cast<OutSocketMessage*>(&buf);
|
||||
|
||||
post_message(out_msg);
|
||||
}
|
||||
|
||||
void TunnelChannel::on_socket_fin_recv(ClientNetSocket& sckt)
|
||||
{
|
||||
TunnelChannel::TunnelSocket* tunnel_sckt = static_cast<TunnelChannel::TunnelSocket*>(&sckt);
|
||||
Message* out_msg = new Message(SPICE_MSGC_TUNNEL_SOCKET_FIN);
|
||||
DBG(0, "FIN from client coonection id=%d", tunnel_sckt->id());
|
||||
SpiceMsgcTunnelSocketFin fin;
|
||||
fin.connection_id = tunnel_sckt->id();
|
||||
_marshallers->msgc_tunnel_socket_fin(out_msg->marshaller(), &fin);
|
||||
post_message(out_msg);
|
||||
}
|
||||
|
||||
void TunnelChannel::on_socket_disconnect(ClientNetSocket& sckt)
|
||||
{
|
||||
TunnelChannel::TunnelSocket* tunnel_sckt = static_cast<TunnelChannel::TunnelSocket*>(&sckt);
|
||||
Message* out_msg;
|
||||
// close initiated by server -> needs ack
|
||||
if (tunnel_sckt->get_guest_closed()) {
|
||||
DBG(0, "send close ack connection_id=%d", tunnel_sckt->id());
|
||||
out_msg = new Message(SPICE_MSGC_TUNNEL_SOCKET_CLOSED_ACK);
|
||||
SpiceMsgcTunnelSocketClosedAck ack;
|
||||
ack.connection_id = tunnel_sckt->id();
|
||||
_marshallers->msgc_tunnel_socket_closed_ack(out_msg->marshaller(), &ack);
|
||||
_sockets[tunnel_sckt->id()] = NULL;
|
||||
delete &sckt;
|
||||
} else { // close initiated by client
|
||||
DBG(0, "send close coonection_id=%d", tunnel_sckt->id());
|
||||
out_msg = new Message(SPICE_MSGC_TUNNEL_SOCKET_CLOSED);
|
||||
SpiceMsgcTunnelSocketClosed closed;
|
||||
closed.connection_id = tunnel_sckt->id();
|
||||
_marshallers->msgc_tunnel_socket_closed(out_msg->marshaller(), &closed);
|
||||
}
|
||||
|
||||
post_message(out_msg);
|
||||
}
|
||||
|
||||
void TunnelChannel::on_socket_message_send_done(ClientNetSocket& sckt)
|
||||
{
|
||||
TunnelChannel::TunnelSocket* tunnel_sckt = static_cast<TunnelChannel::TunnelSocket*>(&sckt);
|
||||
uint32_t num_tokens = tunnel_sckt->get_num_tokens();
|
||||
num_tokens++;
|
||||
|
||||
if (num_tokens == SOCKET_TOKENS_TO_SEND) {
|
||||
Message* out_msg = new Message(SPICE_MSGC_TUNNEL_SOCKET_TOKEN);
|
||||
SpiceMsgcTunnelSocketTokens tokens_msg;
|
||||
tokens_msg.connection_id = tunnel_sckt->id();
|
||||
tokens_msg.num_tokens = num_tokens;
|
||||
_marshallers->msgc_tunnel_socket_token(out_msg->marshaller(), &tokens_msg);
|
||||
post_message(out_msg);
|
||||
|
||||
tunnel_sckt->set_num_tokens(0);
|
||||
tunnel_sckt->set_server_num_tokens(tunnel_sckt->get_server_num_tokens() + num_tokens);
|
||||
|
||||
ASSERT(tunnel_sckt->get_server_num_tokens() <= SOCKET_WINDOW_SIZE);
|
||||
} else {
|
||||
tunnel_sckt->set_num_tokens(num_tokens);
|
||||
}
|
||||
}
|
||||
|
||||
TunnelService* TunnelChannel::find_service(uint32_t id)
|
||||
{
|
||||
for (std::list<TunnelService*>::iterator iter = _services.begin();
|
||||
iter != _services.end(); iter++) {
|
||||
if ((*iter)->id == id) {
|
||||
return *iter;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* returns the first service with the same ip */
|
||||
TunnelService* TunnelChannel::find_service(struct in_addr& ip)
|
||||
{
|
||||
for (std::list<TunnelService*>::iterator iter = _services.begin();
|
||||
iter != _services.end(); iter++) {
|
||||
if ((*iter)->ip.s_addr == ip.s_addr) {
|
||||
return *iter;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TunnelService* TunnelChannel::find_service(struct in_addr& ip, uint32_t port)
|
||||
{
|
||||
for (std::list<TunnelService*>::iterator iter = _services.begin();
|
||||
iter != _services.end(); iter++) {
|
||||
if (((*iter)->ip.s_addr == ip.s_addr) && ((*iter)->port == port)) {
|
||||
return *iter;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void TunnelChannel::destroy_sockets()
|
||||
{
|
||||
for (unsigned int i = 0; i < _sockets.size(); i++) {
|
||||
if (_sockets[i]) {
|
||||
delete _sockets[i];
|
||||
_sockets[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TUNNEL_CONFIG
|
||||
void TunnelChannel::on_connect()
|
||||
{
|
||||
_config_listener = new TunnelConfigListenerIfc(*this);
|
||||
}
|
||||
#endif
|
||||
|
||||
void TunnelChannel::on_disconnect()
|
||||
{
|
||||
destroy_sockets();
|
||||
OutSocketMessage::clear_free_messages();
|
||||
#ifdef TUNNEL_CONFIG
|
||||
if (_config_listener) {
|
||||
delete _config_listener;
|
||||
_config_listener = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef TUNNEL_CONFIG
|
||||
void TunnelChannel::add_service(TunnelConfigConnectionIfc& source,
|
||||
uint32_t type, struct in_addr& ip, uint32_t port,
|
||||
std::string& name, std::string& description)
|
||||
{
|
||||
if (find_service(ip, port)) {
|
||||
LOG_WARN("service ip=%s port=%d was already added",
|
||||
inet_ntoa(ip), port);
|
||||
return;
|
||||
}
|
||||
TunnelService* new_service = new TunnelService;
|
||||
TunnelService* service_group = find_service(ip);
|
||||
new_service->type = type;
|
||||
new_service->id = _service_id++;
|
||||
if (service_group) {
|
||||
if (name != service_group->name) {
|
||||
LOG_WARN("service ip=%s port=%d was not added because of inconsistent name for ip",
|
||||
inet_ntoa(ip), port);
|
||||
delete new_service;
|
||||
return;
|
||||
}
|
||||
new_service->group = service_group->group;
|
||||
} else {
|
||||
new_service->group = _service_group++;
|
||||
}
|
||||
new_service->ip.s_addr = ip.s_addr;
|
||||
new_service->port = port;
|
||||
new_service->name = name;
|
||||
new_service->description = description;
|
||||
new_service->service_src = &source;
|
||||
_services.push_back(new_service);
|
||||
send_service(*new_service);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
class TunnelFactory: public ChannelFactory {
|
||||
public:
|
||||
TunnelFactory() : ChannelFactory(SPICE_CHANNEL_TUNNEL) {}
|
||||
virtual RedChannel* construct(RedClient& client, uint32_t id)
|
||||
{
|
||||
return new TunnelChannel(client, id);
|
||||
}
|
||||
};
|
||||
|
||||
static TunnelFactory factory;
|
||||
|
||||
ChannelFactory& TunnelChannel::Factory()
|
||||
{
|
||||
return factory;
|
||||
}
|
||||
|
||||
#ifdef TUNNEL_CONFIG
|
||||
class CreatePipeListenerEvent: public SyncEvent {
|
||||
public:
|
||||
CreatePipeListenerEvent(NamedPipe::ListenerInterface& listener_ifc)
|
||||
: _listener_ifc (listener_ifc)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void do_response(AbstractProcessLoop& events_loop)
|
||||
{
|
||||
_listener_ref = NamedPipe::create(TUNNEL_CONFIG_PIPE_NAME, _listener_ifc);
|
||||
}
|
||||
|
||||
NamedPipe::ListenerRef get_listener() { return _listener_ref;}
|
||||
private:
|
||||
NamedPipe::ListenerInterface& _listener_ifc;
|
||||
NamedPipe::ListenerRef _listener_ref;
|
||||
};
|
||||
|
||||
class DestroyPipeListenerEvent: public SyncEvent {
|
||||
public:
|
||||
DestroyPipeListenerEvent(NamedPipe::ListenerRef listener_ref)
|
||||
: _listener_ref (listener_ref)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void do_response(AbstractProcessLoop& events_loop)
|
||||
{
|
||||
NamedPipe::destroy(_listener_ref);
|
||||
}
|
||||
|
||||
private:
|
||||
NamedPipe::ListenerRef _listener_ref;
|
||||
};
|
||||
|
||||
class DestroyPipeConnectionEvent: public SyncEvent {
|
||||
public:
|
||||
DestroyPipeConnectionEvent(NamedPipe::ConnectionRef ref) : _conn_ref(ref) {}
|
||||
virtual void do_response(AbstractProcessLoop& events_loop)
|
||||
{
|
||||
NamedPipe::destroy_connection(_conn_ref);
|
||||
}
|
||||
private:
|
||||
NamedPipe::ConnectionRef _conn_ref;
|
||||
};
|
||||
|
||||
TunnelConfigListenerIfc::TunnelConfigListenerIfc(TunnelChannel& tunnel)
|
||||
: _tunnel (tunnel)
|
||||
{
|
||||
AutoRef<CreatePipeListenerEvent> event(new CreatePipeListenerEvent(*this));
|
||||
_tunnel.get_client().push_event(*event);
|
||||
(*event)->wait();
|
||||
_listener_ref = (*event)->get_listener();
|
||||
}
|
||||
|
||||
TunnelConfigListenerIfc::~TunnelConfigListenerIfc()
|
||||
{
|
||||
AutoRef<DestroyPipeListenerEvent> listen_event(new DestroyPipeListenerEvent(_listener_ref));
|
||||
_tunnel.get_client().push_event(*listen_event);
|
||||
(*listen_event)->wait();
|
||||
for (std::list<TunnelConfigConnectionIfc*>::iterator it = _connections.begin();
|
||||
it != _connections.end(); ++it) {
|
||||
if ((*it)->get_ref() != NamedPipe::INVALID_CONNECTION) {
|
||||
AutoRef<DestroyPipeConnectionEvent> conn_event(new DestroyPipeConnectionEvent(
|
||||
(*it)->get_ref()));
|
||||
_tunnel.get_client().push_event(*conn_event);
|
||||
(*conn_event)->wait();
|
||||
}
|
||||
delete (*it);
|
||||
}
|
||||
}
|
||||
|
||||
NamedPipe::ConnectionInterface& TunnelConfigListenerIfc::create()
|
||||
{
|
||||
DBG(0, "new_connection");
|
||||
TunnelConfigConnectionIfc* new_conn = new TunnelConfigConnectionIfc(_tunnel, *this);
|
||||
_connections.push_back(new_conn);
|
||||
return *new_conn;
|
||||
}
|
||||
|
||||
void TunnelConfigListenerIfc::destroy_connection(TunnelConfigConnectionIfc* conn)
|
||||
{
|
||||
if (conn->get_ref() != NamedPipe::INVALID_CONNECTION) {
|
||||
NamedPipe::destroy_connection(conn->get_ref());
|
||||
}
|
||||
_connections.remove(conn);
|
||||
delete conn;
|
||||
}
|
||||
|
||||
TunnelConfigConnectionIfc::TunnelConfigConnectionIfc(TunnelChannel& tunnel,
|
||||
TunnelConfigListenerIfc& listener)
|
||||
: _tunnel (tunnel)
|
||||
, _listener (listener)
|
||||
, _in_msg_len (0)
|
||||
, _out_msg ("")
|
||||
, _out_msg_pos (0)
|
||||
{
|
||||
}
|
||||
|
||||
void TunnelConfigConnectionIfc::bind(NamedPipe::ConnectionRef conn_ref)
|
||||
{
|
||||
_opaque = conn_ref;
|
||||
on_data();
|
||||
}
|
||||
|
||||
void TunnelConfigConnectionIfc::on_data()
|
||||
{
|
||||
if (!_out_msg.empty()) {
|
||||
int ret = NamedPipe::write(_opaque, (uint8_t*)_out_msg.c_str() + _out_msg_pos,
|
||||
_out_msg.length() - _out_msg_pos);
|
||||
if (ret == -1) {
|
||||
_listener.destroy_connection(this);
|
||||
return;
|
||||
}
|
||||
_out_msg_pos += ret;
|
||||
if (_out_msg_pos == _out_msg.length()) {
|
||||
_out_msg = "";
|
||||
_out_msg_pos = 0;
|
||||
}
|
||||
} else {
|
||||
int ret = NamedPipe::read(_opaque, (uint8_t*)_in_msg + _in_msg_len,
|
||||
TUNNEL_CONFIG_MAX_MSG_LEN - _in_msg_len);
|
||||
|
||||
if (ret == -1) {
|
||||
_listener.destroy_connection(this);
|
||||
return;
|
||||
}
|
||||
_in_msg_len += ret;
|
||||
|
||||
if (_in_msg[_in_msg_len - 1] != '\n') {
|
||||
return;
|
||||
}
|
||||
handle_msg();
|
||||
_in_msg_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void TunnelConfigConnectionIfc::send_virtual_ip(struct in_addr& ip)
|
||||
{
|
||||
_out_msg = inet_ntoa(ip);
|
||||
_out_msg += "\n";
|
||||
_out_msg_pos = 0;
|
||||
on_data();
|
||||
}
|
||||
|
||||
void TunnelConfigConnectionIfc::handle_msg()
|
||||
{
|
||||
std::string space = " \t";
|
||||
_in_msg[_in_msg_len - 1] = '\0';
|
||||
std::string msg(_in_msg);
|
||||
|
||||
uint32_t service_type;
|
||||
struct in_addr ip;
|
||||
uint32_t port;
|
||||
std::string name;
|
||||
std::string desc;
|
||||
|
||||
DBG(0, "msg=%s", _in_msg);
|
||||
size_t start_token = 0;
|
||||
size_t end_token;
|
||||
|
||||
start_token = msg.find_first_not_of(space);
|
||||
end_token = msg.find_first_of(space, start_token);
|
||||
|
||||
if ((end_token - start_token) != 1) {
|
||||
THROW("unexpected service type length");
|
||||
}
|
||||
if (msg[start_token] == '0') {
|
||||
service_type = SPICE_TUNNEL_SERVICE_TYPE_GENERIC;
|
||||
} else if (msg[start_token] == '1') {
|
||||
service_type = SPICE_TUNNEL_SERVICE_TYPE_IPP;
|
||||
} else {
|
||||
THROW("unexpected service type");
|
||||
}
|
||||
|
||||
start_token = msg.find_first_not_of(space, end_token);
|
||||
end_token = msg.find_first_of(space, start_token);
|
||||
|
||||
inet_aton(msg.substr(start_token, end_token - start_token).c_str(), &ip);
|
||||
|
||||
start_token = msg.find_first_not_of(space, end_token);
|
||||
end_token = msg.find_first_of(space, start_token);
|
||||
|
||||
port = atoi(msg.substr(start_token, end_token - start_token).c_str());
|
||||
|
||||
start_token = msg.find_first_not_of(space, end_token);
|
||||
end_token = msg.find_first_of(space, start_token);
|
||||
|
||||
name = msg.substr(start_token, end_token - start_token);
|
||||
|
||||
start_token = msg.find_first_not_of(space, end_token);
|
||||
desc = msg.substr(start_token);
|
||||
|
||||
_tunnel.add_service(*this, service_type, ip, port, name, desc);
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1,140 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2009 Red Hat, Inc.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
Author:
|
||||
yhalperi@redhat.com
|
||||
*/
|
||||
|
||||
#ifndef _H_TUNNEL_CHANNEL
|
||||
#define _H_TUNNEL_CHANNEL
|
||||
|
||||
#include "common.h"
|
||||
#include "red_channel.h"
|
||||
#include "red_client.h"
|
||||
#include "client_net_socket.h"
|
||||
#include "platform.h"
|
||||
|
||||
#define TUNNEL_CONFIG
|
||||
|
||||
#ifdef TUNNEL_CONFIG
|
||||
class TunnelConfigConnectionIfc;
|
||||
class TunnelConfigListenerIfc;
|
||||
#endif
|
||||
|
||||
/* channel for tunneling tcp from guest to client network */
|
||||
typedef struct TunnelService TunnelService;
|
||||
class TunnelChannel: public RedChannel,
|
||||
public ClientNetSocket::EventHandler {
|
||||
public:
|
||||
|
||||
TunnelChannel(RedClient& client, uint32_t id);
|
||||
virtual ~TunnelChannel();
|
||||
|
||||
virtual void on_socket_message_recv_done(ClientNetSocket& sckt,
|
||||
ClientNetSocket::ReceiveBuffer& buf);
|
||||
virtual void on_socket_message_send_done(ClientNetSocket& sckt);
|
||||
virtual void on_socket_fin_recv(ClientNetSocket& sckt);
|
||||
virtual void on_socket_disconnect(ClientNetSocket& sckt);
|
||||
|
||||
#ifdef TUNNEL_CONFIG
|
||||
void add_service(TunnelConfigConnectionIfc& source,
|
||||
uint32_t type, struct in_addr& ip, uint32_t port,
|
||||
std::string& name, std::string& description);
|
||||
#endif
|
||||
static ChannelFactory& Factory();
|
||||
|
||||
protected:
|
||||
class TunnelSocket;
|
||||
|
||||
virtual void on_disconnect();
|
||||
virtual void on_connect();
|
||||
|
||||
private:
|
||||
void handle_init(RedPeer::InMessage* message);
|
||||
void handle_service_ip_map(RedPeer::InMessage* message);
|
||||
|
||||
void handle_socket_open(RedPeer::InMessage* message);
|
||||
void handle_socket_fin(RedPeer::InMessage* message);
|
||||
void handle_socket_close(RedPeer::InMessage* message);
|
||||
void handle_socket_closed_ack(RedPeer::InMessage* message);
|
||||
void handle_socket_data(RedPeer::InMessage* message);
|
||||
void handle_socket_token(RedPeer::InMessage* message);
|
||||
|
||||
TunnelService* find_service(uint32_t id);
|
||||
TunnelService* find_service(struct in_addr& ip);
|
||||
TunnelService* find_service(struct in_addr& ip, uint32_t port);
|
||||
|
||||
void send_service(TunnelService& service);
|
||||
void destroy_sockets();
|
||||
|
||||
private:
|
||||
std::vector<TunnelSocket*> _sockets;
|
||||
std::list<TunnelService*> _services;
|
||||
uint32_t _max_socket_data_size;
|
||||
uint32_t _service_id;
|
||||
uint32_t _service_group;
|
||||
#ifdef TUNNEL_CONFIG
|
||||
TunnelConfigListenerIfc* _config_listener;
|
||||
friend class TunnelConfigListenerIfc;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef TUNNEL_CONFIG
|
||||
#ifdef _WIN32
|
||||
#define TUNNEL_CONFIG_PIPE_NAME "tunnel-config.pipe"
|
||||
#else
|
||||
#define TUNNEL_CONFIG_PIPE_NAME "/tmp/tunnel-config.pipe"
|
||||
#endif
|
||||
|
||||
class TunnelConfigConnectionIfc;
|
||||
|
||||
class TunnelConfigListenerIfc: public NamedPipe::ListenerInterface {
|
||||
public:
|
||||
TunnelConfigListenerIfc(TunnelChannel& tunnel);
|
||||
virtual ~TunnelConfigListenerIfc();
|
||||
virtual NamedPipe::ConnectionInterface& create();
|
||||
virtual void destroy_connection(TunnelConfigConnectionIfc* conn);
|
||||
|
||||
private:
|
||||
TunnelChannel& _tunnel;
|
||||
NamedPipe::ListenerRef _listener_ref;
|
||||
std::list<TunnelConfigConnectionIfc*> _connections;
|
||||
};
|
||||
|
||||
#define TUNNEL_CONFIG_MAX_MSG_LEN 2048
|
||||
class TunnelConfigConnectionIfc: public NamedPipe::ConnectionInterface {
|
||||
public:
|
||||
TunnelConfigConnectionIfc(TunnelChannel& tunnel,
|
||||
TunnelConfigListenerIfc& listener);
|
||||
virtual void bind(NamedPipe::ConnectionRef conn_ref);
|
||||
virtual void on_data();
|
||||
void send_virtual_ip(struct in_addr& ip);
|
||||
NamedPipe::ConnectionRef get_ref() {return _opaque;}
|
||||
void handle_msg();
|
||||
|
||||
private:
|
||||
TunnelChannel& _tunnel;
|
||||
TunnelConfigListenerIfc& _listener;
|
||||
char _in_msg[TUNNEL_CONFIG_MAX_MSG_LEN]; // <service_type> <ip> <port> <name> <desc>\n
|
||||
int _in_msg_len;
|
||||
|
||||
std::string _out_msg; // <virtual ip>\n
|
||||
unsigned _out_msg_pos;
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
21
configure.ac
21
configure.ac
@ -118,16 +118,7 @@ AM_CONDITIONAL(OS_UNIX, test "$os_win32" != "yes")
|
||||
AM_CONDITIONAL(OS_LINUX, test "$os_linux" = "yes")
|
||||
|
||||
dnl =========================================================================
|
||||
dnl Chek optional features
|
||||
AC_ARG_ENABLE(tunnel,
|
||||
[ --enable-tunnel Enable network redirection],,
|
||||
[enable_tunnel="no"])
|
||||
AS_IF([test x"$enable_tunnel" != "xno"], [enable_tunnel="yes"])
|
||||
AM_CONDITIONAL(SUPPORT_TUNNEL, test "x$enable_tunnel" != "xno")
|
||||
if test "x$enable_tunnel" != "xno"; then
|
||||
AC_DEFINE([USE_TUNNEL], [1], [Define if supporting tunnel proxying])
|
||||
fi
|
||||
|
||||
dnl Check optional features
|
||||
AC_ARG_ENABLE(gui,
|
||||
[ --enable-gui Enable start dialog with CEGUI],,
|
||||
[enable_gui="no"])
|
||||
@ -221,14 +212,6 @@ if test "x$enable_gui" = "xyes" && test "x$enable_client" = "xyes" ; then
|
||||
])
|
||||
fi
|
||||
|
||||
if test "x$enable_tunnel" = "xyes"; then
|
||||
PKG_CHECK_MODULES(SLIRP, slirp)
|
||||
AC_SUBST(SLIRP_CFLAGS)
|
||||
AC_SUBST(SLIRP_LIBS)
|
||||
SPICE_REQUIRES+=" slirp"
|
||||
AC_DEFINE([HAVE_SLIRP], [], [Define if we have slirp])
|
||||
fi
|
||||
|
||||
if test "x$enable_smartcard" = "xyes"; then
|
||||
PKG_CHECK_MODULES(CAC_CARD, libcacard >= 0.1.2)
|
||||
SMARTCARD_LIBS="$CAC_CARD_LIBS"
|
||||
@ -535,8 +518,6 @@ echo "
|
||||
|
||||
GUI: ${enable_gui}
|
||||
" ; fi ; echo "\
|
||||
Support tunneling: ${enable_tunnel}
|
||||
|
||||
Smartcard: ${enable_smartcard}
|
||||
|
||||
SASL support: ${enable_sasl}
|
||||
|
||||
@ -107,13 +107,6 @@ libspice_server_la_SOURCES = \
|
||||
spice_image_cache.c \
|
||||
$(NULL)
|
||||
|
||||
if SUPPORT_TUNNEL
|
||||
libspice_server_la_SOURCES += \
|
||||
red_tunnel_worker.c \
|
||||
red_tunnel_worker.h \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
if SUPPORT_GL
|
||||
libspice_server_la_SOURCES += \
|
||||
reds_gl_canvas.c \
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,27 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2009 Red Hat, Inc.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
Author:
|
||||
yhalperi@redhat.com
|
||||
*/
|
||||
|
||||
#ifndef _H_RED_TUNNEL_WORKER
|
||||
#define _H_RED_TUNNEL_WORKER
|
||||
|
||||
void *red_tunnel_attach(SpiceCoreInterface *core_interface, SpiceNetWireInstance *sin);
|
||||
|
||||
#endif
|
||||
@ -70,9 +70,6 @@
|
||||
#include "demarshallers.h"
|
||||
#include "char_device.h"
|
||||
#include "migration_protocol.h"
|
||||
#ifdef USE_TUNNEL
|
||||
#include "red_tunnel_worker.h"
|
||||
#endif
|
||||
#ifdef USE_SMARTCARD
|
||||
#include "smartcard.h"
|
||||
#endif
|
||||
@ -120,9 +117,6 @@ uint32_t streaming_video = STREAM_VIDEO_FILTER;
|
||||
spice_image_compression_t image_compression = SPICE_IMAGE_COMPRESS_AUTO_GLZ;
|
||||
spice_wan_compression_t jpeg_state = SPICE_WAN_COMPRESSION_AUTO;
|
||||
spice_wan_compression_t zlib_glz_state = SPICE_WAN_COMPRESSION_AUTO;
|
||||
#ifdef USE_TUNNEL
|
||||
void *red_tunnel = NULL;
|
||||
#endif
|
||||
int agent_mouse = TRUE;
|
||||
int agent_copypaste = TRUE;
|
||||
int agent_file_xfer = TRUE;
|
||||
@ -3782,25 +3776,8 @@ SPICE_GNUC_VISIBLE int spice_server_add_interface(SpiceServer *s,
|
||||
spice_server_char_device_add_interface(s, sin);
|
||||
|
||||
} else if (strcmp(interface->type, SPICE_INTERFACE_NET_WIRE) == 0) {
|
||||
#ifdef USE_TUNNEL
|
||||
SpiceNetWireInstance *net;
|
||||
spice_info("SPICE_INTERFACE_NET_WIRE");
|
||||
if (red_tunnel) {
|
||||
spice_warning("net wire already attached");
|
||||
return -1;
|
||||
}
|
||||
if (interface->major_version != SPICE_INTERFACE_NET_WIRE_MAJOR ||
|
||||
interface->minor_version > SPICE_INTERFACE_NET_WIRE_MINOR) {
|
||||
spice_warning("unsupported net wire interface");
|
||||
return -1;
|
||||
}
|
||||
net = SPICE_CONTAINEROF(sin, SpiceNetWireInstance, base);
|
||||
net->st = spice_new0(SpiceNetWireState, 1);
|
||||
red_tunnel = red_tunnel_attach(core, net);
|
||||
#else
|
||||
spice_warning("unsupported net wire interface");
|
||||
return -1;
|
||||
#endif
|
||||
} else if (strcmp(interface->type, SPICE_INTERFACE_MIGRATION) == 0) {
|
||||
spice_info("SPICE_INTERFACE_MIGRATION");
|
||||
if (migration_interface) {
|
||||
@ -4205,9 +4182,6 @@ SPICE_GNUC_VISIBLE int spice_server_set_channel_security(SpiceServer *s, const c
|
||||
[ SPICE_CHANNEL_CURSOR ] = "cursor",
|
||||
[ SPICE_CHANNEL_PLAYBACK ] = "playback",
|
||||
[ SPICE_CHANNEL_RECORD ] = "record",
|
||||
#ifdef USE_TUNNEL
|
||||
[ SPICE_CHANNEL_TUNNEL ] = "tunnel",
|
||||
#endif
|
||||
#ifdef USE_SMARTCARD
|
||||
[ SPICE_CHANNEL_SMARTCARD] = "smartcard",
|
||||
#endif
|
||||
|
||||
Loading…
Reference in New Issue
Block a user