Preproxy

Description

Ce programme en java permet de connecter deux ordinateurs à internet en même temps, sans connaitre à l'avance l'ordinateur connecté physiquement au web. Il réalise une couche intermédiaire entre un proxy et le logiciel demandant internet. Il est compatible avec les applications utilisant un proxy http, https, ftp, socks, ...
Les deux ordinateurs doivent être reliés entre eux par une connexion réseau (carte réseau 10/100, ...) et avoir des adresses IP fixes.

Source / Exemple :


/**

  • PreProxy :
  • ----------
  • Ce programme sert à aiguiller les données qui lui arrivent vers le proxy sur lequel une connexion internet est active.
  • Ligne de commande :
  • javaw -cp .;systray4j.jar PreProxy ==> en temps normal
  • java -cp .;systray4j.jar PreProxy ==> pour le débugage à l'écran
  • java -cp .;systray4j.jar PreProxy NomFichier ==> pour le débugage dans un fichier...
*
    • /
/** Licence du programme : GNU GPL 2
  • ----------------------
  • |-> Voir le fichier licenceen.txt pour avoir la version officielle, et licence.txt pour avoir une version non officielle traduite en français
*
  • Ce programme est libre, vous pouvez le redistribuer et/ou le modifier selon les termes de la Licence Publique Générale GNU publiée par la Free
  • // * Software Foundation(version 2).
*
  • Ce programme est distribué car potentiellement utile, mais SANS AUCUNE GARANTIE, ni explicite ni implicite, y compris les garanties de commercialisation ou
  • d'adaptation dans un but spécifique. Reportez-vous à la Licence Publique Générale GNU pour plus de détails.
*
  • Vous devez avoir reçu une copie de la Licence Publique Générale GNU en même temps que ce programme ; si ce n'est pas le cas, écrivez à la Free Software
  • Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, États-Unis.
*
    • /
import java.io.*; import java.net.*; import java.util.*; import javax.swing.*; import snoozesoft.systray4j.*; /** /** Ceci est la classe principale */ public class PreProxy { // Nos variables publiques public static int EtatConnexion; public static Config Conf; /** Fonction main() : celle qui gère le déroulement du programme.
  • Arguments : Ceux passés par la ligne de commande */
public static void main(String [] args) { if (System.getProperty("os.name", "").startsWith("Windows")) { try { System.setOut(new PrintStream((OutputStream) System.out, true, "Cp850")); System.setErr(new PrintStream((OutputStream) System.err, true, "Cp850")); } catch (UnsupportedEncodingException e) { }; } // Infos de version Version(); // On traite la ligne de commande CmdeLine(args); // On charge la configuration... Conf = new Config("../config.txt"); // On lance les threads neccessaires... DebutLancement(); } /** Fonction qui gère les paramètres passés par la ligne de commande
  • Arguments : la ligne de commande */
private static void CmdeLine(String [] args) { String Fichier = null; try { Fichier = args[0]; File Fich = new File(Fichier); Fichier = Fich.getAbsolutePath(); // True pour AutoFlush System.setErr(new PrintStream(new FileOutputStream(Fich), true)); System.out.println("CmdeLine: Débugage dans "+Fichier); System.err.println("CmdeLine: Début du débugage : "); } // Pas d'arguments... catch (ArrayIndexOutOfBoundsException Err) { System.out.println("CmdeLine: Pas de débugage dans un fichier."); } catch (Exception Err) { JOptionPane.showMessageDialog(null,"Erreur lors de l'ouverture du fichier de log : \""+Fichier+"\".\n\nCa a retouné ça :\n"+ Err.toString(),"Erreur...",JOptionPane.ERROR_MESSAGE); }; }; /** Fonction qui gère le lancement du processus d'écoute de contrôle...
  • Arguments : aucun */
private static void DebutLancement() { // On lance le processus d'écoute. System.err.println("DebutLc: Met en place l'écoute de contrôle...."); EcouteCtrle Ec = new EcouteCtrle(); Ec.start(); System.err.println("DebutLc: FAIT"); }; /** Cette fonction gère la suite des Threads à lancer, une fois que l'écoute de contrôle est mise en place Ca permet de gérer si le programme est lancé en double (C'est à dire si l'écoute de contrôle a public se lancer...
  • Arguments : Aucun */
public static void SuiteLancement() { // On lance le processus qui gère la présence ou non de la connexion System.err.println("SuiteLc: Met en place la gestion de connexion...."); Connexion Cnn = new Connexion(); Cnn.start(); System.err.println("SuiteLc: FAIT"); Entrée Entree = null; int [] Tabl = new int[2]; // Puis le/les processus pour rediriger... for (int i=1; i<=PreProxy.Conf.Redirection.size();i++) { System.err.println("SuiteLc: Met en place la redirection n°"+i+"...."); Tabl = (int [])PreProxy.Conf.Redirection.get(i-1); System.err.println("SuiteLc: "+Tabl[0]+"-->"+Tabl[1]+"...."); Entree = new Entrée(Tabl[0],Tabl[1]); Entree.start(); System.err.println("SuiteLc: FAIT"); }; } /** Fonction qui affiche les infos de version du programme
  • Arguments : aucun */
private static void Version() { System.out.println("\n** PreProxy version 1.0 Fr **"); // Pour lutter contre le spam, la source étant sur internet. System.out.println("Par Alexandre SECHAUD <ra"+"inbow"+"nar"+"chiste"+"@"+"lapost"+"e.n"+"et>"); System.out.println("http://www.ifrance.fr/MesProgrammes"); System.out.println("Logiciel sous licence GNU GPL 2"); System.out.println("\n\n\n"); }; } /** Cette classe gère les connexions entrantes sur le port de contrôle */ class EcouteCtrle extends Thread { private static int Port; /** Fonction : constructeur
  • Arguments : aucun */
EcouteCtrle() { this.Port = PreProxy.Conf.PortNbrEcoute; } /** Fonction qui est le processus en lui même
  • Arguments : Aucun */
public void run() { ServerSocket SrvS = null; Socket MaSocket = null; try { SrvS = new ServerSocket(Port); SrvS.setSoTimeout(500); } catch (BindException Err) { // Le port est déjà pris... Une instance est déjà lancée... System.out.println("ConnCtrle: Une instance doit déjà tourner..."); System.exit(0); } catch (Exception Err) { JOptionPane.showMessageDialog(null,"Il est impossoble d'écouter sur le port "+Port+".\n\nCa a retouné ça :\n"+ Err.toString(),"Erreur...",JOptionPane.ERROR_MESSAGE); System.err.println("ConnCrtle: Impossible d'écouter sur le port "+Port); Err.printStackTrace(System.err); // On quitte le programme... System.exit(0); }; // Si on est arrivé à faire ça, c'est qu'on a une seul insatnce qui tourne... On peut finir de lancer le reste : PreProxy.SuiteLancement(); // On écoute Toujours. while (true) { try { MaSocket=SrvS.accept(); } catch (IOException Err) { } // Le timeOut de .5s permet de partager le temps CPU, sinon, c'est bloquant... yield(); if (MaSocket!=null) { // Ca y est, on a qqn. On va répondre si on est sur le web en connexion directe. System.err.println("ConnCtrle: Une connection de contrôle entrante"); try { OutputStream OS = MaSocket.getOutputStream(); ObjectOutputStream OOS = new ObjectOutputStream(OS); OOS.writeBoolean((PreProxy.EtatConnexion&1)!=0); System.err.println("ConnCtrle: Vient d'envoyer a l'autre PC : "+ new Boolean((PreProxy.EtatConnexion&1)!=0).toString()); OOS.close(); OS.close(); MaSocket.close(); } catch (Exception Err) { }; // On est reparti pour un tour !!! MaSocket = null; } } } } /** Classe qui s'occupe de connaître l'état de connexion des différrents PC */ class Connexion extends Thread implements SysTrayMenuListener { private String [] Texte = { "Aucune connexion, ni locale, ni web", "Connexion directe au web, pas de connexion locale", "Connexion locale mais pas de connexion web", "Connexion web directe et connection locale", "Cas Impossible", "Cas Impossible", "Connexion au web via la connexion locale", "Cas non prévu, les 2 PC sont directement reliés au web." }; private String IP; private int Port; private SysTrayMenu MonMenu; /** Fonction : constructeur
  • Auguments : aucun */
Connexion() { this.IP = PreProxy.Conf.IP; this.Port = PreProxy.Conf.PortNbrEcoute; } /** Ces 3 fonctions gèrent les actions sur l'icone dans la systray
  • Les arguments sont donnés par le Doc de systray4j */
public void menuItemSelected(SysTrayMenuEvent Evt) { if (Evt.getActionCommand().equals("Quitter")) { System.exit(0); }; } public void iconLeftClicked(SysTrayMenuEvent e) { } public void iconLeftDoubleClicked(SysTrayMenuEvent evt) { } /** Cette fonction est le Thread en lui-même.
  • Arguments : Aucun
  • Valeur retoutnrné : un eniter tel que :
  • le 1er bit 0000 0001 indique la connexion directe ou non au web
  • le 2nd bit 0000 0010 indique la connexion ou non au 2nd PC
  • le 3eme bit 0000 0100 indique la connection directe ou non du 2nd PC au web */
public void run() { InetAddress [] IA; int i=0; boolean IsConnectedWww, IsConnectedLocal, bTmp; /* Les deux icones que voici proviennent du site http://icone.phidji.com/
  • Elles sont inclues dans ce programme avec la permission écrite de leur auteur */
SysTrayMenuIcon Oui = new SysTrayMenuIcon("vert.ico"); SysTrayMenuIcon Non = new SysTrayMenuIcon("rge.ico"); MonMenu = new SysTrayMenu(Non,"Ne connait pas encore l'état des connexions..."); SysTrayMenuItem Quit = new SysTrayMenuItem("Quitter","Quitter"); Quit.addSysTrayMenuListener(this); MonMenu.addItem(Quit); while (true) { Socket Sck = null; InputStream IS = null; ObjectInputStream OIS = null; IsConnectedWww = false; IsConnectedLocal = false; try { // Tableau d'addresses IP, de toutes celles qui correspondent au nom du PC. IA = InetAddress.getAllByName(InetAddress.getLocalHost().getHostName()); // On parcours les ip... for (i=0;i<IA.length; i++) { bTmp = false; // On regarde ici si l'addresse est au début la même que l'addresse donnée en paramètre au programme // |=> IP du réseau local bTmp = !(IP.startsWith(IA[i].getHostAddress().substring(0,IA[i].getHostAddress().lastIndexOf(".")))); IsConnectedLocal |= !bTmp; // On regarde si on est pas en loopback : 127.0.0.1, par exemple... // Si c'est pas le cas, alors on est sur internet si on est en même temps pas sur lengthréseau local bTmp &= !IA[i].isLoopbackAddress(); // On donne l'info pour tous... Il suffit qu'un soit connecté au web pour que ce soit ok. IsConnectedWww |= bTmp; } } catch (Exception Err) { }; if (IsConnectedLocal) i=2; else i=0; if (IsConnectedWww) i++; // Si on est connecté en local, mais pas au web, on demande à l'autre s'il est connecté : if (i==2) { bTmp = false; try { Sck = new Socket(IP, Port); IS = Sck.getInputStream(); OIS = new ObjectInputStream(IS); bTmp = OIS.readBoolean(); OIS.close(); IS.close(); Sck.close(); } catch (Exception Err) { System.out.println("Connexion: Le second PC aurait du répondre si oui ou non, il était connecté. Ca n'a pas été le cas."); }; if (bTmp) i+=4; }; PreProxy.EtatConnexion = i; // On met à jour le systray MonMenu.setToolTip(Texte[i]); // On est connecté if ((i&5)!=0) MonMenu.setIcon(Oui); else MonMenu.setIcon(Non); yield(); try { this.sleep(5000); } catch (Exception Err) { System.err.println("Connexion: Erreur lors de la mise en pause de Connexion :"); Err.printStackTrace(System.err); }; } } } /** Cette classe s'occupe d'écouter les ports pour la redirection des données */ class Entrée extends Thread { private int Entrée, Sortie; private String IP; /** Fonction contructeur.
  • Arguments : 2 entiers, le 1er indique le port d'écoute, le second le port de sortie */
Entrée(int Entrée, int Sortie) { this.Entrée = Entrée; this.Sortie= Sortie; } /** Cette fonction est le Thread en lui-même
  • Arguments : aucun */
public void run() { ServerSocket Srv = null; Socket SckEntr = null; Socket SckSort = null; int Taille; boolean TtOK = true; try { Srv = new ServerSocket(Entrée); Srv.setSoTimeout(500); } catch (Exception Err) { JOptionPane.showMessageDialog(null,"Impossible d'écouter les connexions entrantes pour les rediriger... Ca a retouné ça :\n"+ Err.toString(), "Erreur...",JOptionPane.ERROR_MESSAGE); System.err.println("Entrée: Impssible d'écouter les connexions entrantes pour les rediriger"); Err.printStackTrace(System.err); System.exit(0); }; while (true) { try { SckEntr = null; SckEntr = Srv.accept(); } catch (SocketTimeoutException Err) { } catch (Exception Err) { SckEntr = null; }; // On regarde si on a eu une connexion valide... if (SckEntr!=null) { // Si on peut rediriger vers le web, on prend. Sinon, on ferme, et le navigateur devrait répercuter l'erreur System.err.println("Entrée: On a une entrée de : "+SckEntr.toString()); if ((PreProxy.EtatConnexion&5)!=0) { // On crée la seconde socket vers le bon ordi... IP=PreProxy.Conf.IP; if ((PreProxy.EtatConnexion&1)==1) IP = "127.0.0.1"; try { SckSort = new Socket(IP,Sortie); } catch (Exception Err) { TtOK=false; } // Si tout c'est bien créé, c'est bon... if (TtOK) { // On met tout à la même taille de buffer : celle de celui qui a fait la demande !!! Taille = 4096; // Valeur par défaut ! try { // Celui qui envoie doit correspondre à celui qui reçoit... Taille = SckEntr.getSendBufferSize(); SckSort.setReceiveBufferSize(Taille); // Dans une sens... Redirigeur EntréeVersSortie = new Redirigeur(SckEntr, SckSort, Taille); EntréeVersSortie.start(); } catch (Exception Err) { Err.printStackTrace(System.err); }; try { Taille = SckSort.getSendBufferSize(); SckEntr.setReceiveBufferSize(Taille); // Puis dans l'autre... Redirigeur SortieVersEntrée = new Redirigeur(SckSort, SckEntr, Taille); SortieVersEntrée.start(); } catch (Exception Err) { Err.printStackTrace(System.err); }; }; TtOK = true; SckEntr = null; } else { // On ferme tout de suite try { SckEntr.close(); } catch (Exception Err) { }; SckEntr = null; }; } } } } /** Cette classe sert à rediriger les communications d'un port vers un autre
  • Il faut en lancer une pour un sens, et une seconde pour l'autre direction */
class Redirigeur extends Thread { private Socket SckE, SckS; private int Size; /** Constructeur.
  • 3 Arguments : SckE : Socket Entrante, sans considérer s'il s'agit d'un sens ou de l'autre, c'est là que sont reçues les données
  • SckS : Socket Sortante, idem, c'est là que les données sont renvoyées
  • Size : La taille du Buffer */
Redirigeur(Socket SckE, Socket SckS, int Size) { this.SckE=SckE; this.SckS=SckS; this.Size = Size; } /** Le Thread en lui-même
  • Arguments : Aucun */
public void run() { InputStream ISE; OutputStream OSS; int tmp = 0; String Ecrit; byte[] buffer = new byte[Size]; // Tout c'est bien initialisé... ISE = null; OSS = null; // On crée le flux entrant et sortant pour nos 2 sockets... try { ISE = SckE.getInputStream(); OSS = SckS.getOutputStream(); } catch (Exception Err) { }; try { SckE.setSoTimeout(60000); } catch (Exception Err) { }; try { while (tmp!=-1) { tmp = ISE.read(buffer); Ecrit = new String(buffer,0,tmp); OSS.write(buffer,0, tmp); } } catch (Exception Err) { }; // On essaie ici de tout fermer, comme çà, même l'autre thread devrait fermer, puis, c'est + propre. try { OSS.close(); } catch (Exception Err){ }; try { ISE.close(); } catch (Exception Err) { }; try { SckE.close(); } catch (Exception Err) { }; try { SckS.close(); } catch (Exception Err) { }; } } /** Cette classe s'occupe de lire la configuration */ class Config { public Vector Redirection; public String IP; public static int PortNbrEcoute; private int [] Redir = new int [2]; /** Constructeur
  • Arguments : le nom du fichier de configuration sous forme de String */
Config(String Fichier) { IP = null; PortNbrEcoute = 0; BufferedReader BR = null; String Ligne; int LigneNb = 1; Redirection = new Vector(); // On ouvre le fichier de configuration : try { BR = new BufferedReader(new FileReader(Fichier)); } catch (FileNotFoundException Err) { JOptionPane.showMessageDialog(null,"Le fichier de configuration \""+Fichier+"\" n'existe pas...","Erreur...",JOptionPane.ERROR_MESSAGE); System.err.println("Config: Le fichier de configuration "+Fichier+"n'existe pas."); System.exit(0); } catch (Exception Err) { JOptionPane.showMessageDialog(null,"Erreur lors de l'ouverture du fichier de configuration.... Ca a retouné ça :\n"+ Err.toString(),"Erreur...",JOptionPane.ERROR_MESSAGE); System.err.println("Config: Erreur lors de l'ouverture du fichier de configuration"); Err.printStackTrace(System.err); System.exit(0); }; // On parcours le fichier... try { Ligne = BR.readLine(); do { if (Ligne.length()!=0) Identifie(Ligne, LigneNb); Ligne = BR.readLine(); LigneNb++; } while (Ligne!=null); } catch (Exception Err) { Err.printStackTrace(System.err); }; // Tout n'est pas donné : if ((IP==null)||(PortNbrEcoute==0)||(Redirection.size()==0)) { JOptionPane.showMessageDialog(null,"Fichier de configuration incomplet...","Erreur...",JOptionPane.ERROR_MESSAGE); System.err.println("Config: Le fichier de configuration est incomplet..."); System.exit(0); }; } /** Fonction qui identifie la ligne du fichier de configuration
  • Arguments : La ligne de fichier sous forme de String */
private void Identifie(String Ligne, int Nb) { int i,j; // On s'affranchie des majuscules, minuscules : Ligne = Ligne.toLowerCase(); // Commentaire... if (Ligne.charAt(0)=='#') return; // On redirige if (Ligne.startsWith("redir")) { try { i=(Ligne.indexOf(" "))+1; j=Ligne.indexOf(" ",i); // A la fin de la commande, on fait j+=1, et non au début... Pas comme si ++j !!! Redir[0] = Integer.parseInt(Ligne.substring(i, Ligne.indexOf(" ",j++))); Redir[1] = Integer.parseInt(Ligne.substring(j)); // On en fait un clone, sinon, on écrit toujours dans le même tableau :( Redirection.add(Redir.clone()); System.err.println("Config: "+Redir[0]+"-->"+Redir[1]); } catch (Exception Err) { System.err.println("Config: Une erreur est survenue lors de la lecture de la ligne "+Nb+" du fichier config.txt, instuction reconnue : Redir."); }; return; }; // On récupère le nom de l'autre PC if (Ligne.startsWith("autre")) { IP = Ligne.substring(Ligne.indexOf(" ")+1); System.err.println("Config: Autre="+IP); return; }; // On récupère le numéro du port... if (Ligne.startsWith("port")) try { PortNbrEcoute = Integer.parseInt(Ligne.substring(1+Ligne.indexOf(" "))); System.err.println("Config: Port="+PortNbrEcoute); } catch (Exception Err) { System.err.println("Config: Une erreur est survenue lors de la lecture de la ligne "+Nb+" du fichier config.txt, instruction reconnue : Port."); }; } }

Conclusion :


http://www.ifrance.com/MesProgrammes/

Codes Sources

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.