blob: 0e4c056c8fabb6841249664ba9c17f82d837e5a1 [file] [log] [blame]
// Copyright 2019 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "starboard/common/socket.h"
#include <iomanip>
#include "starboard/common/log.h"
#include "starboard/configuration.h"
namespace starboard {
SbSocketAddress GetUnspecifiedAddress(SbSocketAddressType address_type,
int port) {
SbSocketAddress address = {};
address.type = address_type;
address.port = port;
return address;
}
bool GetLocalhostAddress(SbSocketAddressType address_type,
int port,
SbSocketAddress* address) {
if (address_type != kSbSocketAddressTypeIpv4 &&
address_type != kSbSocketAddressTypeIpv6) {
SB_LOG(ERROR) << __FUNCTION__ << ": unknown address type: " << address_type;
return false;
}
*address = GetUnspecifiedAddress(address_type, port);
switch (address_type) {
case kSbSocketAddressTypeIpv4:
address->address[0] = 127;
address->address[3] = 1;
break;
case kSbSocketAddressTypeIpv6:
address->address[15] = 1;
break;
}
return true;
}
Socket::Socket(SbSocketAddressType address_type, SbSocketProtocol protocol)
: socket_(SbSocketCreate(address_type, protocol)) {}
Socket::Socket(SbSocketAddressType address_type)
: socket_(SbSocketCreate(address_type, kSbSocketProtocolTcp)) {}
Socket::Socket(SbSocketProtocol protocol)
: socket_(SbSocketCreate(kSbSocketAddressTypeIpv4, protocol)) {}
Socket::Socket()
: socket_(SbSocketCreate(kSbSocketAddressTypeIpv4, kSbSocketProtocolTcp)) {}
Socket::~Socket() {
SbSocketDestroy(socket_);
}
bool Socket::IsValid() {
return SbSocketIsValid(socket_);
}
SbSocketError Socket::Connect(const SbSocketAddress* address) {
return SbSocketConnect(socket_, address);
}
SbSocketError Socket::Bind(const SbSocketAddress* local_address) {
return SbSocketBind(socket_, local_address);
}
SbSocketError Socket::Listen() {
return SbSocketListen(socket_);
}
Socket* Socket::Accept() {
SbSocket accepted_socket = SbSocketAccept(socket_);
if (SbSocketIsValid(accepted_socket)) {
return new Socket(accepted_socket);
}
return NULL;
}
bool Socket::IsConnected() {
return SbSocketIsConnected(socket_);
}
bool Socket::IsConnectedAndIdle() {
return SbSocketIsConnectedAndIdle(socket_);
}
bool Socket::IsPending() {
return GetLastError() == kSbSocketPending;
}
SbSocketError Socket::GetLastError() {
return SbSocketGetLastError(socket_);
}
void Socket::ClearLastError() {
SbSocketClearLastError(socket_);
}
int Socket::ReceiveFrom(char* out_data,
int data_size,
SbSocketAddress* out_source) {
return SbSocketReceiveFrom(socket_, out_data, data_size, out_source);
}
int Socket::SendTo(const char* data,
int data_size,
const SbSocketAddress* destination) {
return SbSocketSendTo(socket_, data, data_size, destination);
}
bool Socket::GetLocalAddress(SbSocketAddress* out_address) {
return SbSocketGetLocalAddress(socket_, out_address);
}
bool Socket::SetBroadcast(bool value) {
return SbSocketSetBroadcast(socket_, value);
}
bool Socket::SetReuseAddress(bool value) {
return SbSocketSetReuseAddress(socket_, value);
}
bool Socket::SetReceiveBufferSize(int32_t size) {
return SbSocketSetReceiveBufferSize(socket_, size);
}
bool Socket::SetSendBufferSize(int32_t size) {
return SbSocketSetSendBufferSize(socket_, size);
}
bool Socket::SetTcpKeepAlive(bool value, int64_t period) {
return SbSocketSetTcpKeepAlive(socket_, value, period);
}
bool Socket::SetTcpNoDelay(bool value) {
return SbSocketSetTcpNoDelay(socket_, value);
}
bool Socket::SetTcpWindowScaling(bool value) {
return SbSocketSetTcpWindowScaling(socket_, value);
}
bool Socket::JoinMulticastGroup(const SbSocketAddress* address) {
return SbSocketJoinMulticastGroup(socket_, address);
}
SbSocket Socket::socket() {
return socket_;
}
Socket::Socket(SbSocket socket) : socket_(socket) {}
} // namespace starboard
std::ostream& operator<<(std::ostream& os, const SbSocketAddress& address) {
if (address.type == kSbSocketAddressTypeIpv6) {
os << std::hex << "[";
const uint16_t* fields = reinterpret_cast<const uint16_t*>(address.address);
int i = 0;
while (fields[i] == 0) {
if (i == 0) {
os << ":";
}
++i;
if (i == 8) {
os << ":";
}
}
for (; i < 8; ++i) {
if (i != 0) {
os << ":";
}
#if SB_IS(LITTLE_ENDIAN)
const uint8_t* fields8 = reinterpret_cast<const uint8_t*>(&fields[i]);
const uint16_t value = static_cast<uint16_t>(fields8[0]) * 256 |
static_cast<uint16_t>(fields8[1]);
os << value;
#else
os << fields[i];
#endif
}
os << "]" << std::dec;
} else {
for (int i = 0; i < 4; ++i) {
if (i != 0) {
os << ".";
}
os << static_cast<int>(address.address[i]);
}
}
os << ":" << address.port;
return os;
}