Corrected by previous assumption, since gethostbyname() has nothing to do with
struct sockaddr_in - the real culprits were BNetAddress::GetAddr(sockaddr_in&) and BNetAddress::SetTo(const sockaddr_in&): * moved check_r5_compatibility() into r5_compatibility.h to make that function available to BNetAddress, too * adjusted sockaddr_in-handling methods of BNetAddress to deal with R5-addresses if in compatibility mode * removed is_r5_sockaddr() again, since it is no longer needed With this less hacky solution, Beam, NetPositive, NetworkTime and Vision still work. So, there's hope that the R5 compatibility layer is now complete. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26377 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -44,4 +44,31 @@ extern addr_t __gNetworkEnd;
|
|||||||
extern addr_t __gNetAPIStart;
|
extern addr_t __gNetAPIStart;
|
||||||
extern addr_t __gNetAPIEnd;
|
extern addr_t __gNetAPIEnd;
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif // NET_R5_COMPATIBILITY_H
|
#endif // NET_R5_COMPATIBILITY_H
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
* No trouts were harmed during the development of this class.
|
* No trouts were harmed during the development of this class.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <r5_compatibility.h>
|
||||||
|
|
||||||
#include <ByteOrder.h>
|
#include <ByteOrder.h>
|
||||||
#include <NetAddress.h>
|
#include <NetAddress.h>
|
||||||
#include <Message.h>
|
#include <Message.h>
|
||||||
@@ -184,13 +186,18 @@ BNetAddress::GetAddr(char* hostname, unsigned short* port) const
|
|||||||
status_t BNetAddress::GetAddr( struct sockaddr_in& sa ) const
|
status_t BNetAddress::GetAddr( struct sockaddr_in& sa ) const
|
||||||
{
|
{
|
||||||
if ( fInit != B_OK )
|
if ( fInit != B_OK )
|
||||||
{
|
|
||||||
return B_NO_INIT;
|
return B_NO_INIT;
|
||||||
}
|
|
||||||
|
|
||||||
sa.sin_family = fFamily;
|
|
||||||
sa.sin_port = fPort;
|
sa.sin_port = fPort;
|
||||||
sa.sin_addr.s_addr = fAddress;
|
sa.sin_addr.s_addr = fAddress;
|
||||||
|
if (check_r5_compatibility()) {
|
||||||
|
r5_sockaddr_in* r5Addr = (r5_sockaddr_in *)&sa;
|
||||||
|
if (fFamily == AF_INET)
|
||||||
|
r5Addr->sin_family = R5_AF_INET;
|
||||||
|
else
|
||||||
|
r5Addr->sin_family = fFamily;
|
||||||
|
} else
|
||||||
|
sa.sin_family = fFamily;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -358,10 +365,18 @@ BNetAddress::SetTo(const char* hostname, unsigned short port)
|
|||||||
status_t
|
status_t
|
||||||
BNetAddress::SetTo(const struct sockaddr_in& addr)
|
BNetAddress::SetTo(const struct sockaddr_in& addr)
|
||||||
{
|
{
|
||||||
fFamily = addr.sin_family;
|
|
||||||
fPort = addr.sin_port;
|
fPort = addr.sin_port;
|
||||||
fAddress = addr.sin_addr.s_addr;
|
fAddress = addr.sin_addr.s_addr;
|
||||||
|
|
||||||
|
if (check_r5_compatibility()) {
|
||||||
|
const r5_sockaddr_in* r5Addr = (const r5_sockaddr_in *)&addr;
|
||||||
|
if (r5Addr->sin_family == R5_AF_INET)
|
||||||
|
fFamily = AF_INET;
|
||||||
|
else
|
||||||
|
fFamily = r5Addr->sin_family;
|
||||||
|
} else
|
||||||
|
fFamily = addr.sin_family;
|
||||||
|
|
||||||
return fInit = B_OK;
|
return fInit = B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,53 +22,6 @@
|
|||||||
#include <syscalls.h>
|
#include <syscalls.h>
|
||||||
|
|
||||||
|
|
||||||
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 bool
|
|
||||||
is_r5_sockaddr(const struct sockaddr *_addr)
|
|
||||||
{
|
|
||||||
/* r5_sockaddr_in structs do not contain sin_len, but have a larger
|
|
||||||
* sin_family instead (two bytes), so in a r5_sockaddr_in, the first two
|
|
||||||
* bytes will always be equal to R5_AF_INET, while for haiku's own
|
|
||||||
* sockaddr_in, that will never be the case, since the first byte contains
|
|
||||||
* the length which should never be zero.
|
|
||||||
* The only other case where this check could fail is when the address does
|
|
||||||
* not belong to the internet family at all. But even in that case we would
|
|
||||||
* not want to try to convert the addresses, as the conversion itself
|
|
||||||
* blindly casts the address to sockaddr_in, which would yield unpredictable
|
|
||||||
* results for other address families.
|
|
||||||
*/
|
|
||||||
const r5_sockaddr_in *addr = (r5_sockaddr_in *)_addr;
|
|
||||||
if (addr == NULL || addr->sin_family != R5_AF_INET)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
convert_from_r5_sockaddr(struct sockaddr *_to, const struct sockaddr *_from)
|
convert_from_r5_sockaddr(struct sockaddr *_to, const struct sockaddr *_from)
|
||||||
{
|
{
|
||||||
@@ -195,7 +148,7 @@ bind(int socket, const struct sockaddr *address, socklen_t addressLength)
|
|||||||
{
|
{
|
||||||
struct sockaddr haikuAddr;
|
struct sockaddr haikuAddr;
|
||||||
|
|
||||||
if (check_r5_compatibility() && is_r5_sockaddr(address)) {
|
if (check_r5_compatibility()) {
|
||||||
convert_from_r5_sockaddr(&haikuAddr, address);
|
convert_from_r5_sockaddr(&haikuAddr, address);
|
||||||
address = &haikuAddr;
|
address = &haikuAddr;
|
||||||
addressLength = sizeof(struct sockaddr_in);
|
addressLength = sizeof(struct sockaddr_in);
|
||||||
@@ -217,7 +170,7 @@ connect(int socket, const struct sockaddr *address, socklen_t addressLength)
|
|||||||
{
|
{
|
||||||
struct sockaddr haikuAddr;
|
struct sockaddr haikuAddr;
|
||||||
|
|
||||||
if (check_r5_compatibility() && is_r5_sockaddr(address)) {
|
if (check_r5_compatibility()) {
|
||||||
convert_from_r5_sockaddr(&haikuAddr, address);
|
convert_from_r5_sockaddr(&haikuAddr, address);
|
||||||
address = &haikuAddr;
|
address = &haikuAddr;
|
||||||
addressLength = sizeof(struct sockaddr_in);
|
addressLength = sizeof(struct sockaddr_in);
|
||||||
@@ -331,7 +284,7 @@ sendto(int socket, const void *data, size_t length, int flags,
|
|||||||
{
|
{
|
||||||
struct sockaddr haikuAddr;
|
struct sockaddr haikuAddr;
|
||||||
|
|
||||||
if (check_r5_compatibility() && is_r5_sockaddr(address)) {
|
if (check_r5_compatibility()) {
|
||||||
convert_from_r5_sockaddr(&haikuAddr, address);
|
convert_from_r5_sockaddr(&haikuAddr, address);
|
||||||
address = &haikuAddr;
|
address = &haikuAddr;
|
||||||
addressLength = sizeof(struct sockaddr_in);
|
addressLength = sizeof(struct sockaddr_in);
|
||||||
|
|||||||
Reference in New Issue
Block a user