📄 netcomputer_generic.cpp
字号:
/* $Id: netcomputer_generic.cpp,v 1.22 2003/12/01 13:35:54 mbn Exp $
**
** ClanLib Game SDK
** Copyright (C) 2003 The ClanLib Team
** For a total list of contributers see the file CREDITS.
**
** 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, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "netcomputer_generic.h"
#include "netstream_generic.h"
#include "netsession_generic.h"
#include "netpacket_generic.h"
#include "API/Core/System/threadfunc_v0.h"
#include "API/Core/System/event_trigger.h"
#include "API/Core/System/event_listener.h"
#include "API/Core/System/error.h"
#include "API/Core/IOData/outputsource_memory.h"
#include <cstdio>
/////////////////////////////////////////////////////////////////////////////
// CL_NetComputer_Generic construction:
CL_NetComputer_Generic::CL_NetComputer_Generic(
const CL_Socket &sock, CL_NetSession_Generic *netsession,
bool server, const std::string &server_port)
:
tcp_sock(sock), udp_available(false), disconnected(false),
netsession(netsession), data_left(0), netstream(0), local_atom_counter(0),
send_pos(0), ref(0), async_boot(false), async_port(""), channel_id_counter(0), shutdown(false),
server(server), server_port(server_port)
{
address = tcp_sock.get_dest_address();
netsession->new_connections.push(CL_NetComputer(this));
thread = CL_Thread(new CL_ThreadFunc_Runnable_v0<CL_NetComputer_Generic>(this, &CL_NetComputer_Generic::worker_thread), true);
thread.start();
}
CL_NetComputer_Generic::CL_NetComputer_Generic(const std::string &hostname, const std::string &port, CL_NetSession_Generic *netsession)
:
tcp_sock(CL_Socket::tcp), udp_available(false), disconnected(false),
netsession(netsession), data_left(0), netstream(0), local_atom_counter(0), send_pos(0),
ref(0), async_boot(true), async_hostname(hostname), async_port(port),
channel_id_counter(0), shutdown(false), server(false)
{
netsession->new_connections.push(CL_NetComputer(this));
thread = CL_Thread(new CL_ThreadFunc_Runnable_v0<CL_NetComputer_Generic>(this, &CL_NetComputer_Generic::worker_thread), true);
thread.start();
}
CL_NetComputer_Generic::~CL_NetComputer_Generic()
{
do_shutdown();
}
/////////////////////////////////////////////////////////////////////////////
// CL_NetComputer_Generic attributes:
int CL_NetComputer_Generic::get_ref() const
{
return ref;
}
/////////////////////////////////////////////////////////////////////////////
// CL_NetComputer_Generic operations:
void CL_NetComputer_Generic::add_ref()
{
ref++;
}
int CL_NetComputer_Generic::release_ref()
{
ref--;
if (ref == 0)
{
delete this;
return 0;
}
return ref;
}
void CL_NetComputer_Generic::send_udp_info()
{
unsigned short secret;
try
{
secret = netsession->secret_number_generator.get_number();
}
catch (CL_Error error)
{
// out of secret keys. all numbers have been used up.
// The likely hood of this happening is so small that it can be ignored.
// But catch it anyways.
return;
}
netsession->setup_udp_map(this, address.get_address(), secret);
CL_OutputSource_Memory cmd;
cmd.write_uchar8(cmd_udp_info);
cmd.write_ushort16(secret);
bool tcp_queue_empty = send_tcp_queue.empty();
send_tcp_queue.push(cmd.get_data());
if (tcp_queue_empty) wakeup_trigger.set_flag();
}
void CL_NetComputer_Generic::send_packet(const std::string &packet_channel, CL_NetPacket_Generic *packet)
{
CL_MutexSection mutex_section(&mutex);
CL_OutputSource_Memory cmd;
std::map<std::string, int>::iterator it = local_atoms.find(packet_channel);
if (it == local_atoms.end())
{
local_atoms[packet_channel] = local_atom_counter++;
it = local_atoms.find(packet_channel);
cmd.write_uchar8(cmd_create_atom);
cmd.write_ushort16(it->second);
cmd.write_string(it->first);
}
cmd.write_uchar8(cmd_netpacket_msg);
cmd.write_ushort16(it->second);
cmd.write_ushort16(packet->size);
cmd.write(packet->data, packet->size);
bool tcp_queue_empty = send_tcp_queue.empty();
send_tcp_queue.push(cmd.get_data());
if (tcp_queue_empty) wakeup_trigger.set_flag();
}
//: Send packet to computer using udp.
void CL_NetComputer_Generic::send_packet_udp(const std::string &packet_channel, CL_NetPacket_Generic *packet)
{
CL_MutexSection mutex_section(&mutex);
CL_OutputSource_Memory cmd;
std::map<std::string, int>::iterator it = local_atoms.find(packet_channel);
if (it == local_atoms.end())
{
CL_OutputSource_Memory cmd_atom;
local_atoms[packet_channel] = local_atom_counter++;
it = local_atoms.find(packet_channel);
cmd_atom.write_uchar8(cmd_create_atom);
cmd_atom.write_ushort16(it->second);
cmd_atom.write_string(it->first);
// use tcp to send create atom signal
bool tcp_queue_empty = send_tcp_queue.empty();
send_tcp_queue.push(cmd_atom.get_data());
if (tcp_queue_empty) wakeup_trigger.set_flag();
}
cmd.write_uchar8(cmd_netpacket_msg);
cmd.write_ushort16(it->second);
cmd.write(packet->data, packet->size);
// discard data if packet size is too big
if (cmd.size() > netsession->udp_sock.get_max_msg_size())
return;
if (udp_available)
{
CL_MutexSection mutex_section(&netsession->mutex);
if (server)
{
bool udp_queue_empty = netsession->send_udp_server_queue.empty();
netsession->send_udp_server_queue.push(CL_NetSession_Generic::IPMassagePair(udp_address, cmd.get_data()));
if (udp_queue_empty) netsession->udp_wakeup_server_trigger.set_flag();
}
else
{
bool udp_queue_empty = netsession->send_udp_client_queue.empty();
netsession->send_udp_client_queue.push(CL_NetSession_Generic::IPMassagePair(udp_address, cmd.get_data()));
if (udp_queue_empty) netsession->udp_wakeup_client_trigger.set_flag();
}
}
else
{
// send through tcp???
bool tcp_queue_empty = send_tcp_queue.empty();
send_tcp_queue.push(cmd.get_data());
if (tcp_queue_empty) wakeup_trigger.set_flag();
}
}
void CL_NetComputer_Generic::send_stream_message(unsigned int channel_id, const std::string &data)
{
CL_OutputSource_Memory cmd;
cmd.write_uchar8(cmd_netstream_msg);
cmd.write_ushort16(channel_id);
cmd.write_ushort16(data.length());
cmd.write(data.data(), data.length());
CL_MutexSection mutex_section(&mutex);
bool tcp_queue_empty = send_tcp_queue.empty();
send_tcp_queue.push(cmd.get_data());
if (tcp_queue_empty) wakeup_trigger.set_flag();
}
int CL_NetComputer_Generic::send_stream_connect(const std::string &stream_channel, CL_NetStream_Generic *stream)
{
CL_MutexSection mutex_section(&mutex);
CL_OutputSource_Memory cmd;
std::map<std::string, int>::iterator it = local_atoms.find(stream_channel);
if (it == local_atoms.end())
{
local_atoms[stream_channel] = local_atom_counter++;
it = local_atoms.find(stream_channel);
cmd.write_uchar8(cmd_create_atom);
cmd.write_ushort16(it->second);
cmd.write_string(it->first);
}
int channel_id = channel_id_counter++;
streams[channel_id] = stream;
cmd.write_uchar8(cmd_netstream_connect);
cmd.write_ushort16(it->second); // channel atom
cmd.write_ushort16(channel_id);
bool tcp_queue_empty = send_tcp_queue.empty();
send_tcp_queue.push(cmd.get_data());
if (tcp_queue_empty) wakeup_trigger.set_flag();
return channel_id;
}
void CL_NetComputer_Generic::send_stream_close(int channel_id)
{
CL_MutexSection mutex_section(&mutex);
CL_OutputSource_Memory cmd;
cmd.write_uchar8(cmd_netstream_closed);
cmd.write_ushort16(channel_id);
bool tcp_queue_empty = send_tcp_queue.empty();
send_tcp_queue.push(cmd.get_data());
if (tcp_queue_empty) wakeup_trigger.set_flag();
std::map<int, CL_NetStream_Generic *>::iterator it = streams.find(channel_id);
if (it != streams.end())
{
it->second->closed = true;
streams.erase(it);
}
}
void CL_NetComputer_Generic::disconnect(std::string reason)
{
disconnect_reason = reason;
disconnected = true;
wakeup_trigger.set_flag();
}
void CL_NetComputer_Generic::do_shutdown()
{
if (shutdown) return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -