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