package com.sprintwind.packetcapturetool;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.style.BackgroundColorSpan;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;
import android.widget.TextView;
public class PacketDetailActivity extends Activity {
private TextView txtvwPacketCharData;
private TextView txtvwPacketStringData;
private final String TEXTVIEW_TEXT_ALIGN = " ";
private final String LOG_TAG = "sprintwind";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_packet_detail);
Intent intent = this.getIntent();
byte[] packetContent = intent.getByteArrayExtra("packet_content");
txtvwPacketCharData = (TextView) findViewById(R.id.txtvwPacketCharData);
txtvwPacketStringData = (TextView) findViewById(R.id.txtvwPacketStringData);
initRawData(txtvwPacketCharData, txtvwPacketStringData, packetContent);
LinearLayout lnrlytPacketLayer = (LinearLayout) findViewById(R.id.lnrlytPacketLayer);
LayoutInflater inflater = LayoutInflater.from(this.getApplicationContext());
int start = 0;
/* 添加以太头视图 */
View view = inflater.inflate(R.layout.view_ether_header, null);
EtherHeader etherHeader = new EtherHeader();
etherHeader.initWithByteArray(packetContent, start);
initEtherHeaderView(view, etherHeader, start);
lnrlytPacketLayer.addView(view);
start += EtherHeader.ETH_HDR_LEN;
/* 如果是ARP协议,解析并添加ARP头 */
if(etherHeader.getProtocol() == EtherHeader.ETH_PROTO_ARP) {
/* 添加ARP头视图 */
view = inflater.inflate(R.layout.view_arp_header, null);
ArpHeader arpHeader = new ArpHeader();
arpHeader.initWithByteArray(packetContent, start);
initArpHeaderView(view, arpHeader, start);
lnrlytPacketLayer.addView(view);
}
/* 如果是IP协议,解析并添加IP头 */
else if(etherHeader.getProtocol() == EtherHeader.ETH_PROTO_IP) {
/* 添加IP头视图 */
view = inflater.inflate(R.layout.view_ip_header, null);
IpHeader ipHeader = new IpHeader();
ipHeader.initWithByteArray(packetContent, start);
initIpHeaderView(view, ipHeader, start);
lnrlytPacketLayer.addView(view);
start += ipHeader.getHeaderLen();
switch(ipHeader.getProtocol()){
case IpHeader.IP_PROTO_ICMP:
break;
case IpHeader.IP_PROTO_TCP:
/* 添加TCP头视图 */
view = inflater.inflate(R.layout.view_tcp_header, null);
TcpHeader tcpHeader = new TcpHeader();
tcpHeader.initWithByteArray(packetContent, start);
initTcpHeaderView(view, tcpHeader, start);
lnrlytPacketLayer.addView(view);
break;
case IpHeader.IP_PROTO_UDP:
/* 添加UDP头视图 */
view = inflater.inflate(R.layout.view_udp_header, null);
UdpHeader udpHeader = new UdpHeader();
udpHeader.initWithByteArray(packetContent, start);
initUdpHeaderView(view, udpHeader, start);
lnrlytPacketLayer.addView(view);
break;
}
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.packet_detail, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private void initEtherHeaderView(View view, EtherHeader etherHeader, int start) {
OnEtherHeaderItemClickListener onClickListener = new OnEtherHeaderItemClickListener();
TextView txtvwEtherDestMac = (TextView) view.findViewById(R.id.txtvwEtherDestMac);
txtvwEtherDestMac.setText("目的MAC:"+TEXTVIEW_TEXT_ALIGN+etherHeader.getDestMac().getMacString());
txtvwEtherDestMac.setOnClickListener(onClickListener);
TextView txtvwEtherSourceMac = (TextView) view.findViewById(R.id.txtvwEtherSourceMac);
txtvwEtherSourceMac.setText("源MAC:"+TEXTVIEW_TEXT_ALIGN+etherHeader.getSourceMac().getMacString());
txtvwEtherSourceMac.setOnClickListener(onClickListener);
TextView txtvwEtherProtocol = (TextView) view.findViewById(R.id.txtvwEtherProto);
txtvwEtherProtocol.setText("协议类型:"+TEXTVIEW_TEXT_ALIGN+etherHeader.getProtocolString());
txtvwEtherProtocol.setOnClickListener(onClickListener);
/* 设置边距 */
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
layoutParams.setMargins(5, 5, 5, 5);
view.setLayoutParams(layoutParams);
}
private class OnEtherHeaderItemClickListener implements OnClickListener {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
int originalBeginIndex = 0, originalEndIndex = 0;
int charDataStart = 0, charDataEnd = 0;
int stringDataStart = 0, stringDataEnd = 0;
String charData = txtvwPacketCharData.getText().toString();
SpannableStringBuilder ssbCharData = new SpannableStringBuilder(charData);
String stringData = txtvwPacketStringData.getText().toString();
SpannableStringBuilder ssbStringData = new SpannableStringBuilder(stringData);
switch(arg0.getId()){
case R.id.txtvwEtherDestMac:
originalBeginIndex = 0;
originalEndIndex = MacAddress.ETH_MAC_LEN;
break;
case R.id.txtvwEtherSourceMac:
originalBeginIndex = MacAddress.ETH_MAC_LEN;
originalEndIndex = originalBeginIndex + MacAddress.ETH_MAC_LEN;
break;
case R.id.txtvwEtherProto:
originalBeginIndex = MacAddress.ETH_MAC_LEN *2;
originalEndIndex = originalBeginIndex + ByteTranslater.BYTE_LEN_OF_SHORT;
break;
default:
break;
}
charDataStart = getCharDataBeginIndex(originalBeginIndex);
charDataEnd = getCharDataEndIndex(originalEndIndex);
stringDataStart = getStringDataBeginIndex(originalBeginIndex);
stringDataEnd = getStringDataEndIndex(originalEndIndex);
ssbCharData.setSpan(new BackgroundColorSpan(Color.parseColor("#ADD8E6")), charDataStart, charDataEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
txtvwPacketCharData.setText(ssbCharData);
ssbStringData.setSpan(new BackgroundColorSpan(Color.parseColor("#ADD8E6")), stringDataStart, stringDataEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
txtvwPacketStringData.setText(ssbStringData);
}
}
private int getCharDataBeginIndex(int originalIndex) {
if(originalIndex < 8) {
return originalIndex*3;
}
return originalIndex/8*24 + originalIndex%8*3 + 1;
}
private int getCharDataEndIndex(int originalIndex) {
if(originalIndex < 8){
return originalIndex/8*24 + originalIndex%8*3 - 1;
}
return originalIndex/8*24 + originalIndex%8*3;
}
private int getStringDataBeginIndex(int originalIndex) {
return originalIndex/8*9 + originalIndex%8;
}
private int getStringDataEndIndex(int originalIndex) {
return originalIndex/8*9 + originalIndex%8;
}
private void initArpHeaderView(View view, ArpHeader arpHeader, int start) {
TextView txtvwArpHardwareType = (TextView) view.findViewById(R.id.txtvwArpHardwareType);
txtvwArpHardwareType.setText("硬件类型:"+TEXTVIEW_TEXT_ALIGN+arpHeader.getHardwareTypeString());
TextView txtvwArpProtocolType = (TextView) view.findViewById(R.id.txtvwArpProtocolType);
txtvwArpProtocolType.setText("协议类型:"+TEXTVIEW_TEXT_ALIGN+arpHeader.getProtocolTypeString());
TextView txtvwArpHardwareAddressLen = (TextView) view.findViewById(R.id.txtvwArpHardwareAddressLen);
txtvwArpHardwareAddressLen.setText("硬件地址长度:"+TEXTVIEW_TEXT_ALIGN+arpHeader.getHardwareAddressLen());
TextView txtvwArpProtocolAddressLen = (TextView) view.findViewById(R.id.txtvwArpProtocolAddressLen);
txtvwArpProtocolAddressLen.setText("协议地址长度:"+TEXTVIEW_TEXT_ALIGN+arpHeader.getProtocolAddressLen());
TextView txtvwArpOperation = (TextView) view.findViewById(R.id.txtvwArpOperation);
txtvwArpOperation.setText("操作类型:"+TEXTVIEW_TEXT_ALIGN+arpHeader.getOperationString());
TextView txtvwArpSourceHardwareAddress = (TextView) view.findViewById(R.id.txtvwArpSourceHardwareAddress);
txtvwArpSourceHardwareAddress.setText("发送者硬件地址:"+TEXTVIEW_TEXT_ALIGN+arpHeader.getSourceHardwareAddressString());
TextView txtvwArpSourceIpAddress = (TextView) view.findViewById(R.id.txtvwArpSourceIpAddress);
txtvwArpSourceIpAddress.setText("发送者IP地址:"+TEXTVIEW_TEXT_ALIGN+arpHeader.getSourceProtocolAddress().getIpv4AddressString());
TextView txtvwArpDestHardwareAddress = (TextView) view.findViewById(R.id.txtvwArpDestHardwareAddress);
txtvwArpDestHardwareAddress.setText("接收者硬件地址:"+TEXTVIEW_TEXT_ALIGN+arpHeader.getDestHardwareAddressString());
TextView txtvwArpDestIpAddress = (TextView) view.findViewById(R.id.txtvwArpDestIpAddress);
txtvwArpDestIpAddress.setText("接收者IP地址:"+TEXTVIEW_TEXT_ALIGN+arpHeader.getDestProtocolAddress().getIpv4AddressString());
/* 设置边距 */
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
layoutParams.setMargins(5, 5, 5, 5);
view.setLayoutParams(layoutParams);
}
private void initIpHeaderView(View view, IpHeader ipHeader, int start) {
TextView txtvwIpVersion = (TextView) view.findViewById(R.id.txtvwIpVersion);
txtvwIpVersion.setText("版本号:"+TEXTVIEW_TEXT_ALIGN+ipHeader.getVersion());
TextView txtvwIpHeaderLength = (TextView) view.findViewById(R.id.txtvwIpHeaderLength);
txtvwIpHeaderLength.setText("头部长度:"+TEXTVIEW_TEXT_ALIGN+ipHeader.getHeaderLen());
TextView txtvwIpTOS = (TextView) view.findViewById(R.id.txtvwIpTOS);
txtvwIpTOS.setText("TOS:"+TEXTVIEW_TEXT_ALIGN+ipHeader.getTOS());
TextView txtvwIpTotalLength = (TextView) view.findViewById(R.id.txtvwIpTotalLength);
txtvwIpTotalLength.setText("总长度:"+TEXTVIEW_TEXT_ALIGN+ipHeader.getTotalLen());
TextView txtvwIpIdentification = (TextView) view.findViewById(R.id.txtvwIpIdentification);
txtvwIpIdentification.setText("ID:"+TEXTVIEW_TEXT_ALIGN+ipHeader.getIdentification());
TextView txtvwIpFlags = (TextView) view.findViewById(R.id.txtvwIpFlags);
txtvwIpFlags.setText("标志:"+TEXTVIEW_TEXT_ALIGN+ipHeader.getFlags());
TextView txtvwIpOffset = (TextView) view.findViewById(R.id.txtvwIpOffset);
txtvwIpOffset.setText("分片偏移:"+TEXTVIEW_TEXT_ALIGN+ipHeader.getOffset());
TextView txtvwIpTTL = (TextView) view.findViewById(R.id.txtvwIpTTL);
txtvwIpTTL.setText("TTL:"+TEXTVIEW_TEXT_ALIGN+ipHeader.getTTL());
TextView txtvwIpProtocol = (TextView) view.findViewById(R.id.txtvwIpProtocol);
txtvwIpProtocol.setText("协议类型:"+TEXTVIEW_TEXT_ALIGN+ipHeader.getProtocolString());
TextView txtvwIpChecksum = (TextView) view.findViewById(R.id.txtvwIpChecksum);
txtvwIpChecksum.setText("校验和:"+TEXTVIEW_TEXT_ALIGN+ipHeader.getChecksum());
TextView txtvwIpSourceIP = (TextView) view.findViewById(R.id.txtvwIpSourceIP);
txtvwIpSourceIP.setText("源IP:"+TEXTVIEW_TEXT_ALIGN+ipHeader.getSourceIp().getIpv4AddressString());
TextView txtvwIpDestIP = (TextView) view.findViewById(R.id.txtvwIpDestIP);
txtvwIpDestIP.setText("目的IP:"+TEXTVIEW_TEXT_ALIGN+ipHeader.getDestIp().getIpv4AddressString());
/* TODO: IP选项 */
/* 设置边距 */
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
layoutParams.setMargins(5, 5, 5, 5);
view.setLayoutParams(layoutParams);
}
private void initUdpHeaderView(View view, UdpHeader udpHeader, int start) {
TextView txtvwUdpSourcePort = (TextView) view.findViewById(R.id.txtvwUdpSourcePort);
txtvwUdpSourcePort.setText("源端口号:"+TEXTVIEW_TEXT_ALIGN+udpHeader.getSourcePort());
TextView txtvwUdpDestPort = (TextView) view.findViewById(R.id.txtvwUdpDestPort);
txtvwUdpDestPort.setText("目的端口号:"+TEXTVIEW_TEXT_ALIGN+udpHeader.getDestPort());
TextView txtvwUdpLength = (TextView) view.findViewById(R.id.txtvwUdpLength);
txtvwUdpLength.setText("长度:"+TEXTVIEW_TEXT_ALIGN+udpHeader.getLength());
TextView txtvwUdpCheckSum = (TextView) view.findViewById(R.id.txtvwUdpCheckSum);
txtvwUdpCheckSum.setText("校验和:"+TEXTVIEW_TEXT_ALIGN+udpHeader.getChecksum());
/* 设置边距 */
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
layoutParams.setMargins(5, 5, 5, 5);
view.setLayoutParams(layoutParams);
}
private void initTcpHeaderView(View view, TcpHeader tcpHeader, int start) {
TextView txtvwTcpSourcePort = (TextView) view.findViewById(R.id.txtvwTcpSourcePort);
txtvwTcpSourcePort.setText("源端口号:"+TEXTVIEW_TEXT_ALIGN+tcpHeader.getSourcePort());
TextView txtvwTcpDestPort = (TextView) view.findViewById(R.id.txtvwTcpDestPort);
txtvwTcpDestPort.setText("目的端口号:"+TEXTVIEW_TEXT_ALIGN+tcpHeader.getDestPort());
TextView txtvwTcpSeqNumber = (TextView) view.findViewById(R.id.txtvwTcpSeqNumber);
txtvwTcpSeqNumber.setText("序号:"+TEXTVIEW_TEXT_ALIGN+tcpHeader.getSequenceNumber());
TextView txtvwTcpAckNumber = (TextView) view.findViewById(R.id.txtvwTcpAckNumber);
txtvwTcpAckNumber.setText("应答序号:"+TEXTVIEW_TEXT_ALIGN+tcpHeader.getAckNumber());
TextView txtvwTcpDataOffset = (TextView) view.findViewById(R.id.txtvwTcpDataOffset);
txtvwTcpDataOffset.setText("头长度:"+TEXTVIEW_TEXT_ALIGN+tcpHeader.getHeaderLength());
TextView txtvwTcpReserve = (TextView) view.findViewById(R.id.txtvwTcpReserve);
txtvwTcpReserve.setText("保留字段:"+TEXTVIEW_TEXT_ALIGN+tcpHeader.getReserve());
TextView txtvwTcpFlags = (TextView) view.findViewById(R.id.txtvwTcpFlags);
txtvwTcpFlags.setText("标志位:"+TEXTVIEW_TEXT_ALIGN+tcpHeader.getFlagsString());
TextView txtvwTcpWindowSize = (TextView) view.findViewById(R.id.txtvwTcpWindowSize);
txtvwTcpWindowSize.setText("窗口大小:"+TEXTVIEW_TEXT_ALIGN+tcpHeader.getWindowSize());
TextView txtvwTcpCheckSum = (TextView) view.findViewById(R.id.txtvwTcpCheckSum);
txtvwTcpCheckSum.setText("校验和:"+TEXTVIEW_TEXT_ALIGN+tcpHeader.getChecksum());
TextView txtvwTcpUrgent = (TextView) view.findViewById(R.id.txtvwTcpUrgent);
txtvwTcpUrgent.setText("紧急指针:"+TEXTVIEW_TEXT_ALIGN+tcpHeader.getUrgent());
TextView txtvwTcpOptions = (TextView) view.findViewById(R.id.txtvwTcpOptions);
String tcpOptionsString = new String();
tcpOptionsString += "选项:"+TEXTVIEW_TEXT_ALIGN;
byte[] options = tcpHeader.getOptions();
int count = 0;
if(null != options) {
for(byte data:options) {
tcpOptionsString += String.format("%02x ", data);
++count;
if(count%8 == 0){
tcpOptionsString += '\n';
}
}
}
txtvwTcpOptions.setText(tcpOptionsString);
/* 设置边距 */
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
layoutParams.setMargins(5, 5, 5, 5);
view.setLayoutParams(layoutParams);
}
private void initRawData(TextView txtvwCharData, TextView txtvwStringData, byte[] packetContent) {
String charData = new String();
String stringData = new String();
int count = 0;
for(byte data:packetContent) {
charData = charData + String.format("%02x", data) + " ";
stringData = stringData + (char)data;
++count;
if(count%8 == 0) {
charData += '\n';
stringData += '\n';
}
}
txtvwCharData.setText(charData);
txtvwStringData.setText(stringData);
}
}