1 /* 2 * Copyright 2006-2023, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel Dörfler, axeld@pinc-software.de 7 */ 8 9 10 #include "argv.h" 11 #include "tcp.h" 12 #include "pcap.h" 13 #include "utility.h" 14 15 #include <AutoDeleter.h> 16 #include <NetBufferUtilities.h> 17 #include <Referenceable.h> 18 #include <net_buffer.h> 19 #include <net_datalink.h> 20 #include <net_protocol.h> 21 #include <net_socket.h> 22 #include <net_stack.h> 23 #include <slab/Slab.h> 24 #include <util/AutoLock.h> 25 #include <util/DoublyLinkedList.h> 26 27 #include <KernelExport.h> 28 #include <Select.h> 29 #include <module.h> 30 #include <Locker.h> 31 32 #include <netinet/in.h> 33 #include <netinet/ip.h> 34 35 #include <ctype.h> 36 #include <errno.h> 37 #include <new> 38 #include <set> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <string.h> 42 43 44 struct context { 45 BLocker lock; 46 sem_id wait_sem; 47 struct list list; 48 net_route route; 49 bool server; 50 thread_id thread; 51 }; 52 53 struct cmd_entry { 54 const char* name; 55 void (*func)(int argc, char **argv); 56 const char* help; 57 }; 58 59 60 struct net_socket_private; 61 typedef DoublyLinkedList<net_socket_private> SocketList; 62 63 struct net_socket_private : net_socket, 64 DoublyLinkedListLinkImpl<net_socket_private> { 65 struct net_socket *parent; 66 67 team_id owner; 68 uint32 max_backlog; 69 uint32 child_count; 70 SocketList pending_children; 71 SocketList connected_children; 72 73 struct select_sync_pool *select_pool; 74 mutex lock; 75 }; 76 77 78 struct InterfaceAddress : DoublyLinkedListLinkImpl<InterfaceAddress>, 79 net_interface_address, BReferenceable { 80 }; 81 82 83 extern "C" status_t _add_builtin_module(module_info *info); 84 extern "C" status_t _get_builtin_dependencies(void); 85 extern bool gDebugOutputEnabled; 86 // from libkernelland_emu.so 87 88 extern struct net_buffer_module_info gNetBufferModule; 89 // from net_buffer.cpp 90 extern net_address_module_info gIPv4AddressModule; 91 // from ipv4_address.cpp 92 extern module_info *modules[]; 93 // from tcp.cpp 94 95 96 extern struct net_protocol_module_info gDomainModule; 97 struct InterfaceAddress gInterfaceAddress; 98 extern struct net_socket_module_info gNetSocketModule; 99 struct net_protocol_module_info *gTCPModule; 100 struct net_socket *gServerSocket, *gClientSocket; 101 static struct context sClientContext, sServerContext; 102 103 static int32 sPacketNumber = 1; 104 static double sRandomDrop = 0.0; 105 static std::set<uint32> sDropList; 106 static bigtime_t sRoundTripTime = 0; 107 static bool sIncreasingRoundTrip = false; 108 static bool sRandomRoundTrip = false; 109 static void (*sPacketMonitor)(net_buffer *, int32, bool) = NULL; 110 static int sPcapFD = -1; 111 static bigtime_t sStartTime; 112 static double sRandomReorder = 0.0; 113 static std::set<uint32> sReorderList; 114 static bool sSimultaneousConnect = false; 115 static bool sSimultaneousClose = false; 116 static bool sServerActiveClose = false; 117 118 static struct net_domain sDomain = { 119 "ipv4", 120 AF_INET, 121 122 &gDomainModule, 123 &gIPv4AddressModule 124 }; 125 126 127 static bool 128 is_server(const sockaddr* addr) 129 { 130 return ((sockaddr_in*)addr)->sin_port == htons(1024); 131 } 132 133 134 static uint8 135 tcp_segment_flags(net_buffer* buffer) 136 { 137 NetBufferHeaderReader<tcp_header> bufferHeader(buffer); 138 if (bufferHeader.Status() < B_OK) 139 return bufferHeader.Status(); 140 141 tcp_header &header = bufferHeader.Data(); 142 return header.flags; 143 } 144 145 146 static bool 147 is_syn(net_buffer* buffer) 148 { 149 return (tcp_segment_flags(buffer) & TCP_FLAG_SYNCHRONIZE) != 0; 150 } 151 152 153 static bool 154 is_fin(net_buffer* buffer) 155 { 156 return (tcp_segment_flags(buffer) & TCP_FLAG_FINISH) != 0; 157 } 158 159 160 // #pragma mark - stack 161 162 163 status_t 164 std_ops(int32, ...) 165 { 166 return B_OK; 167 } 168 169 170 net_domain * 171 get_domain(int family) 172 { 173 return &sDomain; 174 } 175 176 177 status_t 178 register_domain_protocols(int family, int type, int protocol, ...) 179 { 180 return B_OK; 181 } 182 183 184 status_t 185 register_domain_datalink_protocols(int family, int type, ...) 186 { 187 return B_OK; 188 } 189 190 191 static status_t 192 register_domain_receiving_protocol(int family, int type, const char *moduleName) 193 { 194 return B_OK; 195 } 196 197 198 static bool 199 dummy_is_syscall(void) 200 { 201 return false; 202 } 203 204 205 static bool 206 dummy_is_restarted_syscall(void) 207 { 208 return false; 209 } 210 211 212 static void 213 dummy_store_syscall_restart_timeout(bigtime_t timeout) 214 { 215 } 216 217 218 static net_stack_module_info gNetStackModule = { 219 { 220 NET_STACK_MODULE_NAME, 221 0, 222 std_ops 223 }, 224 NULL, // register_domain, 225 NULL, // unregister_domain, 226 get_domain, 227 228 register_domain_protocols, 229 register_domain_datalink_protocols, 230 register_domain_receiving_protocol, 231 232 NULL, // get_domain_receiving_protocol, 233 NULL, // put_domain_receiving_protocol, 234 235 NULL, // register_device_deframer, 236 NULL, // unregister_device_deframer, 237 NULL, // register_domain_device_handler, 238 NULL, // register_device_handler, 239 NULL, // unregister_device_handler, 240 NULL, // register_device_monitor, 241 NULL, // unregister_device_monitor, 242 NULL, // device_link_changed, 243 NULL, // device_removed, 244 NULL, // device_enqueue_buffer, 245 246 notify_socket, 247 248 checksum, 249 250 init_fifo, 251 uninit_fifo, 252 fifo_enqueue_buffer, 253 fifo_dequeue_buffer, 254 clear_fifo, 255 fifo_socket_enqueue_buffer, 256 257 init_timer, 258 set_timer, 259 cancel_timer, 260 wait_for_timer, 261 is_timer_active, 262 is_timer_running, 263 264 dummy_is_syscall, 265 dummy_is_restarted_syscall, 266 dummy_store_syscall_restart_timeout, 267 NULL, // restore_syscall_restart_timeout 268 269 // ancillary data is not used by TCP 270 }; 271 272 273 // #pragma mark - socket 274 275 276 status_t 277 socket_create(int family, int type, int protocol, net_socket **_socket) 278 { 279 net_protocol* domainProtocol; 280 281 struct net_socket_private *socket = new (std::nothrow) net_socket_private; 282 if (socket == NULL) 283 return B_NO_MEMORY; 284 285 memset(socket, 0, sizeof(net_socket)); 286 socket->family = family; 287 socket->type = type; 288 socket->protocol = protocol; 289 290 mutex_init(&socket->lock, "socket"); 291 292 // set defaults (may be overridden by the protocols) 293 socket->send.buffer_size = 65535; 294 socket->send.low_water_mark = 1; 295 socket->send.timeout = B_INFINITE_TIMEOUT; 296 socket->receive.buffer_size = 65535; 297 socket->receive.low_water_mark = 1; 298 socket->receive.timeout = B_INFINITE_TIMEOUT; 299 300 socket->first_protocol = gTCPModule->init_protocol(socket); 301 if (socket->first_protocol == NULL) { 302 fprintf(stderr, "tcp_tester: cannot create protocol\n"); 303 mutex_destroy(&socket->lock); 304 delete socket; 305 return B_ERROR; 306 } 307 308 socket->first_info = gTCPModule; 309 310 domainProtocol = new net_protocol; 311 domainProtocol->module = &gDomainModule; 312 domainProtocol->socket = socket; 313 314 socket->first_protocol->next = domainProtocol; 315 socket->first_protocol->module = gTCPModule; 316 socket->first_protocol->socket = socket; 317 318 *_socket = socket; 319 return B_OK; 320 } 321 322 323 void 324 socket_delete(net_socket *_socket) 325 { 326 net_socket_private *socket = (net_socket_private *)_socket; 327 328 if (socket->parent != NULL) 329 panic("socket still has a parent!"); 330 331 socket->first_info->uninit_protocol(socket->first_protocol); 332 mutex_destroy(&socket->lock); 333 delete socket; 334 } 335 336 337 int 338 socket_accept(net_socket *socket, struct sockaddr *address, 339 socklen_t *_addressLength, net_socket **_acceptedSocket) 340 { 341 net_socket *accepted; 342 status_t status = socket->first_info->accept(socket->first_protocol, 343 &accepted); 344 if (status < B_OK) 345 return status; 346 347 if (address && *_addressLength > 0) { 348 memcpy(address, &accepted->peer, min_c(*_addressLength, 349 accepted->peer.ss_len)); 350 *_addressLength = accepted->peer.ss_len; 351 } 352 353 *_acceptedSocket = accepted; 354 return B_OK; 355 } 356 357 358 int 359 socket_bind(net_socket *socket, const struct sockaddr *address, socklen_t addressLength) 360 { 361 sockaddr empty; 362 if (address == NULL) { 363 // special - try to bind to an empty address, like INADDR_ANY 364 memset(&empty, 0, sizeof(sockaddr)); 365 empty.sa_len = sizeof(sockaddr); 366 empty.sa_family = socket->family; 367 368 address = ∅ 369 addressLength = sizeof(sockaddr); 370 } 371 372 if (socket->address.ss_len != 0) { 373 status_t status = socket->first_info->unbind(socket->first_protocol, 374 (sockaddr *)&socket->address); 375 if (status < B_OK) 376 return status; 377 } 378 379 memcpy(&socket->address, address, sizeof(sockaddr)); 380 381 status_t status = socket->first_info->bind(socket->first_protocol, 382 (sockaddr *)address); 383 if (status < B_OK) { 384 // clear address again, as binding failed 385 socket->address.ss_len = 0; 386 } 387 388 return status; 389 } 390 391 392 int 393 socket_connect(net_socket *socket, const struct sockaddr *address, socklen_t addressLength) 394 { 395 if (address == NULL || addressLength == 0) 396 return ENETUNREACH; 397 398 if (socket->address.ss_len == 0) { 399 // try to bind first 400 status_t status = socket_bind(socket, NULL, 0); 401 if (status < B_OK) 402 return status; 403 } 404 405 return socket->first_info->connect(socket->first_protocol, address); 406 } 407 408 409 int 410 socket_listen(net_socket *socket, int backlog) 411 { 412 status_t status = socket->first_info->listen(socket->first_protocol, backlog); 413 if (status == B_OK) 414 socket->options |= SO_ACCEPTCONN; 415 416 return status; 417 } 418 419 420 ssize_t 421 socket_send(net_socket *socket, const void *data, size_t length, int flags) 422 { 423 if (socket->peer.ss_len == 0) 424 return EDESTADDRREQ; 425 426 if (socket->address.ss_len == 0) { 427 // try to bind first 428 status_t status = socket_bind(socket, NULL, 0); 429 if (status < B_OK) 430 return status; 431 } 432 433 // TODO: useful, maybe even computed header space! 434 net_buffer *buffer = gNetBufferModule.create(256); 435 if (buffer == NULL) 436 return ENOBUFS; 437 438 // copy data into buffer 439 if (gNetBufferModule.append(buffer, data, length) < B_OK) { 440 gNetBufferModule.free(buffer); 441 return ENOBUFS; 442 } 443 444 buffer->msg_flags = flags; 445 memcpy(buffer->source, &socket->address, socket->address.ss_len); 446 memcpy(buffer->destination, &socket->peer, socket->peer.ss_len); 447 448 status_t status = socket->first_info->send_data(socket->first_protocol, buffer); 449 if (status < B_OK) { 450 gNetBufferModule.free(buffer); 451 return status; 452 } 453 454 return length; 455 } 456 457 458 ssize_t 459 socket_recv(net_socket *socket, void *data, size_t length, int flags) 460 { 461 net_buffer *buffer; 462 ssize_t status = socket->first_info->read_data( 463 socket->first_protocol, length, flags, &buffer); 464 if (status < B_OK) 465 return status; 466 467 // if 0 bytes we're received, no buffer will be created 468 if (buffer == NULL) 469 return 0; 470 471 ssize_t bytesReceived = buffer->size; 472 gNetBufferModule.read(buffer, 0, data, bytesReceived); 473 gNetBufferModule.free(buffer); 474 475 return bytesReceived; 476 } 477 478 479 bool 480 socket_acquire(net_socket* _socket) 481 { 482 return true; 483 } 484 485 486 bool 487 socket_release(net_socket* _socket) 488 { 489 return true; 490 } 491 492 493 status_t 494 socket_spawn_pending(net_socket *_parent, net_socket **_socket) 495 { 496 net_socket_private *parent = (net_socket_private *)_parent; 497 498 MutexLocker locker(parent->lock); 499 500 // We actually accept more pending connections to compensate for those 501 // that never complete, and also make sure at least a single connection 502 // can always be accepted 503 if (parent->child_count > 3 * parent->max_backlog / 2) 504 return ENOBUFS; 505 506 net_socket_private *socket; 507 status_t status = socket_create(parent->family, parent->type, parent->protocol, 508 (net_socket **)&socket); 509 if (status < B_OK) 510 return status; 511 512 // inherit parent's properties 513 socket->send = parent->send; 514 socket->receive = parent->receive; 515 socket->options = parent->options & ~SO_ACCEPTCONN; 516 socket->linger = parent->linger; 517 memcpy(&socket->address, &parent->address, parent->address.ss_len); 518 memcpy(&socket->peer, &parent->peer, parent->peer.ss_len); 519 520 // add to the parent's list of pending connections 521 parent->pending_children.Add(socket); 522 socket->parent = parent; 523 parent->child_count++; 524 525 *_socket = socket; 526 return B_OK; 527 } 528 529 530 status_t 531 socket_dequeue_connected(net_socket *_parent, net_socket **_socket) 532 { 533 net_socket_private *parent = (net_socket_private *)_parent; 534 535 mutex_lock(&parent->lock); 536 537 net_socket_private *socket = parent->connected_children.RemoveHead(); 538 if (socket != NULL) { 539 socket->parent = NULL; 540 parent->child_count--; 541 *_socket = socket; 542 } 543 544 mutex_unlock(&parent->lock); 545 return socket != NULL ? B_OK : B_ENTRY_NOT_FOUND; 546 } 547 548 549 ssize_t 550 socket_count_connected(net_socket *_parent) 551 { 552 net_socket_private *parent = (net_socket_private *)_parent; 553 554 MutexLocker _(parent->lock); 555 556 return parent->connected_children.Count(); 557 } 558 559 560 status_t 561 socket_set_max_backlog(net_socket *_socket, uint32 backlog) 562 { 563 net_socket_private *socket = (net_socket_private *)_socket; 564 565 // we enforce an upper limit of connections waiting to be accepted 566 if (backlog > 256) 567 backlog = 256; 568 569 mutex_lock(&socket->lock); 570 571 // first remove the pending connections, then the already connected ones as needed 572 net_socket_private *child; 573 while (socket->child_count > backlog 574 && (child = socket->pending_children.RemoveTail()) != NULL) { 575 child->parent = NULL; 576 socket->child_count--; 577 } 578 while (socket->child_count > backlog 579 && (child = socket->connected_children.RemoveTail()) != NULL) { 580 child->parent = NULL; 581 socket_delete(child); 582 socket->child_count--; 583 } 584 585 socket->max_backlog = backlog; 586 mutex_unlock(&socket->lock); 587 return B_OK; 588 } 589 590 591 bool 592 socket_has_parent(net_socket* _socket) 593 { 594 net_socket_private* socket = (net_socket_private*)_socket; 595 return socket->parent != NULL; 596 } 597 598 599 status_t 600 socket_connected(net_socket *socket) 601 { 602 net_socket_private *socket_private = (net_socket_private *)socket; 603 net_socket_private *parent = (net_socket_private *)socket_private->parent; 604 if (parent == NULL) 605 return B_BAD_VALUE; 606 607 mutex_lock(&parent->lock); 608 609 parent->pending_children.Remove(socket_private); 610 parent->connected_children.Add(socket_private); 611 612 mutex_unlock(&parent->lock); 613 return B_OK; 614 } 615 616 617 status_t 618 socket_notify(net_socket *_socket, uint8 event, int32 value) 619 { 620 net_socket_private *socket = (net_socket_private *)_socket; 621 622 mutex_lock(&socket->lock); 623 624 bool notify = true; 625 626 switch (event) { 627 case B_SELECT_READ: 628 { 629 if ((ssize_t)socket->receive.low_water_mark > value && value >= B_OK) 630 notify = false; 631 break; 632 } 633 case B_SELECT_WRITE: 634 { 635 if ((ssize_t)socket->send.low_water_mark > value && value >= B_OK) 636 notify = false; 637 break; 638 } 639 case B_SELECT_ERROR: 640 socket->error = value; 641 break; 642 } 643 644 if (notify) 645 ; 646 647 mutex_unlock(&socket->lock); 648 return B_OK; 649 } 650 651 652 net_socket_module_info gNetSocketModule = { 653 { 654 NET_SOCKET_MODULE_NAME, 655 0, 656 std_ops 657 }, 658 NULL, // open, 659 NULL, // close, 660 NULL, // free, 661 662 NULL, // control, 663 664 NULL, // read_avail, 665 NULL, // send_avail, 666 667 NULL, // send_data, 668 NULL, // receive_data, 669 670 NULL, // get_option, 671 NULL, // set_option, 672 NULL, // get_next_stat, 673 674 socket_acquire, 675 socket_release, 676 677 // connections 678 socket_spawn_pending, 679 socket_dequeue_connected, 680 socket_count_connected, 681 socket_set_max_backlog, 682 socket_has_parent, 683 socket_connected, 684 NULL, // set_aborted 685 686 // notifications 687 NULL, // request_notification, 688 NULL, // cancel_notification, 689 socket_notify, 690 691 // standard socket API 692 NULL, // accept, 693 NULL, // bind, 694 NULL, // connect, 695 NULL, // getpeername, 696 NULL, // getsockname, 697 NULL, // getsockopt, 698 NULL, // listen, 699 NULL, // receive, 700 NULL, // send, 701 NULL, // setsockopt, 702 NULL, // shutdown, 703 NULL, // socketpair 704 }; 705 706 707 // #pragma mark - protocol 708 709 710 net_protocol* 711 init_protocol(net_socket** _socket) 712 { 713 net_socket *socket; 714 status_t status = socket_create(AF_INET, SOCK_STREAM, IPPROTO_TCP, &socket); 715 if (status < B_OK) 716 return NULL; 717 718 status = socket->first_info->open(socket->first_protocol); 719 if (status < B_OK) { 720 fprintf(stderr, "tcp_tester: cannot open client: %s\n", strerror(status)); 721 socket_delete(socket); 722 return NULL; 723 } 724 725 *_socket = socket; 726 return socket->first_protocol; 727 } 728 729 730 void 731 close_protocol(net_protocol* protocol) 732 { 733 gTCPModule->close(protocol); 734 if (gTCPModule->free(protocol) == B_OK) 735 gTCPModule->uninit_protocol(protocol); 736 //socket_delete(protocol->socket); 737 } 738 739 740 // #pragma mark - datalink 741 742 743 status_t 744 datalink_send_data(struct net_route *route, net_buffer *buffer) 745 { 746 struct context* context = (struct context*)route->gateway; 747 748 buffer->interface_address = &gInterfaceAddress; 749 gInterfaceAddress.AcquireReference(); 750 751 context->lock.Lock(); 752 list_add_item(&context->list, buffer); 753 context->lock.Unlock(); 754 755 release_sem(context->wait_sem); 756 return B_OK; 757 } 758 759 760 status_t 761 datalink_send_datagram(net_protocol *protocol, net_domain *domain, 762 net_buffer *buffer) 763 { 764 panic("called"); 765 return B_ERROR; 766 } 767 768 769 struct net_route * 770 get_route(struct net_domain *_domain, const struct sockaddr *address) 771 { 772 if (is_server(address)) { 773 // to the server 774 return &sServerContext.route; 775 } 776 777 return &sClientContext.route; 778 } 779 780 781 static void 782 put_route(struct net_domain* _domain, net_route* route) 783 { 784 } 785 786 787 net_datalink_module_info gNetDatalinkModule = { 788 { 789 NET_DATALINK_MODULE_NAME, 790 0, 791 std_ops 792 }, 793 794 NULL, // control 795 datalink_send_data, 796 datalink_send_datagram, 797 798 NULL, // is_local_address 799 NULL, // is_local_link_address 800 801 NULL, // get_interface 802 NULL, // get_interface_with_address 803 NULL, // put_interface 804 805 NULL, // get_interface_address 806 NULL, // get_next_interface_address, 807 NULL, // put_interface_address 808 809 NULL, // join_multicast 810 NULL, // leave_multicast 811 812 NULL, // add_route, 813 NULL, // remove_route, 814 get_route, 815 NULL, // get_buffer_route 816 put_route, 817 NULL, // register_route_info, 818 NULL, // unregister_route_info, 819 NULL, // update_route_info 820 }; 821 822 823 // #pragma mark - domain 824 825 826 status_t 827 domain_open(net_protocol *protocol) 828 { 829 return B_OK; 830 } 831 832 833 status_t 834 domain_close(net_protocol *protocol) 835 { 836 return B_OK; 837 } 838 839 840 status_t 841 domain_free(net_protocol *protocol) 842 { 843 return B_OK; 844 } 845 846 847 status_t 848 domain_connect(net_protocol *protocol, const struct sockaddr *address) 849 { 850 return B_ERROR; 851 } 852 853 854 status_t 855 domain_accept(net_protocol *protocol, struct net_socket **_acceptedSocket) 856 { 857 return EOPNOTSUPP; 858 } 859 860 861 status_t 862 domain_control(net_protocol *protocol, int level, int option, void *value, 863 size_t *_length) 864 { 865 return B_ERROR; 866 } 867 868 869 status_t 870 domain_bind(net_protocol *protocol, const struct sockaddr *address) 871 { 872 memcpy(&protocol->socket->address, address, sizeof(struct sockaddr_in)); 873 protocol->socket->address.ss_len = sizeof(struct sockaddr_in); 874 // explicitly set length, as our callers can't be trusted to 875 // always provide the correct length! 876 return B_OK; 877 } 878 879 880 status_t 881 domain_unbind(net_protocol *protocol, struct sockaddr *address) 882 { 883 return B_OK; 884 } 885 886 887 status_t 888 domain_listen(net_protocol *protocol, int count) 889 { 890 return EOPNOTSUPP; 891 } 892 893 894 status_t 895 domain_shutdown(net_protocol *protocol, int direction) 896 { 897 return EOPNOTSUPP; 898 } 899 900 901 status_t 902 domain_send_data(net_protocol *protocol, net_buffer *buffer) 903 { 904 // find route 905 struct net_route *route = get_route(&sDomain, (sockaddr *)&buffer->destination); 906 if (route == NULL) 907 return ENETUNREACH; 908 909 return datalink_send_data(route, buffer); 910 } 911 912 913 status_t 914 domain_send_routed_data(net_protocol *protocol, struct net_route *route, 915 net_buffer *buffer) 916 { 917 return datalink_send_data(route, buffer); 918 } 919 920 921 ssize_t 922 domain_send_avail(net_protocol *protocol) 923 { 924 return B_ERROR; 925 } 926 927 928 status_t 929 domain_read_data(net_protocol *protocol, size_t numBytes, uint32 flags, 930 net_buffer **_buffer) 931 { 932 return B_ERROR; 933 } 934 935 936 ssize_t 937 domain_read_avail(net_protocol *protocol) 938 { 939 return B_ERROR; 940 } 941 942 943 struct net_domain * 944 domain_get_domain(net_protocol *protocol) 945 { 946 return &sDomain; 947 } 948 949 950 size_t 951 domain_get_mtu(net_protocol *protocol, const struct sockaddr *address) 952 { 953 return 1480; 954 // 1500 ethernet - IPv4 header 955 } 956 957 958 status_t 959 domain_receive_data(net_buffer *buffer) 960 { 961 uint32 packetNumber = atomic_add(&sPacketNumber, 1); 962 963 bool drop = false; 964 if (sDropList.find(packetNumber) != sDropList.end() 965 || (sRandomDrop > 0.0 && (1.0 * rand() / RAND_MAX) > sRandomDrop)) 966 drop = true; 967 968 if (!drop && (sRoundTripTime > 0 || sRandomRoundTrip || sIncreasingRoundTrip)) { 969 bigtime_t add = 0; 970 if (sRandomRoundTrip) 971 add = (bigtime_t)(1.0 * rand() / RAND_MAX * 500000) - 250000; 972 if (sIncreasingRoundTrip) 973 sRoundTripTime += (bigtime_t)(1.0 * rand() / RAND_MAX * 150000); 974 975 snooze(sRoundTripTime / 2 + add); 976 } 977 978 if (sPacketMonitor != NULL) { 979 sPacketMonitor(buffer, packetNumber, drop); 980 } else if (drop) 981 printf("<**** DROPPED %ld ****>\n", packetNumber); 982 983 if (drop) { 984 gNetBufferModule.free(buffer); 985 return B_OK; 986 } 987 988 return gTCPModule->receive_data(buffer); 989 } 990 991 992 status_t 993 domain_error(net_error error, net_buffer* data) 994 { 995 return B_ERROR; 996 } 997 998 999 status_t 1000 domain_error_reply(net_protocol* self, net_buffer* cause, 1001 net_error error, net_error_data* errorData) 1002 { 1003 return B_ERROR; 1004 } 1005 1006 1007 net_protocol_module_info gDomainModule = { 1008 { 1009 NULL, 1010 0, 1011 std_ops 1012 }, 1013 NET_PROTOCOL_ATOMIC_MESSAGES, 1014 1015 NULL, // init 1016 NULL, // uninit 1017 domain_open, 1018 domain_close, 1019 domain_free, 1020 domain_connect, 1021 domain_accept, 1022 domain_control, 1023 NULL, // getsockopt 1024 NULL, // setsockopt 1025 domain_bind, 1026 domain_unbind, 1027 domain_listen, 1028 domain_shutdown, 1029 domain_send_data, 1030 domain_send_routed_data, 1031 domain_send_avail, 1032 domain_read_data, 1033 domain_read_avail, 1034 domain_get_domain, 1035 domain_get_mtu, 1036 domain_receive_data, 1037 NULL, // deliver_data 1038 domain_error, 1039 domain_error_reply, 1040 NULL, // attach_ancillary_data 1041 NULL, // process_ancillary_data 1042 }; 1043 1044 1045 // #pragma mark - packet capture 1046 1047 1048 static void 1049 dump_printf(net_buffer* buffer, int32 packetNumber, bool willBeDropped) 1050 { 1051 static bigtime_t lastTime = 0; 1052 1053 NetBufferHeaderReader<tcp_header> bufferHeader(buffer); 1054 if (bufferHeader.Status() < B_OK) 1055 return; 1056 1057 tcp_header &header = bufferHeader.Data(); 1058 1059 bigtime_t now = system_time(); 1060 if (lastTime == 0) 1061 lastTime = now; 1062 1063 printf("\33[0m% 3ld %8.6f (%8.6f) ", packetNumber, (now - sStartTime) / 1000000.0, 1064 (now - lastTime) / 1000000.0); 1065 lastTime = now; 1066 1067 if (is_server((sockaddr *)buffer->source)) 1068 printf("\33[31mserver > client: "); 1069 else 1070 printf("client > server: "); 1071 1072 int32 length = buffer->size - header.HeaderLength(); 1073 1074 if ((header.flags & TCP_FLAG_PUSH) != 0) 1075 putchar('P'); 1076 if ((header.flags & TCP_FLAG_SYNCHRONIZE) != 0) 1077 putchar('S'); 1078 if ((header.flags & TCP_FLAG_FINISH) != 0) 1079 putchar('F'); 1080 if ((header.flags & TCP_FLAG_RESET) != 0) 1081 putchar('R'); 1082 if ((header.flags 1083 & (TCP_FLAG_SYNCHRONIZE | TCP_FLAG_FINISH | TCP_FLAG_PUSH | TCP_FLAG_RESET)) == 0) 1084 putchar('.'); 1085 1086 printf(" %lu:%lu (%lu)", header.Sequence(), header.Sequence() + length, length); 1087 if ((header.flags & TCP_FLAG_ACKNOWLEDGE) != 0) 1088 printf(" ack %lu", header.Acknowledge()); 1089 1090 printf(" win %u", header.AdvertisedWindow()); 1091 1092 if (header.HeaderLength() > sizeof(tcp_header)) { 1093 int32 size = header.HeaderLength() - sizeof(tcp_header); 1094 1095 tcp_option *option; 1096 uint8 optionsBuffer[1024]; 1097 if (gBufferModule->direct_access(buffer, sizeof(tcp_header), 1098 size, (void **)&option) != B_OK) { 1099 if (size > 1024) { 1100 printf("options too large to take into account (%ld bytes)\n", size); 1101 size = 1024; 1102 } 1103 1104 gBufferModule->read(buffer, sizeof(tcp_header), optionsBuffer, size); 1105 option = (tcp_option *)optionsBuffer; 1106 } 1107 1108 while (size > 0) { 1109 uint32 length = 1; 1110 switch (option->kind) { 1111 case TCP_OPTION_END: 1112 case TCP_OPTION_NOP: 1113 break; 1114 case TCP_OPTION_MAX_SEGMENT_SIZE: 1115 printf(" <mss %u>", ntohs(option->max_segment_size)); 1116 length = 4; 1117 break; 1118 case TCP_OPTION_WINDOW_SHIFT: 1119 printf(" <ws %u>", option->window_shift); 1120 length = 3; 1121 break; 1122 case TCP_OPTION_TIMESTAMP: 1123 printf(" <ts %lu:%lu>", option->timestamp.value, option->timestamp.reply); 1124 length = 10; 1125 break; 1126 1127 default: 1128 length = option->length; 1129 // make sure we don't end up in an endless loop 1130 if (length == 0) 1131 size = 0; 1132 break; 1133 } 1134 1135 size -= length; 1136 option = (tcp_option *)((uint8 *)option + length); 1137 } 1138 } 1139 1140 if (willBeDropped) 1141 printf(" <DROPPED>"); 1142 printf("\33[0m\n"); 1143 } 1144 1145 1146 static void 1147 dump_pcap(net_buffer* buffer, int32 packetNumber, bool willBeDropped) 1148 { 1149 if (willBeDropped) { 1150 printf(" <DROPPED>\n"); 1151 return; 1152 } 1153 1154 const bigtime_t time = real_time_clock_usecs(); 1155 1156 struct pcap_packet_header pcap_header; 1157 pcap_header.ts_sec = time / 1000000; 1158 pcap_header.ts_usec = time % 1000000; 1159 pcap_header.included_len = sizeof(struct ip) + buffer->size; 1160 pcap_header.original_len = pcap_header.included_len; 1161 1162 struct ip ip_header; 1163 ip_header.ip_v = IPVERSION; 1164 ip_header.ip_hl = sizeof(struct ip) >> 2; 1165 ip_header.ip_tos = 0; 1166 ip_header.ip_len = htons(sizeof(struct ip) + buffer->size); 1167 ip_header.ip_id = htons(packetNumber); 1168 ip_header.ip_off = 0; 1169 ip_header.ip_ttl = 254; 1170 ip_header.ip_p = IPPROTO_TCP; 1171 ip_header.ip_sum = 0; 1172 ip_header.ip_src.s_addr = ((sockaddr_in*)buffer->source)->sin_addr.s_addr; 1173 ip_header.ip_dst.s_addr = ((sockaddr_in*)buffer->destination)->sin_addr.s_addr; 1174 1175 size_t count = 16, used = 0; 1176 iovec vecs[count]; 1177 1178 vecs[used].iov_base = &pcap_header; 1179 vecs[used].iov_len = sizeof(pcap_header); 1180 used++; 1181 1182 vecs[used].iov_base = &ip_header; 1183 vecs[used].iov_len = sizeof(ip_header); 1184 used++; 1185 1186 used += gNetBufferModule.get_iovecs(buffer, vecs + used, count - used); 1187 1188 static mutex writesLock = MUTEX_INITIALIZER("pcap writes"); 1189 MutexLocker _(writesLock); 1190 ssize_t written = writev(sPcapFD, vecs, used); 1191 if (written != (pcap_header.included_len + sizeof(pcap_packet_header))) { 1192 fprintf(stderr, "writing to pcap file failed\n"); 1193 exit(1); 1194 } 1195 } 1196 1197 1198 static bool 1199 setup_dump_pcap(const char* file) 1200 { 1201 sPcapFD = open(file, O_CREAT | O_WRONLY | O_TRUNC); 1202 if (sPcapFD < 0) { 1203 fprintf(stderr, "tcp_shell: Failed to open output pcap file: %d\n", 1204 errno); 1205 return false; 1206 } 1207 1208 struct pcap_header header; 1209 header.magic = PCAP_MAGIC; 1210 header.version_major = 2; 1211 header.version_minor = 4; 1212 header.timezone = 0; 1213 header.timestamp_accuracy = 0; 1214 header.max_packet_length = 65535; 1215 header.linktype = PCAP_LINKTYPE_IPV4; 1216 if (write(sPcapFD, &header, sizeof(header)) != sizeof(header)) { 1217 fprintf(stderr, "tcp_shell: Failed to write pcap file header: %d\n", 1218 errno); 1219 return false; 1220 } 1221 1222 sPacketMonitor = dump_pcap; 1223 return true; 1224 } 1225 1226 1227 // #pragma mark - test 1228 1229 1230 int32 1231 receiving_thread(void* _data) 1232 { 1233 struct context* context = (struct context*)_data; 1234 struct net_buffer* reorderBuffer = NULL; 1235 1236 while (true) { 1237 status_t status; 1238 do { 1239 status = acquire_sem(context->wait_sem); 1240 } while (status == B_INTERRUPTED); 1241 1242 if (status < B_OK) 1243 break; 1244 1245 while (true) { 1246 context->lock.Lock(); 1247 net_buffer* buffer = (net_buffer*)list_remove_head_item( 1248 &context->list); 1249 context->lock.Unlock(); 1250 1251 if (buffer == NULL) 1252 break; 1253 1254 if (sSimultaneousConnect && context->server && is_syn(buffer)) { 1255 // delay getting the SYN request, and connect as well 1256 sockaddr_in address; 1257 memset(&address, 0, sizeof(address)); 1258 address.sin_family = AF_INET; 1259 address.sin_port = htons(1023); 1260 address.sin_addr.s_addr = htonl(0xc0a80001); 1261 1262 status_t status = socket_connect(gServerSocket, 1263 (struct sockaddr *)&address, sizeof(struct sockaddr)); 1264 if (status < B_OK) 1265 fprintf(stderr, "tcp_tester: simultaneous connect failed: %s\n", strerror(status)); 1266 1267 sSimultaneousConnect = false; 1268 } 1269 if (sSimultaneousClose && !context->server && is_fin(buffer)) { 1270 close_protocol(gClientSocket->first_protocol); 1271 sSimultaneousClose = false; 1272 } 1273 if ((sRandomReorder > 0.0 1274 || sReorderList.find(sPacketNumber) != sReorderList.end()) 1275 && reorderBuffer == NULL 1276 && (1.0 * rand() / RAND_MAX) > sRandomReorder) { 1277 reorderBuffer = buffer; 1278 } else { 1279 if (sDomain.module->receive_data(buffer) < B_OK) 1280 gNetBufferModule.free(buffer); 1281 1282 if (reorderBuffer != NULL) { 1283 if (sDomain.module->receive_data(reorderBuffer) < B_OK) 1284 gNetBufferModule.free(reorderBuffer); 1285 reorderBuffer = NULL; 1286 } 1287 } 1288 } 1289 } 1290 1291 return 0; 1292 } 1293 1294 1295 int32 1296 server_thread(void*) 1297 { 1298 while (true) { 1299 // main accept() loop 1300 net_socket* connectionSocket; 1301 sockaddr_in address; 1302 socklen_t size = sizeof(struct sockaddr_in); 1303 status_t status = socket_accept(gServerSocket, 1304 (struct sockaddr *)&address, &size, &connectionSocket); 1305 if (status < B_OK) { 1306 fprintf(stderr, "SERVER: accepting failed: %s\n", strerror(status)); 1307 break; 1308 } 1309 1310 printf("server: got connection from %08x\n", address.sin_addr.s_addr); 1311 1312 char buffer[1024]; 1313 ssize_t bytesRead; 1314 while ((bytesRead = socket_recv(connectionSocket, buffer, 1315 sizeof(buffer), 0)) > 0) { 1316 printf("server: received %ld bytes\n", bytesRead); 1317 1318 if (sServerActiveClose) { 1319 printf("server: active close\n"); 1320 close_protocol(connectionSocket->first_protocol); 1321 return 0; 1322 } 1323 } 1324 if (bytesRead < 0) 1325 printf("server: receiving failed: %s\n", strerror(bytesRead)); 1326 else 1327 printf("server: peer closed connection.\n"); 1328 1329 snooze(1000000); 1330 close_protocol(connectionSocket->first_protocol); 1331 } 1332 1333 return 0; 1334 } 1335 1336 1337 void 1338 setup_server() 1339 { 1340 sockaddr_in address; 1341 memset(&address, 0, sizeof(address)); 1342 address.sin_len = sizeof(sockaddr_in); 1343 address.sin_family = AF_INET; 1344 address.sin_port = htons(1024); 1345 address.sin_addr.s_addr = INADDR_ANY; 1346 1347 status_t status = socket_bind(gServerSocket, (struct sockaddr*)&address, 1348 sizeof(struct sockaddr)); 1349 if (status < B_OK) { 1350 fprintf(stderr, "tcp_tester: cannot bind server: %s\n", strerror(status)); 1351 exit(1); 1352 } 1353 status = socket_listen(gServerSocket, 40); 1354 if (status < B_OK) { 1355 fprintf(stderr, "tcp_tester: server cannot listen: %s\n", 1356 strerror(status)); 1357 exit(1); 1358 } 1359 1360 thread_id serverThread = spawn_thread(server_thread, "server", 1361 B_NORMAL_PRIORITY, NULL); 1362 if (serverThread < B_OK) { 1363 fprintf(stderr, "tcp_tester: cannot start server: %s\n", 1364 strerror(serverThread)); 1365 exit(1); 1366 } 1367 1368 resume_thread(serverThread); 1369 } 1370 1371 1372 void 1373 setup_context(struct context& context, bool server) 1374 { 1375 list_init(&context.list); 1376 context.route.interface_address = &gInterfaceAddress; 1377 context.route.gateway = (sockaddr *)&context; 1378 // backpointer to the context 1379 context.route.mtu = 1500; 1380 context.server = server; 1381 context.wait_sem = create_sem(0, "receive wait"); 1382 1383 context.thread = spawn_thread(receiving_thread, 1384 server ? "server receiver" : "client receiver", B_NORMAL_PRIORITY, 1385 &context); 1386 resume_thread(context.thread); 1387 } 1388 1389 1390 void 1391 cleanup_context(struct context& context) 1392 { 1393 delete_sem(context.wait_sem); 1394 1395 status_t status; 1396 wait_for_thread(context.thread, &status); 1397 } 1398 1399 1400 // #pragma mark - 1401 1402 1403 static void do_help(int argc, char** argv); 1404 1405 1406 static void 1407 do_connect(int argc, char** argv) 1408 { 1409 sSimultaneousConnect = false; 1410 1411 int port = 1024; 1412 if (argc > 1) { 1413 if (!strcmp(argv[1], "-s")) 1414 sSimultaneousConnect = true; 1415 else if (isdigit(argv[1][0])) 1416 port = atoi(argv[1]); 1417 else { 1418 fprintf(stderr, "usage: connect [-s|<port-number>]\n"); 1419 return; 1420 } 1421 } 1422 1423 if (sSimultaneousConnect) { 1424 // bind to a port first, so the other end can find us 1425 sockaddr_in address; 1426 memset(&address, 0, sizeof(address)); 1427 address.sin_family = AF_INET; 1428 address.sin_port = htons(1023); 1429 address.sin_addr.s_addr = htonl(0xc0a80001); 1430 1431 status_t status = socket_bind(gClientSocket, (struct sockaddr *)&address, 1432 sizeof(struct sockaddr)); 1433 if (status < B_OK) { 1434 fprintf(stderr, "Could not bind to port 1023: %s\n", strerror(status)); 1435 sSimultaneousConnect = false; 1436 return; 1437 } 1438 } 1439 1440 sStartTime = system_time(); 1441 1442 sockaddr_in address; 1443 memset(&address, 0, sizeof(address)); 1444 address.sin_family = AF_INET; 1445 address.sin_port = htons(port); 1446 address.sin_addr.s_addr = htonl(0xc0a80001); 1447 1448 status_t status = socket_connect(gClientSocket, (struct sockaddr *)&address, 1449 sizeof(struct sockaddr)); 1450 if (status < B_OK) 1451 fprintf(stderr, "tcp_tester: could not connect: %s\n", strerror(status)); 1452 } 1453 1454 1455 static ssize_t 1456 parse_size(const char* arg) 1457 { 1458 char *unit; 1459 ssize_t size = strtoul(arg, &unit, 0); 1460 if (unit != NULL && unit[0]) { 1461 if (unit[0] == 'k' || unit[0] == 'K') 1462 size *= 1024; 1463 else if (unit[0] == 'm' || unit[0] == 'M') 1464 size *= 1024 * 1024; 1465 else { 1466 fprintf(stderr, "unknown unit specified!\n"); 1467 return -1; 1468 } 1469 } 1470 return size; 1471 } 1472 1473 1474 static void 1475 do_send(int argc, char** argv) 1476 { 1477 ssize_t size = 1024; 1478 if (argc > 1 && isdigit(argv[1][0])) { 1479 size = parse_size(argv[1]); 1480 if (size < 0) 1481 return; 1482 } else if (argc > 1) { 1483 fprintf(stderr, "invalid args!\n"); 1484 return; 1485 } 1486 1487 if (size > 4 * 1024 * 1024) { 1488 printf("amount to send will be limited to 4 MB\n"); 1489 size = 4 * 1024 * 1024; 1490 } 1491 1492 char *buffer = (char *)malloc(size); 1493 if (buffer == NULL) { 1494 fprintf(stderr, "not enough memory!\n"); 1495 return; 1496 } 1497 MemoryDeleter bufferDeleter(buffer); 1498 1499 // initialize buffer with some not so random data 1500 for (uint32 i = 0; i < size; i++) { 1501 buffer[i] = (char)(i & 0xff); 1502 } 1503 1504 ssize_t bytesWritten = socket_send(gClientSocket, buffer, size, 0); 1505 if (bytesWritten < B_OK) { 1506 fprintf(stderr, "failed sending buffer: %s\n", strerror(bytesWritten)); 1507 return; 1508 } 1509 } 1510 1511 1512 static void 1513 do_send_loop(int argc, char** argv) 1514 { 1515 if (argc != 2 || !isdigit(argv[1][0])) { 1516 fprintf(stderr, "invalid args!\n"); 1517 return; 1518 } 1519 ssize_t size = parse_size(argv[1]); 1520 if (size < 0) 1521 return; 1522 1523 const size_t bufferSize = 4096; 1524 char *buffer = (char *)malloc(bufferSize); 1525 if (buffer == NULL) { 1526 fprintf(stderr, "not enough memory!\n"); 1527 return; 1528 } 1529 MemoryDeleter bufferDeleter(buffer); 1530 1531 // initialize buffer with some not so random data 1532 for (uint32 i = 0; i < bufferSize; i++) { 1533 buffer[i] = (char)(i & 0xff); 1534 } 1535 1536 for (ssize_t total = 0; total < size; ) { 1537 ssize_t bytesWritten = socket_send(gClientSocket, buffer, bufferSize, 0); 1538 if (bytesWritten < B_OK) { 1539 fprintf(stderr, "failed sending buffer (after %" B_PRIdSSIZE "): %s\n", 1540 total, strerror(bytesWritten)); 1541 return; 1542 } 1543 1544 total += bufferSize; 1545 } 1546 } 1547 1548 1549 static void 1550 do_close(int argc, char** argv) 1551 { 1552 sSimultaneousClose = false; 1553 sServerActiveClose = true; 1554 1555 if (argc > 1) { 1556 if (!strcmp(argv[1], "-s")) 1557 sSimultaneousClose = true; 1558 else { 1559 fprintf(stderr, "usage: close [-s]\n"); 1560 return; 1561 } 1562 } 1563 1564 gClientSocket->send.timeout = 0; 1565 1566 char buffer[32767] = {'q'}; 1567 ssize_t bytesWritten = socket_send(gClientSocket, buffer, sizeof(buffer), 0); 1568 if (bytesWritten < B_OK) { 1569 fprintf(stderr, "failed sending buffer: %s\n", strerror(bytesWritten)); 1570 return; 1571 } 1572 } 1573 1574 1575 static void 1576 do_drop(int argc, char** argv) 1577 { 1578 if (argc == 1) { 1579 // show list of dropped packets 1580 if (sRandomDrop > 0.0) 1581 printf("Drop probability is %f\n", sRandomDrop); 1582 1583 printf("Drop pakets:\n"); 1584 1585 std::set<uint32>::iterator iterator = sDropList.begin(); 1586 uint32 count = 0; 1587 for (; iterator != sDropList.end(); iterator++) { 1588 printf("%4lu\n", *iterator); 1589 count++; 1590 } 1591 1592 if (count == 0) 1593 printf("<empty>\n"); 1594 } else if (!strcmp(argv[1], "-f")) { 1595 // flush drop list 1596 sDropList.clear(); 1597 puts("drop list cleared."); 1598 } else if (!strcmp(argv[1], "-r")) { 1599 if (argc < 3) { 1600 fprintf(stderr, "No drop probability specified.\n"); 1601 return; 1602 } 1603 1604 sRandomDrop = atof(argv[2]); 1605 if (sRandomDrop < 0.0) 1606 sRandomDrop = 0; 1607 else if (sRandomDrop > 1.0) 1608 sRandomDrop = 1.0; 1609 } else if (isdigit(argv[1][0])) { 1610 // add to drop list 1611 for (int i = 1; i < argc; i++) { 1612 uint32 packet = strtoul(argv[i], NULL, 0); 1613 if (packet == 0) { 1614 fprintf(stderr, "invalid packet number: %s\n", argv[i]); 1615 break; 1616 } 1617 1618 sDropList.insert(packet); 1619 } 1620 } else { 1621 // print usage 1622 puts("usage: drop <packet-number> [...]\n" 1623 " or: drop -r <probability>\n\n" 1624 " or: drop [-f]\n\n" 1625 "Specifiying -f flushes the drop list, -r sets the probability a packet\n" 1626 "is dropped; if you called drop without any arguments, the current\n" 1627 "drop list is dumped."); 1628 } 1629 } 1630 1631 1632 static void 1633 do_reorder(int argc, char** argv) 1634 { 1635 if (argc == 1) { 1636 // show list of dropped packets 1637 if (sRandomReorder > 0.0) 1638 printf("Reorder probability is %f\n", sRandomReorder); 1639 1640 printf("Reorder packets:\n"); 1641 1642 std::set<uint32>::iterator iterator = sReorderList.begin(); 1643 uint32 count = 0; 1644 for (; iterator != sReorderList.end(); iterator++) { 1645 printf("%4lu\n", *iterator); 1646 count++; 1647 } 1648 1649 if (count == 0) 1650 printf("<empty>\n"); 1651 } else if (!strcmp(argv[1], "-f")) { 1652 // flush reorder list 1653 sReorderList.clear(); 1654 puts("reorder list cleared."); 1655 } else if (!strcmp(argv[1], "-r")) { 1656 if (argc < 3) { 1657 fprintf(stderr, "No reorder probability specified.\n"); 1658 return; 1659 } 1660 1661 sRandomReorder = atof(argv[2]); 1662 if (sRandomReorder < 0.0) 1663 sRandomReorder = 0; 1664 else if (sRandomReorder > 1.0) 1665 sRandomReorder = 1.0; 1666 } else if (isdigit(argv[1][0])) { 1667 // add to reorder list 1668 for (int i = 1; i < argc; i++) { 1669 uint32 packet = strtoul(argv[i], NULL, 0); 1670 if (packet == 0) { 1671 fprintf(stderr, "invalid packet number: %s\n", argv[i]); 1672 break; 1673 } 1674 1675 sReorderList.insert(packet); 1676 } 1677 } else { 1678 // print usage 1679 puts("usage: reorder <packet-number> [...]\n" 1680 " or: reorder -r <probability>\n\n" 1681 " or: reorder [-f]\n\n" 1682 "Specifiying -f flushes the reorder list, -r sets the probability a packet\n" 1683 "is reordered; if you called reorder without any arguments, the current\n" 1684 "reorder list is dumped."); 1685 } 1686 } 1687 1688 1689 static void 1690 do_round_trip_time(int argc, char** argv) 1691 { 1692 if (argc == 1) { 1693 // show current time 1694 printf("Current round trip time: %g ms\n", sRoundTripTime / 1000.0); 1695 } else if (!strcmp(argv[1], "-r")) { 1696 // toggle random time 1697 sRandomRoundTrip = !sRandomRoundTrip; 1698 printf("Round trip time is now %s.\n", sRandomRoundTrip ? "random" : "fixed"); 1699 } else if (!strcmp(argv[1], "-i")) { 1700 // toggle increasing time 1701 sIncreasingRoundTrip = !sIncreasingRoundTrip; 1702 printf("Round trip time is now %s.\n", sIncreasingRoundTrip ? "increasing" : "fixed"); 1703 } else if (isdigit(argv[1][0])) { 1704 // set time 1705 sRoundTripTime = 1000LL * strtoul(argv[1], NULL, 0); 1706 } else { 1707 // print usage 1708 puts("usage: rtt <time in ms>\n" 1709 " or: rtt [-r|-i]\n\n" 1710 "Specifiying -r sets random time, -i causes the times to increase over time;\n" 1711 "witout any arguments, the current time is printed."); 1712 } 1713 } 1714 1715 1716 static void 1717 do_dprintf(int argc, char** argv) 1718 { 1719 if (argc > 1) 1720 gDebugOutputEnabled = !strcmp(argv[1], "on"); 1721 else 1722 gDebugOutputEnabled = !gDebugOutputEnabled; 1723 1724 printf("debug output turned %s.\n", gDebugOutputEnabled ? "on" : "off"); 1725 } 1726 1727 1728 static cmd_entry sBuiltinCommands[] = { 1729 {"connect", do_connect, "Connects the client"}, 1730 {"send", do_send, "Sends data from the client to the server"}, 1731 {"send_loop", do_send_loop, "Sends data in a loop"}, 1732 {"close", do_close, "Performs an active or simultaneous close"}, 1733 {"dprintf", do_dprintf, "Toggles debug output"}, 1734 {"drop", do_drop, "Lets you drop packets during transfer"}, 1735 {"reorder", do_reorder, "Lets you reorder packets during transfer"}, 1736 {"help", do_help, "prints this help text"}, 1737 {"rtt", do_round_trip_time, "Specifies the round trip time"}, 1738 {"quit", NULL, "exits the application"}, 1739 {NULL, NULL, NULL}, 1740 }; 1741 1742 1743 static void 1744 do_help(int argc, char** argv) 1745 { 1746 printf("Available commands:\n"); 1747 1748 for (cmd_entry* command = sBuiltinCommands; command->name != NULL; command++) { 1749 printf("%8s - %s\n", command->name, command->help); 1750 } 1751 } 1752 1753 1754 // #pragma mark - 1755 1756 1757 int 1758 main(int argc, char* argv[]) 1759 { 1760 for (int i = 1; i < argc; i++) { 1761 if (strcmp(argv[i], "-w") == 0 && (i + 1) < argc) { 1762 if (!setup_dump_pcap(argv[++i])) 1763 return 1; 1764 } 1765 } 1766 1767 if (sPacketMonitor == NULL) 1768 sPacketMonitor = dump_printf; 1769 1770 status_t status = init_timers(); 1771 if (status < B_OK) { 1772 fprintf(stderr, "tcp_tester: Could not initialize timers: %s\n", 1773 strerror(status)); 1774 return 1; 1775 } 1776 1777 _add_builtin_module((module_info*)&gNetStackModule); 1778 _add_builtin_module((module_info*)&gNetBufferModule); 1779 _add_builtin_module((module_info*)&gNetSocketModule); 1780 _add_builtin_module((module_info*)&gNetDatalinkModule); 1781 _add_builtin_module(modules[0]); 1782 if (_get_builtin_dependencies() < B_OK) { 1783 fprintf(stderr, "tcp_tester: Could not initialize modules: %s\n", 1784 strerror(status)); 1785 return 1; 1786 } 1787 1788 sockaddr_in interfaceAddress; 1789 interfaceAddress.sin_len = sizeof(sockaddr_in); 1790 interfaceAddress.sin_family = AF_INET; 1791 interfaceAddress.sin_addr.s_addr = htonl(0xc0a80001); 1792 gInterfaceAddress.local = (sockaddr*)&interfaceAddress; 1793 gInterfaceAddress.domain = &sDomain; 1794 1795 status = get_module("network/protocols/tcp/v1", (module_info **)&gTCPModule); 1796 if (status < B_OK) { 1797 fprintf(stderr, "tcp_tester: Could not open TCP module: %s\n", 1798 strerror(status)); 1799 return 1; 1800 } 1801 1802 net_protocol* client = init_protocol(&gClientSocket); 1803 if (client == NULL) 1804 return 1; 1805 net_protocol* server = init_protocol(&gServerSocket); 1806 if (server == NULL) 1807 return 1; 1808 1809 setup_context(sClientContext, false); 1810 setup_context(sServerContext, true); 1811 1812 printf("*** Server: %p (%ld), Client: %p (%ld)\n", server, 1813 sServerContext.thread, client, sClientContext.thread); 1814 1815 setup_server(); 1816 1817 while (true) { 1818 printf("> "); 1819 fflush(stdout); 1820 1821 char line[1024]; 1822 if (fgets(line, sizeof(line), stdin) == NULL) 1823 break; 1824 1825 argc = 0; 1826 argv = build_argv(line, &argc); 1827 if (argv == NULL || argc == 0) 1828 continue; 1829 1830 int length = strlen(argv[0]); 1831 1832 #if 0 1833 char *newLine = strchr(line, '\n'); 1834 if (newLine != NULL) 1835 newLine[0] = '\0'; 1836 #endif 1837 1838 if (!strcmp(argv[0], "quit") 1839 || !strcmp(argv[0], "exit") 1840 || !strcmp(argv[0], "q")) 1841 break; 1842 1843 bool found = false; 1844 1845 for (cmd_entry* command = sBuiltinCommands; command->name != NULL; command++) { 1846 if (!strncmp(command->name, argv[0], length)) { 1847 command->func(argc, argv); 1848 found = true; 1849 break; 1850 } 1851 } 1852 1853 if (!found) 1854 fprintf(stderr, "Unknown command \"%s\". Type \"help\" for a list of commands.\n", argv[0]); 1855 1856 free(argv); 1857 } 1858 1859 close_protocol(client); 1860 close_protocol(server); 1861 1862 snooze(2000000); 1863 1864 cleanup_context(sClientContext); 1865 cleanup_context(sServerContext); 1866 1867 put_module("network/protocols/tcp/v1"); 1868 uninit_timers(); 1869 return 0; 1870 } 1871