582 lines
18 KiB
C
582 lines
18 KiB
C
|
/*
|
||
|
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
|
||
|
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||
|
|
||
|
This file is part of GtkRadiant.
|
||
|
|
||
|
GtkRadiant is free software; you can redistribute it and/or modify
|
||
|
it under the terms of the GNU General Public License as published by
|
||
|
the Free Software Foundation; either version 2 of the License, or
|
||
|
(at your option) any later version.
|
||
|
|
||
|
GtkRadiant is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
GNU General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License
|
||
|
along with GtkRadiant; if not, write to the Free Software
|
||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||
|
*/
|
||
|
|
||
|
//====================================================================
|
||
|
//
|
||
|
// Name: l_net.c
|
||
|
// Function: -
|
||
|
// Programmer: MrElusive
|
||
|
// Last update: -
|
||
|
// Tab size: 3
|
||
|
// Notes:
|
||
|
//====================================================================
|
||
|
|
||
|
#include "globaldefs.h"
|
||
|
#include <stdio.h>
|
||
|
#include <stdarg.h>
|
||
|
#include <string.h>
|
||
|
#include <stdlib.h>
|
||
|
#include "l_net.h"
|
||
|
#include "l_net_wins.h"
|
||
|
|
||
|
#if GDEF_DEBUG
|
||
|
void WinPrint( const char *str, ... ){
|
||
|
va_list argptr;
|
||
|
char text[4096];
|
||
|
|
||
|
va_start( argptr,str );
|
||
|
vsprintf( text, str, argptr );
|
||
|
va_end( argptr );
|
||
|
|
||
|
printf( "%s", text );
|
||
|
}
|
||
|
#else
|
||
|
void WinPrint( const 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 ){
|
||
|
#if GDEF_OS_WINDOWS
|
||
|
return _stricmp( addr1->ip, addr2->ip );
|
||
|
#else
|
||
|
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
|
||
|
#if GDEF_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 *) malloc( 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 ){
|
||
|
free( 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( const 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
|
||
|
memcpy( &msg->data[msg->size], string, strlen( string ) + 1 );
|
||
|
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->read + 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 ( (size_t) l < sizeof( string ) - 1 );
|
||
|
string[l] = 0;
|
||
|
return string;
|
||
|
} //end of the function NMSG_ReadString
|