int zmq::socket_base_t::bind (const char *addr_) { if (unlikely (ctx_terminated)) { errno = ETERM; return -1; } // Process pending commands, if any. int rc = process_commands (0, false); if (unlikely (rc != 0)) return -1; // Parse addr_ string. std::string protocol; std::string address; rc = parse_uri (addr_, protocol, address); if (rc != 0) return -1; rc = check_protocol (protocol); if (rc != 0) return -1; if (protocol == "inproc") { endpoint_t endpoint = {this, options}; int rc = register_endpoint (addr_, endpoint); if (rc == 0) { connect_pending(addr_, this); last_endpoint.assign (addr_); } return rc; } if (protocol == "pgm" || protocol == "epgm" || protocol == "norm") { // For convenience's sake, bind can be used interchageable with // connect for PGM, EPGM and NORM transports. return connect (addr_); } // Remaining trasnports require to be run in an I/O thread, so at this // point we'll choose one. io_thread_t *io_thread = choose_io_thread (options.affinity); if (!io_thread) { errno = EMTHREAD; return -1; } if (protocol == "tcp") { tcp_listener_t *listener = new (std::nothrow) tcp_listener_t ( io_thread, this, options); alloc_assert (listener); int rc = listener->set_address (address.c_str ()); if (rc != 0) { delete listener; event_bind_failed (address, zmq_errno()); return -1; } // Save last endpoint URI listener->get_address (last_endpoint); add_endpoint (addr_, (own_t *) listener, NULL); return 0; } #if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS if (protocol == "ipc") { ipc_listener_t *listener = new (std::nothrow) ipc_listener_t ( io_thread, this, options); alloc_assert (listener); int rc = listener->set_address (address.c_str ()); if (rc != 0) { delete listener; event_bind_failed (address, zmq_errno()); return -1; } // Save last endpoint URI listener->get_address (last_endpoint); add_endpoint (addr_, (own_t *) listener, NULL); return 0; } #endif #if defined ZMQ_HAVE_TIPC if (protocol == "tipc") { tipc_listener_t *listener = new (std::nothrow) tipc_listener_t ( io_thread, this, options); alloc_assert (listener); int rc = listener->set_address (address.c_str ()); if (rc != 0) { delete listener; event_bind_failed (address, zmq_errno()); return -1; } // Save last endpoint URI listener->get_address (last_endpoint); add_endpoint (addr_, (own_t *) listener, NULL); return 0; } #endif zmq_assert (false); return -1; }
int zmq::socket_base_t::bind (const char *addr_) { scoped_optional_lock_t sync_lock(thread_safe ? &sync : NULL); if (unlikely (ctx_terminated)) { errno = ETERM; return -1; } // Process pending commands, if any. int rc = process_commands (0, false); if (unlikely (rc != 0)) { return -1; } // Parse addr_ string. std::string protocol; std::string address; if (parse_uri (addr_, protocol, address) || check_protocol (protocol)) { return -1; } if (protocol == "inproc") { const endpoint_t endpoint = { this, options }; rc = register_endpoint (addr_, endpoint); if (rc == 0) { connect_pending (addr_, this); last_endpoint.assign (addr_); options.connected = true; } return rc; } if (protocol == "pgm" || protocol == "epgm" || protocol == "norm") { // For convenience's sake, bind can be used interchangeable with // connect for PGM, EPGM, NORM transports. rc = connect (addr_); if (rc != -1) options.connected = true; return rc; } if (protocol == "udp") { if (!(options.type == ZMQ_DGRAM || options.type == ZMQ_DISH)) { errno = ENOCOMPATPROTO; return -1; } // Choose the I/O thread to run the session in. io_thread_t *io_thread = choose_io_thread (options.affinity); if (!io_thread) { errno = EMTHREAD; return -1; } address_t *paddr = new (std::nothrow) address_t (protocol, address, this->get_ctx ()); alloc_assert (paddr); paddr->resolved.udp_addr = new (std::nothrow) udp_address_t (); alloc_assert (paddr->resolved.udp_addr); rc = paddr->resolved.udp_addr->resolve (address.c_str(), true); if (rc != 0) { LIBZMQ_DELETE(paddr); return -1; } session_base_t *session = session_base_t::create (io_thread, true, this, options, paddr); errno_assert (session); pipe_t *newpipe = NULL; // Create a bi-directional pipe. object_t *parents [2] = {this, session}; pipe_t *new_pipes [2] = {NULL, NULL}; int hwms [2] = {options.sndhwm, options.rcvhwm}; bool conflates [2] = {false, false}; rc = pipepair (parents, new_pipes, hwms, conflates); errno_assert (rc == 0); // Attach local end of the pipe to the socket object. attach_pipe (new_pipes [0], true); newpipe = new_pipes [0]; // Attach remote end of the pipe to the session object later on. session->attach_pipe (new_pipes [1]); // Save last endpoint URI paddr->to_string (last_endpoint); add_endpoint (addr_, (own_t *) session, newpipe); return 0; } // Remaining transports require to be run in an I/O thread, so at this // point we'll choose one. io_thread_t *io_thread = choose_io_thread (options.affinity); if (!io_thread) { errno = EMTHREAD; return -1; } if (protocol == "tcp") { tcp_listener_t *listener = new (std::nothrow) tcp_listener_t ( io_thread, this, options); alloc_assert (listener); rc = listener->set_address (address.c_str ()); if (rc != 0) { LIBZMQ_DELETE(listener); event_bind_failed (address, zmq_errno()); return -1; } // Save last endpoint URI listener->get_address (last_endpoint); add_endpoint (last_endpoint.c_str (), (own_t *) listener, NULL); options.connected = true; return 0; } #if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS if (protocol == "ipc") { ipc_listener_t *listener = new (std::nothrow) ipc_listener_t ( io_thread, this, options); alloc_assert (listener); int rc = listener->set_address (address.c_str ()); if (rc != 0) { LIBZMQ_DELETE(listener); event_bind_failed (address, zmq_errno()); return -1; } // Save last endpoint URI listener->get_address (last_endpoint); add_endpoint (last_endpoint.c_str (), (own_t *) listener, NULL); options.connected = true; return 0; } #endif #if defined ZMQ_HAVE_TIPC if (protocol == "tipc") { tipc_listener_t *listener = new (std::nothrow) tipc_listener_t ( io_thread, this, options); alloc_assert (listener); int rc = listener->set_address (address.c_str ()); if (rc != 0) { LIBZMQ_DELETE(listener); event_bind_failed (address, zmq_errno()); return -1; } // Save last endpoint URI listener->get_address (last_endpoint); add_endpoint (addr_, (own_t *) listener, NULL); options.connected = true; return 0; } #endif #if defined ZMQ_HAVE_VMCI if (protocol == "vmci") { vmci_listener_t *listener = new (std::nothrow) vmci_listener_t ( io_thread, this, options); alloc_assert (listener); int rc = listener->set_address (address.c_str ()); if (rc != 0) { LIBZMQ_DELETE(listener); event_bind_failed (address, zmq_errno ()); return -1; } listener->get_address (last_endpoint); add_endpoint (last_endpoint.c_str(), (own_t *) listener, NULL); options.connected = true; return 0; } #endif zmq_assert (false); return -1; }