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 29 int Loop_Init (void) 30 { 31 if (cls.state == ca_dedicated) 32 return -1; 33 return 0; 34 } 35 36 37 void Loop_Shutdown (void) 38 { 39 } 40 41 42 void Loop_Listen (qboolean state) 43 { 44 } 45 46 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 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 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 121 static int IntAlign(int value) 122 { 123 return (value + (sizeof(int) - 1)) & (~(sizeof(int) - 1)); 124 } 125 126 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 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 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 220 qboolean Loop_CanSendMessage (qsocket_t *sock) 221 { 222 if (!sock->driverdata) 223 return false; 224 return sock->canSend; 225 } 226 227 228 qboolean Loop_CanSendUnreliableMessage (qsocket_t *sock) 229 { 230 return true; 231 } 232 233 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