Welcome to mirror list, hosted at ThFree Co, Russian Federation.

vs_master.c « dist « verse « extern - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 4fa020d58b674cabca5898f21653ffc4a4715b6a (plain)
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
 * Master server communication code.
*/

#include <stdio.h>
#include <string.h>

#include "verse.h"
#include "v_util.h"
#include "vs_server.h"

#define	MASTER_SERVER_PERIOD	(60.0)	/* Period between ANNOUNCE to master server, in seconds. */

static struct {
	boolean		enabled;
	boolean		started;
	const char	*master;
	char		desc[64];
	const char	*tags;
	VUtilTimer	timer;
} server_info;

#define	LEFT(d)	(sizeof server_info.desc - (d - server_info.desc) - 1)

void vs_master_set_enabled(boolean enabled)
{
	server_info.enabled = enabled;
}

const char * vs_master_get_address(void)
{
	return server_info.master;
}

void vs_master_set_address(const char *address)
{
	server_info.master = address;
}

void vs_master_set_desc(const char *desc)
{
	const char	*src = desc;
	char		*dst = server_info.desc;

	for(; *src != '\0' && LEFT(dst) > 0;)
	{
		if(*src == '"')
		{
			if(LEFT(dst) < 2)
				break;
			*dst++ = '\\';
		}
		else if(*src == '\\')
		{
			if(LEFT(dst) < 2)
				break;
			*dst++ = '\\';
		}
		*dst++ = *src++;
	}
	*dst = '\0';
}

void vs_master_set_tags(const char *tags)
{
	server_info.tags = tags;	/* This needs more protection, instead of relying on the master server. */
}

void vs_master_update(void)
{
	if(!server_info.enabled || server_info.master == NULL)
		return;

	if(!server_info.started)
	{
		v_timer_start(&server_info.timer);
		v_timer_advance(&server_info.timer, MASTER_SERVER_PERIOD);
		server_info.started = TRUE;
		return;
	}
	if(v_timer_elapsed(&server_info.timer) < MASTER_SERVER_PERIOD)
		return;
	verse_send_ping(server_info.master, "MS:ANNOUNCE");
	v_timer_start(&server_info.timer);
/*	printf("MS:ANNOUNCE sent to %s\n", server_info.master);*/
}

/* Check if a description request, of the form "A,B,C,...,D" includes the given keyword. This needs to
 * do more than just a simple strstr(), since the keyword may be a prefix. Shades of OpenGL extensions.
*/
static int desc_has_keyword(const char *desc, const char *keyword)
{
	const char	*ptr;

	if(desc == NULL || *desc == '\0')	/* Quick-check for empty description. */
		return 0;

	if((ptr = strstr(desc, keyword)) != NULL)
	{
		size_t	kl = strlen(keyword);

		return ptr[kl] == ',' || ptr[kl] == '\0';
	}
	return 0;
}

static int keyword_fits(size_t used, size_t max, const char *key, const char *value)
{
	size_t	vsize = 0;

	if(key != NULL && value != NULL)
		vsize += 1 + strlen(key) + 1 + 1 + strlen(value) + 1;

	return max - 1 - used >= vsize;
}

static char * append_desc(char *buf, const char *key, const char *value)
{
	return buf + sprintf(buf, " %s=\"%s\"", key, value);
}

void vs_master_handle_describe(const char *address, const char *message)
{
	char	desc[1380] = "DESCRIPTION", *put = desc + 11;

	if(desc_has_keyword(message, "DE") && server_info.desc != NULL && keyword_fits(put - desc, sizeof desc, "DE", server_info.desc))
		put = append_desc(put, "DE", server_info.desc);
	if(desc_has_keyword(message, "TA") && server_info.tags != NULL && keyword_fits(put - desc, sizeof desc, "TA", server_info.tags))
		put = append_desc(put, "TA", server_info.tags);
	verse_send_ping(address, desc);
}