⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.cpp

📁 PPP服务端实现例子
💻 CPP
字号:
//rDUN server version 0.1
////Copyright (C) Robert Merrison 2002-03 
//
////This program 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.
////This program 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 this program; if not, write to the 
////Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

#include "main.h"

#define MAX_CLIENTS 4 
#define PROTOCOL_VERSION	1
#define STATE_IDLE			0
#define STATE_ASKAUTH			1
#define STATE_WAITAUTH			2
#define STATE_GOODPASS			3
#define STATE_BADPASS			4
#define STATE_CONNECTING		5
#define STATE_CONNECTED			6
#define STATE_DISCONNECTING		7
#define STATE_DISCONNECTED		8
#define STATE_USERDISCONNECTING		9
#define STATE_USERDISCONNECTED		10
#define STATE_WAITPROTOCOL		11
#define STATE_GOODPROTOCOL		12
#define STATE_BADPROTOCOL		13

struct client{
	int socket;
	int state;
	int ping_response_time;
	char recv_buffer[256];
};

int	listen_socket;
client clients[MAX_CLIENTS];

fd_set	listen_set;
fd_set	write_set;
fd_set	error_set;
fd_set  base_listen_set;
fd_set  base_write_set;
fd_set  base_error_set;
			
char	auth_code[128];
cfg_ptr	config;
time_engine	timer;
debug_engine	debug;
int	connection_state;
FILE*	wvdial_pipe;
bool	awaiting_ping;
void	closedown( int );
int	get_free_socket();
void	process_client_sets();
void	write_data( int client );
void	read_data( int client );
int	get_highest_descriptor();
void	process_recv_buffer( int client );
int	send_data( int client, char* buffer );
void	process_wvdial_pipe();
void	set_global_state( int state );

int main()
{
	signal( SIGHUP, closedown );	//Call closedown() on SIGHUP
	signal( SIGTERM, closedown );
	signal(SIGCHLD,SIG_IGN); /* ignore child */
	signal(SIGTSTP,SIG_IGN); /* ignore tty signals */
	signal(SIGTTOU,SIG_IGN);
	signal(SIGTTIN,SIG_IGN);
	

	if( !debug.init( DBLEVEL_HIGH, "debug2.log", &timer )){
		return 0;
	}
	config = cfgParse( "rDUNd.conf" );
	
	connection_state	= STATE_DISCONNECTED;
		//Set the connect password
	memset( auth_code, 0, sizeof( auth_code )); 
	strcpy( auth_code, cfgGetString( config, "MAIN", "PASSWORD", "" ));
	printf( "%s\n", auth_code );		
		//Clear out the client socket array
	for( int i = 0; i < MAX_CLIENTS; i++ ){
		clients[i].socket	= -1;
		memset( clients[i].recv_buffer, 0, sizeof( clients[i].recv_buffer ));
	}

		//Create the socket to listen on
	listen_socket	= socket( AF_INET, SOCK_STREAM, 0 );
	if( listen_socket == -1 ){
		debug.log_message( MSG_CRITICAL, "Error creating listen socket" );
		closedown( 0 );
	}
	
		//Set up address to bind listen socket to
	sockaddr_in	listen_addr;
	listen_addr.sin_family		= AF_INET;
	listen_addr.sin_port		= htons( cfgGetInt( config, "MAIN", "LISTEN_PORT", 2244 ));
	listen_addr.sin_addr.s_addr	= INADDR_ANY;
	memset( &( listen_addr.sin_zero ), '\0', 8 );

		//Bind the listen socket
	if( bind( listen_socket, ( sockaddr* )&listen_addr, sizeof( sockaddr )) == -1 ){
		debug.log_message( MSG_CRITICAL, "Error binding listen socket" );
		closedown( 0 );
	}
	linger lingerSettings;
	lingerSettings.l_onoff	= 1;
	lingerSettings.l_linger	= 0;
	setsockopt( listen_socket, SOL_SOCKET, SO_LINGER, &lingerSettings, sizeof( lingerSettings ));
	BOOL reuseAddrSetting = TRUE;
	setsockopt( listen_socket, SOL_SOCKET, SO_REUSEADDR, &reuseAddrSetting, sizeof( reuseAddrSetting ));
		//Start listening on the listen socket
	if( listen( listen_socket, 2 ) == -1 ){
		//Error message here
		closedown( 0 );
	}
		//Set up the listen set
	FD_ZERO( &listen_set );
	FD_SET( listen_socket, &listen_set );

		//Set up the write and error sets
	FD_ZERO( &write_set );
	FD_ZERO( &error_set );

	timeval	select_timeout;
	select_timeout.tv_sec	= 0;
	select_timeout.tv_usec	= 0;
	
	FD_ZERO( &base_listen_set );
	memcpy( &base_listen_set, &listen_set, sizeof( base_listen_set ));
	FD_ZERO( &base_write_set );
	memcpy( &base_write_set, &write_set, sizeof( base_write_set ));
	FD_ZERO( &base_error_set );
	memcpy( &base_error_set, &error_set, sizeof( base_error_set ));					
	if(fork()) exit(0);
	//Main program loop
	while( 1 ){
		memcpy( &listen_set, &base_listen_set, sizeof( base_listen_set ));
		memcpy( &write_set, &base_write_set, sizeof( base_write_set ));
		memcpy( &error_set, &base_error_set, sizeof( base_error_set ));

		select( get_highest_descriptor()+1, &listen_set, &write_set, &error_set, &select_timeout );
		if( FD_ISSET( listen_socket, &listen_set )){	//Check for a new connection waiting
			int	free_socket	= get_free_socket();
			if( free_socket == -1 ){	//If there are no free client sockets
				debug.log_message( MSG_STATUS, "Full, dropping new client" );
				int	temp_socket	= accept( listen_socket, NULL, NULL );
				send( temp_socket, "FULL\r\n", 4, 0 );
				close( temp_socket );
			}
			else{	//Otherwise, accept the new client
				clients[free_socket].socket	= accept( listen_socket, NULL, NULL );
				if( clients[free_socket].socket == -1 ){
					debug.log_message( MSG_ERROR,  "Error accepting new client in slot %d\n", free_socket );
				}
				clients[free_socket].state	= STATE_ASKAUTH;
				FD_SET( clients[free_socket].socket, &base_listen_set );
				FD_SET( clients[free_socket].socket, &base_write_set );
				FD_SET( clients[free_socket].socket, &base_error_set );
			        linger lingerSettings;
				lingerSettings.l_onoff  = 1;
				lingerSettings.l_linger = 0;
				setsockopt( clients[free_socket].socket, SOL_SOCKET, SO_LINGER, &lingerSettings, sizeof( lingerSettings ));
				BOOL reuseAddrSetting = TRUE;
				setsockopt( clients[free_socket].socket, SOL_SOCKET, SO_REUSEADDR, &reuseAddrSetting, sizeof( reuseAddrSetting ));
									
				debug.log_message( MSG_STATUS, "Accepted new client in slot %d", free_socket );
			}
		}
		process_client_sets();
		process_wvdial_pipe();
	}
	
	closedown( 0 );

	return 1;
}

void process_client_sets()
{
	for( int i=0; i<MAX_CLIENTS; i++ ){
		if( clients[i].socket == -1 ){
			continue;
		}

		if( FD_ISSET( clients[i].socket, &listen_set )){
			read_data( i );
		}
		//if( FD_ISSET( clients[i].socket, &write_set )){
			write_data( i );
		//}
		if( FD_ISSET( clients[i].socket, &error_set )){
			debug.log_message( MSG_STATUS, "Client %d in error set, dropping", i );
			shutdown( clients[i].socket, 2 );
			close( clients[i].socket );
			FD_CLR( clients[i].socket, &base_listen_set );
			FD_CLR( clients[i].socket, &base_write_set );
			FD_CLR( clients[i].socket, &base_error_set );
			memset( clients[i].recv_buffer, 0, sizeof( clients[i].recv_buffer ));
			clients[i].socket	= -1;
			return;
		}
	}
}

void process_wvdial_pipe()
{
	if( wvdial_pipe == NULL ){
		return;
	}
	
	char wvbuffer[256];
	memset( wvbuffer, 0, sizeof( wvbuffer ));
	if( fgets( wvbuffer, (int)sizeof( wvbuffer ), wvdial_pipe )){
		if( strstr( wvbuffer, "Disconnect" )){
			debug.log_message( MSG_STATUS, "WVdial disconnect" );
			fclose( wvdial_pipe );
			wvdial_pipe	= NULL;
			system( "killall wvdial" );
			if( connection_state == STATE_USERDISCONNECTING ){
				set_global_state( STATE_USERDISCONNECTED );
				connection_state = STATE_USERDISCONNECTED;
			}
			else{
				set_global_state( STATE_DISCONNECTED );
				connection_state = STATE_DISCONNECTED;
			}
	
			return;
		}
		if( strstr( wvbuffer, "Starting pppd" )){
			debug.log_message( MSG_STATUS, "WVdial connect" );
			set_global_state( STATE_CONNECTED );
			connection_state = STATE_CONNECTED;
			return;
		}
	}
	return;
}
void read_data( int client )
{
	char data;
	if( recv( clients[client].socket, &data, 1, 0 ) == 0 ){
		FD_SET( clients[client].socket, &error_set );
		debug.log_message( MSG_STATUS,  "Error on client %d, socket closed", client );
		return;
	}
	if( strlen( clients[client].recv_buffer )+1 >= sizeof( clients[client].recv_buffer )){
		debug.log_message( MSG_NOTICE, "Buffer overflow on client %d, dropping\n", client );
		FD_SET( clients[client].socket, &error_set );
		return;
	}
	if( data == '\r' ){
		return;
	}

	if( data == '\n' ){
	
		process_recv_buffer( client );
		memset( clients[client].recv_buffer, 0, sizeof( clients[client].recv_buffer ));

		return;
	}
	printf( "Added %c, ", data );
	clients[client].recv_buffer[ strlen( clients[client].recv_buffer )] = data;
	printf( "New buffer: %s\n", clients[client].recv_buffer );		
	return;	

}

void write_data( int client )
{
	if( clients[client].state == STATE_ASKAUTH ){
		send_data( client, "AUTH\r\n" );
		clients[client].state = STATE_WAITAUTH;
		return;
	}
 	if( clients[client].state == STATE_GOODPASS ){
		send_data( client, "OK\r\n" );
		clients[client].state	= STATE_WAITPROTOCOL;
		return;
	}
	if( clients[client].state == STATE_GOODPROTOCOL ){
		send_data( client, "GOODPROTOCOL\r\n" );
		clients[client].state	= connection_state;
		return;
	}
	if( clients[client].state == STATE_BADPROTOCOL ){
		send_data( client, "BADPROTOCOL\r\n" );
		clients[client].state	= STATE_WAITPROTOCOL;
		FD_SET( clients[client].socket, &error_set );
	}
	if( clients[client].state == STATE_BADPASS ){
		send_data( client, "BADPASS\r\n" );
		clients[client].state	= STATE_WAITAUTH;
		return;
	}
	if( clients[client].state == STATE_CONNECTING ){
		send_data( client, "CONNECTING\r\n");
		clients[client].state	= STATE_IDLE;
		return;
	}
	if( clients[client].state == STATE_CONNECTED ){
		send_data( client, "CONNECTED\r\n" );
		clients[client].state	= STATE_IDLE;
		return;
	}
	if( clients[client].state == STATE_DISCONNECTING ){
		send_data( client, "DISCONNECTING\r\n" );
		clients[client].state = STATE_IDLE;
		return;
	}
	if( clients[client].state == STATE_DISCONNECTED ){
		send_data( client, "DISCONNECTED\r\n" );
		clients[client].state = STATE_IDLE;
		return;
	}
	if( clients[client].state == STATE_USERDISCONNECTING ){
		send_data( client, "USERDISCONNECTING\r\n" );
		clients[client].state = STATE_IDLE;
		return;
	}
	if( clients[client].state == STATE_USERDISCONNECTED ){
		send_data( client, "USERDISCONNECTED\r\n" );
		clients[client].state = STATE_IDLE;
		return;
	}

	return;
}

void process_recv_buffer( int client )
{
	printf( "Processing: %s on client %d\n", clients[client].recv_buffer, client );
	if( clients[client].state == STATE_WAITAUTH ){
		if( strcmp( clients[client].recv_buffer, auth_code ) == 0 ){
			clients[client].state	= STATE_GOODPASS;
			return;
		}
		else{
			clients[client].state	= STATE_BADPASS;
			return;
		}
	}
	if( clients[client].state == STATE_WAITPROTOCOL ){
		if( strncasecmp( clients[client].recv_buffer, "PROTOCOL", 8 ) != 0 ){

			return;
		}
		int proto_version	= 0;
		sscanf( clients[client].recv_buffer, "PROTOCOL %d", &proto_version );
		printf( "Protocol: %d\n", proto_version );
		if( proto_version < PROTOCOL_VERSION ){
			clients[client].state = STATE_BADPROTOCOL;
			return;
		}
		clients[client].state = STATE_GOODPROTOCOL;
		return;
	}
	if( strcasecmp( clients[client].recv_buffer, "CONNECT" ) == 0 ){
		if( connection_state == STATE_CONNECTED ){
			return;
		}
		
		if( wvdial_pipe ){
			fclose( wvdial_pipe );
		}
		system( "rm -f wv_out" );
		system( "touch wv_out" );
		wvdial_pipe	= fopen( "wv_out", "r" );
		system( "./start_wvdial" );
		debug.log_message( MSG_STATUS, "Connecting" );
		connection_state	= STATE_CONNECTING;
		set_global_state( STATE_CONNECTING );
		return;
	}
	if( strcasecmp( clients[client].recv_buffer, "DISCONNECT" ) == 0 ){
		debug.log_message( MSG_STATUS, "Disconnecting" );
		system( "killall wvdial" );
		connection_state	= STATE_USERDISCONNECTING;
		set_global_state( STATE_USERDISCONNECTING );		
		return;
	}

	return;
}

int send_data( int client, char* data )
{
	int ret = send( clients[client].socket, data, strlen( data ), 0 );
	debug.log_message( MSG_STATUS, "Sending %s to client %d", data, client );
	return ret;
}

void set_global_state( int state )
{
	for( int i=0; i<MAX_CLIENTS; i++ ){
		clients[i].state	= state;
	}
	return;
}

void closedown( int )
{
	debug.log_message( MSG_STATUS, "Beginning closedown" );
	close( listen_socket );
	for( int i=0; i < MAX_CLIENTS; i++ ){
		if( clients[i].socket != -1 ){
			debug.log_message( MSG_STATUS, "Killing client %d", i );
			close( clients[i].socket );
		}
	}

	exit( 1 );
}

int get_free_socket()
{
	for( int i=0; i < MAX_CLIENTS; i++ ){
		if( clients[i].socket == -1 ){
			return i;
		}
	}

	return -1;
}

int get_highest_descriptor()
{
	int highest	= listen_socket;
	for( int i=0; i < MAX_CLIENTS; i++ ){
		if( clients[i].socket > highest ){
			highest	= clients[i].socket;
		}
	}

	return highest;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -