diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/DHT.c | 104 |
1 files changed, 62 insertions, 42 deletions
@@ -1053,21 +1053,24 @@ int friend_ips(IP_Port * ip_portlist, uint8_t * friend_id) | |||
1053 | int send_NATping(uint8_t * public_key, uint64_t ping_id, uint8_t type) | 1053 | int send_NATping(uint8_t * public_key, uint64_t ping_id, uint8_t type) |
1054 | { | 1054 | { |
1055 | uint8_t data[sizeof(uint64_t) + 1]; | 1055 | uint8_t data[sizeof(uint64_t) + 1]; |
1056 | uint8_t packet[MAX_DATA_SIZE]; | ||
1057 | |||
1058 | /* 254 is NAT ping request packet id */ | ||
1059 | int len = create_request(packet, public_key, data, sizeof(uint64_t) + 1, 254); | ||
1060 | int num = 0; | ||
1061 | |||
1056 | data[0] = type; | 1062 | data[0] = type; |
1057 | memcpy(data + 1, &ping_id, sizeof(uint64_t)); | 1063 | memcpy(data + 1, &ping_id, sizeof(uint64_t)); |
1058 | 1064 | ||
1059 | uint8_t packet[MAX_DATA_SIZE]; | 1065 | if (len == -1) |
1060 | int len = create_request(packet, public_key, data, sizeof(uint64_t) + 1, 254); /* 254 is NAT ping request packet id */ | ||
1061 | if(len == -1) | ||
1062 | return -1; | 1066 | return -1; |
1063 | 1067 | ||
1064 | int num = 0; | 1068 | if (type == 0) /*If packet is request use many people to route it*/ |
1069 | num = route_tofriend(public_key, packet, len); | ||
1070 | else if (type == 1) /*If packet is response use only one person to route it*/ | ||
1071 | num = routeone_tofriend(public_key, packet, len); | ||
1065 | 1072 | ||
1066 | if(type == 0) | 1073 | if (num == 0) |
1067 | num = route_tofriend(public_key, packet, len);/*If packet is request use many people to route it*/ | ||
1068 | else if(type == 1) | ||
1069 | num = routeone_tofriend(public_key, packet, len);/*If packet is response use only one person to route it*/ | ||
1070 | if(num == 0) | ||
1071 | return -1; | 1074 | return -1; |
1072 | return num; | 1075 | return num; |
1073 | } | 1076 | } |
@@ -1075,45 +1078,54 @@ int send_NATping(uint8_t * public_key, uint64_t ping_id, uint8_t type) | |||
1075 | /* Handle a recieved ping request for */ | 1078 | /* Handle a recieved ping request for */ |
1076 | int handle_NATping(uint8_t * packet, uint32_t length, IP_Port source) | 1079 | int handle_NATping(uint8_t * packet, uint32_t length, IP_Port source) |
1077 | { | 1080 | { |
1078 | if(length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING && | 1081 | if (length < crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + ENCRYPTION_PADDING |
1079 | length > MAX_DATA_SIZE + ENCRYPTION_PADDING) | 1082 | && length > MAX_DATA_SIZE + ENCRYPTION_PADDING) |
1080 | return 1; | 1083 | return 1; |
1084 | |||
1081 | /* check if request is for us. */ | 1085 | /* check if request is for us. */ |
1082 | if(memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { | 1086 | if (memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { |
1083 | uint8_t public_key[crypto_box_PUBLICKEYBYTES]; | 1087 | uint8_t public_key[crypto_box_PUBLICKEYBYTES]; |
1084 | uint8_t data[MAX_DATA_SIZE]; | 1088 | uint8_t data[MAX_DATA_SIZE]; |
1089 | |||
1085 | int len = handle_request(public_key, data, packet, length); | 1090 | int len = handle_request(public_key, data, packet, length); |
1086 | if(len != sizeof(uint64_t) + 1) | 1091 | if (len != sizeof(uint64_t) + 1) |
1087 | return 1; | 1092 | return 1; |
1093 | |||
1088 | uint64_t ping_id; | 1094 | uint64_t ping_id; |
1089 | memcpy(&ping_id, data + 1, sizeof(uint64_t)); | 1095 | memcpy(&ping_id, data + 1, sizeof(uint64_t)); |
1090 | 1096 | ||
1091 | int friendnumber = friend_number(public_key); | 1097 | int friendnumber = friend_number(public_key); |
1092 | if(friendnumber == -1) | 1098 | if (friendnumber == -1) |
1093 | return 1; | 1099 | return 1; |
1094 | 1100 | ||
1095 | if(data[0] == 0) { | 1101 | Friend * friend = &friends_list[friendnumber]; |
1096 | send_NATping(public_key, ping_id, 1); /*1 is reply*/ | 1102 | |
1097 | friends_list[friendnumber].recvNATping_timestamp = unix_time(); | 1103 | if (data[0] == 0) { |
1104 | /* 1 is reply */ | ||
1105 | send_NATping(public_key, ping_id, 1); | ||
1106 | friend->recvNATping_timestamp = unix_time(); | ||
1098 | return 0; | 1107 | return 0; |
1099 | } else if (data[0] == 1) | 1108 | } else if (data[0] == 1) { |
1100 | if(friends_list[friendnumber].NATping_id == ping_id) { | 1109 | if (friend->NATping_id == ping_id) { |
1101 | friends_list[friendnumber].NATping_id = ((uint64_t)random_int() << 32) + random_int(); | 1110 | friend->NATping_id = ((uint64_t)random_int() << 32) + random_int(); |
1102 | friends_list[friendnumber].hole_punching = 1; | 1111 | friend->hole_punching = 1; |
1103 | return 0; | 1112 | return 0; |
1104 | } | 1113 | } |
1114 | } | ||
1105 | return 1; | 1115 | return 1; |
1106 | } | 1116 | } |
1117 | |||
1107 | /* if request is not for us, try routing it. */ | 1118 | /* if request is not for us, try routing it. */ |
1108 | else if(route_packet(packet + 1, packet, length) == length) | 1119 | route_packet(packet + 1, packet, length); |
1109 | return 0; | 1120 | |
1110 | return 0; | 1121 | return 0; |
1111 | } | 1122 | } |
1112 | 1123 | ||
1113 | /*Get the most common ip in the ip_portlist | 1124 | /* Get the most common ip in the ip_portlist |
1114 | Only return ip if it appears in list min_num or more | 1125 | * Only return ip if it appears in list min_num or more |
1115 | len must not be bigger than MAX_FRIEND_CLIENTS | 1126 | * len must not be bigger than MAX_FRIEND_CLIENTS |
1116 | return ip of 0 if failure */ | 1127 | * return ip of 0 if failure |
1128 | */ | ||
1117 | static IP NAT_commonip(IP_Port * ip_portlist, uint16_t len, uint16_t min_num) | 1129 | static IP NAT_commonip(IP_Port * ip_portlist, uint16_t len, uint16_t min_num) |
1118 | { | 1130 | { |
1119 | IP zero = {{0}}; | 1131 | IP zero = {{0}}; |
@@ -1122,29 +1134,34 @@ static IP NAT_commonip(IP_Port * ip_portlist, uint16_t len, uint16_t min_num) | |||
1122 | 1134 | ||
1123 | uint32_t i, j; | 1135 | uint32_t i, j; |
1124 | uint16_t numbers[MAX_FRIEND_CLIENTS] = {0}; | 1136 | uint16_t numbers[MAX_FRIEND_CLIENTS] = {0}; |
1137 | |||
1125 | for(i = 0; i < len; ++i) { | 1138 | for(i = 0; i < len; ++i) { |
1126 | for(j = 0; j < len; ++j) | 1139 | for(j = 0; j < len; ++j) { |
1127 | if(ip_portlist[i].ip.i == ip_portlist[j].ip.i) | 1140 | if(ip_portlist[i].ip.i == ip_portlist[j].ip.i) |
1128 | ++numbers[i]; | 1141 | ++numbers[i]; |
1142 | } | ||
1129 | if(numbers[i] >= min_num) | 1143 | if(numbers[i] >= min_num) |
1130 | return ip_portlist[i].ip; | 1144 | return ip_portlist[i].ip; |
1131 | } | 1145 | } |
1132 | return zero; | 1146 | return zero; |
1133 | } | 1147 | } |
1134 | 1148 | ||
1135 | /*Return all the ports for one ip in a list | 1149 | /* Return all the ports for one ip in a list |
1136 | portlist must be at least len long | 1150 | * portlist must be at least len long |
1137 | where len is the length of ip_portlist | 1151 | * where len is the length of ip_portlist |
1138 | returns the number of ports and puts the list of ports in portlist*/ | 1152 | * returns the number of ports and puts the list of ports in portlist |
1153 | */ | ||
1139 | static uint16_t NAT_getports(uint16_t * portlist, IP_Port * ip_portlist, uint16_t len, IP ip) | 1154 | static uint16_t NAT_getports(uint16_t * portlist, IP_Port * ip_portlist, uint16_t len, IP ip) |
1140 | { | 1155 | { |
1141 | uint32_t i; | 1156 | uint32_t i; |
1142 | uint16_t num = 0; | 1157 | uint16_t num = 0; |
1143 | for(i = 0; i < len; ++i) | 1158 | |
1159 | for(i = 0; i < len; ++i) { | ||
1144 | if(ip_portlist[i].ip.i == ip.i) { | 1160 | if(ip_portlist[i].ip.i == ip.i) { |
1145 | portlist[num] = ntohs(ip_portlist[i].port); | 1161 | portlist[num] = ntohs(ip_portlist[i].port); |
1146 | ++num; | 1162 | ++num; |
1147 | } | 1163 | } |
1164 | } | ||
1148 | return num; | 1165 | return num; |
1149 | } | 1166 | } |
1150 | 1167 | ||
@@ -1152,8 +1169,10 @@ static void punch_holes(IP ip, uint16_t * port_list, uint16_t numports, uint16_t | |||
1152 | { | 1169 | { |
1153 | if(numports > MAX_FRIEND_CLIENTS || numports == 0) | 1170 | if(numports > MAX_FRIEND_CLIENTS || numports == 0) |
1154 | return; | 1171 | return; |
1172 | |||
1155 | uint32_t i; | 1173 | uint32_t i; |
1156 | uint32_t top = friends_list[friend_num].punching_index + MAX_PUNCHING_PORTS; | 1174 | uint32_t top = friends_list[friend_num].punching_index + MAX_PUNCHING_PORTS; |
1175 | |||
1157 | for(i = friends_list[friend_num].punching_index; i != top; i++) { | 1176 | for(i = friends_list[friend_num].punching_index; i != top; i++) { |
1158 | /*TODO: improve port guessing algorithm*/ | 1177 | /*TODO: improve port guessing algorithm*/ |
1159 | uint16_t port = port_list[(i/2) % numports] + (i/(2*numports))*((i % 2) ? -1 : 1); | 1178 | uint16_t port = port_list[(i/2) % numports] + (i/(2*numports))*((i % 2) ? -1 : 1); |
@@ -1165,25 +1184,26 @@ static void punch_holes(IP ip, uint16_t * port_list, uint16_t numports, uint16_t | |||
1165 | 1184 | ||
1166 | static void doNAT() | 1185 | static void doNAT() |
1167 | { | 1186 | { |
1168 | uint32_t i; | 1187 | uint32_t i, temp_time = unix_time(); |
1169 | uint32_t temp_time = unix_time(); | 1188 | |
1170 | for(i = 0; i < num_friends; ++i) { | 1189 | for (i = 0; i < num_friends; ++i) { |
1171 | IP_Port ip_list[MAX_FRIEND_CLIENTS]; | 1190 | IP_Port ip_list[MAX_FRIEND_CLIENTS]; |
1172 | int num = friend_iplist(ip_list, i); | 1191 | int num = friend_iplist(ip_list, i); |
1173 | /*If we are connected to friend or if friend is not online don't try to hole punch with him*/ | ||
1174 | if(num < MAX_FRIEND_CLIENTS/2) | ||
1175 | continue; | ||
1176 | 1192 | ||
1193 | /*If already connected or friend is not online don't try to hole punch*/ | ||
1194 | if (num < MAX_FRIEND_CLIENTS/2) | ||
1195 | continue; | ||
1177 | 1196 | ||
1178 | if(friends_list[i].NATping_timestamp + PUNCH_INTERVAL < temp_time) { | 1197 | if (friends_list[i].NATping_timestamp + PUNCH_INTERVAL < temp_time) { |
1179 | send_NATping(friends_list[i].client_id, friends_list[i].NATping_id, 0); /*0 is request*/ | 1198 | send_NATping(friends_list[i].client_id, friends_list[i].NATping_id, 0); /*0 is request*/ |
1180 | friends_list[i].NATping_timestamp = temp_time; | 1199 | friends_list[i].NATping_timestamp = temp_time; |
1181 | } | 1200 | } |
1182 | if(friends_list[i].hole_punching == 1 && | 1201 | if (friends_list[i].hole_punching == 1 && |
1183 | friends_list[i].punching_timestamp + PUNCH_INTERVAL < temp_time && | 1202 | friends_list[i].punching_timestamp + PUNCH_INTERVAL < temp_time && |
1184 | friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL*2 >= temp_time) { | 1203 | friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL*2 >= temp_time) { |
1204 | |||
1185 | IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS/2); | 1205 | IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS/2); |
1186 | if(ip.i == 0) | 1206 | if (ip.i == 0) |
1187 | continue; | 1207 | continue; |
1188 | 1208 | ||
1189 | uint16_t port_list[MAX_FRIEND_CLIENTS]; | 1209 | uint16_t port_list[MAX_FRIEND_CLIENTS]; |