Einzelnen Beitrag anzeigen

Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#1

[Java] Daten zwischen zwei Sockets tunneln

  Alt 30. Dez 2011, 18:27
Hey,

ich versuche grade mit meinen eher bescheidenen Java Kenntnissen einen kleinen HTTP Proxy zu schreiben. Die Geschichte funktioniert sogar schon recht gut, allerdings nur solange keine Binärdaten empfangen werden.

Empfange ich beispielsweise Bilder, komprimierte Websites, etc., dann empfangen meine Methoden tunnelData() bzw. reveiveData() aus irgendeinem mir unbekannten Grund zu wenig Daten. Es fehlt also immer das Ende des Streams.

Hat jemand eine Idee, woran das liegen könnte?

Code:
package me.zacherl.proxy;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.nio.CharBuffer;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.StringTokenizer;

import me.zacherl.proxy.HttpProxyContext.TransferMode;

public class HttpProxyConnection implements Runnable{

    protected Socket localSocket = null;
    protected Socket remoteSocket = null;
    protected BufferedReader localInput = null;
    protected BufferedWriter localOutput = null;
    protected BufferedReader remoteInput = null;
    protected BufferedWriter remoteOutput = null;

    public HttpProxyConnection(Socket localSocket) {
        this.localSocket = localSocket;
    }
   
    private void BeforeHttpRequest(HttpProxyRequest request) {
       
    }
   
    private void BeforeHttpResponse(HttpProxyResponse response) {
       
    }
   
    private void HttpRequest(HttpProxyRequest request, HttpProxyData data) {
       
    }
   
    private void HttpResponse(HttpProxyResponse response, HttpProxyData data) {
       
    }
   
    private HttpProxyRequest parseRequest(BufferedReader input) {
       HttpProxyRequest request = new HttpProxyRequest();
       try {
         String line = input.readLine();
         String[] header = line.split(" ");
         if (header.length < 3) {
            return null;
         }
         request.setMethod(header[0]);
         request.setProtocol(header[2]);      
         if (request.getMethod().equalsIgnoreCase("CONNECT")) {
            request.setSslConnection(true);
            header = header[1].split(":");
            if (header.length < 1) {
               return null;
            }
            request.setToHost(header[0]);
            try {
               request.setToPort(Integer.parseInt(header[1]));
            } catch (Exception e) {
               request.setToPort(443);
            }
         } else {
            request.setSslConnection(false);
            try {
               request.setUri(new URI(header[1]));
            } catch (URISyntaxException e) {
               return null;
            }         
            while ((line = input.readLine()).length() > 0) {
               header = line.split(": ");
               StringBuffer sb = new StringBuffer();
               for (int i = 1; i < header.length; i++) {
                  sb.append(header[i]);
               }
               request.setHeader(header[0], sb.toString());
            }
         }      
      } catch (IOException e) {
         return null;
      }
       return request;
    }
   
    private void sendRequestHeader(BufferedWriter output, HttpProxyRequest request) {
       try {
         StringBuffer sb = new StringBuffer();
         sb.append(request.getMethod() + " ");
         URI uri = request.getUri();
         sb.append(uri.getPath());
            if (uri.getQuery() != null) {
                sb.append(uri.getQuery());
            }
            if (uri.getFragment() != null) {
                sb.append(uri.getFragment());
            }
            sb.append(" " + request.getProtocol());
            output.write(sb.toString() + "\r\n");
           
            System.out.print(sb.toString() + "\r\n");
           
            Iterator it = request.getHeaders().entrySet().iterator();
            while (it.hasNext()) {
                Entry pairs = (Entry)it.next();
                output.write(pairs.getKey() + ": " + pairs.getValue() + "\r\n");
               
                System.out.print(pairs.getKey() + ": " + pairs.getValue() + "\r\n");
            }
            output.write("\r\n");
      } catch (IOException e) {
         return;
      }
   }

   private void receiveData(BufferedReader input, HttpProxyData data) {
      try {
         char[] buf = new char[1024 * 8];
         while (input.ready()) {
            int size = input.read(buf, 0, buf.length);
            if (size < 1) {
               break;
            }
            data.addContent(buf, size);
            if (size < buf.length) {
               break;
            }
         }
      } catch (IOException e) {
         return;
      }
   }
   
   private void sendData(BufferedWriter output, HttpProxyData data) {
      try {
         output.write(data.getContent(), 0, data.getContentLength());
      } catch (IOException e) {
   
      }
   }
   
   private void tunnelData(BufferedReader input, BufferedWriter output) {
      try {
         char[] buf = new char[1024*8];
         while (input.ready()) {
            int size = input.read(buf, 0, buf.length);
            if (size < 1) {
               break;
            }
            output.write(buf, 0, size);
            if (size < buf.length) {
               break;
            }
         }
      } catch (IOException e) {
         return;
      }
   }

    public void run() {   
       try {
         localInput = new BufferedReader(new InputStreamReader(localSocket.getInputStream()));
         localOutput = new BufferedWriter(new OutputStreamWriter(localSocket.getOutputStream()));   
         
         HttpProxyRequest request = parseRequest(localInput);
          if (request == null) {
             return;
          }
          System.out.println("REQUEST:");
          System.out.println(request.getToHost() + ":" + request.getToPort());
          System.out.println(request.getDocument());
          BeforeHttpRequest(request);
          try {
            remoteSocket = new Socket(request.getToHost(), request.getToPort());
            remoteInput = new BufferedReader(new InputStreamReader(remoteSocket.getInputStream()));
             remoteOutput = new BufferedWriter(new OutputStreamWriter(remoteSocket.getOutputStream()));
         } catch (UnknownHostException e) {
            return;
         }
          
          // request.setTransferMode(TransferMode.TRANSFER_MODE_FULL_DOCUMENT);
          
          HttpProxyData requestData = new HttpProxyData();
          if (!request.getSslConnection() && (request.getTransferMode() == TransferMode.TRANSFER_MODE_FULL_DOCUMENT)) {
             receiveData(localInput, requestData);
             HttpRequest(request, requestData);
             request.setHeader(HttpProxyContext.HEADER_CONTENT_LENGTH, Integer.toString(requestData.getContentLength()));
          }
          if (!request.getSslConnection()) {
             sendRequestHeader(remoteOutput, request);
             if (request.getTransferMode() == TransferMode.TRANSFER_MODE_FULL_DOCUMENT) {
                sendData(remoteOutput, requestData);
             }
          }
          if (request.getSslConnection() || (request.getTransferMode() == TransferMode.TRANSFER_MODE_STREAM)) {
             String contentLength = request.getHeader(HttpProxyContext.HEADER_CONTENT_LENGTH);
             if ((contentLength != null) && (Integer.parseInt(contentLength) > 0)) { 
                tunnelData(localInput, remoteOutput);
             }
          }     
          remoteOutput.flush();
          
          HttpProxyResponse response = parseResponse(remoteInput);
          if (response == null) {
             return;
          }
          response.setSslConnection(request.getSslConnection());
          
          response.setTransferMode(TransferMode.TRANSFER_MODE_FULL_DOCUMENT);
          
          HttpProxyData responseData = new HttpProxyData();
          if (!response.getSslConnection() && (response.getTransferMode() == TransferMode.TRANSFER_MODE_FULL_DOCUMENT)) {
             
             System.out.println(Integer.toString(remoteSocket.getInputStream().available()));
             
             receiveData(remoteInput, responseData);
             HttpResponse(response, responseData);
             //response.setHeader(HttpProxyContext.HEADER_CONTENT_LENGTH, Integer.toString(responseData.getContentLength()));
             
             System.out.println(Integer.toString(responseData.getContentLength()));
          }
          if (!response.getSslConnection()) {
             sendResponseHeader(localOutput, response);
             if (response.getTransferMode() == TransferMode.TRANSFER_MODE_FULL_DOCUMENT) {
                sendData(localOutput, responseData);
             }
          }
          if (response.getSslConnection() || (response.getTransferMode() == TransferMode.TRANSFER_MODE_STREAM)) {
             tunnelData(remoteInput, localOutput);
          }     
          localOutput.flush();
         

          if (remoteSocket != null) {
              remoteSocket.close();
           }
          if (localSocket != null) {
             localSocket.close();
          }
      } catch (IOException e) {
         
      }
    }

   private void sendResponseHeader(BufferedWriter output, HttpProxyResponse response) {
      try {
         StringBuffer sb = new StringBuffer();
         sb.append(response.getProtocol() + " ");
            sb.append(Integer.toString(response.getStatusCode()) + " ");
            sb.append(response.getStatusMessage());
            output.write(sb.toString() + "\r\n");
            Iterator it = response.getHeaders().entrySet().iterator();
            while (it.hasNext()) {
                Entry pairs = (Entry)it.next();
                output.write(pairs.getKey() + ": " + pairs.getValue() + "\r\n");
            }
            output.write("\r\n");
      } catch (IOException e) {
         return;
      }
   }

   private HttpProxyResponse parseResponse(BufferedReader input) {
      HttpProxyResponse response = new HttpProxyResponse();
      try {
         String line = input.readLine();
         String[] header = line.split(" ");
         if (header.length < 3) {
            return null;
         }
         response.setProtocol(header[0]);
         try {
            response.setStatusCode(Integer.parseInt(header[1]));
         } catch (Exception e) {
            return null;
         }
         response.setStatusMessage(header[2]);         
         while ((line = input.readLine()).length() > 0) {
            header = line.split(": ");
            StringBuffer sb = new StringBuffer();
            for (int i = 1; i < header.length; i++) {
               sb.append(header[i]);
            }
            response.setHeader(header[0], sb.toString());
         }
      } catch (IOException e) {
         return null;
      }
      return response;
   }
   
}
Viele Grüße
Zacherl
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat