📄 aenet.cpp
字号:
void
traceRoute(
JNIEnv* env,
jobject callback,
unsigned short trace_id,
unsigned long source_ip,
unsigned long target_ip,
unsigned int send_sock,
unsigned int receive_sock,
bool ping_mode )
{
char receive_buffer[ sizeof(ip_header) + sizeof(icmp_header) + 1024];
unsigned short source_port = TRACE_ROUTE_BASE_PORT;
unsigned short target_port = TRACE_ROUTE_BASE_PORT;
int seq = 0;
bool complete = false;
bool use_udp = true;
bool use_icmp = true;
int ttl;
if ( ping_mode ){
ttl = 32;
}else{
ttl = 0;
}
while( ttl < 33 && ( ping_mode || !complete )){
complete = false;
if ( !ping_mode ){
ttl++;
}
// try each node up to 3 times
bool probe_successful = false;
for (int probe_count=0; probe_count<3 && !( complete || probe_successful); probe_count++){
int probe_sequence = seq++;
if ( !sendTraceRouteMessage( env, trace_id, ttl, send_sock, receive_sock, source_ip, source_port, target_ip, target_port + probe_sequence, use_udp, use_icmp )){
// send failed, exception already reported
return;
}
unsigned long start_ticks = 0;
while( !complete ){
int receive_timeout = PROBE_TIMEOUT;
unsigned long current_ticks = GetTickCount();
if ( start_ticks == 0 ){
start_ticks = current_ticks;
}else{
receive_timeout -= ( current_ticks - start_ticks );
}
if ( receive_timeout <= 0 ){
if ( !traceRouteReportTimeout( env, callback, ttl )){
return;
}
break;
}
if( setsockopt(receive_sock, SOL_SOCKET, SO_RCVTIMEO, (char *) &receive_timeout, sizeof(receive_timeout)) == SOCKET_ERROR ){
throwException( env, "setsockopt", "failed to set receive timeout socket options" );
return;
}
struct sockaddr_in from;
int from_len = sizeof( from );
unsigned int read_len = recvfrom( receive_sock, receive_buffer, sizeof( receive_buffer ), 0, (struct sockaddr *)&from, &from_len );
if ( read_len == SOCKET_ERROR ){
if ( WSAGetLastError() == WSAETIMEDOUT ){
if ( !traceRouteReportTimeout( env, callback, ttl )){
return;
}
break;
}else{
throwException( env, "recvfrom", "operation failed", WSAGetLastError());
return;
}
}else{
if ( read_len < sizeof( 4 )){
// printf( "invalid packet read - length < 4\n" );
continue;
}
ip_header *ip = (ip_header *)receive_buffer;
unsigned char ip_len = ip->ip_header_len << 2;
unsigned short total_len = ntohs( ip->total_len );
// ensure we have a whole packet and an icmp reply
if ( read_len != total_len || read_len < ip_len + sizeof(icmp_header)){
// printf( "invalid packet read - read_len != total_len\n" );
continue;
}
int elapsed_time = (int)( GetTickCount() - current_ticks );
icmp_header *icmp = (icmp_header *)(receive_buffer + ip_len );
unsigned char icmp_type = icmp->type;
if ( icmp_type == ICMP_TYPE_ECHO_REPLY ){
icmp_echo_header *icmp = (icmp_echo_header *)(receive_buffer + ip_len );
unsigned short reply_seq = ntohs( icmp->sequence ) - TRACE_ROUTE_BASE_PORT;
if ( reply_seq != probe_sequence ){
continue;
}
traceRouteReportResult( env, callback, ttl, ntohl( from.sin_addr.s_addr ), elapsed_time, false );
if ( ping_mode ){
use_udp = false;
}
complete = true;
break;
}
if ( read_len != total_len || read_len < ip_len + sizeof(icmp_header) + sizeof( ip_header ) + 2){
// printf( "invalid packet read - read_len != total_len\n" );
continue;
}
ip_header* old_ip = (ip_header *)(receive_buffer + ip_len + sizeof( icmp_header ));
if ( icmp_type != ICMP_TYPE_TTL_EXCEEDED &&
icmp_type != ICMP_TYPE_UNREACHABLE ){
// printf( "Unexpected ICMP reply type %d\n", icmp_type );
continue;
}
if ( trace_id != ntohs(old_ip->ident )){
// not our reply
continue;
}
bool reply_was_udp;
if ( old_ip->protocol == IPPROTO_ICMP ){
icmp_probe_packet* probe = (icmp_probe_packet *)(receive_buffer + ip_len + sizeof( icmp_header ));
unsigned short reply_seq = ntohs( probe->icmp.sequence ) - TRACE_ROUTE_BASE_PORT;
if ( reply_seq != probe_sequence ){
continue;
}
reply_was_udp = false;
}else{
udp_probe_packet* probe = (udp_probe_packet *)(receive_buffer + ip_len + sizeof( icmp_header ));
unsigned short reply_seq = ntohs( probe->udp.dest_port ) - TRACE_ROUTE_BASE_PORT;
if ( reply_seq != probe_sequence ){
continue;
}
reply_was_udp = true;
}
probe_successful = true;
if ( icmp_type == ICMP_TYPE_ECHO_REPLY ){
complete = true;
}else if ( icmp_type == ICMP_TYPE_TTL_EXCEEDED ){
}else if ( icmp_type == ICMP_TYPE_UNREACHABLE ){
unsigned char icmp_code = icmp->code;
if ( icmp_code == ICMP_CODE_PROTOCOL_UNREACHABLE ||
icmp_code == ICMP_CODE_PORT_UNREACHABLE ){
// these are received from the target host
complete = true;
}else{
}
}
if ( ping_mode ){
if ( reply_was_udp ){
use_icmp = false;
}else{
use_udp = false;
}
}
if ( !traceRouteReportResult( env, callback, ttl, ntohl( from.sin_addr.s_addr ), elapsed_time, reply_was_udp )){
return;
}
break;
}
}
}
}
return;
}
JNIEXPORT void JNICALL
Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_traceRoute(
JNIEnv* env,
jclass cla,
jint trace_id,
jint source_ip,
jint target_ip,
jint ping_mode,
jobject callback )
{
initialiseWinsock();
int receive_sock = socket( AF_INET, SOCK_RAW, IPPROTO_ICMP );
if ( receive_sock == SOCKET_ERROR ) {
throwException( env, "socket", "failed to create receive socket" );
return;
}
int receive_timeout = PROBE_TIMEOUT;
if( setsockopt(receive_sock, SOL_SOCKET, SO_RCVTIMEO, (char *) &receive_timeout, sizeof(receive_timeout)) == SOCKET_ERROR ){
closesocket(receive_sock);
throwException( env, "setsockopt", "failed to set receive timeout socket options" );
return;
}
int so_reuseaddress = 1;
if( setsockopt(receive_sock, SOL_SOCKET, SO_REUSEADDR, (char *) &so_reuseaddress, sizeof(so_reuseaddress)) == SOCKET_ERROR ){
closesocket(receive_sock);
throwException( env, "setsockopt", "failed to set receive reuse address socket options" );
return;
}
// we have to bind the socket before we can receive ICMP messages on it
struct sockaddr_in recv_bind_addr;
recv_bind_addr.sin_family = AF_INET;
recv_bind_addr.sin_addr.s_addr = htonl( source_ip );
recv_bind_addr.sin_port = 0;
if ( bind( receive_sock, (struct sockaddr *)&recv_bind_addr, sizeof( recv_bind_addr )) == SOCKET_ERROR ){
closesocket(receive_sock);
throwException( env, "socket", "failed to bind send socket" );
return;
}
int send_sock = socket( AF_INET, SOCK_RAW, IPPROTO_RAW );
if ( send_sock == SOCKET_ERROR ) {
closesocket(receive_sock);
throwException( env, "socket", "failed to create send socket" );
return;
}
int enable = 1;
if ( setsockopt(send_sock, IPPROTO_IP, IP_HDRINCL, (char *)&enable,sizeof(enable)) == SOCKET_ERROR ){
closesocket(send_sock);
closesocket(receive_sock);
throwException( env, "setsockopt", "failed to set receive socket options" );
return;
}
traceRoute( env, callback, (unsigned short)trace_id, (unsigned long)source_ip, (unsigned long)target_ip, send_sock, receive_sock, ping_mode==1?true:false );
closesocket(send_sock);
closesocket(receive_sock);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -