From bcb0dd2b3b1a771f4ffc6e00ba163950648bf7a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Tue, 5 Dec 2006 03:03:15 +0000 Subject: [PATCH] The R5 compatibility is now turned off when the socket functions are used within the library - theoretically, this mechanism could be extended to turn the compatibility layer on and off based on the images that call the functions (allowing to mix R5 and BONE network add-ons in a single executable). This change fixes R5 networking apps such as Vision, and NetworkTime (both now seem to work fine under Haiku). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19431 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/net/r5_compatibility.h | 2 + src/kits/network/init.cpp | 21 ++++++++++ src/kits/network/socket.cpp | 56 +++++++++++++++++++------- 3 files changed, 65 insertions(+), 14 deletions(-) diff --git a/headers/private/net/r5_compatibility.h b/headers/private/net/r5_compatibility.h index 2be5708207..eb9f086e5f 100644 --- a/headers/private/net/r5_compatibility.h +++ b/headers/private/net/r5_compatibility.h @@ -39,5 +39,7 @@ struct r5_sockaddr_in { }; extern bool __gR5Compatibility; +extern addr_t __gNetworkStart; +extern addr_t __gNetworkEnd; #endif // NET_R5_COMPATIBILITY_H diff --git a/src/kits/network/init.cpp b/src/kits/network/init.cpp index 291591b886..71c5741385 100644 --- a/src/kits/network/init.cpp +++ b/src/kits/network/init.cpp @@ -16,6 +16,26 @@ bool __gR5Compatibility = false; +addr_t __gNetworkStart; +addr_t __gNetworkEnd; + + +static void +find_own_image() +{ + int32 cookie = 0; + image_info info; + while (get_next_image_info(B_CURRENT_TEAM, &cookie, &info) == B_OK) { + if (((uint32)info.text <= (uint32)find_own_image + && (uint32)info.text + (uint32)info.text_size > (uint32)find_own_image)) { + // found us + __gNetworkStart = (addr_t)min_c(info.text, info.data); + __gNetworkEnd = min_c((addr_t)info.text + info.text_size, + (addr_t)info.data + info.data_size); + break; + } + } +} extern "C" void @@ -55,6 +75,7 @@ initialize_before() if (enable > 0) { __gR5Compatibility = true; + find_own_image(); debug_printf("libnetwork.so running in R5 compatibility mode.\n"); } } diff --git a/src/kits/network/socket.cpp b/src/kits/network/socket.cpp index 2d377dbe79..ff0f1dcc31 100644 --- a/src/kits/network/socket.cpp +++ b/src/kits/network/socket.cpp @@ -33,6 +33,30 @@ stack_driver_path(void) } +static inline bool +check_r5_compatibility() +{ + if (!__gR5Compatibility) + return false; + +#ifndef __INTEL__ + return false; +#else + + struct stack_frame { + struct stack_frame* previous; + addr_t return_address; + }; + + stack_frame* frame = (stack_frame*)get_stack_frame(); + if (frame->return_address >= __gNetworkStart && frame->return_address < __gNetworkEnd) + return false; + + return true; +#endif +} + + static void convert_from_r5_sockaddr(struct sockaddr *_to, const struct sockaddr *_from) { @@ -143,7 +167,7 @@ socket(int family, int type, int protocol) if (socket < 0) return -1; - if (__gR5Compatibility) + if (check_r5_compatibility()) convert_from_r5_socket(family, type, protocol); socket_args args; @@ -165,7 +189,7 @@ bind(int socket, const struct sockaddr *address, socklen_t addressLength) { struct sockaddr r5addr; - if (__gR5Compatibility) { + if (check_r5_compatibility()) { convert_from_r5_sockaddr(&r5addr, address); address = &r5addr; addressLength = sizeof(struct sockaddr_in); @@ -191,7 +215,7 @@ connect(int socket, const struct sockaddr *address, socklen_t addressLength) { struct sockaddr r5addr; - if (__gR5Compatibility) { + if (check_r5_compatibility()) { convert_from_r5_sockaddr(&r5addr, address); address = &r5addr; addressLength = sizeof(struct sockaddr_in); @@ -229,12 +253,13 @@ accept(int socket, struct sockaddr *address, socklen_t *_addressLength) return -1; } + bool r5compatible = check_r5_compatibility(); struct sockaddr r5addr; accept_args args; args.cookie = cookie; - if (__gR5Compatibility) { + if (r5compatible) { args.address = &r5addr; args.address_length = sizeof(r5addr); } else { @@ -247,7 +272,7 @@ accept(int socket, struct sockaddr *address, socklen_t *_addressLength) return -1; } - if (__gR5Compatibility) { + if (r5compatible) { convert_to_r5_sockaddr(address, &r5addr); if (_addressLength != NULL) *_addressLength = sizeof(struct r5_sockaddr_in); @@ -276,6 +301,7 @@ extern "C" ssize_t recvfrom(int socket, void *data, size_t length, int flags, struct sockaddr *address, socklen_t *_addressLength) { + bool r5compatible = check_r5_compatibility(); struct sockaddr r5addr; transfer_args args; @@ -283,7 +309,7 @@ recvfrom(int socket, void *data, size_t length, int flags, args.data_length = length; args.flags = flags; - if (__gR5Compatibility) { + if (r5compatible) { args.address = &r5addr; args.address_length = sizeof(r5addr); } else { @@ -295,7 +321,7 @@ recvfrom(int socket, void *data, size_t length, int flags, if (bytesReceived < 0) return -1; - if (__gR5Compatibility) { + if (r5compatible) { convert_to_r5_sockaddr(address, &r5addr); if (_addressLength != NULL) *_addressLength = sizeof(struct r5_sockaddr_in); @@ -334,7 +360,7 @@ sendto(int socket, const void *data, size_t length, int flags, { struct sockaddr r5addr; - if (__gR5Compatibility) { + if (check_r5_compatibility()) { convert_from_r5_sockaddr(&r5addr, address); address = &r5addr; addressLength = sizeof(struct sockaddr_in); @@ -362,7 +388,7 @@ sendmsg(int socket, const struct msghdr *message, int flags) extern "C" int getsockopt(int socket, int level, int option, void *value, size_t *_length) { - if (__gR5Compatibility) { + if (check_r5_compatibility()) { if (option == R5_SO_FIONREAD) { // there is no SO_FIONREAD in our stack; we're using FIONREAD instead *_length = sizeof(int); @@ -391,7 +417,7 @@ getsockopt(int socket, int level, int option, void *value, size_t *_length) extern "C" int setsockopt(int socket, int level, int option, const void *value, size_t length) { - if (__gR5Compatibility) + if (check_r5_compatibility()) convert_from_r5_sockopt(level, option); sockopt_args args; @@ -407,10 +433,11 @@ setsockopt(int socket, int level, int option, const void *value, size_t length) extern "C" int getpeername(int socket, struct sockaddr *address, socklen_t *_addressLength) { + bool r5compatible = check_r5_compatibility(); struct sockaddr r5addr; sockaddr_args args; - if (__gR5Compatibility) { + if (r5compatible) { args.address = &r5addr; args.address_length = sizeof(r5addr); } else { @@ -421,7 +448,7 @@ getpeername(int socket, struct sockaddr *address, socklen_t *_addressLength) if (ioctl(socket, NET_STACK_GETPEERNAME, &args, sizeof(args)) < 0) return -1; - if (__gR5Compatibility) { + if (r5compatible) { convert_to_r5_sockaddr(address, &r5addr); if (_addressLength != NULL) *_addressLength = sizeof(struct r5_sockaddr_in); @@ -435,10 +462,11 @@ getpeername(int socket, struct sockaddr *address, socklen_t *_addressLength) extern "C" int getsockname(int socket, struct sockaddr *address, socklen_t *_addressLength) { + bool r5compatible = check_r5_compatibility(); struct sockaddr r5addr; sockaddr_args args; - if (__gR5Compatibility) { + if (r5compatible) { args.address = &r5addr; args.address_length = sizeof(r5addr); } else { @@ -449,7 +477,7 @@ getsockname(int socket, struct sockaddr *address, socklen_t *_addressLength) if (ioctl(socket, NET_STACK_GETSOCKNAME, &args, sizeof(args)) < 0) return -1; - if (__gR5Compatibility) { + if (r5compatible) { convert_to_r5_sockaddr(address, &r5addr); if (_addressLength != NULL) *_addressLength = sizeof(struct r5_sockaddr_in);