/**
 * Send a keepalive back to the client to confirm we have received his
 *
 * @param s the server
 * @param pl the player to send this to
 * @param ka_id the counter of the keepalived we received
 */
static void s_resp_keepalive(struct player *pl, uint32_t ka_id)
{
    char *data, *ptr;
    int data_size = 24;

    data = (char *)calloc(data_size, sizeof(char));
    if (data == NULL) {
        logger(LOG_WARN, "s_resp_keepalive : calloc failed : %s.", strerror(errno));
        return;
    }
    ptr = data;

    wu32(0x0002bef4, &ptr);		/* Function field */
    wu32(pl->private_id, &ptr);	/* Private ID */
    wu32(pl->public_id, &ptr);	/* Public ID */
    wu32(pl->f4_s_counter, &ptr);	/* Packet counter */
    /* Checksum initialize at the end */		ptr += 4;
    wu32(ka_id, &ptr);		/* ID of the keepalive to confirm */

    /* check we filled the whole packet */
    assert((ptr - data) == data_size);

    /* Add CRC */
    packet_add_crc(data, 24, 16);

    sendto(pl->in_chan->in_server->socket_desc, data, 24, 0, (struct sockaddr *)pl->cli_addr, pl->cli_len);
    pl->f4_s_counter++;
    free(data);
}
Esempio n. 2
0
/**
 * Send the list of bans to a player
 *
 * @param s the server
 * @param pl the player who asked for the list of bans
 */
static void s_resp_bans(struct player *pl)
{
	char *data, *ptr;
	int data_size, tmp_size;
	struct ban *b;
	struct server *s = pl->in_chan->in_server;
	size_t iter;
	
	data_size = 24;
	data_size += 4;	/* number of bans */

	ar_each(struct ban *, b, iter, s->bans)
		data_size += ban_to_data_size(b);
	ar_end_each;

	data = (char *)calloc(data_size, sizeof(char));
	if (data == NULL) {
		logger(LOG_WARN, "s_resp_ban, packet allocation failed : %s.", strerror(errno));
		return;
	}
	ptr = data;

	wu16(PKT_TYPE_CTL, &ptr);	/* */
	wu16(CTL_BANLIST, &ptr);	/* */
	wu32(pl->private_id, &ptr);	/* private ID */
	wu32(pl->public_id, &ptr);	/* public ID */
	wu32(pl->f0_s_counter, &ptr);	/* packet counter */
	ptr += 4;			/* packet version */
	ptr += 4;			/* checksum */
	wu32(s->bans->used_slots, &ptr);/* number of bans */
	logger(LOG_INFO, "number of bans : %zu", s->bans->used_slots);
	ar_each(struct ban *, b, iter, s->bans)
		tmp_size = ban_to_data(b, ptr);
		ptr += tmp_size;
	ar_end_each;
	
	packet_add_crc_d(data, data_size);
	logger(LOG_INFO, "list of bans : sending %i bytes", data_size);
	send_to(s, data, data_size, 0, pl);

	pl->f0_s_counter++;
	free(data);
}
Esempio n. 3
0
/**
 * Send a "player kicked" notification to all players.
 *
 * @param s the server
 * @param kicker the player who kicked
 * @param kicked the player kicked from the server
 * @param reason the reason the player was kicked
 */
static void s_notify_kick_server(struct player *kicker, struct player *kicked, char *reason)
{
	char *data, *ptr;
	struct player *tmp_pl;
	int data_size = 64;
	struct server *s = kicker->in_chan->in_server;
	size_t iter;

	data = (char *)calloc(data_size, sizeof(char));
	if (data == NULL) {
		logger(LOG_WARN, "s_notify_kick_server, packet allocation failed : %s.", strerror(errno));
		return;
	}
	ptr = data;

	wu16(PKT_TYPE_CTL, &ptr);	/* */
	wu16(CTL_PLAYERLEFT, &ptr);	/* */
	ptr += 4;			/* private ID */
	ptr += 4; 			/* public ID */
	ptr += 4;			/* packet counter */
	ptr += 4;			/* packet version */
	ptr += 4;			/* empty checksum */
	wu32(kicked->public_id, &ptr);	/* ID of player who left */
	wu16(2, &ptr);	/* visible notification : kicked */
	wu32(kicker->public_id, &ptr);	/* kicker ID */
	wstaticstring(reason, 29, &ptr);

	/* check we filled all the packet */
	assert((ptr - data) == data_size);

	ar_each(struct player *, tmp_pl, iter, s->players)
			ptr = data + 4;
			wu32(tmp_pl->private_id, &ptr);
			wu32(tmp_pl->public_id, &ptr);
			wu32(tmp_pl->f0_s_counter, &ptr);
			packet_add_crc_d(data, data_size);
			send_to(s, data, data_size, 0, tmp_pl);
			tmp_pl->f0_s_counter++;
	ar_end_each;
	free(data);
}
/**
 * Send a packet to the player, indicating that his connection
 * was accepted.
 *
 * @param pl the player we send this packet to
 */
static void server_accept_connection(struct player *pl)
{
    char *data, *ptr;
    int data_size = 436;
    struct server *s = pl->in_chan->in_server;

    data = (char *)calloc(data_size, sizeof(char));
    if (data == NULL) {
        logger(LOG_WARN, "server_accept_connection : calloc failed : %s.", strerror(errno));
        return;
    }
    ptr = data;

    wu32(0x0004bef4, &ptr);		/* Function field */
    wu32(pl->private_id, &ptr);	/* Private ID */
    wu32(pl->public_id, &ptr);	/* Public ID */
    wu32(pl->f4_s_counter, &ptr);	/* Packet counter */
    ptr += 4;			/* Checksum initialize at the end */

    wstaticstring(s->server_name, 29, &ptr);/* Server name */
    wstaticstring(s->machine, 29, &ptr);	/* Server machine */

    /* Server version */
    wu16(2, &ptr);			/* Server version (major 1) */
    wu16(0, &ptr);			/* Server version (major 2) */
    wu16(20, &ptr);			/* Server version (minor 1) */
    wu16(1, &ptr);			/* Server version (minor 2) */
    wu32(1, &ptr);			/* Error code (1 = OK, 2 = Server Offline */
    wu16(0x1FEF, &ptr);		/* supported codecs (1<<codec | 1<<codec2 ...) */

    ptr += 7;
    /* 0 = SA, 1 = CA, 2 = Op, 3 = Voice, 4 = Reg, 5 = Anonymous */
    sp_to_bitfield(s->privileges, ptr);
    /* garbage data */
    ptr += 71;
    wu32(pl->private_id, &ptr);	/* Private ID */
    wu32(pl->public_id, &ptr);	/* Public ID */

    wstaticstring(s->welcome_msg, 255, &ptr);	/* Welcome message */

    /* check we filled the whole packet */
    assert((ptr - data) == data_size);

    /* Add CRC */
    packet_add_crc(data, 436, 16);
    /* Send packet */
    /*send_to(pl->in_chan->in_server, data, 436, 0, pl);*/
    sendto(pl->in_chan->in_server->socket_desc, data, 436, 0, (struct sockaddr *)pl->cli_addr, pl->cli_len);
    pl->f4_s_counter++;
    free(data);
}
/**
 * Refuse a connection from a player because he has been banned.
 *
 * @param cli_addr the address of the player
 * @param cli_len the length of cli_addr
 */
static void server_refuse_connection_ban(struct sockaddr_in *cli_addr, int cli_len, struct server *s)
{
    char *data, *ptr;
    int data_size = 436;

    data = (char *)calloc(data_size, sizeof(char));
    if (data == NULL) {
        logger(LOG_WARN, "server_refuse_connection : calloc failed : %s.", strerror(errno));
        return;
    }
    ptr = data;

    wu32(0x0004bef4, &ptr);		/* Function field */
    /* *(uint32_t *)ptr = pl->private_id;*/		ptr += 4;	/* Private ID */
    wu32(5, &ptr);			/* Public ID */
    wu32(2, &ptr);			/* Packet counter */
    /* Checksum initialize at the end */		ptr += 4;
    /* *ptr = 14;*/					ptr += 1;	/* Length of server name */
    /* memcpy(ptr, "Nom du serveur", 14);*/		ptr += 29;	/* Server name */
    /* *ptr = 18;*/					ptr += 1;	/* Length of server machine */
    /* memcpy(ptr, "Machine du serveur", 18);*/	ptr += 29;	/* Server machine */
    /* Server version */
    /* *(uint16_t *)ptr = 2;*/			ptr += 2;	/* Server version (major 1) */
    /* *(uint16_t *)ptr = 0;*/			ptr += 2;	/* Server version (major 2) */
    /* *(uint16_t *)ptr = 20;*/			ptr += 2;	/* Server version (minor 1) */
    /* *(uint16_t *)ptr = 1;*/			ptr += 2;	/* Server version (minor 2) */
    wu32(0xFFFFFFFA, &ptr);	/* Error code (1 = OK, 2 = Server Offline, 0xFFFFFFFA = Banned */
    /* rights */					ptr += 80;

    wu32(0x00584430, &ptr);	/* Private ID */
    wu32(5, &ptr);		/* Public ID */
    /* *ptr = 26;*/					ptr += 1;	/* Length of welcome message */
    /* memcpy(ptr, "Bienvenue sur mon serveur.", 26);*/	ptr += 255;	/* Welcome message */

    /* check we filled the whole packet */
    assert((ptr - data) == data_size);

    /* Add CRC */
    packet_add_crc(data, 436, 16);
    /* Send packet */
    sendto(s->socket_desc, data, 436, 0, (struct sockaddr *)cli_addr, cli_len);
    free(data);
}
Esempio n. 6
0
extern "C" int zehn_load(NUC_FILE *file, void **mem_ptr, int (**entry)(int,char*[]), bool *supports_hww)
{
	Zehn_header header;

	// The Zehn file may not begin at the file start
	size_t file_start = nuc_ftell(file);

	if(nuc_fread(&header, sizeof(header), 1, file) != 1)
		return 1;

	if(header.signature != ZEHN_SIGNATURE || header.version != ZEHN_VERSION || header.file_size > header.alloc_size)
	{
		puts("[Zehn] This Zehn file is not supported!");
		return 1;
	}

	Storage<Zehn_reloc> relocs(header.reloc_count);
	Storage<Zehn_flag> flags(header.flag_count);
	Storage<uint8_t> extra_data(header.extra_size);

	if(nuc_fread(reinterpret_cast<void*>(relocs.data), sizeof(Zehn_reloc), header.reloc_count, file) != header.reloc_count
		|| nuc_fread(reinterpret_cast<void*>(flags.data), sizeof(Zehn_flag), header.flag_count, file) != header.flag_count
		|| nuc_fread(reinterpret_cast<void*>(extra_data.data), 1, header.extra_size, file) != header.extra_size)
	{
		puts("[Zehn] File read failed!");
		return 1;
	}

	size_t remaining_mem = header.alloc_size - nuc_ftell(file) + file_start, remaining_file = header.file_size - nuc_ftell(file) + file_start;

	if(emu_debug_alloc_ptr)
	{
		if(emu_debug_alloc_size < remaining_mem)
		{
			puts("[Zehn] emu_debug_alloc_size too small!");
			*mem_ptr = malloc(remaining_mem);
		}
		else
			*mem_ptr = emu_debug_alloc_ptr;
	}
	else
		*mem_ptr = malloc(remaining_mem);

	uint8_t *base = reinterpret_cast<uint8_t*>(*mem_ptr);
	if(!base)
	{
		puts("[Zehn] Memory allocation failed!");
		return 1;
	}

	if(relocs.data[0].type == Zehn_reloc_type::FILE_COMPRESSED)
	{
		if(relocs.data[0].offset != static_cast<int>(Zehn_compress_type::ZLIB))
		{
			puts("[Zehn] Compression format not supported!");
			return 1;
		}

		Storage<uint8_t> compressed(remaining_file);
		if(nuc_fread(compressed.data, remaining_file, 1, file) != 1)
		{
			puts("[Zehn] File read failed!");
			return 1;
		}

		uLongf dest_len = remaining_mem;
		if(uncompress(base, &dest_len, compressed.data, remaining_file) != Z_OK)
		{
			puts("[Zehn] Decompression failed!");
			return 1;
		}

		std::fill(base + dest_len, base + remaining_mem, 0);
	}
	else
	{
		if(nuc_fread(base, remaining_file, 1, file) != 1)
		{
			puts("[Zehn] File read failed!");
			return 1;
		}
	
		// Fill rest with zeros (.bss and other NOBITS sections)
		std::fill(base + remaining_file, base + remaining_mem, 0);
	}

	const char *application_name = "(unknown)", *application_author = "(unknown)", *application_notice = "(no notice)";
	unsigned int application_version = 1, ndless_version_min = 0, ndless_version_max = UINT_MAX,
		ndless_revision_min = 0, ndless_revision_max = UINT_MAX;

	// Iterate through each flag
	for(Zehn_flag &f : flags)
	{
		const char *ptr;
		switch(f.type)
		{
		case Zehn_flag_type::EXECUTABLE_NAME:
			if(!zehn_check_string(extra_data.begin(), f, 255, &application_name))
			{
				puts("[Zehn] Invalid application name!");
				return 1;
			}

			break;
		case Zehn_flag_type::EXECUTABLE_NOTICE:
			if(zehn_check_string(extra_data.begin(), f, 1024, &ptr))
				application_notice = ptr;

			break;
		case Zehn_flag_type::EXECUTABLE_AUTHOR:
			if(zehn_check_string(extra_data.begin(), f, 128, &ptr))
				application_author = ptr;

			break;
		case Zehn_flag_type::EXECUTABLE_VERSION:
			application_version = f.data;
			break;
		case Zehn_flag_type::NDLESS_VERSION_MIN:
			ndless_version_min = f.data;
			break;
		case Zehn_flag_type::NDLESS_REVISION_MIN:
			ndless_revision_min = f.data;
			break;
		case Zehn_flag_type::NDLESS_VERSION_MAX:
			ndless_version_max = f.data;
			break;
		case Zehn_flag_type::NDLESS_REVISION_MAX:
			ndless_revision_max = f.data;
			break;
		case Zehn_flag_type::RUNS_ON_COLOR:
			if(f.data == false && has_colors)
			{
				msgbox("Error", "The application %s doesn't support CX and CM calculators!", application_name);
				return 2;
			}
			break;
		case Zehn_flag_type::RUNS_ON_CLICKPAD:
			if(f.data == false && !is_touchpad)
			{
				msgbox("Error", "The application %s doesn't support clickpads!", application_name);
				return 2;
			}
			break;
		case Zehn_flag_type::RUNS_ON_TOUCHPAD:
			if(f.data == false && is_touchpad)
			{
				msgbox("Error", "The application %s doesn't support touchpads!", application_name);
				return 2;
			}
			break;
		case Zehn_flag_type::RUNS_ON_32MB:
			if(f.data == false && (!has_colors || is_cm))
			{
				msgbox("Error", "The application %s requires more than 32MB of RAM!", application_name);
				return 2;
			}
			break;
                case Zehn_flag_type::RUNS_ON_HWW:
                        *supports_hww = f.data;
			break;
		default:
			break;
		}
	}

	// Show some information about the executable
	if(isKeyPressed(KEY_NSPIRE_CAT))
	{
		char info[1536];
		sprintf(info, "Name: %s Version: %u\nAuthor: %s\nNotice: %s", application_name, application_version, application_author, application_notice);
		show_msgbox("Information about the executable", info);

		return 2;
	}

	if(NDLESS_VERSION < ndless_version_min || (NDLESS_VERSION == ndless_version_min && NDLESS_REVISION < ndless_revision_min))
	{
		msgbox("Error", "The application %s requires at least ndless %d.%d.%d!", application_name, ndless_version_min / 10, ndless_version_min % 10, ndless_revision_min);
		return 2;
	}

	if(NDLESS_VERSION > ndless_version_max || (NDLESS_VERSION == ndless_version_max && NDLESS_REVISION > ndless_revision_max))
	{
		if(ndless_revision_max != UINT_MAX)
			msgbox("Error", "The application %s requires ndless %d.%d.%d or older!", application_name, ndless_version_max / 10, ndless_version_max % 10, ndless_revision_max);
		else
			msgbox("Error", "The application %s requires ndless %d.%d or older!", application_name, ndless_version_max / 10, ndless_version_max % 10);

		return 2;
	}

	// Iterate through the reloc table
	for(Zehn_reloc &r : relocs)
	{
		if(r.offset >= remaining_mem)
		{
			puts("[Zehn] Wrong reloc in Zehn file!");
			return 1;
		}

		// No alignment guaranteed!
		uint32_t *place = reinterpret_cast<uint32_t*>(base + r.offset);
		switch(r.type)
		{
		//Handled above
		case Zehn_reloc_type::FILE_COMPRESSED:
                        break;
                case Zehn_reloc_type::UNALIGNED_RELOC:
                        if(r.offset != 0)
                        {
                            printf("[Zehn] Unexpected UNALIGNED_RELOC value %lu!\n", r.offset);
                            return 1;
                        }

			break;
		case Zehn_reloc_type::ADD_BASE:
			wu32(place, ru32(place) + reinterpret_cast<uint32_t>(base));
			break;
		case Zehn_reloc_type::ADD_BASE_GOT:
		{
			uint32_t u32;
			while((u32 = ru32(place)) != 0xFFFFFFFF)
				wu32(place++, u32 + reinterpret_cast<uint32_t>(base));

			break;
		}
		case Zehn_reloc_type::SET_ZERO:
			wu32(place, 0);
			break;
		default:
			printf("[Zehn] Unsupported reloc %d!\n", static_cast<int>(r.type));
			return 1;
		}
	}

	*entry = reinterpret_cast<int (*)(int,char*[])>(base + header.entry_offset);

	return 0;
}