1/*
2Copyright (C) 1996-1997 Id Software, Inc.
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19*/
20// net_loop.c
21
22#include "quakedef.h"
23#include "net_loop.h"
24
25qboolean	localconnectpending = false;
26qsocket_t	*loop_client = NULL;
27qsocket_t	*loop_server = NULL;
28
29int Loop_Init (void)
30{
31	if (cls.state == ca_dedicated)
32		return -1;
33	return 0;
34}
35
36
37void Loop_Shutdown (void)
38{
39}
40
41
42void Loop_Listen (qboolean state)
43{
44}
45
46
47void Loop_SearchForHosts (qboolean xmit)
48{
49	if (!sv.active)
50		return;
51
52	hostCacheCount = 1;
53	if (Q_strcmp(hostname.string, "UNNAMED") == 0)
54		Q_strcpy(hostcache[0].name, "local");
55	else
56		Q_strcpy(hostcache[0].name, hostname.string);
57	Q_strcpy(hostcache[0].map, sv.name);
58	hostcache[0].users = net_activeconnections;
59	hostcache[0].maxusers = svs.maxclients;
60	hostcache[0].driver = net_driverlevel;
61	Q_strcpy(hostcache[0].cname, "local");
62}
63
64
65qsocket_t *Loop_Connect (const char *host)
66{
67	if (Q_strcmp(host,"local") != 0)
68		return NULL;
69
70	localconnectpending = true;
71
72	if (!loop_client)
73	{
74		if ((loop_client = NET_NewQSocket ()) == NULL)
75		{
76			Con_Printf("Loop_Connect: no qsocket available\n");
77			return NULL;
78		}
79		Q_strcpy (loop_client->address, "localhost");
80	}
81	loop_client->receiveMessageLength = 0;
82	loop_client->sendMessageLength = 0;
83	loop_client->canSend = true;
84
85	if (!loop_server)
86	{
87		if ((loop_server = NET_NewQSocket ()) == NULL)
88		{
89			Con_Printf("Loop_Connect: no qsocket available\n");
90			return NULL;
91		}
92		Q_strcpy (loop_server->address, "LOCAL");
93	}
94	loop_server->receiveMessageLength = 0;
95	loop_server->sendMessageLength = 0;
96	loop_server->canSend = true;
97
98	loop_client->driverdata = (void *)loop_server;
99	loop_server->driverdata = (void *)loop_client;
100
101	return loop_client;
102}
103
104
105qsocket_t *Loop_CheckNewConnections (void)
106{
107	if (!localconnectpending)
108		return NULL;
109
110	localconnectpending = false;
111	loop_server->sendMessageLength = 0;
112	loop_server->receiveMessageLength = 0;
113	loop_server->canSend = true;
114	loop_client->sendMessageLength = 0;
115	loop_client->receiveMessageLength = 0;
116	loop_client->canSend = true;
117	return loop_server;
118}
119
120
121static int IntAlign(int value)
122{
123	return (value + (sizeof(int) - 1)) & (~(sizeof(int) - 1));
124}
125
126
127int Loop_GetMessage (qsocket_t *sock)
128{
129	int		ret;
130	int		length;
131
132	if (sock->receiveMessageLength == 0)
133		return 0;
134
135	ret = sock->receiveMessage[0];
136	length = sock->receiveMessage[1] + (sock->receiveMessage[2] << 8);
137	// alignment byte skipped here
138	SZ_Clear (&net_message);
139	SZ_Write (&net_message, &sock->receiveMessage[4], length);
140
141	length = IntAlign(length + 4);
142	sock->receiveMessageLength -= length;
143
144	if (sock->receiveMessageLength)
145		Q_memcpy(sock->receiveMessage, &sock->receiveMessage[length], sock->receiveMessageLength);
146
147	if (sock->driverdata && ret == 1)
148		((qsocket_t *)sock->driverdata)->canSend = true;
149
150	return ret;
151}
152
153
154int Loop_SendMessage (qsocket_t *sock, sizebuf_t *data)
155{
156	byte *buffer;
157	int  *bufferLength;
158
159	if (!sock->driverdata)
160		return -1;
161
162	bufferLength = &((qsocket_t *)sock->driverdata)->receiveMessageLength;
163
164	if ((*bufferLength + data->cursize + 4) > NET_MAXMESSAGE)
165		Sys_Error("Loop_SendMessage: overflow\n");
166
167	buffer = ((qsocket_t *)sock->driverdata)->receiveMessage + *bufferLength;
168
169	// message type
170	*buffer++ = 1;
171
172	// length
173	*buffer++ = data->cursize & 0xff;
174	*buffer++ = data->cursize >> 8;
175
176	// align
177	buffer++;
178
179	// message
180	Q_memcpy(buffer, data->data, data->cursize);
181	*bufferLength = IntAlign(*bufferLength + data->cursize + 4);
182
183	sock->canSend = false;
184	return 1;
185}
186
187
188int Loop_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data)
189{
190	byte *buffer;
191	int  *bufferLength;
192
193	if (!sock->driverdata)
194		return -1;
195
196	bufferLength = &((qsocket_t *)sock->driverdata)->receiveMessageLength;
197
198	if ((*bufferLength + data->cursize + sizeof(byte) + sizeof(short)) > NET_MAXMESSAGE)
199		return 0;
200
201	buffer = ((qsocket_t *)sock->driverdata)->receiveMessage + *bufferLength;
202
203	// message type
204	*buffer++ = 2;
205
206	// length
207	*buffer++ = data->cursize & 0xff;
208	*buffer++ = data->cursize >> 8;
209
210	// align
211	buffer++;
212
213	// message
214	Q_memcpy(buffer, data->data, data->cursize);
215	*bufferLength = IntAlign(*bufferLength + data->cursize + 4);
216	return 1;
217}
218
219
220qboolean Loop_CanSendMessage (qsocket_t *sock)
221{
222	if (!sock->driverdata)
223		return false;
224	return sock->canSend;
225}
226
227
228qboolean Loop_CanSendUnreliableMessage (qsocket_t *sock)
229{
230	return true;
231}
232
233
234void Loop_Close (qsocket_t *sock)
235{
236	if (sock->driverdata)
237		((qsocket_t *)sock->driverdata)->driverdata = NULL;
238	sock->receiveMessageLength = 0;
239	sock->sendMessageLength = 0;
240	sock->canSend = true;
241	if (sock == loop_client)
242		loop_client = NULL;
243	else
244		loop_server = NULL;
245}
246