/* ===================== CL_Rcon_f Send the rest of the command line over as an unconnected command. ===================== */ void CL_Rcon_f (void) { char message[1024]; int i; netadr_t to; if (!rcon_client_password->string) { Com_Printf ("You must set 'rcon_password' before\n" "issuing an rcon command.\n"); return; } message[0] = (char)255; message[1] = (char)255; message[2] = (char)255; message[3] = (char)255; message[4] = 0; NET_Config (true); // allow remote strcat (message, "rcon "); strcat (message, rcon_client_password->string); strcat (message, " "); for (i=1 ; i<Cmd_Argc() ; i++) { strcat (message, Cmd_Argv(i)); strcat (message, " "); } if (cls.state >= ca_connected) to = cls.netchan.remote_address; else { if (!strlen(rcon_address->string)) { Com_Printf ("You must either be connected,\n" "or set the 'rcon_address' cvar\n" "to issue rcon commands\n"); return; } NET_StringToAdr (rcon_address->string, &to); if (to.port == 0) to.port = BigShort (PORT_SERVER); } NET_SendPacket (NS_CLIENT, strlen(message)+1, message, to); }
/* ================ CL_Connect_f MAUTH version -- kick off an authentication sequence as first part of connection routine. ================ */ void CL_Connect_f (void) { char *server; char *masterserver; char data[2048]; if (Cmd_Argc() != 3) { Com_Printf ("usage: connect <master> <server>\n"); return; } Host_EndGame (); server = Cmd_Argv (1); strlcpy (cls.servername, server, sizeof(cls.servername)); // Have to check for valid server address here as we must send to master... if (!NET_StringToAdr (cls.servername, &cls.server_adr)) { Com_Printf ("Bad server address\n"); return; } if (cls.server_adr.port == 0) cls.server_adr.port = BigShort (PORT_SERVER); masterserver = Cmd_Argv (2); strlcpy (cls.masterservername, masterserver, sizeof(cls.masterservername)); // Start off auth sequence before trying to connect... if (!NET_StringToAdr (cls.masterservername, &cls.masterserver_adr)) { Com_Printf ("Bad master server address\n"); return; } if (cls.masterserver_adr.port == 0) cls.masterserver_adr.port = BigShort (27000); // master port Com_Printf ("Attempting to auth with %s...\n", cls.masterservername); sprintf (data, "%c\n%s\n%s:%d\n", C2M_AUTH_INIT, Cvar_String("name"), cls.servername, cls.server_adr.port); NET_SendPacket (NS_CLIENT, strlen(data), data, cls.masterserver_adr); // Normal connection procedure... // FIXME wait? // FIXME use some qbools to work out if we get a NACK to stop trying to connect -- ie preserve state CL_BeginServerConnect(); }
/* =============== Netchan_Transmit Sends a message to a connection, fragmenting if necessary A 0 length will still generate a packet. ================ */ void Netchan_Transmit( netchan_t *chan, int length, const byte *data ) { msg_t send; byte send_buf[ MAX_PACKETLEN ]; if ( length > MAX_MSGLEN ) { Com_Error( ERR_DROP, "Netchan_Transmit: length = %i", length ); } chan->unsentFragmentStart = 0; // fragment large reliable messages if ( length >= FRAGMENT_SIZE ) { chan->unsentFragments = qtrue; chan->unsentLength = length; Com_Memcpy( chan->unsentBuffer, data, length ); // only send the first fragment now Netchan_TransmitNextFragment( chan ); return; } // write the packet header MSG_InitOOB( &send, send_buf, sizeof( send_buf ) ); MSG_WriteLong( &send, chan->outgoingSequence ); chan->outgoingSequence++; // send the qport if we are a client if ( chan->sock == NS_CLIENT ) { MSG_WriteShort( &send, qport->integer ); } MSG_WriteData( &send, data, length ); // send the datagram NET_SendPacket( chan->sock, send.cursize, send.data, chan->remoteAddress ); if ( showpackets->integer ) { Com_Printf( "%s send %4i : s=%i ack=%i\n" , netsrcString[ chan->sock ] , send.cursize , chan->outgoingSequence - 1 , chan->incomingSequence ); } }
static void CL_SendConnectPacket_QW(peer_t *p) { char data[2048]; char biguserinfo[MAX_INFO_STRING + 32]; if (p->ps != ps_challenge) return; // Let the server know what extensions we support. strlcpy (biguserinfo, p->userinfo, sizeof (biguserinfo)); snprintf(data, sizeof(data), "\xff\xff\xff\xff" "connect %i %i %i \"%s\"\n", QW_PROTOCOL_VERSION, p->qport, p->challenge, biguserinfo); NET_SendPacket(net_from_socket, strlen(data), data, &net_from); }
/* =============== NET_OutOfBandPrint Sends a text message in an out-of-band datagram ================ */ void QDECL PRINTF_LIKE(3) NET_OutOfBandPrint( netsrc_t sock, netadr_t adr, const char *format, ... ) { va_list argptr; char string[ MAX_MSGLEN ]; NET_SetOOBHeader( string ); va_start( argptr, format ); Q_vsnprintf( string + 4, sizeof( string ) - 4, format, argptr ); va_end( argptr ); // send the datagram NET_SendPacket( sock, strlen( string ), string, adr ); }
void NET_SV_SendQueryResponse(net_addr_t *addr) { net_packet_t *reply; net_querydata_t querydata; int p; // Version querydata.version = PACKAGE_STRING; // Server state querydata.server_state = server_state; // Number of players/maximum players querydata.num_players = NET_SV_NumPlayers(); querydata.max_players = NET_SV_MaxPlayers(); // Game mode/mission querydata.gamemode = sv_gamemode; querydata.gamemission = sv_gamemission; //! // @category net // @arg <name> // // When starting a network server, specify a name for the server. // p = M_CheckParmWithArgs("-servername", 1); if (p > 0) { querydata.description = myargv[p + 1]; } else { querydata.description = "Unnamed server"; } // Send it and we're done. NET_Log("server: sending query response to %s", NET_AddrToString(addr)); reply = NET_NewPacket(64); NET_WriteInt16(reply, NET_PACKET_TYPE_QUERY_RESPONSE); NET_WriteQueryData(reply, &querydata); NET_SendPacket(addr, reply); NET_FreePacket(reply); }
/* =============== Netchan_OutOfBand Sends an out-of-band datagram ================ */ void Netchan_OutOfBand (int net_socket, netadr_t adr, int length, byte *data) { sizebuf_t send; byte send_buf[MAX_MSGLEN]; // write the packet header SZ_Init (&send, send_buf, sizeof(send_buf)); MSG_WriteLong (&send, -1); // -1 sequence means out of band SZ_Write (&send, data, length); // send the datagram NET_SendPacket (net_socket, send.cursize, send.data, adr); }
void Host_GetBatchModList_f() { //Odd... master_server_t * ptr; NET_Config(1); if(gfNoMasterServer != 0 || masterlist == NULL) { return; } for(ptr = masterlist; ptr != NULL; ptr = ptr->next) { Con_Printf("Requesting batch mod status from %s", NET_AdrToString(ptr->address)); NET_SendPacket(NS_CLIENT, sizeof("x\r\nstart-of-list\r\n"), "x\r\nstart-of-list\r\n", ptr->address); } }
/* CL_SendConnectPacket called by CL_Connect_f and CL_CheckResend */ void CL_SendConnectPacket (void) { netadr_t adr; char data[2048]; double t1, t2; // JACK: Fixed bug where DNS lookups would cause two connects real fast // Now, adds lookup time to the connect time. // Should I add it to realtime instead?!?! if (cls.state != ca_disconnected) return; t1 = Sys_DoubleTime (); if (!NET_StringToAdr (cls.servername, &adr)) { Con_Printf ("Bad server address\n"); connect_time = -1; return; } if (!NET_IsClientLegal (&adr)) { Con_Printf ("Illegal server address\n"); connect_time = -1; return; } if (adr.port == 0) adr.port = BigShort (27500); t2 = Sys_DoubleTime (); connect_time = realtime + t2 - t1; // for retransmit requests cls.qport = Cvar_VariableValue ("qport"); // Arrgh, this was not in the old binary only release, and eats up // far too much of the 196 chars in the userinfo space, leaving nothing // for player use, thus, its commented out for the moment.. // // Info_SetValueForStarKey (cls.userinfo, "*ip", NET_AdrToString(adr), // MAX_INFO_STRING); // Con_Printf ("Connecting to %s...\n", cls.servername); snprintf (data, sizeof (data), "%c%c%c%cconnect %i %i %i \"%s\"\n", 255, 255, 255, 255, PROTOCOL_VERSION, cls.qport, cls.challenge, cls.userinfo); NET_SendPacket (strlen (data), data, adr); }
/* ================= Netchan_TransmitNextFragment Send one fragment of the current message ================= */ qboolean Netchan_TransmitNextFragment( netchan_t *chan ) { msg_t send; qboolean sendsucc; byte send_buf[MAX_PACKETLEN]; int fragmentLength; qboolean var_01 = qfalse; // write the packet header MSG_Init( &send, send_buf, sizeof( send_buf ) ); // <-- only do the oob here MSG_WriteLong( &send, chan->outgoingSequence | FRAGMENT_BIT ); // send the qport if we are a client if ( chan->sock == NS_CLIENT ) { MSG_WriteShort( &send, qport->integer ); } // copy the reliable message to the packet first fragmentLength = FRAGMENT_SIZE; if ( chan->unsentFragmentStart + fragmentLength > chan->unsentLength ) { fragmentLength = chan->unsentLength - chan->unsentFragmentStart; var_01 = qtrue; } MSG_WriteLong(&send, chan->unsentFragmentStart); MSG_WriteShort( &send, fragmentLength ); MSG_WriteData( &send, chan->unsentBuffer + chan->unsentFragmentStart, fragmentLength ); // send the datagram sendsucc = NET_SendPacket( chan->sock, send.cursize, send.data, &chan->remoteAddress ); if ( showpackets->boolean ) { Com_Printf( "%s send %4i : s=%i fragment=%i,%i\n" , netsrcString[ chan->sock ] , send.cursize , chan->outgoingSequence , chan->unsentFragmentStart, fragmentLength ); } chan->unsentFragmentStart += fragmentLength; // this exit condition is a little tricky, because a packet // that is exactly the fragment length still needs to send // a second packet of zero length so that the other side // can tell there aren't more to follow if ( chan->unsentFragmentStart == chan->unsentLength && var_01 ) { chan->outgoingSequence++; chan->unsentFragments = qfalse; } return sendsucc; }
/* ================= SV_ConnectionlessPacket A connectionless packet has four leading 0xff characters to distinguish it from a game channel. Clients that are in the game can still send connectionless packets. ================= */ static void SV_ConnectionlessPacket (void) { const char *s; const char *c; MSG_BeginReading (); MSG_ReadLong (); // skip the -1 marker s = MSG_ReadStringLine (); Cmd_TokenizeString (s); c = Cmd_Argv(0); if (!strcmp(c, "ping") || ( c[0] == A2A_PING && (c[1] == 0 || c[1] == '\n')) ) { SVC_Ping (); return; } if (c[0] == A2A_ACK && (c[1] == 0 || c[1] == '\n') ) { Con_Printf ("A2A_ACK from %s\n", NET_AdrToString (net_from)); return; } else if (c[0] == A2S_ECHO) { NET_SendPacket (net_message.cursize, net_message.data, net_from); return; } else if (!strcmp(c,"status")) { SVC_Status (); return; } else if (!strcmp(c,"log")) { SVC_Log (); return; } else if (!strcmp(c,"connect")) { SVC_DirectConnect (); return; } else if (!strcmp(c, "rcon")) SVC_RemoteCommand (); else Con_Printf ("bad connectionless packet from %s:\n%s\n", NET_AdrToString (net_from), s); }
/* ================= CL_InternetServers_f ================= */ void CL_InternetServers_f( void ) { netadr_t adr; char fullquery[512] = "\x31\xFF" "0.0.0.0:0\0" "\\gamedir\\"; MsgDev( D_INFO, "Scanning for servers on the internet area...\n" ); NET_Config( true ); // allow remote if( !NET_StringToAdr( MASTERSERVER_ADR, &adr ) ) MsgDev( D_INFO, "Can't resolve adr: %s\n", MASTERSERVER_ADR ); Q_strcpy( &fullquery[21], GI->gamedir ); NET_SendPacket( NS_CLIENT, Q_strlen( GI->gamedir ) + 22, fullquery, adr ); }
/* ================ SVC_Log Responds with all the logged frags for ranking programs. If a sequence number is passed as a parameter and it is the same as the current sequence, an A2A_NACK will be returned instead of the data. ================ */ void SVC_Log (void) { int seq; char data[MAX_DATAGRAM+64]; if (Cmd_Argc() == 2) seq = atoi(Cmd_Argv(1)); else seq = -1; if (seq == svs.logsequence-1 || !sv_fraglogfile) { // they already have this data, or we aren't logging frags data[0] = A2A_NACK; NET_SendPacket (NS_SERVER, 1, data, net_from); return; } Com_DPrintf ("sending log %i to %s\n", svs.logsequence-1, NET_AdrToString(net_from)); sprintf (data, "stdlog %i\n", svs.logsequence-1); strcat (data, (char *)svs.log_buf[((svs.logsequence-1)&1)]); NET_SendPacket (NS_SERVER, strlen(data)+1, data, net_from); }
/* ================= Master_Shutdown Informs all masters that this server is going down ================= */ void Master_Shutdown (void) { char string[2048]; int i; sprintf (string, "%c\n", S2M_SHUTDOWN); // send to group master for (i=0 ; i<MAX_MASTERS ; i++) if (master_adr[i].port) { Com_Printf ("Sending heartbeat to %s\n", NET_AdrToString (master_adr[i])); NET_SendPacket (NS_SERVER, strlen(string), string, master_adr[i]); } }
/* * Netchan_OutOfBand * * Sends an out-of-band datagram */ void Netchan_OutOfBand( const socket_t *socket, const netadr_t *address, size_t length, const uint8_t *data ) { msg_t send; uint8_t send_buf[MAX_PACKETLEN]; // write the packet header MSG_Init( &send, send_buf, sizeof( send_buf ) ); MSG_WriteLong( &send, -1 ); // -1 sequence means out of band MSG_WriteData( &send, data, length ); // send the datagram if( !NET_SendPacket( socket, send.data, send.cursize, address ) ) Com_Printf( "NET_SendPacket: Error: %s\n", NET_ErrorString() ); }
/* ===================== CL_Rcon_f Send the rest of the command line over as an unconnected command. ===================== */ void CL_Rcon_f (void) { char message[1024]; int i; netadr_t to; if (!rcon_password.string) { Con_Printf ("You must set 'rcon_password' before\n" "issuing an rcon command.\n"); return; } message[0] = 255; message[1] = 255; message[2] = 255; message[3] = 255; message[4] = 0; strcat (message, "rcon "); strcat (message, rcon_password.string); strcat (message, " "); for (i=1 ; i<Cmd_Argc() ; i++) { strcat (message, Cmd_Argv(i)); strcat (message, " "); } if (cls.state >= ca_connected) to = cls.netchan.remote_address; else { if (!strlen(rcon_address.string)) { Con_Printf ("You must either be connected,\n" "or set the 'rcon_address' cvar\n" "to issue rcon commands\n"); return; } NET_StringToAdr (rcon_address.string, &to); } NET_SendPacket (strlen(message)+1, message , to); }
void OutofBandPrintf(netadr_t where, char *fmt, ...) { va_list argptr; char send[1024]; send[0] = 0xff; send[1] = 0xff; send[2] = 0xff; send[3] = 0xff; send[4] = A2C_PRINT; va_start (argptr, fmt); vsprintf (send+5, fmt, argptr); va_end (argptr); NET_SendPacket (strlen(send)+1, send, where); }
/* ================= CL_InternetServers_f ================= */ void CL_InternetServers_f( void ) { netadr_t adr; char fullquery[512] = MS_SCAN_REQUEST; MsgDev( D_INFO, "Scanning for servers on the internet area...\n" ); NET_Config( true ); // allow remote if( !NET_StringToAdr( sv_master->string, &adr ) ) { MsgDev( D_INFO, "Can't resolve adr: %s\n", sv_master->string ); return; } NET_SendPacket( NS_CLIENT, sizeof( MS_SCAN_REQUEST ) + Q_strcpy( fullquery + sizeof( MS_SCAN_REQUEST ) - 1, GI->gamedir ), fullquery, adr ); }
void SendAllTMPackets (void) { int i; if (packets.count > 0) DEBUGPRINT(GENERAL, HIGH) printf ("Thread: %d\t\tIn SendAllTMPackets ... packet : %d\n", omp_get_thread_num(), packets.count); for (i=0 ; i<packets.count ; i++) { NET_SendPacket(packets.lenght[i], packets.data[i], packets.to[i]); } // clear the state of the buffer packets.count = 0; }
static void QRY_SV_PingServers(void) { static int idx; static double last; double current = Sys_DoubleTime(); // we need double time for ping measurement server_t *sv; // do not ping servers since we do not query masters if (!masters_query->integer) return; if (!servers) return; // nothing to do if (current - last < QW_SERVER_RATE) return; // do not ping servers too fast last = current; idx = (int)max(0, idx); sv = QRY_SV_ByIndex(idx++); if (!sv) sv = QRY_SV_ByIndex(idx = 0); // can't find server by index, try with index 0 if (!sv) return; // hm, should not be the case... // check for dead server if (!sv->reply && sv->ping_sent_at - sv->ping_reply_at > QW_SERVER_DEAD_TIME) { Sys_DPrintf("dead -> %s:%d\n", inet_ntoa(sv->addr.sin_addr), (int)ntohs(sv->addr.sin_port)); QRY_SV_free(sv, true); // remove damn server, however master server may add it back... idx--; // step back index return; } if (sv->ping_sent_at && current - sv->ping_sent_at < QW_SERVER_MIN_PING_REQUEST_TIME) return; // do not spam server sv->ping_sent_at = current; // remember when we sent ping sv->reply = false; // reset reply flag NET_SendPacket(net_socket, sizeof(QW_SERVER_PING_QUERY)-1, QW_SERVER_PING_QUERY, &sv->addr); // Sys_Printf("ping(%3d) -> %s:%d\n", idx, inet_ntoa(sv->addr.sin_addr), (int)ntohs(sv->addr.sin_port)); }
/* =============== Netchan_OutOfBand Sends an out-of-band datagram ================ */ void Netchan_OutOfBand( int net_socket, netadr_t adr, int length, byte *data ) { sizebuf_t send; byte send_buf[NET_MAX_PAYLOAD]; // write the packet header BF_Init( &send, "SequencePacket", send_buf, sizeof( send_buf )); BF_WriteLong( &send, -1 ); // -1 sequence means out of band BF_WriteBytes( &send, data, length ); if( !CL_IsPlaybackDemo( )) { // send the datagram NET_SendPacket( net_socket, BF_GetNumBytesWritten( &send ), BF_GetData( &send ), adr ); } }
__cdecl void QDECL NET_OutOfBandPrint( netsrc_t sock, netadr_t *adr, const char *format, ... ) { va_list argptr; char string[MAX_MSGLEN]; // set the header string[0] = -1; string[1] = -1; string[2] = -1; string[3] = -1; va_start( argptr, format ); Q_vsnprintf( string+4, sizeof(string)-4, format, argptr ); va_end( argptr ); // send the datagram NET_SendPacket( sock, strlen( string ), string, adr ); }
/* ================= Master_Shutdown Informs all masters that this server is going down ================= */ static void Master_Shutdown (void) { char text[2048]; int i; sprintf (text, "%c\n", S2M_SHUTDOWN); // send to group master for (i = 0; i < MAX_MASTERS; i++) { if (master_adr[i].port) { Con_Printf ("Sending heartbeat to %s\n", NET_AdrToString (master_adr[i])); NET_SendPacket (strlen(text), text, master_adr[i]); } } }
void OnPacketTV() { if(NET_CompareAdr(net_from, net_server)) { buf_t out = net_message; // if this is a server connect message, keep a copy for other clients int t = net_message.ReadLong(); if(t == CHALLENGE) { std::cout << "first client connected" << std::endl; challenge_message = net_message; } else if(t == 0) { first_message = net_message; buf_t tmp; tr.Go(net_message, tmp); } else { out.clear(); out.WriteLong(t); tr.Go(net_message, out); } // replicate server packet to all connected clients for(int i = 0; i < spectators.size(); i++) { NET_SendPacket(out.cursize, out.data, spectators[i]); } } else { // is this an existing client? for(int i = 0; i < spectators.size(); i++) { if(NET_CompareAdr(net_from, spectators[i])) { OnClientTV(i); return; } } // must be a new client OnNewClientTV(); } }
static void NET_Query_SendQuery(net_addr_t *addr) { net_packet_t *request; request = NET_NewPacket(10); NET_WriteInt16(request, NET_PACKET_TYPE_QUERY); if (addr == NULL) { NET_SendBroadcast(query_context, request); } else { NET_SendPacket(addr, request); } NET_FreePacket(request); }
void Master_Heartbeat() { master_server_t * ptr; if(gfNoMasterServer != 0 || global_sv.active == 0 || global_svs.allocated_client_slots <= 1) { return; } Master_Init(); for(ptr = masterlist; ptr != NULL; ptr = ptr->next) { if(global_realtime - ptr->last_heartbeat < 0) { continue; } //Not enough time has passed since the last heartbeat if(ptr->HasRequested && global_realtime - ptr->TimeOfRequest < MasterHeartbeatTimeout) { continue; } //not enough time has passed to consider the last request lost. ptr->HasRequested = 1; ptr->last_heartbeat = ptr->TimeOfRequest = global_realtime; NET_SendPacket(NS_SERVER, sizeof("q\n"), "q\n", ptr->address); } }
__cdecl int PbSvSendToAddrPort(char* netdest, unsigned short port, int msgsize, char* message){ netadr_t netadr; mvabuf; NET_StringToAdr(va("%s:%i", netdest, port), &netadr, NA_UNSPEC); netadr.sock = 0; netadr_t *sockadr; if((sockadr = NET_GetDefaultCommunicationSocket()) != NULL) netadr.sock = sockadr->sock; NET_SendPacket(NS_SERVER, msgsize, message, &netadr); return 0; }
boolean NET_StartSecureDemo(prng_seed_t seed) { net_packet_t *request, *response; net_addr_t *master_addr; char *signature; boolean result; NET_Query_Init(); master_addr = NET_Query_ResolveMaster(query_context); // Send request packet to master server. request = NET_NewPacket(10); NET_WriteInt16(request, NET_MASTER_PACKET_TYPE_SIGN_START); NET_SendPacket(master_addr, request); NET_FreePacket(request); // Block for response and read contents. // The signed start message will be saved for later. response = BlockForPacket(master_addr, NET_MASTER_PACKET_TYPE_SIGN_START_RESPONSE, SIGNATURE_TIMEOUT_SECS * 1000); result = false; if (response != NULL) { if (NET_ReadPRNGSeed(response, seed)) { signature = NET_ReadString(response); if (signature != NULL) { securedemo_start_message = strdup(signature); result = true; } } NET_FreePacket(response); } return result; }
/* * SV_MasterHeartbeat * Send a message to the master every few minutes to * let it know we are alive, and log information */ void SV_MasterHeartbeat( void ) { unsigned int time = Sys_Milliseconds(); int i; if( svc.nextHeartbeat > time ) return; svc.nextHeartbeat = time + HEARTBEAT_SECONDS * 1000; if( !sv_public->integer || ( sv_maxclients->integer == 1 ) ) return; // never go public when not acting as a game server if( sv.state > ss_game ) return; // send to group master for( i = 0; i < MAX_MASTERS; i++ ) { sv_master_t *master = &sv_masters[i]; if( master->address.type != NA_NOTRANSMIT ) { socket_t *socket; if( dedicated && dedicated->integer ) Com_Printf( "Sending heartbeat to %s\n", NET_AddressToString( &master->address ) ); socket = ( master->address.type == NA_IP6 ? &svs.socket_udp6 : &svs.socket_udp ); if( master->steam ) { uint8_t steamHeartbeat = 'q'; NET_SendPacket( socket, &steamHeartbeat, sizeof( steamHeartbeat ), &master->address ); } else { // warning: "DarkPlaces" is a protocol name here, not a game name. Do not replace it. Netchan_OutOfBandPrint( socket, &master->address, "heartbeat DarkPlaces\n" ); } } } }
/* =============== SV_UpdateSharedConfig =============== */ void SV_UpdateSharedConfig( unsigned int port, const char *rconpass ) { char message[MAX_RCON_MESSAGE]; netadr_t to; message[0] = -1; message[1] = -1; message[2] = -1; message[3] = -1; message[4] = 0; Q_strcat (message, MAX_RCON_MESSAGE, "rcon "); Q_strcat (message, MAX_RCON_MESSAGE, rconpass); Q_strcat (message, MAX_RCON_MESSAGE, " !readconfig"); NET_StringToAdr ("127.0.0.1", &to, NA_UNSPEC); to.port = BigShort (port); NET_SendPacket (NS_SERVER, strlen(message)+1, message, to); }