|
13 | 13 | import signal |
14 | 14 | import fcntl |
15 | 15 | import ctypes |
| 16 | +import time |
16 | 17 | import tempfile |
17 | 18 | import pathlib |
18 | 19 | import contextlib |
|
32 | 33 | 3..10 bind(3, {sa_family=AF_INET, sin_port=htons(<bind_port>), sin_addr=inet_addr("<bind_address>")}, 16) = 0 |
33 | 34 | 4..10 listen(3, 0) = 0 |
34 | 35 | 5..10 accept(3, NULL, NULL) = 4 |
35 | | -6..8 read(4, <read_request>, <read_request_count>) = <read_request_result> |
| 36 | +7..8 read(4, <read_request>, <read_request_count>) = <read_request_result> |
36 | 37 | 7..8 open("<open_path>", O_RDONLY) = 5 |
37 | 38 | 7..8 read(5, <read_file>, <read_file_count>) = <read_file_result> |
38 | 39 | 7..8 close(5) = 0 |
@@ -354,12 +355,31 @@ def connect(): |
354 | 355 | pass |
355 | 356 |
|
356 | 357 |
|
357 | | -def validate_connect(): |
358 | | - session = retry_session() |
359 | | - try: |
360 | | - session.get("http://localhost", timeout=1) |
361 | | - except requests.exceptions.RequestException as e: |
362 | | - return request_failure("Connect", e) |
| 358 | +def validate_static_response(): |
| 359 | + expected = b"HTTP/1.0 200 OK\r\n\r\n" |
| 360 | + |
| 361 | + for attempt in range(5): |
| 362 | + try: |
| 363 | + client = socket.create_connection(("localhost", 80), timeout=1) |
| 364 | + break |
| 365 | + except ConnectionRefusedError as e: |
| 366 | + if attempt == 4: |
| 367 | + return f"Static response: Failed to connect ({type(e).__name__}: {e})" |
| 368 | + time.sleep(0.1) |
| 369 | + |
| 370 | + with client: |
| 371 | + response = b"" |
| 372 | + try: |
| 373 | + while len(response) < len(expected): |
| 374 | + chunk = client.recv(len(expected) - len(response)) |
| 375 | + if not chunk: |
| 376 | + break |
| 377 | + response += chunk |
| 378 | + except TimeoutError as e: |
| 379 | + return f"Static response: Timed out ({type(e).__name__}: {e})" |
| 380 | + |
| 381 | + if response != expected: |
| 382 | + return "Static response: Response not correct" |
363 | 383 |
|
364 | 384 |
|
365 | 385 | def validate_get(data=None): |
@@ -401,7 +421,7 @@ def challenge(): |
401 | 421 | 3: "bind an address to a socket", |
402 | 422 | 4: "listen on a socket", |
403 | 423 | 5: "accept a connection", |
404 | | - 6: "respond to an http request", |
| 424 | + 6: "send a static HTTP response to a client", |
405 | 425 | 7: "respond to a GET request for the contents of a specified file", |
406 | 426 | 8: "accept multiple requests", |
407 | 427 | 9: "concurrently accept multiple requests", |
@@ -451,14 +471,14 @@ def target(): |
451 | 471 |
|
452 | 472 | operation_names = { |
453 | 473 | connect: "connect", |
454 | | - validate_connect: "validated connect", |
| 474 | + validate_static_response: "static HTTP response", |
455 | 475 | validate_get: "HTTP GET request", |
456 | 476 | validate_post: "HTTP POST request", |
457 | 477 | } |
458 | 478 |
|
459 | 479 | operations = { |
460 | 480 | 5: [connect], |
461 | | - 6: [validate_connect], |
| 481 | + 6: [validate_static_response], |
462 | 482 | 7: [validate_get], |
463 | 483 | 8: [validate_get, connect], |
464 | 484 | 9: [validate_get, connect], |
|
0 commit comments