⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 netcomputer_generic.cpp

📁 这是一款2d游戏引擎
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*  $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 + -