status_t BAbstractSocket::Connect(const BNetworkAddress& peer, int type, bigtime_t timeout) { Disconnect(); fInitStatus = _OpenIfNeeded(peer.Family(), type); if (fInitStatus == B_OK) fInitStatus = SetTimeout(timeout); if (fInitStatus == B_OK && !IsBound()) { BNetworkAddress local; local.SetToWildcard(peer.Family()); fInitStatus = Bind(local); } if (fInitStatus != B_OK) return fInitStatus; BNetworkAddress normalized = peer; if (connect(fSocket, normalized, normalized.Length()) != 0) { TRACE("%p: connecting to %s: %s\n", this, normalized.ToString().c_str(), strerror(errno)); return fInitStatus = errno; } fIsConnected = true; fPeer = normalized; _UpdateLocalAddress(); TRACE("%p: connected to %s (local %s)\n", this, peer.ToString().c_str(), fLocal.ToString().c_str()); return fInitStatus = B_OK; }
/*! Parses the \a argument as network \a address for the specified \a family. If \a family is \c AF_UNSPEC, \a family will be overwritten with the family of the successfully parsed address. */ bool parse_address(int& family, const char* argument, BNetworkAddress& address) { if (argument == NULL) return false; status_t status = address.SetTo(family, argument, (uint16)0, B_NO_ADDRESS_RESOLUTION); if (status != B_OK) return false; if (family == AF_UNSPEC) { // Test if we support the resulting address family bool supported = false; for (int32 i = 0; kFamilies[i].family >= 0; i++) { if (kFamilies[i].family == address.Family()) { supported = true; break; } } if (!supported) return false; // Take over family from address family = address.Family(); } return true; }
bool BNetworkAddress::operator<(const BNetworkAddress& other) const { if (Family() < other.Family()) return true; if (Family() > other.Family()) return false; int compare; switch (fAddress.ss_family) { default: case AF_INET: { sockaddr_in& address = (sockaddr_in&)fAddress; sockaddr_in& otherAddress = (sockaddr_in&)other.fAddress; compare = memcmp(&address.sin_addr, &otherAddress.sin_addr, sizeof(address.sin_addr)); break; } case AF_INET6: { sockaddr_in6& address = (sockaddr_in6&)fAddress; sockaddr_in6& otherAddress = (sockaddr_in6&)other.fAddress; compare = memcmp(&address.sin6_addr, &otherAddress.sin6_addr, sizeof(address.sin6_addr)); break; } case AF_LINK: if (LinkLevelAddressLength() < other.LinkLevelAddressLength()) return true; if (LinkLevelAddressLength() > other.LinkLevelAddressLength()) return true; // TODO: could compare index, and name, too compare = memcmp(LinkLevelAddress(), other.LinkLevelAddress(), LinkLevelAddressLength()); break; } if (compare < 0) return true; if (compare > 0) return false; return Port() < other.Port(); }
status_t SocketConnection::Connect(const char* server, uint32 port) { if (fSocket >= 0) Disconnect(); TRACE("SocketConnection to server %s:%i\n", server, (int)port); BNetworkAddress address; status_t status = address.SetTo(server, port); if (status != B_OK) return status; fSocket = socket(address.Family(), SOCK_STREAM, 0); if (fSocket < 0) return errno; int result = connect(fSocket, address, address.Length()); if (result < 0) { close(fSocket); return errno; } TRACE("SocketConnection: connected\n"); return B_OK; }
bool BNetworkAddress::Equals(const BNetworkAddress& other, bool includePort) const { if (IsEmpty() && other.IsEmpty()) return true; if (Family() != other.Family() || (includePort && Port() != other.Port())) { return false; } switch (fAddress.ss_family) { case AF_INET: { sockaddr_in& address = (sockaddr_in&)fAddress; sockaddr_in& otherAddress = (sockaddr_in&)other.fAddress; return memcmp(&address.sin_addr, &otherAddress.sin_addr, sizeof(address.sin_addr)) == 0; } case AF_INET6: { sockaddr_in6& address = (sockaddr_in6&)fAddress; sockaddr_in6& otherAddress = (sockaddr_in6&)other.fAddress; return memcmp(&address.sin6_addr, &otherAddress.sin6_addr, sizeof(address.sin6_addr)) == 0; } default: if (fAddress.ss_len != other.fAddress.ss_len) return false; return memcmp(&fAddress, &other.fAddress, fAddress.ss_len); } }
status_t SocketConnection::Connect(const char* server, uint32 port) { if (fSocket >= 0) Disconnect(); TRACE("SocketConnection to server %s:%i\n", server, (int)port); BNetworkAddress address; status_t status = address.SetTo(server, port); if (status != B_OK) { TRACE("%s: Address Error: %s\n", __func__, strerror(status)); return status; } TRACE("Server resolves to %s\n", address.ToString().String()); fSocket = socket(address.Family(), SOCK_STREAM, 0); if (fSocket < 0) { TRACE("%s: Socket Error: %s\n", __func__, strerror(errno)); return errno; } int result = connect(fSocket, address, address.Length()); if (result < 0) { TRACE("%s: Connect Error: %s\n", __func__, strerror(errno)); close(fSocket); return errno; } TRACE("SocketConnection: connected\n"); return B_OK; }
status_t BNetworkInterface::RemoveAddress(const BNetworkAddress& address) { ifreq request; memcpy(&request.ifr_addr, &address.SockAddr(), address.Length()); return do_request(address.Family(), request, Name(), B_SOCKET_REMOVE_ALIAS); }
status_t BNetworkDevice::GetNetwork(const BNetworkAddress& address, wireless_network& network) { if (address.Family() != AF_LINK) return B_BAD_VALUE; return get_network(Name(), network, UINT32_MAX, &address, NULL); }
status_t BAbstractSocket::Bind(const BNetworkAddress& local, int type) { fInitStatus = _OpenIfNeeded(local.Family(), type); if (fInitStatus != B_OK) return fInitStatus; if (bind(fSocket, local, local.Length()) != 0) return fInitStatus = errno; fIsBound = true; _UpdateLocalAddress(); return B_OK; }
int32 BNetworkInterface::FindAddress(const BNetworkAddress& address) { int socket = ::socket(address.Family(), SOCK_DGRAM, 0); if (socket < 0) return -1; FileDescriptorCloser closer(socket); ifaliasreq request; memset(&request, 0, sizeof(ifaliasreq)); strlcpy(request.ifra_name, Name(), IF_NAMESIZE); request.ifra_index = -1; memcpy(&request.ifra_addr, &address.SockAddr(), address.Length()); if (ioctl(socket, B_SOCKET_GET_ALIAS, &request, sizeof(struct ifaliasreq)) < 0) { return -1; } return request.ifra_index; }