void MockUDPSocket::AddExpectedData(IOQueue *ioqueue, const IPV4SocketAddress &dest) { unsigned int size; uint8_t *data = IOQueueToBuffer(ioqueue, &size); expected_call call = {data, size, dest.Host(), dest.Port(), true}; m_expected_calls.push(call); }
void AdvancedTCPConnector::Disconnect(const IPV4SocketAddress &endpoint, bool pause) { IPPortPair key(endpoint.Host(), endpoint.Port()); ConnectionMap::iterator iter = m_connections.find(key); if (iter == m_connections.end()) return; if (iter->second->state != CONNECTED) return; iter->second->failed_attempts = 0; if (pause) { iter->second->state = PAUSED; } else { // schedule a retry as if this endpoint failed once iter->second->state = DISCONNECTED; iter->second->retry_timeout = m_ss->RegisterSingleTimeout( iter->second->policy->BackOffTime(1), ola::NewSingleCallback( this, &AdvancedTCPConnector::RetryTimeout, iter->first)); } }
/* * Called when there is data on this socket */ void PathportNode::SocketReady(UDPSocket *socket) { pathport_packet_s packet; ssize_t packet_size = sizeof(packet); IPV4SocketAddress source; if (!socket->RecvFrom(reinterpret_cast<uint8_t*>(&packet), &packet_size, &source)) return; // skip packets sent by us if (source.Host() == m_interface.ip_address) return; if (packet_size < static_cast<ssize_t>(sizeof(packet.header))) { OLA_WARN << "Small pathport packet received, discarding"; return; } packet_size -= static_cast<ssize_t>(sizeof(packet.header)); // Validate header if (!ValidateHeader(packet.header)) { OLA_WARN << "Invalid pathport packet"; return; } uint32_t destination = NetworkToHost(packet.header.destination); if (destination != m_device_id && destination != PATHPORT_ID_BROADCAST && destination != PATHPORT_STATUS_GROUP && destination != PATHPORT_CONFIG_GROUP && destination != PATHPORT_DATA_GROUP) { ola::network::IPV4Address addr(destination); OLA_WARN << "pathport destination not set to us: " << addr; return; } // TODO(simon): Handle multiple pdus here pathport_packet_pdu *pdu = &packet.d.pdu; if (packet_size < static_cast<ssize_t>(sizeof(pathport_pdu_header))) { OLA_WARN << "Pathport packet too small to fit a pdu header"; return; } packet_size -= sizeof(pathport_pdu_header); switch (NetworkToHost(pdu->head.type)) { case PATHPORT_DATA: HandleDmxData(pdu->d.data, packet_size); break; case PATHPORT_ARP_REQUEST: SendArpReply(); break; case PATHPORT_ARP_REPLY: OLA_DEBUG << "Got pathport arp reply"; break; default: OLA_INFO << "Unhandled pathport packet with id: " << NetworkToHost(pdu->head.type); } }
/** * Inject the data in an IOQueue into the socket. This acts as if the data was * received on the UDP socket. * @param ioqueue the data to inject * @param source the socket address where this fake data came from */ void MockUDPSocket::InjectData(IOQueue *ioqueue, const IPV4SocketAddress &source) { unsigned int data_size; // This incurs a copy, but this is just testing code so it doesn't matter. uint8_t *data = IOQueueToBuffer(ioqueue, &data_size); expected_call call = {data, data_size, source.Host(), source.Port(), true}; m_received_data.push(call); PerformRead(); }
void AdvancedTCPConnector::RemoveEndpoint(const IPV4SocketAddress &endpoint) { IPPortPair key(endpoint.Host(), endpoint.Port()); ConnectionMap::iterator iter = m_connections.find(key); if (iter == m_connections.end()) return; AbortConnection(iter->second); delete iter->second; m_connections.erase(iter); }
void AdvancedTCPConnector::Resume(const IPV4SocketAddress &endpoint) { IPPortPair key(endpoint.Host(), endpoint.Port()); ConnectionMap::iterator iter = m_connections.find(key); if (iter == m_connections.end()) return; if (iter->second->state == PAUSED) { iter->second->state = DISCONNECTED; AttemptConnection(iter->first, iter->second); } }
bool AdvancedTCPConnector::GetEndpointState( const IPV4SocketAddress &endpoint, ConnectionState *connected, unsigned int *failed_attempts) const { IPPortPair key(endpoint.Host(), endpoint.Port()); ConnectionMap::const_iterator iter = m_connections.find(key); if (iter == m_connections.end()) return false; *connected = iter->second->state; *failed_attempts = iter->second->failed_attempts; return true; }
/* * Receive some data and check it. */ void SocketTest::UDPReceiveAndTerminate(UDPSocket *socket) { IPV4Address expected_address; OLA_ASSERT_TRUE(IPV4Address::FromString("127.0.0.1", &expected_address)); IPV4SocketAddress source; uint8_t buffer[sizeof(test_cstring) + 10]; ssize_t data_read = sizeof(buffer); socket->RecvFrom(buffer, &data_read, &source); OLA_ASSERT_EQ(static_cast<ssize_t>(sizeof(test_cstring)), data_read); OLA_ASSERT_EQ(expected_address, source.Host()); m_ss->Terminate(); }
/** * Add a remote host. This will trigger the connection process to start. * If the ip:port already exists this won't do anything. * When the connection is successfull the on_connect callback will be run, and * ownership of the TCPSocket object is transferred. * @param endpoint the IPV4SocketAddress to connect to. * @param backoff_policy the BackOffPolicy to use for this connection. * @param paused true if we don't want to immediately connect to this peer. */ void AdvancedTCPConnector::AddEndpoint(const IPV4SocketAddress &endpoint, BackOffPolicy *backoff_policy, bool paused) { IPPortPair key(endpoint.Host(), endpoint.Port()); ConnectionMap::iterator iter = m_connections.find(key); if (iter != m_connections.end()) return; // new ip:port ConnectionInfo *state = new ConnectionInfo; state->state = paused ? PAUSED : DISCONNECTED; state->failed_attempts = 0; state->retry_timeout = ola::thread::INVALID_TIMEOUT; state->connection_id = 0; state->policy = backoff_policy; m_connections[key] = state; if (!paused) AttemptConnection(key, state); }
TCPConnector::TCPConnectionID TCPConnector::Connect( const IPV4SocketAddress &endpoint, const ola::TimeInterval &timeout, TCPConnectCallback *callback) { struct sockaddr server_address; if (!endpoint.ToSockAddr(&server_address, sizeof(server_address))) { callback->Run(-1, 0); return 0; } int sd = socket(endpoint.Family(), SOCK_STREAM, 0); if (sd < 0) { int error = errno; OLA_WARN << "socket() failed, " << strerror(error); callback->Run(-1, error); return 0; } #ifdef _WIN32 ola::io::DescriptorHandle descriptor; descriptor.m_handle.m_fd = sd; descriptor.m_type = ola::io::SOCKET_DESCRIPTOR; #else ola::io::DescriptorHandle descriptor = sd; #endif ola::io::ConnectedDescriptor::SetNonBlocking(descriptor); int r = connect(sd, &server_address, sizeof(server_address)); if (r) { #ifdef _WIN32 if (WSAGetLastError() != WSAEWOULDBLOCK) { #else if (errno != EINPROGRESS) { #endif int error = errno; OLA_WARN << "connect() to " << endpoint << " returned, " << strerror(error); close(sd); callback->Run(-1, error); return 0; } } else { // connect returned immediately callback->Run(sd, 0); return 0; } PendingTCPConnection *connection = new PendingTCPConnection( this, endpoint.Host(), sd, callback); m_connections.insert(connection); connection->timeout_id = m_ss->RegisterSingleTimeout( timeout, ola::NewSingleCallback(this, &TCPConnector::TimeoutEvent, connection)); m_ss->AddWriteDescriptor(connection); return connection; } bool TCPConnector::Cancel(TCPConnectionID id) { PendingTCPConnection *connection = const_cast<PendingTCPConnection*>( reinterpret_cast<const PendingTCPConnection*>(id)); ConnectionSet::iterator iter = m_connections.find(connection); if (iter == m_connections.end()) return false; if (connection->timeout_id != ola::thread::INVALID_TIMEOUT) { m_ss->RemoveTimeout(connection->timeout_id); connection->timeout_id = ola::thread::INVALID_TIMEOUT; } Timeout(iter); m_connections.erase(iter); return true; }
/** * Ownership of the data is not transferred. */ void MockUDPSocket::InjectData(const uint8_t *data, unsigned int size, const IPV4SocketAddress &source) { InjectData(data, size, source.Host(), source.Port()); }