Skip to content

Commit

Permalink
Merge pull request #58 from DeNA/feature-http1-streaming-response
Browse files Browse the repository at this point in the history
Feature http1 streaming response
  • Loading branch information
funa-tk authored Dec 15, 2019
2 parents 333885e + 2de38c9 commit 5bfe7e3
Show file tree
Hide file tree
Showing 10 changed files with 253 additions and 49 deletions.
7 changes: 4 additions & 3 deletions src/main/java/core/packetproxy/common/FilterTextParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,10 @@ public class FilterTextParser {
{ put("modified", 10); }
{ put("type", 11); }
{ put("encode", 12); }
{ put("group", 13); }
{ put("full_text", 14); }
{ put("full_text_i", 15); }
{ put("alpn", 13); }
{ put("group", 14); }
{ put("full_text", 15); }
{ put("full_text_i", 16); }
};

FilterTextParser(String str) {
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/core/packetproxy/encode/EncodeHTTPBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import java.io.InputStream;

import packetproxy.http.Http;
import packetproxy.http2.HTTP2;
import packetproxy.http2.Http2;
import packetproxy.model.Packet;

public abstract class EncodeHTTPBase extends Encoder
Expand All @@ -27,7 +27,7 @@ public enum HTTPVersion {
HTTP1, HTTP2
}
private HTTPVersion httpVersion;
private HTTP2 http2;
private Http2 http2;

public EncodeHTTPBase() {
super("http/1.1");
Expand All @@ -42,7 +42,7 @@ public EncodeHTTPBase(String ALPN) throws Exception {
httpVersion = HTTPVersion.HTTP1;
} else if (ALPN.equals("h2") || ALPN.equals("grpc")) {
httpVersion = HTTPVersion.HTTP2;
http2 = new HTTP2();
http2 = new Http2();
} else {
httpVersion = HTTPVersion.HTTP1;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
import java.io.InputStream;

import packetproxy.http.Http;
import packetproxy.http2.HTTP2;
import packetproxy.http2.StreamingResponse;
import packetproxy.http1.Http1StreamingResponse;
import packetproxy.http2.Http2StreamingResponse;
import packetproxy.model.Packet;

public class EncodeHTTPStreamingResponse extends Encoder
Expand All @@ -28,7 +28,8 @@ public enum HTTPVersion {
HTTP1, HTTP2
}
private HTTPVersion httpVersion;
private StreamingResponse http2StreamingResponse;
private Http1StreamingResponse http1StreamingResponse;
private Http2StreamingResponse http2StreamingResponse;

public EncodeHTTPStreamingResponse() {
super("http/1.1");
Expand All @@ -39,12 +40,15 @@ public EncodeHTTPStreamingResponse(String ALPN) throws Exception {
super(ALPN);
if (ALPN == null) {
httpVersion = HTTPVersion.HTTP1;
} else if (ALPN.equals("http/1.0") || ALPN.equals("http/1.1")) {
httpVersion = HTTPVersion.HTTP1;
} else if (ALPN.equals("h2") || ALPN.equals("grpc")) {
httpVersion = HTTPVersion.HTTP2;
http2StreamingResponse = new StreamingResponse();
} else {
httpVersion = HTTPVersion.HTTP1;
}
http1StreamingResponse = new Http1StreamingResponse();
http2StreamingResponse = new Http2StreamingResponse();
}

public HTTPVersion getHttpVersion() { return httpVersion; }
Expand All @@ -53,47 +57,56 @@ public EncodeHTTPStreamingResponse(String ALPN) throws Exception {
public String getName() {
return "HTTP Streaming Response";
}

@Override
public int checkRequestDelimiter(byte[] data) throws Exception {
if (this.httpVersion == HTTPVersion.HTTP1) {
return http1StreamingResponse.checkRequestDelimiter(data);
} else {
return http2StreamingResponse.checkDelimiter(data);
}
}

@Override
public int checkDelimiter(byte[] data) throws Exception {
public int checkResponseDelimiter(byte[] data) throws Exception {
if (this.httpVersion == HTTPVersion.HTTP1) {
return Http.parseHttpDelimiter(data);
return http1StreamingResponse.checkResponseDelimiter(data);
} else {
return http2StreamingResponse.checkDelimiter(data);
}
}

@Override
public void clientRequestArrived(byte[] frames) throws Exception {
public void clientRequestArrived(byte[] data) throws Exception {
if (this.httpVersion == HTTPVersion.HTTP1) {
super.clientRequestArrived(frames);
http1StreamingResponse.clientRequestArrived(data);
} else {
http2StreamingResponse.clientRequestArrived(frames);
http2StreamingResponse.clientRequestArrived(data);
}
}

@Override
public void serverResponseArrived(byte[] frames) throws Exception {
public void serverResponseArrived(byte[] data) throws Exception {
if (this.httpVersion == HTTPVersion.HTTP1) {
super.serverResponseArrived(frames);
http1StreamingResponse.serverResponseArrived(data);
} else {
http2StreamingResponse.serverResponseArrived(frames);
http2StreamingResponse.serverResponseArrived(data);
}
}

@Override
public byte[] passThroughClientRequest() throws Exception {
if (this.httpVersion == HTTPVersion.HTTP1) {
return super.passThroughClientRequest();
return http1StreamingResponse.passThroughClientRequest();
} else {
return http2StreamingResponse.passThroughClientRequest();
}
}

@Override
public byte[] passThroughServerResponse() throws Exception {
if (this.httpVersion == HTTPVersion.HTTP1) {
return super.passThroughServerResponse();
return http1StreamingResponse.passThroughServerResponse();
} else {
return http2StreamingResponse.passThroughServerResponse();
}
Expand All @@ -102,7 +115,7 @@ public byte[] passThroughServerResponse() throws Exception {
@Override
public byte[] clientRequestAvailable() throws Exception {
if (this.httpVersion == HTTPVersion.HTTP1) {
return super.clientRequestAvailable();
return http1StreamingResponse.clientRequestAvailable();
} else {
return http2StreamingResponse.clientRequestAvailable();
}
Expand All @@ -111,7 +124,7 @@ public byte[] clientRequestAvailable() throws Exception {
@Override
public byte[] serverResponseAvailable() throws Exception {
if (this.httpVersion == HTTPVersion.HTTP1) {
return super.serverResponseAvailable();
return http1StreamingResponse.serverResponseAvailable();
} else {
return http2StreamingResponse.serverResponseAvailable();
}
Expand All @@ -120,7 +133,7 @@ public byte[] serverResponseAvailable() throws Exception {
@Override
final public byte[] decodeServerResponse(byte[] input_data) throws Exception {
if (this.httpVersion == HTTPVersion.HTTP1) {
return input_data;
return http1StreamingResponse.decodeServerResponse(input_data);
} else {
return http2StreamingResponse.decodeServerResponse(input_data);
}
Expand All @@ -129,7 +142,7 @@ final public byte[] decodeServerResponse(byte[] input_data) throws Exception {
@Override
public byte[] encodeServerResponse(byte[] input_data) throws Exception {
if (this.httpVersion == HTTPVersion.HTTP1) {
return input_data;
return http1StreamingResponse.encodeServerResponse(input_data);
} else {
return http2StreamingResponse.encodeServerResponse(input_data);
}
Expand All @@ -138,7 +151,7 @@ public byte[] encodeServerResponse(byte[] input_data) throws Exception {
@Override
public byte[] decodeClientRequest(byte[] input_data) throws Exception {
if (this.httpVersion == HTTPVersion.HTTP1) {
return input_data;
return http1StreamingResponse.decodeClientRequest(input_data);
} else {
return http2StreamingResponse.decodeClientRequest(input_data);
}
Expand All @@ -147,7 +160,7 @@ public byte[] decodeClientRequest(byte[] input_data) throws Exception {
@Override
public byte[] encodeClientRequest(byte[] input_data) throws Exception {
if (this.httpVersion == HTTPVersion.HTTP1) {
return input_data;
return http1StreamingResponse.encodeClientRequest(input_data);
} else {
return http2StreamingResponse.encodeClientRequest(input_data);
}
Expand Down Expand Up @@ -196,8 +209,7 @@ public String getContentType(byte[] input_data) throws Exception {
}

@Override
public String getSummarizedResponse(Packet packet)
{
public String getSummarizedResponse(Packet packet) {
String summary = "";
if (packet.getDecodedData().length == 0 && packet.getModifiedData().length == 0) { return ""; }
try {
Expand All @@ -213,8 +225,7 @@ public String getSummarizedResponse(Packet packet)
}

@Override
public String getSummarizedRequest(Packet packet)
{
public String getSummarizedRequest(Packet packet) {
String summary = "";
if (packet.getDecodedData().length == 0 && packet.getModifiedData().length == 0) { return ""; }
try {
Expand All @@ -237,4 +248,9 @@ public void setGroupId(Packet packet) throws Exception {
}
}

@Override
public int checkDelimiter(byte[] input_data) throws Exception {
return input_data.length;
}

}
6 changes: 6 additions & 0 deletions src/main/java/core/packetproxy/gui/GUIOption.java
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,12 @@ public void actionPerformed(ActionEvent ae) {

panel.add(createSeparator());

panel.add(createElement("Priority Order of HTTP Versions", I18nString.get("Set order of priority between HTTP1 and HTTP2.")));
GUIOptionHttp http = new GUIOptionHttp();
panel.add(http.createPanel());

panel.add(createSeparator());

panel.add(createElement("PacketProxy CA Certificates", I18nString.get("Export CA certificate used to view SSL packets. It needs to be registered in trusted CA list of PC/Mac/Linux/Android/iOS")));

JPanel caPanel = new JPanel();
Expand Down
61 changes: 61 additions & 0 deletions src/main/java/core/packetproxy/gui/GUIOptionHttp.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package packetproxy.gui;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;

import javax.swing.BoxLayout;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;

import packetproxy.model.ConfigString;

public class GUIOptionHttp {

private JComboBox<String> combo = new JComboBox<>();
private ConfigString configPriority = new ConfigString("PriorityOrderOfHttpVersions");

public GUIOptionHttp() throws Exception {
combo.setPrototypeDisplayValue("xxxxxxx");
combo.addItem("HTTP1");
combo.addItem("HTTP2");
combo.setMaximumRowCount(combo.getItemCount());
String priority = configPriority.getString();
if (priority == null || priority.length() == 0) {
configPriority.setString("HTTP2");
priority = configPriority.getString();
}
combo.setSelectedItem(priority);
combo.addItemListener(new ItemListener(){
@Override
public void itemStateChanged(ItemEvent event) {
try {
if (event.getStateChange() != ItemEvent.SELECTED || combo.getSelectedItem() == null) {
return;
}
String priority = (String)combo.getSelectedItem();
configPriority.setString(priority);
combo.setSelectedItem(priority);
} catch (Exception e) {
e.printStackTrace();
}
}
});
combo.setMaximumSize(new Dimension(combo.getPreferredSize().width, combo.getMinimumSize().height));
}

public JPanel createPanel() throws Exception {
JPanel panel = new JPanel();
panel.setBackground(Color.WHITE);
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
panel.add(combo);
panel.add(new JLabel("has a high priority"));
panel.setAlignmentX(Component.LEFT_ALIGNMENT);
panel.setMaximumSize(new Dimension(Short.MAX_VALUE, panel.getMaximumSize().height));
return panel;
}

}
31 changes: 27 additions & 4 deletions src/main/java/core/packetproxy/http/Http.java
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ private byte[] getCookedBody(HttpHeader header, byte[] rawBody) throws Exception

if (enc.isPresent() && enc.get().equalsIgnoreCase("chunked")) {
header.removeAll(headerName);
cookedBody = getChankedHttpBody(cookedBody);
cookedBody = getChankedHttpBodyFussy(cookedBody);
if (cookedBody == null)
return null;
}
Expand Down Expand Up @@ -495,6 +495,31 @@ private static byte[] gzip(byte[] input_data) throws Exception
return out.toByteArray();
}

private static byte[] getChankedHttpBodyFussy(byte[] input_data) throws Exception
{
// TODO 改行コードの対応
byte[] search_word = new String("\r\n").getBytes();
int index = 0;
int start_index = 0;
byte[] body = new byte[0];
while ((index = Utils.indexOf(input_data, start_index, input_data.length, search_word)) >= 0) {
try {
byte[] chank_header = ArrayUtils.subarray(input_data, start_index, index);
String chank_length_str = new String(chank_header, "UTF-8").replaceAll("^0+([^0].*)$", "$1");
int chank_length = Integer.parseInt(chank_length_str.trim(), 16);
if (chank_length == 0) {
return body;
}
byte[] chank = ArrayUtils.subarray(input_data, index + search_word.length, index + search_word.length + chank_length);
body = ArrayUtils.addAll(body, chank);
start_index = index + search_word.length*2 + chank_length;
} catch (Exception e) {
return body;
}
}
return body;
}

private static byte[] getChankedHttpBody(byte[] input_data) throws Exception
{
// TODO 改行コードの対応
Expand All @@ -514,9 +539,7 @@ private static byte[] getChankedHttpBody(byte[] input_data) throws Exception
body = ArrayUtils.addAll(body, chank);
start_index = index + search_word.length*2 + chank_length;
} catch (Exception e) {
e.printStackTrace();
Binary b = new Binary(input_data);
PacketProxyUtility.getInstance().packetProxyLog(new String(b.toHexString().toString()));
return null;
}
}
return null;
Expand Down
13 changes: 12 additions & 1 deletion src/main/java/core/packetproxy/http/Https.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import javax.net.ServerSocketFactory;
Expand All @@ -49,6 +50,7 @@
import packetproxy.CertCacheManager;
import packetproxy.common.ClientKeyManager;
import packetproxy.common.Utils;
import packetproxy.model.ConfigString;
import packetproxy.model.Server;
import packetproxy.model.Servers;
import packetproxy.model.CAs.CA;
Expand Down Expand Up @@ -106,7 +108,16 @@ public static SSLSocket[] createBothSideSSLSockets(Socket clientSocket, InputStr
serverSSLSocket[0] = (SSLSocket) createSSLSocketFactory().createSocket(serverSocket, null, true);
serverSSLSocket[0].setUseClientMode(true);
SSLParameters sp = serverSSLSocket[0].getSSLParameters();
sp.setApplicationProtocols(clientProtocols.toArray(new String[clientProtocols.size()]));

List<String> alpns = new LinkedList<>(clientProtocols);
if (new ConfigString("PriorityOrderOfHttpVersions").getString().equals("HTTP1")) {
if (alpns.contains("http/1.1") || alpns.contains("http/1.0")) {
alpns.remove("h2");
alpns.remove("grpc");
}
}
sp.setApplicationProtocols(alpns.toArray(new String[alpns.size()]));

serverSSLSocket[0].setSSLParameters(sp);
serverSSLSocket[0].startHandshake();
} catch (Exception e) {
Expand Down
Loading

0 comments on commit 5bfe7e3

Please sign in to comment.