All pastes #282083 Raw Edit

Stuff

public text v1 · immutable
#282083 ·published 2006-12-17 08:09 UTC
rendered paste body

/* WifiServer PC: Application to connect the Wifiloader Client in the NDS

	Copyright (C) 2006 
	    Hermes (Spain)

	This software is provided 'as-is', without any express or implied
	warranty.  In no event will the authors be held liable31/08/2006 for any
	damages arising from the use of this software.

	Permission is granted to anyone to use this software for any
	purpose, including commercial applications, and to alter it and
	redistribute it freely, subject to the following restrictions:

	1.	The origin of this software must not be misrepresented; you
		must not claim that you wrote the original software. If you use
		this software in a product, an acknowledgment in the product
		documentation would be appreciated but is not required.
	2.	Altered source versions must be plainly marked as such, and
		must not be misrepresented as being the original software.
	3.	This notice may not be removed or altered from any source
		distribution.

*/



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <errno.h>

//#include "winsock2.h"
//#include "windows.h"
//#include "commdlg.h"
//#define BIG_ENDIAN 1

#define CONECTION_CLOSED -2

#ifdef BIG_ENDIAN
unsigned int CPU_swap_u32(unsigned int value)
{
	unsigned int byte1, byte2, byte3, byte4, swapped;

	byte4 = (value >> 24) & 0xff;
	byte3 = (value >> 16) & 0xff;
	byte2 = (value >> 8)  & 0xff;
	byte1 =  value        & 0xff;

	swapped = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
	return( swapped );
}
#endif

int send_com(int sck,char *comando,int dat,int dat2)
{
	int i;

	char packet[16];

	memset(packet,0,16);
	strcpy(packet,comando);

#ifdef BIG_ENDIAN
	dat=CPU_swap_u32(dat);
	dat2=CPU_swap_u32(dat2);
#endif

	memcpy(packet+8, &dat,4);
	memcpy(packet+12, &dat2,4);

	if(send(sck, packet, 16, 0)!=16)
	{
		return -1;
	}
	
	return 0;
}

int get_com(int sck,char * comando,int *dat,int *dat2)
{
	int r;
	int i;
	
	char tmp[4];
	char tmp2[4];
	char packet[16];
	
	r=recv(sck, packet, 16, 0);
	
	if(r<=0)
	{	
		return -2;
	}
	if(r!=16)  
	{
   	return -1;
	}

	packet[7]=0;
	memcpy(comando,packet,8);
   memcpy(dat,packet+8,4);
	memcpy(dat2,packet+12,4);

#ifdef BIG_ENDIAN
	*dat =  CPU_swap_u32((unsigned int)*dat);
	*dat2 =  CPU_swap_u32((unsigned int)*dat2);
#endif
	
	return 0;
}

int get_data(int sck,char * datas,int len)
{
	int r;
	int b;
	b=0;

	while(len>0) 
	{
		r=recv(sck, datas+b, len, 0);
		if(r<=0) return -2; // conexion cerrada
		b+=r; len-=r;
	}

	return b;
}

int send_int(int sck, int data)
{
	int r;

#ifdef BIG_ENDIAN
	data = CPU_swap_u32(data);
#endif

	r = send_data(sck, (char *)&data, 4);
	return r;
}  

int send_data(int sck,char *datas,int len)
{
	int i;
	int r;
	int b;
	b=0;

	while(len>0) 
	{
		r=send(sck, datas+b, len, 0);
		if(r<=0) return -1; 
		b+=r; len-=r;
	}

	return b;
}


// rutina simple de checksum

int my_checksum(char *p,int size) 
{
	int n,m;
	m=0;

	for(n=0;n<size;n++)
	{
		m+=*p ^85;
		p++;
	}
	
	return m;
}




/***************************************************/
/* variables                                       */
/***************************************************/

//WSADATA wsaData;

int port=9999;


char comando[16]; // :-> comando entrante
int uno,dos; // :-> uno, recibe el numero de paquete (que luego hay que reenviar en la respuesta), dos, recibe normalmente la longitud de los datos
             // asociados a la respuestas (coger con pinzas esto, por que no tiene porque ser asi)

int datfseek[2]; // :-> aqui se reciben los datos para mover el puntero fseek

char filename[256]; //:-> aqui se recibe el nombre el fichero a abrir cuando la DS envia el comando 'OPENFIL'

unsigned char recvbuf[4096+8]; //:-> buffer de salida de datos del fichero

// IMPORTANTE: Tened en cuenta que los datos estan pensados para gestionar un unico cliente.




/********************************************************/
/* main()                                               */
/********************************************************/

int main(int argc, char *argv[]) 
{
	int n;
	int yes = 1;
	int filesize;

	int my_socket,my_socket2; // sockets for the connection
	struct sockaddr_in serve; // contains the details of the server
	struct sockaddr_in client; // recieves the client data (through getpeername())

	FILE *fp[16]; // holds 16 files
	char szFileName[255] = "";

	/* datos d ela venta de seleccion de archivos */

	printf("Wifiloader Server, (c) 2006, Hermes (www.elotrolado.net) and Rattboi\n");
                  
	if(argc < 2)
	{
		printf("Error: Needs at least 1 argument\n");
		return;
	}

	strcpy(szFileName, argv[1]);
		
	if(argc>=3)
	{
		port=atoi(argv[2]);
	}

	for(n=0;n<16;n++) fp[n]=NULL; // inicializa los punteros de fichero

	my_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); // obtiene un socket para protocolo TCP/IP

	if (my_socket == -1 ) 
	{
		printf(" Error at socket(), INVALID_SOCKET\n");
		return;
	}
	
	setsockopt(my_socket, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(int));
	
	serve.sin_family = AF_INET;
	serve.sin_addr.s_addr = INADDR_ANY; // :-> escucha todas las direcciones //inet_addr( "192.168.0.1" );
	serve.sin_port = htons( port);

	if ( bind( my_socket, (struct sockaddr *) &serve, sizeof(struct sockaddr)) == -1 ) 
	{
		printf( "bind() failed.\n" );
		perror("server.c");
		close(my_socket);
		return;
	}

	if ( listen( my_socket, 1 ) == -1 )
	{
		printf( "Error listening on socket.\n");
	}

	printf( "\nWaiting for the Wifiloader Client on port %i ...\n",port );

	my_socket2 = -1;
	while ( my_socket2 == -1 ) 
	{
		my_socket2 = accept( my_socket, NULL, NULL );
	}
	printf( "Wifiloader Connected.\n");
	
	getpeername(my_socket2, (struct sockaddr *)&client, (socklen_t *)sizeof(client)); //:-> averigua la IP del cliente

	printf("Client IP %s \n",inet_ntoa(client.sin_addr));

	// aqui se gestionan todos los comandos recibidos
	while(1)
	{
		int r;               
			
		r=get_com(my_socket2,comando,&uno,&dos);

//		printf("Command = %s, uno = %d, dos = %d\n", comando, uno, dos);
		
		if(r==-2) break;	 // salir (conexion perdida u error)

		if(r==0)
		{
			if(!strcmp(comando,"FIN")) 
				break; // libera la conexion (este server solo admite una conexion)

			if(!strcmp(comando,"EXECFIL")) // comando de ejecutar fichero: abre la ventana de seleccion y abre el fichero
			{
		
				for(n=0;n<16;n++) // negocia en busca de un puntero de fichero libre
				{
					if(fp[n]==0)
						break; 
				}

           	if(n==16)
					n=-1; // todos los punteros en uso :S

		
			 	if(n!=-1)
				{
					fp[n] = fopen(szFileName, "rb");
					if(!fp[n])
					{
						printf("Error Opening Execution file\n");
						n=-1; 
					} 
				}
		
				if(n==-1) 
					printf("Command Open Failed!\n");

				r=send_com(my_socket2,"ACKDATA",uno,4); // :-> envia el comando de respuesta con el numero de paquete asociado
				r=send_int(my_socket2,n); // :-> envia el 'fd' del fichero (-1 si hubo error)
			}
			else
			if(!strcmp(comando,"OPENFIL")) // comando de abrir fichero: lo mismo que EXECFIL pero aqui el nombre de fichero lo elige la NDS
			{
				r=get_data(my_socket2,filename,256); //:-> recibe la ruta del fichero a abrir

				for(n=0;n<16;n++)
				{
					if(fp[n]==0) break;
				}
       
				if(n==16) n=-1; // todos los punteros en uso :S

				if(n!=-1)
				{
					fp[n] = fopen(filename, "rb");
					filesize = fsize(fp[n]);
					if(!fp[n]) 
						n=-1;
					if(n==-1) 
						printf("Command Open Failed!\n");
				}
		
				r=send_com(my_socket2,"ACKDATA",uno,4); // :-> send the command of request with the packet number associated
				r=send_int(my_socket2,n); // :-> send the file 'fd'  (-1 if there's an  error)
			}
			else
			if(!strcmp(comando,"READDAT")) // :-> comando de lectura secuencial de ficheros: lee un bloque de 4KB y lo envia
			{
				r=fread(recvbuf+8, 1,1024*4, fp[dos]); // lee 4KB desde el fichero (recvbuf+8)
#ifdef BIG_ENDIAN
				r=CPU_swap_u32(r);
#endif
				memcpy(recvbuf,&r,4);		  // almacena el numero de bytes leidos (recvbuf+0)
#ifdef BIG_ENDIAN
				r=CPU_swap_u32(r);
#endif			
				r=my_checksum((char *)recvbuf+8,r);  // calcula el checksum para enviar    (recvbuf+4)
#ifdef BIG_ENDIAN
				r=CPU_swap_u32(r);
#endif			  
				memcpy(recvbuf+4,&r,4);

				r=send_com(my_socket2,"ACKDATA",uno,8+1024*4); // envia el comando 'ACKDATA' con la respuesta
				r=send_data(my_socket2,(char *)recvbuf,8+1024*4);
			}
			else
			if(!strcmp(comando,"READBYS")) //: este comando se recibe si el checksum de un comando READDAT, no coincide en el cliente
			{                              // con los datos recibidos. READBYS repite el envio de los datos anteriores
	 			r=send_com(my_socket2,"ACKDATA",uno,8+1024*4); // envia de nuevo el buffer de datos
	 			r=send_data(my_socket2,(char *)recvbuf,8+1024*4);
			}
			else
			if(!strcmp(comando,"SEEKPOS")) // :-> comando de lectura secuencial de ficheros: lee un bloque de 4KB y lo envia
			{
				r=get_data(my_socket2,(char *)datfseek,8); //:-> recibe los parametros para fseek
				n=-1;
				if(dos>=0 && dos<16)
			 	{
			 		n=fseek( fp[dos],datfseek[0],datfseek[1]); // lee 4KB desde el fichero (recvbuf+8)
			 	}
				r=send_com(my_socket2,"ACKDATA",uno,4); // :-> envia el comando de respuesta con el numero de paquete asociado
				r=send_int(my_socket2,n); // :-> envia la  posicion del fichero
			}
			else
			if(!strcmp(comando,"CLOSEFI")) //:-> cierra un fichero. 'dos' contiene el FD del fichero
			{
				if(dos>=0 && dos<16)
				{
					if(fp[dos])
						fclose(fp[dos]);
						fp[dos]=NULL;
				}
			  	else
					printf("Command CLOSEFI with invalid FD\n");
		
				r=send_com(my_socket2,"ACKDATA",uno,0);
			}
			else
			if(!strcmp(comando,"CLOSEAL")) // cierra todos los ficheros
			{
				for(n=0;n<16;n++)
				{
		    		if(fp[n]!=NULL) 
					{
						fclose(fp[n]);
						fp[n]=NULL;
					}
				}
			
				r=send_com(my_socket2,"ACKDATA",uno,0);
			}
		}
	}////

	close(my_socket2);
	close(my_socket);

	for(n=0;n<16;n++) 
	{
		if(fp[n]!=NULL) 
		{
			fclose(fp[n]);
			fp[n]=NULL;
		}
	}

	printf("Finished Sending\n");
	return 0;
}