/* This code is based on source provided under the terms of the Id Software LIMITED USE SOFTWARE LICENSE AGREEMENT, a copy of which is included with the GtkRadiant sources (see LICENSE_ID). If you did not receive a copy of LICENSE_ID, please contact Id Software immediately at info@idsoftware.com. All changes and additions to the original source which have been developed by other contributors (see CONTRIBUTORS) are provided under the terms of the license the contributors choose (see LICENSE), to the extent permitted by the LICENSE_ID. If you did not receive a copy of the contributor license, please contact the GtkRadiant maintainers at info@gtkradiant.com immediately. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ //==================================================================== // // Name: l_net.c // Function: - // Programmer: MrElusive // Last update: - // Tab size: 3 // Notes: //==================================================================== #include #include #include #include #include "l_net.h" #include "l_net_wins.h" #define GetMemory malloc #define FreeMemory free #define qtrue 1 #define qfalse 0 #ifdef _DEBUG void WinPrint(char *str, ...) { va_list argptr; char text[4096]; va_start (argptr,str); vsprintf (text, str, argptr); va_end (argptr); printf(text); } #else void WinPrint(char *str, ...) { } #endif //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void Net_SetAddressPort(address_t *address, int port) { sockaddr_t addr; WINS_StringToAddr(address->ip, &addr); WINS_SetSocketPort(&addr, port); strcpy(address->ip, WINS_AddrToString(&addr)); } //end of the function Net_SetAddressPort //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== int Net_AddressCompare(address_t *addr1, address_t *addr2) { #ifdef WIN32 return stricmp(addr1->ip, addr2->ip); #endif #ifdef __linux__ return strcasecmp(addr1->ip, addr2->ip); #endif } //end of the function Net_AddressCompare //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void Net_SocketToAddress(socket_t *sock, address_t *address) { strcpy(address->ip, WINS_AddrToString(&sock->addr)); } //end of the function Net_SocketToAddress //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== int Net_Send(socket_t *sock, netmessage_t *msg) { int size; size = msg->size; msg->size = 0; NMSG_WriteLong(msg, size-4); msg->size = size; //WinPrint("Net_Send: message of size %d\n", sendmsg.size); return WINS_Write(sock->socket, msg->data, msg->size, NULL); } //end of the function Net_SendSocketReliable //=========================================================================== // returns the number of bytes recieved // -1 on error // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== int Net_Receive(socket_t *sock, netmessage_t *msg) { int curread; if (sock->remaining > 0) { curread = WINS_Read(sock->socket, &sock->msg.data[sock->msg.size], sock->remaining, NULL); if (curread == -1) { WinPrint("Net_Receive: read error\n"); return -1; } //end if sock->remaining -= curread; sock->msg.size += curread; if (sock->remaining <= 0) { sock->remaining = 0; memcpy(msg, &sock->msg, sizeof(netmessage_t)); sock->msg.size = 0; return msg->size - 4; } //end if return 0; } //end if sock->msg.size = WINS_Read(sock->socket, sock->msg.data, 4, NULL); if (sock->msg.size == 0) return 0; if (sock->msg.size == -1) { WinPrint("Net_Receive: size header read error\n"); return -1; } //end if //WinPrint("Net_Receive: message size header %d\n", msg->size); sock->msg.read = 0; sock->remaining = NMSG_ReadLong(&sock->msg); if (sock->remaining == 0) return 0; if (sock->remaining < 0 || sock->remaining > MAX_NETMESSAGE) { WinPrint("Net_Receive: invalid message size %d\n", sock->remaining); return -1; } //end if //try to read the message curread = WINS_Read(sock->socket, &sock->msg.data[sock->msg.size], sock->remaining, NULL); if (curread == -1) { WinPrint("Net_Receive: read error\n"); return -1; } //end if sock->remaining -= curread; sock->msg.size += curread; if (sock->remaining <= 0) { sock->remaining = 0; memcpy(msg, &sock->msg, sizeof(netmessage_t)); sock->msg.size = 0; return msg->size - 4; } //end if //the message has not been completely read yet #ifdef _DEBUG printf("++timo TODO: debug the Net_Receive on big size messages\n"); #endif return 0; } //end of the function Net_Receive //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== socket_t *Net_AllocSocket(void) { socket_t *sock; sock = (socket_t *) GetMemory(sizeof(socket_t)); memset(sock, 0, sizeof(socket_t)); return sock; } //end of the function Net_AllocSocket //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void Net_FreeSocket(socket_t *sock) { FreeMemory(sock); } //end of the function Net_FreeSocket //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== socket_t *Net_Connect(address_t *address, int port) { int newsock; socket_t *sock; sockaddr_t sendaddr; // see if we can resolve the host name WINS_StringToAddr(address->ip, &sendaddr); newsock = WINS_OpenReliableSocket(port); if (newsock == -1) return NULL; sock = Net_AllocSocket(); if (sock == NULL) { WINS_CloseSocket(newsock); return NULL; } //end if sock->socket = newsock; //connect to the host if (WINS_Connect(newsock, &sendaddr) == -1) { Net_FreeSocket(sock); WINS_CloseSocket(newsock); WinPrint("Net_Connect: error connecting\n"); return NULL; } //end if memcpy(&sock->addr, &sendaddr, sizeof(sockaddr_t)); //now we can send messages // return sock; } //end of the function Net_Connect //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== socket_t *Net_ListenSocket(int port) { int newsock; socket_t *sock; newsock = WINS_OpenReliableSocket(port); if (newsock == -1) return NULL; if (WINS_Listen(newsock) == -1) { WINS_CloseSocket(newsock); return NULL; } //end if sock = Net_AllocSocket(); if (sock == NULL) { WINS_CloseSocket(newsock); return NULL; } //end if sock->socket = newsock; WINS_GetSocketAddr(newsock, &sock->addr); WinPrint("listen socket opened at %s\n", WINS_AddrToString(&sock->addr)); // return sock; } //end of the function Net_ListenSocket //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== socket_t *Net_Accept(socket_t *sock) { int newsocket; sockaddr_t sendaddr; socket_t *newsock; newsocket = WINS_Accept(sock->socket, &sendaddr); if (newsocket == -1) return NULL; newsock = Net_AllocSocket(); if (newsock == NULL) { WINS_CloseSocket(newsocket); return NULL; } //end if newsock->socket = newsocket; memcpy(&newsock->addr, &sendaddr, sizeof(sockaddr_t)); // return newsock; } //end of the function Net_Accept //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void Net_Disconnect(socket_t *sock) { WINS_CloseSocket(sock->socket); Net_FreeSocket(sock); } //end of the function Net_Disconnect //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void Net_StringToAddress(char *string, address_t *address) { strcpy(address->ip, string); } //end of the function Net_StringToAddress //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void Net_MyAddress(address_t *address) { strcpy(address->ip, WINS_MyAddress()); } //end of the function Net_MyAddress //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== int Net_Setup(void) { WINS_Init(); // WinPrint("my address is %s\n", WINS_MyAddress()); // return qtrue; } //end of the function Net_Setup //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void Net_Shutdown(void) { WINS_Shutdown(); } //end of the function Net_Shutdown //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void NMSG_Clear(netmessage_t *msg) { msg->size = 4; } //end of the function NMSG_Clear //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void NMSG_WriteChar (netmessage_t *msg, int c) { if (c < -128 || c > 127) WinPrint("NMSG_WriteChar: range error\n"); if (msg->size >= MAX_NETMESSAGE) { WinPrint("NMSG_WriteChar: overflow\n"); return; } //end if msg->data[msg->size] = c; msg->size++; } //end of the function NMSG_WriteChar //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void NMSG_WriteByte(netmessage_t *msg, int c) { if (c < -128 || c > 127) WinPrint("NMSG_WriteByte: range error\n"); if (msg->size + 1 >= MAX_NETMESSAGE) { WinPrint("NMSG_WriteByte: overflow\n"); return; } //end if msg->data[msg->size] = c; msg->size++; } //end of the function NMSG_WriteByte //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void NMSG_WriteShort(netmessage_t *msg, int c) { if (c < ((short)0x8000) || c > (short)0x7fff) WinPrint("NMSG_WriteShort: range error"); if (msg->size + 2 >= MAX_NETMESSAGE) { WinPrint("NMSG_WriteShort: overflow\n"); return; } //end if msg->data[msg->size] = c&0xff; msg->data[msg->size+1] = c>>8; msg->size += 2; } //end of the function NMSG_WriteShort //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void NMSG_WriteLong(netmessage_t *msg, int c) { if (msg->size + 4 >= MAX_NETMESSAGE) { WinPrint("NMSG_WriteLong: overflow\n"); return; } //end if msg->data[msg->size] = c&0xff; msg->data[msg->size+1] = (c>>8)&0xff; msg->data[msg->size+2] = (c>>16)&0xff; msg->data[msg->size+3] = c>>24; msg->size += 4; } //end of the function NMSG_WriteLong //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void NMSG_WriteFloat(netmessage_t *msg, float c) { if (msg->size + 4 >= MAX_NETMESSAGE) { WinPrint("NMSG_WriteLong: overflow\n"); return; } //end if msg->data[msg->size] = *((int *)&c)&0xff; msg->data[msg->size+1] = (*((int *)&c)>>8)&0xff; msg->data[msg->size+2] = (*((int *)&c)>>16)&0xff; msg->data[msg->size+3] = *((int *)&c)>>24; msg->size += 4; } //end of the function NMSG_WriteFloat //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void NMSG_WriteString(netmessage_t *msg, char *string) { if (msg->size + strlen(string) + 1 >= MAX_NETMESSAGE) { WinPrint("NMSG_WriteString: overflow\n"); return; } //end if strcpy(&msg->data[msg->size], string); msg->size += strlen(string) + 1; } //end of the function NMSG_WriteString //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void NMSG_ReadStart(netmessage_t *msg) { msg->readoverflow = qfalse; msg->read = 4; } //end of the function NMSG_ReadStart //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== int NMSG_ReadChar(netmessage_t *msg) { if (msg->size + 1 > msg->size) { msg->readoverflow = qtrue; WinPrint("NMSG_ReadChar: read overflow\n"); return 0; } //end if msg->read++; return msg->data[msg->read-1]; } //end of the function NMSG_ReadChar //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== int NMSG_ReadByte(netmessage_t *msg) { if (msg->read + 1 > msg->size) { msg->readoverflow = qtrue; WinPrint("NMSG_ReadByte: read overflow\n"); return 0; } //end if msg->read++; return msg->data[msg->read-1]; } //end of the function NMSG_ReadByte //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== int NMSG_ReadShort(netmessage_t *msg) { int c; if (msg->read + 2 > msg->size) { msg->readoverflow = qtrue; WinPrint("NMSG_ReadShort: read overflow\n"); return 0; } //end if c = (short)(msg->data[msg->read] + (msg->data[msg->read+1]<<8)); msg->read += 2; return c; } //end of the function NMSG_ReadShort //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== int NMSG_ReadLong(netmessage_t *msg) { int c; if (msg->read + 4 > msg->size) { msg->readoverflow = qtrue; WinPrint("NMSG_ReadLong: read overflow\n"); return 0; } //end if c = msg->data[msg->read] + (msg->data[msg->read+1]<<8) + (msg->data[msg->read+2]<<16) + (msg->data[msg->read+3]<<24); msg->read += 4; return c; } //end of the function NMSG_ReadLong //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== float NMSG_ReadFloat(netmessage_t *msg) { int c; if (msg->read + 4 > msg->size) { msg->readoverflow = qtrue; WinPrint("NMSG_ReadLong: read overflow\n"); return 0; } //end if c = msg->data[msg->read] + (msg->data[msg->read+1]<<8) + (msg->data[msg->read+2]<<16) + (msg->data[msg->read+3]<<24); msg->read += 4; return *(float *)&c; } //end of the function NMSG_ReadFloat //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== char *NMSG_ReadString(netmessage_t *msg) { static char string[2048]; int l, c; l = 0; do { if (msg->read + 1 > msg->size) { msg->readoverflow = qtrue; WinPrint("NMSG_ReadString: read overflow\n"); string[l] = 0; return string; } //end if c = msg->data[msg->read]; msg->read++; if (c == 0) break; string[l] = c; l++; } while (l < sizeof(string)-1); string[l] = 0; return string; } //end of the function NMSG_ReadString