static void bt_audio_close(const void *buf, uint16_t len) { const struct audio_cmd_close *cmd = buf; struct a2dp_endpoint *endpoint; DBG(""); endpoint = find_endpoint(cmd->id); if (!endpoint) { error("Unable to find endpoint %u", cmd->id); ipc_send_rsp(audio_ipc, AUDIO_SERVICE_ID, AUDIO_OP_CLOSE, AUDIO_STATUS_FAILED); return; } endpoints = g_slist_remove(endpoints, endpoint); unregister_endpoint(endpoint); ipc_send_rsp(audio_ipc, AUDIO_SERVICE_ID, AUDIO_OP_CLOSE, AUDIO_STATUS_SUCCESS); }
int API_EXPORTED libusb_get_max_packet_size(libusb_device *dev, unsigned char endpoint) { struct libusb_config_descriptor *config; const struct libusb_endpoint_descriptor *ep; int r; r = libusb_get_active_config_descriptor(dev, &config); if (r < 0) { usbi_err(DEVICE_CTX(dev), "could not retrieve active config descriptor"); return LIBUSB_ERROR_OTHER; } ep = find_endpoint(config, endpoint); if (!ep) return LIBUSB_ERROR_NOT_FOUND; r = ep->wMaxPacketSize; libusb_free_config_descriptor(config); return r; }
/* * epm_Insert * * Add the specified entries to an endpoint map. */ error_status_t _epm_Insert(struct pipes_struct *p, struct epm_Insert *r) { TALLOC_CTX *tmp_ctx; error_status_t rc; NTSTATUS status; uint32_t i; struct dcerpc_binding *b; struct dcesrv_endpoint *ep; struct dcesrv_iface_list *iflist; struct dcesrv_iface *iface; bool add_ep; /* If this is not a priviledged users, return */ if (p->transport != NCALRPC || !is_priviledged_pipe(p->session_info)) { p->fault_state = DCERPC_FAULT_OP_RNG_ERROR; return EPMAPPER_STATUS_CANT_PERFORM_OP; } tmp_ctx = talloc_stackframe(); if (tmp_ctx == NULL) { return EPMAPPER_STATUS_NO_MEMORY; } DEBUG(3, ("_epm_Insert: Trying to add %u new entries.\n", r->in.num_ents)); for (i = 0; i < r->in.num_ents; i++) { add_ep = false; b = NULL; status = dcerpc_binding_from_tower(tmp_ctx, &r->in.entries[i].tower->tower, &b); if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) { rc = EPMAPPER_STATUS_NO_MEMORY; goto done; } if (!NT_STATUS_IS_OK(status)) { rc = EPMAPPER_STATUS_CANT_PERFORM_OP; goto done; } DEBUG(3, ("_epm_Insert: Adding transport %s for %s\n", derpc_transport_string_by_transport(b->transport), r->in.entries[i].annotation)); /* Check if the entry already exits */ ep = find_endpoint(endpoint_table, b); if (ep == NULL) { /* No entry found, create it */ ep = talloc_zero(NULL, struct dcesrv_endpoint); if (ep == NULL) { rc = EPMAPPER_STATUS_NO_MEMORY; goto done; } add_ep = true; ep->ep_description = talloc_steal(ep, b); } /* TODO Replace the entry if the replace flag is set */ /* Create an interface */ iface = talloc(tmp_ctx, struct dcesrv_iface); if (iface == NULL) { rc = EPMAPPER_STATUS_NO_MEMORY; goto done; } iface->name = talloc_strdup(iface, r->in.entries[i].annotation); if (iface->name == NULL) { rc = EPMAPPER_STATUS_NO_MEMORY; goto done; } iface->syntax_id = b->object; /* * Check if the rpc service is alrady registered on the * endpoint. */ if (find_interface(ep, iface) != NULL) { DEBUG(8, ("dcesrv_interface_register: interface '%s' " "already registered on endpoint\n", iface->name)); /* FIXME wrong error code? */ rc = EPMAPPER_STATUS_OK; goto done; } /* Create an entry for the interface */ iflist = talloc(ep, struct dcesrv_iface_list); if (iflist == NULL) { rc = EPMAPPER_STATUS_NO_MEMORY; goto done; } iflist->iface = talloc_move(iflist, &iface); /* Finally add the interface on the endpoint */ DLIST_ADD(ep->iface_list, iflist); /* If it's a new endpoint add it to the endpoint_table */ if (add_ep) { DLIST_ADD(endpoint_table, ep); } }
int zmq::socket_base_t::connect (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") { // TODO: inproc connect is specific with respect to creating pipes // as there's no 'reconnect' functionality implemented. Once that // is in place we should follow generic pipe creation algorithm. // Find the peer endpoint. endpoint_t peer = find_endpoint (addr_); // The total HWM for an inproc connection should be the sum of // the binder's HWM and the connector's HWM. int sndhwm = 0; if (peer.socket == NULL) sndhwm = options.sndhwm; else if (options.sndhwm != 0 && peer.options.rcvhwm != 0) sndhwm = options.sndhwm + peer.options.rcvhwm; int rcvhwm = 0; if (peer.socket == NULL) rcvhwm = options.rcvhwm; else if (options.rcvhwm != 0 && peer.options.sndhwm != 0) rcvhwm = options.rcvhwm + peer.options.sndhwm; // Create a bi-directional pipe to connect the peers. object_t *parents [2] = {this, peer.socket == NULL ? this : peer.socket}; pipe_t *new_pipes [2] = {NULL, NULL}; bool conflate = options.conflate && (options.type == ZMQ_DEALER || options.type == ZMQ_PULL || options.type == ZMQ_PUSH || options.type == ZMQ_PUB || options.type == ZMQ_SUB); int hwms [2] = {conflate? -1 : sndhwm, conflate? -1 : rcvhwm}; bool conflates [2] = {conflate, conflate}; int rc = pipepair (parents, new_pipes, hwms, conflates); errno_assert (rc == 0); // Attach local end of the pipe to this socket object. attach_pipe (new_pipes [0]); if (!peer.socket) { // The peer doesn't exist yet so we don't know whether // to send the identity message or not. To resolve this, // we always send our identity and drop it later if // the peer doesn't expect it. msg_t id; rc = id.init_size (options.identity_size); errno_assert (rc == 0); memcpy (id.data (), options.identity, options.identity_size); id.set_flags (msg_t::identity); bool written = new_pipes [0]->write (&id); zmq_assert (written); new_pipes [0]->flush (); endpoint_t endpoint = {this, options}; pending_connection_t pending_connection = {endpoint, new_pipes [0], new_pipes [1]}; pend_connection (addr_, pending_connection); } else { // If required, send the identity of the local socket to the peer. if (peer.options.recv_identity) { msg_t id; rc = id.init_size (options.identity_size); errno_assert (rc == 0); memcpy (id.data (), options.identity, options.identity_size); id.set_flags (msg_t::identity); bool written = new_pipes [0]->write (&id); zmq_assert (written); new_pipes [0]->flush (); } // If required, send the identity of the peer to the local socket. if (options.recv_identity) { msg_t id; rc = id.init_size (peer.options.identity_size); errno_assert (rc == 0); memcpy (id.data (), peer.options.identity, peer.options.identity_size); id.set_flags (msg_t::identity); bool written = new_pipes [1]->write (&id); zmq_assert (written); new_pipes [1]->flush (); } // Attach remote end of the pipe to the peer socket. Note that peer's // seqnum was incremented in find_endpoint function. We don't need it // increased here. send_bind (peer.socket, new_pipes [1], false); } // Save last endpoint URI last_endpoint.assign (addr_); // remember inproc connections for disconnect inprocs.insert (inprocs_t::value_type (std::string (addr_), new_pipes[0])); return 0; } bool is_single_connect = (options.type == ZMQ_DEALER || options.type == ZMQ_SUB || options.type == ZMQ_REQ); if (unlikely (is_single_connect)) { endpoints_t::iterator it = endpoints.find (addr_); if (it != endpoints.end ()) { // There is no valid use for multiple connects for SUB-PUB nor // DEALER-ROUTER nor REQ-REP. Multiple connects produces // nonsensical results. return 0; } } // 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); alloc_assert (paddr); // Resolve address (if needed by the protocol) if (protocol == "tcp") { // Defer resolution until a socket is opened paddr->resolved.tcp_addr = NULL; } #if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS else if (protocol == "ipc") { paddr->resolved.ipc_addr = new (std::nothrow) ipc_address_t (); alloc_assert (paddr->resolved.ipc_addr); int rc = paddr->resolved.ipc_addr->resolve (address.c_str ()); if (rc != 0) { delete paddr; return -1; } } #endif // TBD - Should we check address for ZMQ_HAVE_NORM??? #ifdef ZMQ_HAVE_OPENPGM if (protocol == "pgm" || protocol == "epgm") { struct pgm_addrinfo_t *res = NULL; uint16_t port_number = 0; int rc = pgm_socket_t::init_address(address.c_str(), &res, &port_number); if (res != NULL) pgm_freeaddrinfo (res); if (rc != 0 || port_number == 0) return -1; } #endif #if defined ZMQ_HAVE_TIPC else if (protocol == "tipc") { paddr->resolved.tipc_addr = new (std::nothrow) tipc_address_t (); alloc_assert (paddr->resolved.tipc_addr); int rc = paddr->resolved.tipc_addr->resolve (address.c_str()); if (rc != 0) { delete paddr; return -1; } } #endif // Create session. session_base_t *session = session_base_t::create (io_thread, true, this, options, paddr); errno_assert (session); // PGM does not support subscription forwarding; ask for all data to be // sent to this pipe. (same for NORM, currently?) bool subscribe_to_all = protocol == "pgm" || protocol == "epgm" || protocol == "norm"; pipe_t *newpipe = NULL; if (options.immediate != 1 || subscribe_to_all) { // Create a bi-directional pipe. object_t *parents [2] = {this, session}; pipe_t *new_pipes [2] = {NULL, NULL}; bool conflate = options.conflate && (options.type == ZMQ_DEALER || options.type == ZMQ_PULL || options.type == ZMQ_PUSH || options.type == ZMQ_PUB || options.type == ZMQ_SUB); int hwms [2] = {conflate? -1 : options.sndhwm, conflate? -1 : options.rcvhwm }; bool conflates [2] = {conflate, conflate}; 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], subscribe_to_all); 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; }
int zmq::socket_base_t::connect (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") { // TODO: inproc connect is specific with respect to creating pipes // as there's no 'reconnect' functionality implemented. Once that // is in place we should follow generic pipe creation algorithm. // Find the peer endpoint. endpoint_t peer = find_endpoint (addr_); if (!peer.socket) return -1; // The total HWM for an inproc connection should be the sum of // the binder's HWM and the connector's HWM. int sndhwm; int rcvhwm; if (options.sndhwm == 0 || peer.options.rcvhwm == 0) sndhwm = 0; else sndhwm = options.sndhwm + peer.options.rcvhwm; if (options.rcvhwm == 0 || peer.options.sndhwm == 0) rcvhwm = 0; else rcvhwm = options.rcvhwm + peer.options.sndhwm; // Create a bi-directional pipe to connect the peers. object_t *parents [2] = {this, peer.socket}; pipe_t *pipes [2] = {NULL, NULL}; int hwms [2] = {sndhwm, rcvhwm}; bool delays [2] = {options.delay_on_disconnect, options.delay_on_close}; int rc = pipepair (parents, pipes, hwms, delays); errno_assert (rc == 0); // Attach local end of the pipe to this socket object. attach_pipe (pipes [0]); // If required, send the identity of the local socket to the peer. if (options.send_identity) { msg_t id; rc = id.init_size (options.identity_size); zmq_assert (rc == 0); memcpy (id.data (), options.identity, options.identity_size); id.set_flags (msg_t::identity); bool written = pipes [0]->write (&id); zmq_assert (written); pipes [0]->flush (); } // If required, send the identity of the peer to the local socket. if (peer.options.send_identity) { msg_t id; rc = id.init_size (peer.options.identity_size); zmq_assert (rc == 0); memcpy (id.data (), peer.options.identity, peer.options.identity_size); id.set_flags (msg_t::identity); bool written = pipes [1]->write (&id); zmq_assert (written); pipes [1]->flush (); } // Attach remote end of the pipe to the peer socket. Note that peer's // seqnum was incremented in find_endpoint function. We don't need it // increased here. send_bind (peer.socket, pipes [1], false); // Save last endpoint URI options.last_endpoint.assign (addr_); return 0; } // 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); zmq_assert (paddr); // Resolve address (if needed by the protocol) if (protocol == "tcp") { paddr->resolved.tcp_addr = new (std::nothrow) tcp_address_t (); zmq_assert (paddr->resolved.tcp_addr); int rc = paddr->resolved.tcp_addr->resolve ( address.c_str (), false, options.ipv4only ? true : false); if (rc != 0) { delete paddr; return -1; } } #if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS else if(protocol == "ipc") { paddr->resolved.ipc_addr = new (std::nothrow) ipc_address_t (); zmq_assert (paddr->resolved.ipc_addr); int rc = paddr->resolved.ipc_addr->resolve (address.c_str ()); if (rc != 0) { delete paddr; return -1; } } #endif // Create session. session_base_t *session = session_base_t::create (io_thread, true, this, options, paddr); errno_assert (session); // Create a bi-directional pipe. object_t *parents [2] = {this, session}; pipe_t *pipes [2] = {NULL, NULL}; int hwms [2] = {options.sndhwm, options.rcvhwm}; bool delays [2] = {options.delay_on_disconnect, options.delay_on_close}; rc = pipepair (parents, pipes, hwms, delays); errno_assert (rc == 0); // PGM does not support subscription forwarding; ask for all data to be // sent to this pipe. bool icanhasall = false; if (protocol == "pgm" || protocol == "epgm") icanhasall = true; // Attach local end of the pipe to the socket object. attach_pipe (pipes [0], icanhasall); // Attach remote end of the pipe to the session object later on. session->attach_pipe (pipes [1]); // Save last endpoint URI paddr->to_string (options.last_endpoint); add_endpoint (addr_, (own_t *) session); return 0; }
int zmq::socket_base_t::connect (const char *addr_) { if (unlikely (ctx_terminated)) { errno = ETERM; return -1; } // Parse addr_ string. std::string protocol; std::string address; int rc = parse_uri (addr_, protocol, address); if (rc != 0) return -1; rc = check_protocol (protocol); if (rc != 0) return -1; if (protocol == "inproc" || protocol == "sys") { // TODO: inproc connect is specific with respect to creating pipes // as there's no 'reconnect' functionality implemented. Once that // is in place we should follow generic pipe creation algorithm. // Find the peer endpoint. endpoint_t peer = find_endpoint (addr_); if (!peer.socket) return -1; reader_t *inpipe_reader = NULL; writer_t *inpipe_writer = NULL; reader_t *outpipe_reader = NULL; writer_t *outpipe_writer = NULL; // The total HWM for an inproc connection should be the sum of // the binder's HWM and the connector's HWM. (Similarly for the // SWAP.) int64_t hwm; if (options.hwm == 0 || peer.options.hwm == 0) hwm = 0; else hwm = options.hwm + peer.options.hwm; int64_t swap; if (options.swap == 0 && peer.options.swap == 0) swap = 0; else swap = options.swap + peer.options.swap; // Create inbound pipe, if required. if (options.requires_in) create_pipe (this, peer.socket, hwm, swap, &inpipe_reader, &inpipe_writer); // Create outbound pipe, if required. if (options.requires_out) create_pipe (peer.socket, this, hwm, swap, &outpipe_reader, &outpipe_writer); // Attach the pipes to this socket object. attach_pipes (inpipe_reader, outpipe_writer, peer.options.identity); // Attach the pipes to the peer socket. Note that peer's seqnum // was incremented in find_endpoint function. We don't need it // increased here. send_bind (peer.socket, outpipe_reader, inpipe_writer, options.identity, false); return 0; } // 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; } // Create session. connect_session_t *session = new (std::nothrow) connect_session_t ( io_thread, this, options, protocol.c_str (), address.c_str ()); alloc_assert (session); // If 'immediate connect' feature is required, we'll create the pipes // to the session straight away. Otherwise, they'll be created by the // session once the connection is established. if (options.immediate_connect) { reader_t *inpipe_reader = NULL; writer_t *inpipe_writer = NULL; reader_t *outpipe_reader = NULL; writer_t *outpipe_writer = NULL; // Create inbound pipe, if required. if (options.requires_in) create_pipe (this, session, options.hwm, options.swap, &inpipe_reader, &inpipe_writer); // Create outbound pipe, if required. if (options.requires_out) create_pipe (session, this, options.hwm, options.swap, &outpipe_reader, &outpipe_writer); // Attach the pipes to the socket object. attach_pipes (inpipe_reader, outpipe_writer, blob_t ()); // Attach the pipes to the session object. session->attach_pipes (outpipe_reader, inpipe_writer, blob_t ()); } // Activate the session. Make it a child of this socket. launch_child (session); return 0; }
int zmq::socket_base_t::connect (const char *addr_) { ENTER_MUTEX(); if (unlikely (ctx_terminated)) { errno = ETERM; EXIT_MUTEX(); return -1; } // Process pending commands, if any. int rc = process_commands (0, false); if (unlikely (rc != 0)) { EXIT_MUTEX(); return -1; } // Parse addr_ string. std::string protocol; std::string address; if (parse_uri (addr_, protocol, address) || check_protocol (protocol)) { EXIT_MUTEX(); return -1; } if (protocol == "inproc") { // TODO: inproc connect is specific with respect to creating pipes // as there's no 'reconnect' functionality implemented. Once that // is in place we should follow generic pipe creation algorithm. // Find the peer endpoint. endpoint_t peer = find_endpoint (addr_); // The total HWM for an inproc connection should be the sum of // the binder's HWM and the connector's HWM. int sndhwm = 0; if (peer.socket == NULL) sndhwm = options.sndhwm; else if (options.sndhwm != 0 && peer.options.rcvhwm != 0) sndhwm = options.sndhwm + peer.options.rcvhwm; int rcvhwm = 0; if (peer.socket == NULL) rcvhwm = options.rcvhwm; else if (options.rcvhwm != 0 && peer.options.sndhwm != 0) rcvhwm = options.rcvhwm + peer.options.sndhwm; // Create a bi-directional pipe to connect the peers. object_t *parents [2] = {this, peer.socket == NULL ? this : peer.socket}; pipe_t *new_pipes [2] = {NULL, NULL}; bool conflate = options.conflate && (options.type == ZMQ_DEALER || options.type == ZMQ_PULL || options.type == ZMQ_PUSH || options.type == ZMQ_PUB || options.type == ZMQ_SUB); int hwms [2] = {conflate? -1 : sndhwm, conflate? -1 : rcvhwm}; bool conflates [2] = {conflate, conflate}; int rc = pipepair (parents, new_pipes, hwms, conflates); if (!conflate) { new_pipes[0]->set_hwms_boost(peer.options.sndhwm, peer.options.rcvhwm); new_pipes[1]->set_hwms_boost(options.sndhwm, options.rcvhwm); } errno_assert (rc == 0); if (!peer.socket) { // The peer doesn't exist yet so we don't know whether // to send the identity message or not. To resolve this, // we always send our identity and drop it later if // the peer doesn't expect it. msg_t id; rc = id.init_size (options.identity_size); errno_assert (rc == 0); memcpy (id.data (), options.identity, options.identity_size); id.set_flags (msg_t::identity); bool written = new_pipes [0]->write (&id); zmq_assert (written); new_pipes [0]->flush (); const endpoint_t endpoint = {this, options}; pend_connection (std::string (addr_), endpoint, new_pipes); } else { // If required, send the identity of the local socket to the peer. if (peer.options.recv_identity) { msg_t id; rc = id.init_size (options.identity_size); errno_assert (rc == 0); memcpy (id.data (), options.identity, options.identity_size); id.set_flags (msg_t::identity); bool written = new_pipes [0]->write (&id); zmq_assert (written); new_pipes [0]->flush (); } // If required, send the identity of the peer to the local socket. if (options.recv_identity) { msg_t id; rc = id.init_size (peer.options.identity_size); errno_assert (rc == 0); memcpy (id.data (), peer.options.identity, peer.options.identity_size); id.set_flags (msg_t::identity); bool written = new_pipes [1]->write (&id); zmq_assert (written); new_pipes [1]->flush (); } // Attach remote end of the pipe to the peer socket. Note that peer's // seqnum was incremented in find_endpoint function. We don't need it // increased here. send_bind (peer.socket, new_pipes [1], false); } // Attach local end of the pipe to this socket object. attach_pipe (new_pipes [0]); // Save last endpoint URI last_endpoint.assign (addr_); // remember inproc connections for disconnect inprocs.insert (inprocs_t::value_type (std::string (addr_), new_pipes [0])); options.connected = true; EXIT_MUTEX(); return 0; } bool is_single_connect = (options.type == ZMQ_DEALER || options.type == ZMQ_SUB || options.type == ZMQ_REQ); if (unlikely (is_single_connect)) { const endpoints_t::iterator it = endpoints.find (addr_); if (it != endpoints.end ()) { // There is no valid use for multiple connects for SUB-PUB nor // DEALER-ROUTER nor REQ-REP. Multiple connects produces // nonsensical results. EXIT_MUTEX(); return 0; } } // 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; EXIT_MUTEX(); return -1; } address_t *paddr = new (std::nothrow) address_t (protocol, address); alloc_assert (paddr); // Resolve address (if needed by the protocol) if (protocol == "tcp") { // Do some basic sanity checks on tcp:// address syntax // - hostname starts with digit or letter, with embedded '-' or '.' // - IPv6 address may contain hex chars and colons. // - IPv4 address may contain decimal digits and dots. // - Address must end in ":port" where port is *, or numeric // - Address may contain two parts separated by ':' // Following code is quick and dirty check to catch obvious errors, // without trying to be fully accurate. const char *check = address.c_str (); if (isalnum (*check) || isxdigit (*check) || *check == '[') { check++; while (isalnum (*check) || isxdigit (*check) || *check == '.' || *check == '-' || *check == ':'|| *check == ';' || *check == ']') check++; } // Assume the worst, now look for success rc = -1; // Did we reach the end of the address safely? if (*check == 0) { // Do we have a valid port string? (cannot be '*' in connect check = strrchr (address.c_str (), ':'); if (check) { check++; if (*check && (isdigit (*check))) rc = 0; // Valid } } if (rc == -1) { errno = EINVAL; LIBZMQ_DELETE(paddr); EXIT_MUTEX(); return -1; } // Defer resolution until a socket is opened paddr->resolved.tcp_addr = NULL; } #if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS else if (protocol == "ipc") { paddr->resolved.ipc_addr = new (std::nothrow) ipc_address_t (); alloc_assert (paddr->resolved.ipc_addr); int rc = paddr->resolved.ipc_addr->resolve (address.c_str ()); if (rc != 0) { LIBZMQ_DELETE(paddr); EXIT_MUTEX(); return -1; } } #endif // TBD - Should we check address for ZMQ_HAVE_NORM??? #ifdef ZMQ_HAVE_OPENPGM if (protocol == "pgm" || protocol == "epgm") { struct pgm_addrinfo_t *res = NULL; uint16_t port_number = 0; int rc = pgm_socket_t::init_address(address.c_str(), &res, &port_number); if (res != NULL) pgm_freeaddrinfo (res); if (rc != 0 || port_number == 0) { EXIT_MUTEX(); return -1; } } #endif #if defined ZMQ_HAVE_TIPC else if (protocol == "tipc") { paddr->resolved.tipc_addr = new (std::nothrow) tipc_address_t (); alloc_assert (paddr->resolved.tipc_addr); int rc = paddr->resolved.tipc_addr->resolve (address.c_str()); if (rc != 0) { LIBZMQ_DELETE(paddr); EXIT_MUTEX(); return -1; } } #endif // Create session. session_base_t *session = session_base_t::create (io_thread, true, this, options, paddr); errno_assert (session); // PGM does not support subscription forwarding; ask for all data to be // sent to this pipe. (same for NORM, currently?) bool subscribe_to_all = protocol == "pgm" || protocol == "epgm" || protocol == "norm"; pipe_t *newpipe = NULL; if (options.immediate != 1 || subscribe_to_all) { // Create a bi-directional pipe. object_t *parents [2] = {this, session}; pipe_t *new_pipes [2] = {NULL, NULL}; bool conflate = options.conflate && (options.type == ZMQ_DEALER || options.type == ZMQ_PULL || options.type == ZMQ_PUSH || options.type == ZMQ_PUB || options.type == ZMQ_SUB); int hwms [2] = {conflate? -1 : options.sndhwm, conflate? -1 : options.rcvhwm}; bool conflates [2] = {conflate, conflate}; 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], subscribe_to_all); 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); EXIT_MUTEX(); return 0; }
int zmq::socket_base_t::connect (const char *addr_) { if (unlikely (app_thread->is_terminated ())) { errno = ETERM; return -1; } // Parse addr_ string. std::string addr_type; std::string addr_args; std::string addr (addr_); std::string::size_type pos = addr.find ("://"); if (pos == std::string::npos) { errno = EINVAL; return -1; } addr_type = addr.substr (0, pos); addr_args = addr.substr (pos + 3); if (addr_type == "inproc") { // TODO: inproc connect is specific with respect to creating pipes // as there's no 'reconnect' functionality implemented. Once that // is in place we should follow generic pipe creation algorithm. // Find the peer socket. socket_base_t *peer = find_endpoint (addr_args.c_str ()); if (!peer) return -1; pipe_t *in_pipe = NULL; pipe_t *out_pipe = NULL; // Create inbound pipe, if required. if (options.requires_in) { in_pipe = new (std::nothrow) pipe_t (this, peer, options.hwm); zmq_assert (in_pipe); } // Create outbound pipe, if required. if (options.requires_out) { out_pipe = new (std::nothrow) pipe_t (peer, this, options.hwm); zmq_assert (out_pipe); } // Attach the pipes to this socket object. attach_pipes (in_pipe ? &in_pipe->reader : NULL, out_pipe ? &out_pipe->writer : NULL, blob_t ()); // Attach the pipes to the peer socket. Note that peer's seqnum // was incremented in find_endpoint function. The callee is notified // about the fact via the last parameter. send_bind (peer, out_pipe ? &out_pipe->reader : NULL, in_pipe ? &in_pipe->writer : NULL, options.identity, false); return 0; } // Create unnamed session. io_thread_t *io_thread = choose_io_thread (options.affinity); session_t *session = new (std::nothrow) session_t (io_thread, this, options); zmq_assert (session); // If 'immediate connect' feature is required, we'll created the pipes // to the session straight away. Otherwise, they'll be created by the // session once the connection is established. if (options.immediate_connect) { pipe_t *in_pipe = NULL; pipe_t *out_pipe = NULL; // Create inbound pipe, if required. if (options.requires_in) { in_pipe = new (std::nothrow) pipe_t (this, session, options.hwm); zmq_assert (in_pipe); } // Create outbound pipe, if required. if (options.requires_out) { out_pipe = new (std::nothrow) pipe_t (session, this, options.hwm); zmq_assert (out_pipe); } // Attach the pipes to the socket object. attach_pipes (in_pipe ? &in_pipe->reader : NULL, out_pipe ? &out_pipe->writer : NULL, blob_t ()); // Attach the pipes to the session object. session->attach_pipes (out_pipe ? &out_pipe->reader : NULL, in_pipe ? &in_pipe->writer : NULL, blob_t ()); } // Activate the session. send_plug (session); send_own (this, session); if (addr_type == "tcp" || addr_type == "ipc") { #if defined ZMQ_HAVE_WINDOWS || defined ZMQ_HAVE_OPENVMS // Windows named pipes are not compatible with Winsock API. // There's no UNIX domain socket implementation on OpenVMS. if (addr_type == "ipc") { errno = EPROTONOSUPPORT; return -1; } #endif // Create the connecter object. Supply it with the session name // so that it can bind the new connection to the session once // it is established. zmq_connecter_t *connecter = new (std::nothrow) zmq_connecter_t ( choose_io_thread (options.affinity), this, options, session->get_ordinal (), false); zmq_assert (connecter); int rc = connecter->set_address (addr_type.c_str(), addr_args.c_str ()); if (rc != 0) { delete connecter; return -1; } send_plug (connecter); send_own (this, connecter); return 0; } #if defined ZMQ_HAVE_OPENPGM if (addr_type == "pgm" || addr_type == "epgm") { // If the socket type requires bi-directional communication // multicast is not an option (it is uni-directional). if (options.requires_in && options.requires_out) { errno = ENOCOMPATPROTO; return -1; } // For epgm, pgm transport with UDP encapsulation is used. bool udp_encapsulation = (addr_type == "epgm"); // At this point we'll create message pipes to the session straight // away. There's no point in delaying it as no concept of 'connect' // exists with PGM anyway. if (options.requires_out) { // PGM sender. pgm_sender_t *pgm_sender = new (std::nothrow) pgm_sender_t ( choose_io_thread (options.affinity), options); zmq_assert (pgm_sender); int rc = pgm_sender->init (udp_encapsulation, addr_args.c_str ()); if (rc != 0) { delete pgm_sender; return -1; } send_attach (session, pgm_sender, blob_t ()); } else if (options.requires_in) { // PGM receiver. pgm_receiver_t *pgm_receiver = new (std::nothrow) pgm_receiver_t ( choose_io_thread (options.affinity), options); zmq_assert (pgm_receiver); int rc = pgm_receiver->init (udp_encapsulation, addr_args.c_str ()); if (rc != 0) { delete pgm_receiver; return -1; } send_attach (session, pgm_receiver, blob_t ()); } else zmq_assert (false); return 0; } #endif // Unknown protoco. errno = EPROTONOSUPPORT; return -1; }
int zmq::socket_base_t::connect (const char *addr_) { if (unlikely (ctx_terminated)) { errno = ETERM; return -1; } // Parse addr_ string. std::string protocol; std::string address; int rc = parse_uri (addr_, protocol, address); if (rc != 0) return -1; rc = check_protocol (protocol); if (rc != 0) return -1; if (protocol == "inproc" || protocol == "sys") { // TODO: inproc connect is specific with respect to creating pipes // as there's no 'reconnect' functionality implemented. Once that // is in place we should follow generic pipe creation algorithm. // Find the peer endpoint. endpoint_t peer = find_endpoint (addr_); if (!peer.socket) return -1; // The total HWM for an inproc connection should be the sum of // the binder's HWM and the connector's HWM. int sndhwm; int rcvhwm; if (options.sndhwm == 0 || peer.options.rcvhwm == 0) sndhwm = 0; else sndhwm = options.sndhwm + peer.options.rcvhwm; if (options.rcvhwm == 0 || peer.options.sndhwm == 0) rcvhwm = 0; else rcvhwm = options.rcvhwm + peer.options.sndhwm; // Create a bi-directional pipe to connect the peers. object_t *parents [2] = {this, peer.socket}; pipe_t *pipes [2] = {NULL, NULL}; int hwms [2] = {sndhwm, rcvhwm}; bool delays [2] = {options.delay_on_disconnect, options.delay_on_close}; int rc = pipepair (parents, pipes, hwms, delays); errno_assert (rc == 0); // Attach local end of the pipe to this socket object. attach_pipe (pipes [0]); // If required, send the identity of the local socket to the peer. if (options.send_identity) { msg_t id; rc = id.init_size (options.identity_size); zmq_assert (rc == 0); memcpy (id.data (), options.identity, options.identity_size); id.set_flags (msg_t::identity); bool written = pipes [0]->write (&id); zmq_assert (written); } // Attach remote end of the pipe to the peer socket. Note that peer's // seqnum was incremented in find_endpoint function. We don't need it // increased here. send_bind (peer.socket, pipes [1], false); return 0; } // 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; } // Create session. session_base_t *session = session_base_t::create (io_thread, true, this, options, protocol.c_str (), address.c_str ()); errno_assert (session); // Create a bi-directional pipe. object_t *parents [2] = {this, session}; pipe_t *pipes [2] = {NULL, NULL}; int hwms [2] = {options.sndhwm, options.rcvhwm}; bool delays [2] = {options.delay_on_disconnect, options.delay_on_close}; rc = pipepair (parents, pipes, hwms, delays); errno_assert (rc == 0); // PGM does not support subscription forwarding; ask for all data to be // sent to this pipe. bool icanhasall = false; if (protocol == "pgm" || protocol == "epgm") icanhasall = true; // Attach local end of the pipe to the socket object. attach_pipe (pipes [0], icanhasall); // Attach remote end of the pipe to the session object later on. session->attach_pipe (pipes [1]); // Activate the session. Make it a child of this socket. launch_child (session); return 0; }
int zmq::socket_base_t::connect (const char *addr_) { if (unlikely (ctx_terminated)) { errno = ETERM; return -1; } // Parse addr_ string. std::string protocol; std::string address; int rc = parse_uri (addr_, protocol, address); if (rc != 0) return -1; // Checks that protocol is valid and supported on this system rc = check_protocol (protocol); if (rc != 0) return -1; // Parsed address for validation sockaddr_storage addr; socklen_t addr_len; if (protocol == "tcp") rc = resolve_ip_hostname (&addr, &addr_len, address.c_str ()); else if (protocol == "ipc") rc = resolve_local_path (&addr, &addr_len, address.c_str ()); if (rc != 0) return -1; if (protocol == "inproc" || protocol == "sys") { // TODO: inproc connect is specific with respect to creating pipes // as there's no 'reconnect' functionality implemented. Once that // is in place we should follow generic pipe creation algorithm. // Find the peer endpoint. endpoint_t peer = find_endpoint (addr_); if (!peer.socket) return -1; // The total HWM for an inproc connection should be the sum of // the binder's HWM and the connector's HWM. int sndhwm; int rcvhwm; if (options.sndhwm == 0 || peer.options.rcvhwm == 0) sndhwm = 0; else sndhwm = options.sndhwm + peer.options.rcvhwm; if (options.rcvhwm == 0 || peer.options.sndhwm == 0) rcvhwm = 0; else rcvhwm = options.rcvhwm + peer.options.sndhwm; // Create a bi-directional pipe to connect the peers. object_t *parents [2] = {this, peer.socket}; pipe_t *pipes [2] = {NULL, NULL}; int hwms [2] = {sndhwm, rcvhwm}; bool delays [2] = {options.delay_on_disconnect, options.delay_on_close}; int rc = pipepair (parents, pipes, hwms, delays); errno_assert (rc == 0); // Attach local end of the pipe to this socket object. attach_pipe (pipes [0], peer.options.identity); // Attach remote end of the pipe to the peer socket. Note that peer's // seqnum was incremented in find_endpoint function. We don't need it // increased here. send_bind (peer.socket, pipes [1], options.identity, false); return 0; } // 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; } // Create session. connect_session_t *session = new (std::nothrow) connect_session_t ( io_thread, this, options, protocol.c_str (), address.c_str ()); alloc_assert (session); // If 'immediate connect' feature is required, we'll create the pipes // to the session straight away. Otherwise, they'll be created by the // session once the connection is established. if (options.immediate_connect) { // Create a bi-directional pipe. object_t *parents [2] = {this, session}; pipe_t *pipes [2] = {NULL, NULL}; int hwms [2] = {options.sndhwm, options.rcvhwm}; bool delays [2] = {options.delay_on_disconnect, options.delay_on_close}; int rc = pipepair (parents, pipes, hwms, delays); errno_assert (rc == 0); // Attach local end of the pipe to the socket object. attach_pipe (pipes [0], blob_t ()); // Attach remote end of the pipe to the session object later on. session->attach_pipe (pipes [1]); } // Activate the session. Make it a child of this socket. launch_child (session); return 0; }