void TestNrSocket::fire_readable_callback() { MOZ_ASSERT(poll_flags() & PR_POLL_READ); // Stop listening on all mapped sockets; we will start listening again // if the app starts listening to us again. cancel_port_mapping_async_wait(NR_ASYNC_WAIT_READ); r_log(LOG_GENERIC, LOG_DEBUG, "TestNrSocket %s ready for read", my_addr_.as_string); fire_callback(NR_ASYNC_WAIT_READ); }
int NrSocket::cancel(int how) { int r = NrSocketBase::cancel(how); if (!r) { mPollFlags = poll_flags(); } return r; }
// async_event APIs int NrSocket::async_wait(int how, NR_async_cb cb, void *cb_arg, char *function, int line) { int r = NrSocketBase::async_wait(how, cb, cb_arg, function, line); if (!r) { mPollFlags = poll_flags(); } return r; }
int TestNrSocket::sendto(const void *msg, size_t len, int flags, nr_transport_addr *to) { MOZ_ASSERT(my_addr_.protocol != IPPROTO_TCP); ASSERT_ON_THREAD(ststhread_); if (!nat_->enabled_ || nat_->is_an_internal_tuple(*to)) { return NrSocket::sendto(msg, len, flags, to); } destroy_stale_port_mappings(); if (to->protocol == IPPROTO_UDP && nat_->block_udp_) { // Silently eat the packet return 0; } // Choose our port mapping based on our most selective criteria PortMapping *port_mapping = get_port_mapping(*to, std::max(nat_->filtering_type_, nat_->mapping_type_)); if (!port_mapping) { // See if we have already made the external socket we need to use. PortMapping *similar_port_mapping = get_port_mapping(*to, nat_->mapping_type_); nsRefPtr<NrSocket> external_socket; if (similar_port_mapping) { external_socket = similar_port_mapping->external_socket_; } else { external_socket = create_external_socket(*to); if (!external_socket) { MOZ_ASSERT(false); return R_INTERNAL; } } port_mapping = create_port_mapping(*to, external_socket); port_mappings_.push_back(port_mapping); if (poll_flags() & PR_POLL_READ) { // Make sure the new port mapping is ready to receive traffic if the // TestNrSocket is already waiting. port_mapping->async_wait(NR_ASYNC_WAIT_READ, port_mapping_readable_callback, this, (char*)__FUNCTION__, __LINE__); } } // We probably don't want to propagate the flags, since this is a simulated // external IP address. return port_mapping->sendto(msg, len, *to); }
void TestNrSocket::on_port_mapping_readable(NrSocket *external_socket) { if (!readable_socket_) { readable_socket_ = external_socket; } // None of our port mappings should be waiting for readable callbacks // if nobody is waiting for readable callbacks from us. MOZ_ASSERT(poll_flags() & PR_POLL_READ); fire_readable_callback(); }
void NrSocketIpc::recv_callback_s(RefPtr<nr_udp_message> msg) { ASSERT_ON_THREAD(sts_thread_); { ReentrantMonitorAutoEnter mon(monitor_); if (state_ != NR_CONNECTED) { return; } } //enqueue received message received_msgs_.push(msg); if ((poll_flags() & PR_POLL_READ)) { fire_callback(NR_ASYNC_WAIT_READ); } }
int TestNrSocket::connect(nr_transport_addr *addr) { if (connect_invoked_ || !port_mappings_.empty()) { MOZ_CRASH("TestNrSocket::connect() called more than once!"); return R_INTERNAL; } if (!nat_->enabled_ || addr->protocol==IPPROTO_UDP // Horrible hack to allow default address // discovery to work. Only works because // we don't normally connect on UDP. || nat_->is_an_internal_tuple(*addr)) { // This will set connect_invoked_ return internal_socket_->connect(addr); } RefPtr<NrSocketBase> external_socket(create_external_socket(*addr)); if (!external_socket) { return R_INTERNAL; } PortMapping *port_mapping = create_port_mapping(*addr, external_socket); port_mappings_.push_back(port_mapping); int r = port_mapping->external_socket_->connect(addr); if (r && r != R_WOULDBLOCK) { return r; } port_mapping->last_used_ = PR_IntervalNow(); if (poll_flags() & PR_POLL_READ) { port_mapping->async_wait(NR_ASYNC_WAIT_READ, port_mapping_tcp_passthrough_callback, this, (char*)__FUNCTION__, __LINE__); } return r; }
void TestNrSocket::fire_readable_callback() { MOZ_ASSERT(poll_flags() & PR_POLL_READ); r_log(LOG_GENERIC, LOG_DEBUG, "TestNrSocket %s ready for read", internal_socket_->my_addr().as_string); fire_callback(NR_ASYNC_WAIT_READ); }
int TestNrSocket::sendto(const void *msg, size_t len, int flags, nr_transport_addr *to) { MOZ_ASSERT(internal_socket_->my_addr().protocol != IPPROTO_TCP); UCHAR *buf = static_cast<UCHAR*>(const_cast<void*>(msg)); if (nat_->block_stun_ && nr_is_stun_message(buf, len)) { return 0; } /* TODO: improve the functionality of this in bug 1253657 */ if (!nat_->enabled_ || nat_->is_an_internal_tuple(*to)) { if (nat_->delay_stun_resp_ms_ && nr_is_stun_response_message(buf, len)) { NR_ASYNC_TIMER_SET(nat_->delay_stun_resp_ms_, process_delayed_cb, new DeferredPacket(this, msg, len, flags, to, internal_socket_), &timer_handle_); return 0; } return internal_socket_->sendto(msg, len, flags, to); } destroy_stale_port_mappings(); if (to->protocol == IPPROTO_UDP && nat_->block_udp_) { // Silently eat the packet return 0; } // Choose our port mapping based on our most selective criteria PortMapping *port_mapping = get_port_mapping(*to, std::max(nat_->filtering_type_, nat_->mapping_type_)); if (!port_mapping) { // See if we have already made the external socket we need to use. PortMapping *similar_port_mapping = get_port_mapping(*to, nat_->mapping_type_); RefPtr<NrSocketBase> external_socket; if (similar_port_mapping) { external_socket = similar_port_mapping->external_socket_; } else { external_socket = create_external_socket(*to); if (!external_socket) { MOZ_ASSERT(false); return R_INTERNAL; } } port_mapping = create_port_mapping(*to, external_socket); port_mappings_.push_back(port_mapping); if (poll_flags() & PR_POLL_READ) { // Make sure the new port mapping is ready to receive traffic if the // TestNrSocket is already waiting. port_mapping->async_wait(NR_ASYNC_WAIT_READ, socket_readable_callback, this, (char*)__FUNCTION__, __LINE__); } } // We probably don't want to propagate the flags, since this is a simulated // external IP address. return port_mapping->sendto(msg, len, *to); }