/* 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 #include #include #include #include #include #include #include #include //#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 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; }