int zmq::tcp_connecter_t::set_address (const char *protocol_, const char *addr_) { if (strcmp (protocol_, "tcp") == 0) return resolve_ip_hostname (&addr, &addr_len, addr_); else if (strcmp (protocol_, "ipc") == 0) return resolve_local_path (&addr, &addr_len, addr_); 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; // 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; 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; } #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 // 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::tcp_listener_t::set_address (const char *protocol_, const char *addr_, int backlog_) { if (strcmp (protocol_, "tcp") == 0 ) { // Resolve the sockaddr to bind to. int rc = resolve_ip_interface (&addr, &addr_len, addr_); if (rc != 0) return -1; // Create a listening socket. s = socket (addr.ss_family, SOCK_STREAM, IPPROTO_TCP); if (s == -1) return -1; // Allow reusing of the address. int flag = 1; rc = setsockopt (s, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof (int)); errno_assert (rc == 0); // Set the non-blocking flag. #ifdef ZMQ_HAVE_OPENVMS flag = 1; rc = ioctl (s, FIONBIO, &flag); errno_assert (rc != -1); #else flag = fcntl (s, F_GETFL, 0); if (flag == -1) flag = 0; rc = fcntl (s, F_SETFL, flag | O_NONBLOCK); errno_assert (rc != -1); #endif // Bind the socket to the network interface and port. rc = bind (s, (struct sockaddr*) &addr, addr_len); if (rc != 0) { close (); return -1; } // Listen for incomming connections. rc = listen (s, backlog_); if (rc != 0) { close (); return -1; } return 0; } #ifndef ZMQ_HAVE_OPENVMS else if (strcmp (protocol_, "ipc") == 0) { // Get rid of the file associated with the UNIX domain socket that // may have been left behind by the previous run of the application. ::unlink (addr_); // Convert the address into sockaddr_un structure. int rc = resolve_local_path (&addr, &addr_len, addr_); if (rc != 0) return -1; // Create a listening socket. s = socket (AF_UNIX, SOCK_STREAM, 0); if (s == -1) return -1; // Set the non-blocking flag. int flag = fcntl (s, F_GETFL, 0); if (flag == -1) flag = 0; rc = fcntl (s, F_SETFL, flag | O_NONBLOCK); errno_assert (rc != -1); // Bind the socket to the file path. rc = bind (s, (struct sockaddr*) &addr, addr_len); if (rc != 0) { close (); return -1; } has_file = true; // Listen for incomming connections. rc = listen (s, backlog_); if (rc != 0) { close (); return -1; } return 0; } #endif else { 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; // 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; }