mirror of
https://github.com/emanuele-f/PCAPdroid.git
synced 2026-06-16 21:10:57 +08:00
Join HTTP request and reponse tabs
This commit is contained in:
parent
64ae11f6f4
commit
64721ea64c
@ -48,6 +48,7 @@ public class HTTPReassembly {
|
||||
private final ReassemblyListener mListener;
|
||||
private boolean mReassembleChunks;
|
||||
private boolean mInvalidHttp;
|
||||
private boolean mIsTx;
|
||||
|
||||
public HTTPReassembly(boolean reassembleChunks, ReassemblyListener listener) {
|
||||
mListener = listener;
|
||||
@ -80,6 +81,10 @@ public class HTTPReassembly {
|
||||
void onChunkReassembled(PayloadChunk chunk);
|
||||
}
|
||||
|
||||
private void log_d(String msg) {
|
||||
Log.d(TAG + "(" + (mIsTx ? "TX" : "RX") + ")", msg);
|
||||
}
|
||||
|
||||
/* The request/response tab shows reassembled HTTP chunks.
|
||||
* Reassembling chunks is requires when using a content-encoding like gzip since we can only
|
||||
* decode the data when we have the full chunk and we cannot determine data bounds.
|
||||
@ -89,6 +94,7 @@ public class HTTPReassembly {
|
||||
int body_start = 0;
|
||||
byte[] payload = chunk.payload;
|
||||
boolean chunked_complete = false;
|
||||
mIsTx = chunk.is_sent;
|
||||
|
||||
if(mReadingHeaders) {
|
||||
// Reading the HTTP headers
|
||||
@ -100,11 +106,11 @@ public class HTTPReassembly {
|
||||
String line = reader.readLine();
|
||||
while((line != null) && (line.length() > 0)) {
|
||||
line = line.toLowerCase();
|
||||
//Log.d(TAG, "[HEADER] " + line);
|
||||
//log_d("[HEADER] " + line);
|
||||
|
||||
if(line.startsWith("content-encoding: ")) {
|
||||
String contentEncoding = line.substring(18);
|
||||
Log.d(TAG, "Content-Encoding: " + contentEncoding);
|
||||
log_d("Content-Encoding: " + contentEncoding);
|
||||
|
||||
switch (contentEncoding) {
|
||||
case "gzip":
|
||||
@ -121,17 +127,17 @@ public class HTTPReassembly {
|
||||
}
|
||||
} else if(line.startsWith("content-type: ")) {
|
||||
String contentType = line.substring(14);
|
||||
Log.d(TAG, "Content-Type: " + contentType);
|
||||
log_d("Content-Type: " + contentType);
|
||||
} else if(line.startsWith("content-length: ")) {
|
||||
try {
|
||||
int contentLength = Integer.parseInt(line.substring(16));
|
||||
Log.d(TAG, "Content-Length: " + contentLength);
|
||||
log_d("Content-Length: " + contentLength);
|
||||
} catch (NumberFormatException ignored) {}
|
||||
} else if(line.startsWith("upgrade: ")) {
|
||||
Log.d(TAG, "Upgrade found, stop parsing");
|
||||
log_d("Upgrade found, stop parsing");
|
||||
mReassembleChunks = false;
|
||||
} else if(line.equals("transfer-encoding: chunked")) {
|
||||
Log.d(TAG, "Detected chunked encoding");
|
||||
log_d("Detected chunked encoding");
|
||||
mChunkedEncoding = true;
|
||||
}
|
||||
|
||||
@ -145,6 +151,8 @@ public class HTTPReassembly {
|
||||
mHeaders.add(chunk.subchunk(0, body_start));
|
||||
} else {
|
||||
if(mHeadersSize > MAX_HEADERS_SIZE) {
|
||||
log_d("Assuming not HTTP");
|
||||
|
||||
// Assume this is not valid HTTP traffic
|
||||
mReadingHeaders = false;
|
||||
mReassembleChunks = false;
|
||||
@ -159,8 +167,10 @@ public class HTTPReassembly {
|
||||
|
||||
// If not Content-Length provided and not using chunked encoding, then we cannot determine
|
||||
// chunks bounds, so disable reassembly
|
||||
if(!mReadingHeaders && (mContentLength < 0) && (!mChunkedEncoding))
|
||||
if(!mReadingHeaders && (mContentLength < 0) && (!mChunkedEncoding) && mReassembleChunks) {
|
||||
log_d("Cannot determine bounds, disable reassembly");
|
||||
mReassembleChunks = false;
|
||||
}
|
||||
|
||||
// When mReassembleChunks is false, each chunk should be passed to the mListener
|
||||
if(!mReassembleChunks)
|
||||
@ -181,7 +191,7 @@ public class HTTPReassembly {
|
||||
body_start += line.length() + 2;
|
||||
body_size -= line.length() + 2;
|
||||
|
||||
Log.d(TAG, "Chunk length: " + mContentLength);
|
||||
log_d("Chunk length: " + mContentLength);
|
||||
|
||||
if(mContentLength == 0)
|
||||
chunked_complete = true;
|
||||
@ -193,6 +203,7 @@ public class HTTPReassembly {
|
||||
// NOTE: Content-Length is optional in HTTP/2.0, mitmproxy reconstructs the entire message
|
||||
if(body_size > 0) {
|
||||
if(mContentLength > 0) {
|
||||
//log_d("body: " + body_size + " / " + mContentLength);
|
||||
if(body_size < mContentLength)
|
||||
mContentLength -= body_size;
|
||||
else {
|
||||
@ -215,11 +226,14 @@ public class HTTPReassembly {
|
||||
if(chunked_complete || !mReassembleChunks)
|
||||
mChunkedEncoding = false;
|
||||
|
||||
if(((mContentLength <= 0) || !mReassembleChunks) && !mChunkedEncoding) {
|
||||
if(((mContentLength <= 0) || !mReassembleChunks)
|
||||
&& !mChunkedEncoding) {
|
||||
// Reassemble the chunks (NOTE: gzip is applied only after all the chunks are collected)
|
||||
PayloadChunk headers = reassembleChunks(mHeaders);
|
||||
PayloadChunk body = mBody.size() > 0 ? reassembleChunks(mBody) : null;
|
||||
|
||||
//log_d("mContentLength=" + mContentLength + ", mReassembleChunks=" + mReassembleChunks + ", mChunkedEncoding=" + mChunkedEncoding);
|
||||
|
||||
// Decode body
|
||||
if((body != null) && (mContentEncoding != ContentEncoding.UNKNOWN))
|
||||
decodeBody(body);
|
||||
@ -245,7 +259,7 @@ public class HTTPReassembly {
|
||||
|
||||
if((new_body_start > 0) && (chunk.payload.length > new_body_start)) {
|
||||
// Part of this chunk should be processed as a new chunk
|
||||
Log.d(TAG, "Continue from " + new_body_start);
|
||||
log_d("Continue from " + new_body_start);
|
||||
handleChunk(chunk.subchunk(new_body_start, chunk.payload.length - new_body_start));
|
||||
}
|
||||
}
|
||||
@ -254,7 +268,7 @@ public class HTTPReassembly {
|
||||
private void decodeBody(PayloadChunk body) {
|
||||
InputStream inputStream = null;
|
||||
|
||||
//Log.d(TAG, "Decoding as " + mContentEncoding.name().toLowerCase());
|
||||
//log_d("Decoding as " + mContentEncoding.name().toLowerCase());
|
||||
|
||||
try(ByteArrayInputStream bis = new ByteArrayInputStream(body.payload)) {
|
||||
switch (mContentEncoding) {
|
||||
@ -282,7 +296,7 @@ public class HTTPReassembly {
|
||||
}
|
||||
}
|
||||
} catch (IOException ignored) {
|
||||
Log.d(TAG, mContentEncoding.name().toLowerCase() + " decoding failed");
|
||||
log_d(mContentEncoding.name().toLowerCase() + " decoding failed");
|
||||
//ignored.printStackTrace();
|
||||
} finally {
|
||||
Utils.safeClose(inputStream);
|
||||
|
||||
@ -55,14 +55,14 @@ public class ConnectionDetailsActivity extends BaseActivity implements Connectio
|
||||
private int mCurChunks;
|
||||
private boolean mListenerSet;
|
||||
private boolean mHasPayload;
|
||||
private boolean mHasRequestTab;
|
||||
private boolean mHasResponseTab;
|
||||
private boolean mHasHttpTab;
|
||||
private boolean mHasWsTab;
|
||||
private final ArrayList<ConnUpdateListener> mListeners = new ArrayList<>();
|
||||
|
||||
private static final int POS_OVERVIEW = 0;
|
||||
private static final int POS_REQUEST = 1;
|
||||
private static final int POS_RESPONSE = 2;
|
||||
private static final int POS_PAYLOAD = 3;
|
||||
private static final int POS_WEBSOCKET = 1;
|
||||
private static final int POS_HTTP = 2;
|
||||
private static final int POS_RAW_PAYLOAD = 3;
|
||||
|
||||
public interface ConnUpdateListener {
|
||||
void connectionUpdated();
|
||||
@ -134,12 +134,12 @@ public class ConnectionDetailsActivity extends BaseActivity implements Connectio
|
||||
int pos = getVisibleTabsPositions()[position];
|
||||
|
||||
switch (pos) {
|
||||
case POS_REQUEST:
|
||||
return ConnectionPayload.newInstance(ConnectionPayload.Direction.REQUEST_ONLY);
|
||||
case POS_RESPONSE:
|
||||
return ConnectionPayload.newInstance(ConnectionPayload.Direction.RESPONSE_ONLY);
|
||||
case POS_PAYLOAD:
|
||||
return ConnectionPayload.newInstance(ConnectionPayload.Direction.BOTH);
|
||||
case POS_WEBSOCKET:
|
||||
return ConnectionPayload.newInstance(PayloadChunk.ChunkType.WEBSOCKET);
|
||||
case POS_HTTP:
|
||||
return ConnectionPayload.newInstance(PayloadChunk.ChunkType.HTTP);
|
||||
case POS_RAW_PAYLOAD:
|
||||
return ConnectionPayload.newInstance(PayloadChunk.ChunkType.RAW);
|
||||
case POS_OVERVIEW:
|
||||
default:
|
||||
return new ConnectionOverview();
|
||||
@ -147,18 +147,18 @@ public class ConnectionDetailsActivity extends BaseActivity implements Connectio
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() { return 1 + (mHasPayload ? 1 : 0) + (mHasRequestTab ? 1 : 0) + (mHasResponseTab ? 1 : 0); }
|
||||
public int getItemCount() { return 1 + (mHasPayload ? 1 : 0) + (mHasHttpTab ? 1 : 0) + (mHasWsTab ? 1 : 0); }
|
||||
|
||||
public int getPageTitle(final int position) {
|
||||
int pos = getVisibleTabsPositions()[position];
|
||||
|
||||
switch (pos) {
|
||||
case POS_REQUEST:
|
||||
return R.string.request;
|
||||
case POS_RESPONSE:
|
||||
return R.string.response;
|
||||
case POS_PAYLOAD:
|
||||
return R.string.payload;
|
||||
case POS_WEBSOCKET:
|
||||
return R.string.websocket;
|
||||
case POS_HTTP:
|
||||
return R.string.http;
|
||||
case POS_RAW_PAYLOAD:
|
||||
return R.string.raw_payload;
|
||||
case POS_OVERVIEW:
|
||||
default:
|
||||
return R.string.overview;
|
||||
@ -171,12 +171,12 @@ public class ConnectionDetailsActivity extends BaseActivity implements Connectio
|
||||
|
||||
visible[i++] = POS_OVERVIEW;
|
||||
|
||||
if(mHasRequestTab)
|
||||
visible[i++] = POS_REQUEST;
|
||||
if(mHasResponseTab)
|
||||
visible[i++] = POS_RESPONSE;
|
||||
if(mHasWsTab)
|
||||
visible[i++] = POS_WEBSOCKET;
|
||||
if(mHasHttpTab)
|
||||
visible[i++] = POS_HTTP;
|
||||
if(mHasPayload)
|
||||
visible[i] = POS_PAYLOAD;
|
||||
visible[i] = POS_RAW_PAYLOAD;
|
||||
|
||||
return visible;
|
||||
}
|
||||
@ -254,7 +254,7 @@ public class ConnectionDetailsActivity extends BaseActivity implements Connectio
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
private void recheckTabs() {
|
||||
if(mHasRequestTab && mHasResponseTab)
|
||||
if(mHasHttpTab && mHasWsTab)
|
||||
return;
|
||||
|
||||
int max_check = Math.min(mConn.getNumPayloadChunks(), MAX_CHUNKS_TO_CHECK);
|
||||
@ -268,14 +268,12 @@ public class ConnectionDetailsActivity extends BaseActivity implements Connectio
|
||||
for(int i=mCurChunks; i<max_check; i++) {
|
||||
PayloadChunk chunk = mConn.getPayloadChunk(i);
|
||||
|
||||
if((chunk.type == PayloadChunk.ChunkType.HTTP) || (chunk.type == PayloadChunk.ChunkType.WEBSOCKET)) {
|
||||
if(chunk.is_sent && !mHasRequestTab) {
|
||||
mHasRequestTab = true;
|
||||
changed = true;
|
||||
} else if(!chunk.is_sent && !mHasResponseTab) {
|
||||
mHasResponseTab = true;
|
||||
changed = true;
|
||||
}
|
||||
if(!mHasHttpTab && (chunk.type == PayloadChunk.ChunkType.HTTP)) {
|
||||
mHasHttpTab = true;
|
||||
changed = true;
|
||||
} else if (!mHasWsTab && (chunk.type == PayloadChunk.ChunkType.WEBSOCKET)) {
|
||||
mHasWsTab = true;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -34,7 +34,6 @@ import com.emanuelef.remote_capture.CaptureService;
|
||||
import com.emanuelef.remote_capture.HTTPReassembly;
|
||||
import com.emanuelef.remote_capture.R;
|
||||
import com.emanuelef.remote_capture.Utils;
|
||||
import com.emanuelef.remote_capture.fragments.ConnectionPayload.Direction;
|
||||
import com.emanuelef.remote_capture.model.ConnectionDescriptor;
|
||||
import com.emanuelef.remote_capture.model.PayloadChunk;
|
||||
import com.emanuelef.remote_capture.model.PayloadChunk.ChunkType;
|
||||
@ -56,19 +55,25 @@ public class PayloadAdapter extends RecyclerView.Adapter<PayloadAdapter.PayloadV
|
||||
private final LayoutInflater mLayoutInflater;
|
||||
private final ConnectionDescriptor mConn;
|
||||
private final Context mContext;
|
||||
private final Direction mDir;
|
||||
private final ChunkType mMode;
|
||||
private int mHandledChunks;
|
||||
private final ArrayList<AdapterChunk> mChunks = new ArrayList<>();
|
||||
private final HTTPReassembly mHttp;
|
||||
private final HTTPReassembly mHttpReq;
|
||||
private final HTTPReassembly mHttpRes;
|
||||
|
||||
public PayloadAdapter(Context context, ConnectionDescriptor conn, Direction dir) {
|
||||
public PayloadAdapter(Context context, ConnectionDescriptor conn, ChunkType mode) {
|
||||
mLayoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
mConn = conn;
|
||||
mContext = context;
|
||||
mDir = dir;
|
||||
mMode = mode;
|
||||
|
||||
// Note: in minimal mode, only the first chunk is captured, so don't reassemble them
|
||||
mHttp = new HTTPReassembly(CaptureService.getCurPayloadMode() == Prefs.PayloadMode.FULL, this);
|
||||
boolean reassemble = (CaptureService.getCurPayloadMode() == Prefs.PayloadMode.FULL);
|
||||
|
||||
// each direction must have its separate reassembly
|
||||
mHttpReq = new HTTPReassembly(reassemble, this);
|
||||
mHttpRes = new HTTPReassembly(reassemble, this);
|
||||
|
||||
handleChunksAdded(mConn.getNumPayloadChunks());
|
||||
}
|
||||
|
||||
@ -103,7 +108,7 @@ public class PayloadAdapter extends RecyclerView.Adapter<PayloadAdapter.PayloadV
|
||||
private void makeText() {
|
||||
int dump_len = mIsExpanded ? mChunk.payload.length : Math.min(mChunk.payload.length, COLLAPSE_CHUNK_SIZE);
|
||||
|
||||
if(isPayloadTab())
|
||||
if(mMode == ChunkType.RAW)
|
||||
mTheText = Utils.hexdump(mChunk.payload, 0, dump_len);
|
||||
else
|
||||
mTheText = new String(mChunk.payload, 0, dump_len, StandardCharsets.UTF_8);
|
||||
@ -203,40 +208,38 @@ public class PayloadAdapter extends RecyclerView.Adapter<PayloadAdapter.PayloadV
|
||||
|
||||
if(page.adaptChunk.isExpanded()) {
|
||||
int numPages = page.adaptChunk.getNumPages();
|
||||
int firstPagePos = pos - (numPages - 1);
|
||||
page.adaptChunk.collapse();
|
||||
notifyItemRangeRemoved(pos - (numPages - 1), numPages - 1);
|
||||
notifyItemChanged(firstPagePos);
|
||||
notifyItemRangeRemoved(firstPagePos + 1, numPages - 1);
|
||||
} else {
|
||||
page.adaptChunk.expand();
|
||||
notifyItemChanged(pos);
|
||||
notifyItemRangeInserted(pos + 1, page.adaptChunk.getNumPages() - 1);
|
||||
}
|
||||
|
||||
notifyItemChanged(pos);
|
||||
});
|
||||
|
||||
return holder;
|
||||
}
|
||||
|
||||
private String getHeaderTag(PayloadChunk chunk) {
|
||||
if(mMode == ChunkType.HTTP)
|
||||
return (chunk.is_sent) ? mContext.getString(R.string.request) : mContext.getString(R.string.response);
|
||||
else
|
||||
return chunk.is_sent ? mContext.getString(R.string.tx_direction) : mContext.getString(R.string.rx_direction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull PayloadViewHolder holder, int position) {
|
||||
Page page = getItem(position);
|
||||
Locale locale = Utils.getPrimaryLocale(mContext);
|
||||
String prefix = "";
|
||||
PayloadChunk chunk = page.adaptChunk.getPayloadChunk();
|
||||
|
||||
if(page.isFirst()) {
|
||||
// Show the header for the first page
|
||||
if(!isPayloadTab()) {
|
||||
// NOTE: do not add the prefix in the "Payload" tab, as the chunk is not analyzed by the
|
||||
// HTTPReassembly
|
||||
if(chunk.type == ChunkType.HTTP)
|
||||
prefix = "HTTP_";
|
||||
else if(chunk.type == ChunkType.WEBSOCKET)
|
||||
prefix = "WS_";
|
||||
}
|
||||
Locale locale = Utils.getPrimaryLocale(mContext);
|
||||
|
||||
holder.header.setText(String.format(locale,
|
||||
"#%d [%s%s] %s — %s", page.adaptChunk.originalPos + 1,
|
||||
prefix, chunk.is_sent ? "TX" : "RX",
|
||||
"#%d [%s] %s — %s", page.adaptChunk.originalPos + 1,
|
||||
getHeaderTag(chunk),
|
||||
(new SimpleDateFormat("HH:mm:ss.SSS", locale)).format(new Date(chunk.timestamp)),
|
||||
Utils.formatBytes(chunk.payload.length)));
|
||||
holder.header.setVisibility(View.VISIBLE);
|
||||
@ -295,24 +298,24 @@ public class PayloadAdapter extends RecyclerView.Adapter<PayloadAdapter.PayloadV
|
||||
return mChunks.get(i).getPage(pageIdx);
|
||||
}
|
||||
|
||||
private boolean isPayloadTab() {
|
||||
return(mDir == Direction.BOTH);
|
||||
}
|
||||
|
||||
public void handleChunksAdded(int tot_chunks) {
|
||||
for(int i = mHandledChunks; i<tot_chunks; i++) {
|
||||
PayloadChunk chunk = mConn.getPayloadChunk(i);
|
||||
|
||||
if((mDir == Direction.BOTH) ||
|
||||
(mDir == Direction.REQUEST_ONLY && chunk.is_sent) ||
|
||||
(mDir == Direction.RESPONSE_ONLY && !chunk.is_sent)) {
|
||||
if(!isPayloadTab() && (chunk.type == ChunkType.HTTP))
|
||||
mHttp.handleChunk(chunk); // will call onChunkReassembled
|
||||
else {
|
||||
int insert_pos = getItemCount();
|
||||
mChunks.add(new AdapterChunk(chunk, mChunks.size()));
|
||||
notifyItemInserted(insert_pos);
|
||||
}
|
||||
// Exclude unrelated chunks
|
||||
if((mMode != ChunkType.RAW) && (mMode != chunk.type))
|
||||
continue;
|
||||
|
||||
if(mMode == ChunkType.HTTP) {
|
||||
// will call onChunkReassembled
|
||||
if(chunk.is_sent)
|
||||
mHttpReq.handleChunk(chunk);
|
||||
else
|
||||
mHttpRes.handleChunk(chunk);
|
||||
} else {
|
||||
int insert_pos = getItemCount();
|
||||
mChunks.add(new AdapterChunk(chunk, mChunks.size()));
|
||||
notifyItemInserted(insert_pos);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -34,10 +34,9 @@ import com.emanuelef.remote_capture.R;
|
||||
import com.emanuelef.remote_capture.activities.ConnectionDetailsActivity;
|
||||
import com.emanuelef.remote_capture.adapters.PayloadAdapter;
|
||||
import com.emanuelef.remote_capture.model.ConnectionDescriptor;
|
||||
import com.emanuelef.remote_capture.model.PayloadChunk;
|
||||
import com.emanuelef.remote_capture.views.EmptyRecyclerView;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class ConnectionPayload extends Fragment implements ConnectionDetailsActivity.ConnUpdateListener {
|
||||
private ConnectionDetailsActivity mActivity;
|
||||
private ConnectionDescriptor mConn;
|
||||
@ -45,16 +44,10 @@ public class ConnectionPayload extends Fragment implements ConnectionDetailsActi
|
||||
private TextView mTruncatedWarning;
|
||||
private int mCurChunks;
|
||||
|
||||
public enum Direction implements Serializable {
|
||||
REQUEST_ONLY,
|
||||
RESPONSE_ONLY,
|
||||
BOTH
|
||||
}
|
||||
|
||||
public static ConnectionPayload newInstance(Direction dir) {
|
||||
public static ConnectionPayload newInstance(PayloadChunk.ChunkType mode) {
|
||||
ConnectionPayload fragment = new ConnectionPayload();
|
||||
Bundle args = new Bundle();
|
||||
args.putSerializable("direction", dir);
|
||||
args.putSerializable("mode", mode);
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
@ -83,11 +76,11 @@ public class ConnectionPayload extends Fragment implements ConnectionDetailsActi
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
Bundle args = getArguments();
|
||||
Direction dir;
|
||||
if((args != null) && args.containsKey("direction"))
|
||||
dir = (Direction) args.getSerializable("direction");
|
||||
PayloadChunk.ChunkType mode;
|
||||
if((args != null) && args.containsKey("mode"))
|
||||
mode = (PayloadChunk.ChunkType) args.getSerializable("mode");
|
||||
else
|
||||
dir = Direction.BOTH;
|
||||
mode = PayloadChunk.ChunkType.RAW;
|
||||
|
||||
EmptyRecyclerView recyclerView = view.findViewById(R.id.payload);
|
||||
EmptyRecyclerView.MyLinearLayoutManager layoutMan = new EmptyRecyclerView.MyLinearLayoutManager(requireContext());
|
||||
@ -98,7 +91,7 @@ public class ConnectionPayload extends Fragment implements ConnectionDetailsActi
|
||||
if(mConn.isPayloadTruncated())
|
||||
mTruncatedWarning.setVisibility(View.VISIBLE);
|
||||
|
||||
mAdapter = new PayloadAdapter(requireContext(), mConn, dir);
|
||||
mAdapter = new PayloadAdapter(requireContext(), mConn, mode);
|
||||
mCurChunks = mConn.getNumPayloadChunks();
|
||||
recyclerView.setAdapter(mAdapter);
|
||||
}
|
||||
|
||||
@ -28,7 +28,8 @@ public class PayloadChunk implements Serializable {
|
||||
public long timestamp;
|
||||
public ChunkType type;
|
||||
|
||||
public enum ChunkType {
|
||||
// Serializable need in ConnectionPayload fragment
|
||||
public enum ChunkType implements Serializable {
|
||||
RAW,
|
||||
HTTP,
|
||||
WEBSOCKET
|
||||
|
||||
@ -299,7 +299,6 @@
|
||||
<string name="payload_mode_none">The connections payload will not be shown</string>
|
||||
<string name="payload_mode_minimal">Only the initial bytes of the payload will be shown</string>
|
||||
<string name="payload_mode_full">The full payload will be shown (e.g. the full HTTP request and response). This requires a lot of memory</string>
|
||||
<string name="payload">Payload</string>
|
||||
<string name="connection">Connection</string>
|
||||
<string name="encrypted">Encrypted</string>
|
||||
<string name="cleartext">Cleartext</string>
|
||||
@ -310,4 +309,9 @@
|
||||
<string name="string_http_response">HTTP response</string>
|
||||
<string name="payload_visualization">Payload visualization</string>
|
||||
<string name="payload_truncated">Only a portion of the actual payload is shown, see \"%1$s\"</string>
|
||||
<string name="websocket">WebSocket</string>
|
||||
<string name="http">HTTP</string>
|
||||
<string name="raw_payload">Raw</string>
|
||||
<string name="tx_direction">TX</string>
|
||||
<string name="rx_direction">RX</string>
|
||||
</resources>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user