1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, 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
25 qboolean localconnectpending = false;
26 qsocket_t *loop_client = NULL;
27 qsocket_t *loop_server = NULL;
28
Loop_Init(void)29 int Loop_Init (void)
30 {
31 if (cls.state == ca_dedicated)
32 return -1;
33 return 0;
34 }
35
36
Loop_Shutdown(void)37 void Loop_Shutdown (void)
38 {
39 }
40
41
Loop_Listen(qboolean state)42 void Loop_Listen (qboolean state)
43 {
44 }
45
46
Loop_SearchForHosts(qboolean xmit)47 void 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
Loop_Connect(const char * host)65 qsocket_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
Loop_CheckNewConnections(void)105 qsocket_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
IntAlign(int value)121 static int IntAlign(int value)
122 {
123 return (value + (sizeof(int) - 1)) & (~(sizeof(int) - 1));
124 }
125
126
Loop_GetMessage(qsocket_t * sock)127 int 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
Loop_SendMessage(qsocket_t * sock,sizebuf_t * data)154 int 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
Loop_SendUnreliableMessage(qsocket_t * sock,sizebuf_t * data)188 int 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
Loop_CanSendMessage(qsocket_t * sock)220 qboolean Loop_CanSendMessage (qsocket_t *sock)
221 {
222 if (!sock->driverdata)
223 return false;
224 return sock->canSend;
225 }
226
227
Loop_CanSendUnreliableMessage(qsocket_t * sock)228 qboolean Loop_CanSendUnreliableMessage (qsocket_t *sock)
229 {
230 return true;
231 }
232
233
Loop_Close(qsocket_t * sock)234 void 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