├── DeleteEmptyFolders.bat ├── Pings.bat └── optimize_app_store_hosts.py /DeleteEmptyFolders.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | set target=%1 3 | if not defined target ( 4 | goto :usage 5 | ) 6 | for /f "usebackq delims=^" %%j in (`"@dir /ad/b/s %target% | sort /r"`) do ( 7 | rd %%j 2>NUL 8 | ) 9 | echo All empty folders under %target% has been deleted. 10 | goto :EOF 11 | :usage 12 | echo Example: %~n0 [target_folder] 13 | -------------------------------------------------------------------------------- /Pings.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | set network=%1 3 | set findHost=0 4 | echo %network%| findstr "^[0-9]*\.[0-9]*\.[0-9]*$" > NUL 5 | if %errorlevel% NEQ 0 ( 6 | goto usage 7 | ) 8 | for /L %%i in (1,1,254) do ( 9 | for /f "usebackq delims=^" %%j in (`"@ping -n 1 -w 20 %network%.%%i | findstr TTL"`) do ( 10 | echo %%j 11 | set /a findHost += 1 12 | ) 13 | ) 14 | echo Find %findHost% hosts in %network%.* 15 | goto :EOF 16 | :usage 17 | echo Example: %~n0 192.168.0 18 | -------------------------------------------------------------------------------- /optimize_app_store_hosts.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import sys,socket 3 | 4 | PING_TIMEOUT = 1000 5 | def main(): 6 | hosts = ['a%d.phobos.apple.com' % i for i in range(1, 200)] 7 | ips = get_ips(hosts) 8 | records = ping_ips(ips) 9 | output(records) 10 | 11 | def get_ips(hosts): 12 | ips = [] 13 | for host in hosts: 14 | ips.extend(get_ip(host)) 15 | return {}.fromkeys(ips).keys() 16 | 17 | def get_ip(host): 18 | print 'Getting IP for %s' % host 19 | ip_records = socket.getaddrinfo(host, None, socket.AF_INET) 20 | return [ip_record[4][0] for ip_record in ip_records] 21 | 22 | def ping_ips(ips): 23 | ping_result = [(ip, my_ping(ip)) for ip in ips] 24 | ping_result.sort(cmp=lambda x, y: cmp(x[1], y[1])) 25 | return ping_result 26 | 27 | def output(records): 28 | record_lines = ['IP: %s\tTime: %f ms\n' % (record[0], round(record[1])) for record in records] 29 | write_file('apple_ip.txt', record_lines) 30 | if len(records) > 0 and records[0][1] < PING_TIMEOUT: 31 | ip = records[0][0] 32 | hosts_lines = ['%s\ta%d.phobos.apple.com\n' % (ip, i) for i in range(1, 2000)] 33 | hosts_lines.insert(0, "#START APPLE STORE#\n") 34 | hosts_lines.append("#END APPLE STORE#\n") 35 | write_file('hosts', hosts_lines) 36 | 37 | def write_file(filename, lines): 38 | with open(filename, 'w') as output_file: 39 | output_file.writelines(lines) 40 | output_file.close() 41 | 42 | def my_ping(hostname): 43 | return Ping(hostname, PING_TIMEOUT, 8).run(4) 44 | 45 | # Following code is copied from https://github.com/jedie/python-ping/blob/master/ping.py 46 | # I make some minor changes 47 | """ 48 | A pure python ping implementation using raw sockets. 49 | 50 | Note that ICMP messages can only be send from processes running as root 51 | (in Windows, you must run this script as 'Administrator'). 52 | 53 | Bugs are naturally mine. I'd be glad to hear about them. There are 54 | certainly word - size dependencies here. 55 | 56 | :homepage: https://github.com/jedie/python-ping/ 57 | :copyleft: 1989-2011 by the python-ping team, see AUTHORS for more details. 58 | :license: GNU GPL v2, see LICENSE for more details. 59 | """ 60 | 61 | 62 | import os 63 | import select 64 | import signal 65 | import socket 66 | import struct 67 | import sys 68 | import time 69 | 70 | 71 | if sys.platform.startswith("win32"): 72 | # On Windows, the best timer is time.clock() 73 | default_timer = time.clock 74 | else: 75 | # On most other platforms the best timer is time.time() 76 | default_timer = time.time 77 | 78 | 79 | # ICMP parameters 80 | ICMP_ECHOREPLY = 0 # Echo reply (per RFC792) 81 | ICMP_ECHO = 8 # Echo request (per RFC792) 82 | ICMP_MAX_RECV = 2048 # Max size of incoming buffer 83 | 84 | MAX_SLEEP = 1000 85 | 86 | 87 | def calculate_checksum(source_string): 88 | """ 89 | A port of the functionality of in_cksum() from ping.c 90 | Ideally this would act on the string as a series of 16-bit ints (host 91 | packed), but this works. 92 | Network data is big-endian, hosts are typically little-endian 93 | """ 94 | countTo = (int(len(source_string) / 2)) * 2 95 | sum = 0 96 | count = 0 97 | 98 | # Handle bytes in pairs (decoding as short ints) 99 | loByte = 0 100 | hiByte = 0 101 | while count < countTo: 102 | if (sys.byteorder == "little"): 103 | loByte = source_string[count] 104 | hiByte = source_string[count + 1] 105 | else: 106 | loByte = source_string[count + 1] 107 | hiByte = source_string[count] 108 | sum = sum + (ord(hiByte) * 256 + ord(loByte)) 109 | count += 2 110 | 111 | # Handle last byte if applicable (odd-number of bytes) 112 | # Endianness should be irrelevant in this case 113 | if countTo < len(source_string): # Check for odd length 114 | loByte = source_string[len(source_string) - 1] 115 | sum += ord(loByte) 116 | 117 | sum &= 0xffffffff # Truncate sum to 32 bits (a variance from ping.c, which 118 | # uses signed ints, but overflow is unlikely in ping) 119 | 120 | sum = (sum >> 16) + (sum & 0xffff) # Add high 16 bits to low 16 bits 121 | sum += (sum >> 16) # Add carry from above (if any) 122 | answer = ~sum & 0xffff # Invert and truncate to 16 bits 123 | answer = socket.htons(answer) 124 | 125 | return answer 126 | 127 | 128 | def is_valid_ip4_address(addr): 129 | parts = addr.split(".") 130 | if not len(parts) == 4: 131 | return False 132 | for part in parts: 133 | try: 134 | number = int(part) 135 | except ValueError: 136 | return False 137 | if number > 255: 138 | return False 139 | return True 140 | 141 | def to_ip(addr): 142 | if is_valid_ip4_address(addr): 143 | return addr 144 | return socket.gethostbyname(addr) 145 | 146 | 147 | class Ping(object): 148 | def __init__(self, destination, timeout=1000, packet_size=55, own_id=None): 149 | self.destination = destination 150 | self.timeout = timeout 151 | self.packet_size = packet_size 152 | if own_id is None: 153 | self.own_id = os.getpid() & 0xFFFF 154 | else: 155 | self.own_id = own_id 156 | 157 | try: 158 | # FIXME: Use destination only for display this line here? see: https://github.com/jedie/python-ping/issues/3 159 | self.dest_ip = to_ip(self.destination) 160 | except socket.gaierror as e: 161 | self.print_unknown_host(e) 162 | else: 163 | self.print_start() 164 | 165 | self.seq_number = 0 166 | self.send_count = 0 167 | self.receive_count = 0 168 | self.min_time = 999999999 169 | self.max_time = 0.0 170 | self.total_time = 0.0 171 | 172 | #-------------------------------------------------------------------------- 173 | 174 | def print_start(self): 175 | print("\nPYTHON-PING %s (%s): %d data bytes" % (self.destination, self.dest_ip, self.packet_size)) 176 | 177 | def print_unknown_host(self, e): 178 | print("\nPYTHON-PING: Unknown host: %s (%s)\n" % (self.destination, e.args[1])) 179 | 180 | def print_success(self, delay, ip, packet_size, ip_header, icmp_header): 181 | if ip == self.destination: 182 | from_info = ip 183 | else: 184 | from_info = "%s (%s)" % (self.destination, ip) 185 | 186 | print("%d bytes from %s: icmp_seq=%d ttl=%d time=%.1f ms" % ( 187 | packet_size, from_info, icmp_header["seq_number"], ip_header["ttl"], delay) 188 | ) 189 | #print("IP header: %r" % ip_header) 190 | #print("ICMP header: %r" % icmp_header) 191 | 192 | def print_failed(self): 193 | print("Request timed out.") 194 | 195 | def print_exit(self): 196 | print("\n----%s PYTHON PING Statistics----" % (self.destination)) 197 | 198 | lost_count = self.send_count - self.receive_count 199 | #print("%i packets lost" % lost_count) 200 | lost_rate = float(lost_count) / self.send_count * 100.0 201 | 202 | print("%d packets transmitted, %d packets received, %0.1f%% packet loss" % ( 203 | self.send_count, self.receive_count, lost_rate 204 | )) 205 | 206 | if self.receive_count > 0: 207 | print("round-trip (ms) min/avg/max = %0.3f/%0.3f/%0.3f" % ( 208 | self.min_time, self.total_time / self.receive_count, self.max_time 209 | )) 210 | 211 | print("") 212 | 213 | #-------------------------------------------------------------------------- 214 | 215 | def signal_handler(self, signum, frame): 216 | """ 217 | Handle print_exit via signals 218 | """ 219 | self.print_exit() 220 | print("\n(Terminated with signal %d)\n" % (signum)) 221 | sys.exit(0) 222 | 223 | def setup_signal_handler(self): 224 | signal.signal(signal.SIGINT, self.signal_handler) # Handle Ctrl-C 225 | if hasattr(signal, "SIGBREAK"): 226 | # Handle Ctrl-Break e.g. under Windows 227 | signal.signal(signal.SIGBREAK, self.signal_handler) 228 | 229 | #-------------------------------------------------------------------------- 230 | 231 | def header2dict(self, names, struct_format, data): 232 | """ unpack the raw received IP and ICMP header informations to a dict """ 233 | unpacked_data = struct.unpack(struct_format, data) 234 | return dict(zip(names, unpacked_data)) 235 | 236 | #-------------------------------------------------------------------------- 237 | 238 | def run(self, count=None, deadline=None): 239 | """ 240 | send and receive pings in a loop. Stop if count or until deadline. 241 | """ 242 | self.setup_signal_handler() 243 | 244 | while True: 245 | delay = self.do() 246 | 247 | self.seq_number += 1 248 | if count and self.seq_number >= count: 249 | break 250 | if deadline and self.total_time >= deadline: 251 | break 252 | 253 | if delay == None: 254 | delay = 0 255 | 256 | # Pause for the remainder of the MAX_SLEEP period (if applicable) 257 | if (MAX_SLEEP > delay): 258 | time.sleep((MAX_SLEEP - delay) / 1000.0) 259 | 260 | #self.print_exit() 261 | if self.receive_count == 0: 262 | return self.timeout 263 | else: 264 | return self.total_time / self.receive_count 265 | 266 | def do(self): 267 | """ 268 | Send one ICMP ECHO_REQUEST and receive the response until self.timeout 269 | """ 270 | try: # One could use UDP here, but it's obscure 271 | current_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.getprotobyname("icmp")) 272 | except socket.error, (errno, msg): 273 | if errno == 1: 274 | # Operation not permitted - Add more information to traceback 275 | etype, evalue, etb = sys.exc_info() 276 | evalue = etype( 277 | "%s - Note that ICMP messages can only be send from processes running as root." % evalue 278 | ) 279 | raise etype, evalue, etb 280 | raise # raise the original error 281 | 282 | send_time = self.send_one_ping(current_socket) 283 | if send_time == None: 284 | return 285 | self.send_count += 1 286 | 287 | receive_time, packet_size, ip, ip_header, icmp_header = self.receive_one_ping(current_socket) 288 | current_socket.close() 289 | 290 | if receive_time: 291 | self.receive_count += 1 292 | delay = (receive_time - send_time) * 1000.0 293 | self.total_time += delay 294 | if self.min_time > delay: 295 | self.min_time = delay 296 | if self.max_time < delay: 297 | self.max_time = delay 298 | 299 | self.print_success(delay, ip, packet_size, ip_header, icmp_header) 300 | return delay 301 | else: 302 | self.print_failed() 303 | 304 | def send_one_ping(self, current_socket): 305 | """ 306 | Send one ICMP ECHO_REQUEST 307 | """ 308 | # Header is type (8), code (8), checksum (16), id (16), sequence (16) 309 | checksum = 0 310 | 311 | # Make a dummy header with a 0 checksum. 312 | header = struct.pack( 313 | "!BBHHH", ICMP_ECHO, 0, checksum, self.own_id, self.seq_number 314 | ) 315 | 316 | padBytes = [] 317 | startVal = 0x42 318 | for i in range(startVal, startVal + (self.packet_size)): 319 | padBytes += [(i & 0xff)] # Keep chars in the 0-255 range 320 | data = bytes(padBytes) 321 | 322 | # Calculate the checksum on the data and the dummy header. 323 | checksum = calculate_checksum(header + data) # Checksum is in network order 324 | 325 | # Now that we have the right checksum, we put that in. It's just easier 326 | # to make up a new header than to stuff it into the dummy. 327 | header = struct.pack( 328 | "!BBHHH", ICMP_ECHO, 0, checksum, self.own_id, self.seq_number 329 | ) 330 | 331 | packet = header + data 332 | 333 | send_time = default_timer() 334 | 335 | try: 336 | current_socket.sendto(packet, (self.destination, 1)) # Port number is irrelevant for ICMP 337 | except socket.error as e: 338 | print("General failure (%s)" % (e.args[1])) 339 | current_socket.close() 340 | return 341 | 342 | return send_time 343 | 344 | def receive_one_ping(self, current_socket): 345 | """ 346 | Receive the ping from the socket. timeout = in ms 347 | """ 348 | timeout = self.timeout / 1000.0 349 | 350 | while True: # Loop while waiting for packet or timeout 351 | select_start = default_timer() 352 | inputready, outputready, exceptready = select.select([current_socket], [], [], timeout) 353 | select_duration = (default_timer() - select_start) 354 | if inputready == []: # timeout 355 | return None, 0, 0, 0, 0 356 | 357 | receive_time = default_timer() 358 | 359 | packet_data, address = current_socket.recvfrom(ICMP_MAX_RECV) 360 | 361 | icmp_header = self.header2dict( 362 | names=[ 363 | "type", "code", "checksum", 364 | "packet_id", "seq_number" 365 | ], 366 | struct_format="!BBHHH", 367 | data=packet_data[20:28] 368 | ) 369 | 370 | if icmp_header["packet_id"] == self.own_id: # Our packet 371 | ip_header = self.header2dict( 372 | names=[ 373 | "version", "type", "length", 374 | "id", "flags", "ttl", "protocol", 375 | "checksum", "src_ip", "dest_ip" 376 | ], 377 | struct_format="!BBHHHBBHII", 378 | data=packet_data[:20] 379 | ) 380 | packet_size = len(packet_data) - 28 381 | ip = socket.inet_ntoa(struct.pack("!I", ip_header["src_ip"])) 382 | # XXX: Why not ip = address[0] ??? 383 | return receive_time, packet_size, ip, ip_header, icmp_header 384 | 385 | timeout = timeout - select_duration 386 | if timeout <= 0: 387 | return None, 0, 0, 0, 0 388 | 389 | if __name__ == '__main__': 390 | main() --------------------------------------------------------------------------------