- {
- int res, err;
- socklen_t len;
-
- len = sizeof (err);
- /* On Windows, the fourth parameter to getsockopt is a "char *";
- on UNIX systems it is generally "void *". The cast to "void *"
- is OK everywhere, since in C "void *" can be implicitly
- converted to any pointer type. */
- res = getsockopt (scb->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len);
- if (res < 0 || err)
- {
- /* Maybe the target still isn't ready to accept the connection. */
- if (tcp_auto_retry
+ int err;
+ socklen_t len = sizeof (err);
+
+ /* On Windows, the fourth parameter to getsockopt is a "char *";
+ on UNIX systems it is generally "void *". The cast to "char *"
+ is OK everywhere, since in C++ any data pointer type can be
+ implicitly converted to "void *". */
+ int ret = getsockopt (sock, SOL_SOCKET, SO_ERROR, (char *) &err, &len);
+
+ if (ret < 0)
+ {
+ int saved_errno = errno;
+
+ close (sock);
+ errno = saved_errno;
+ return -1;
+ }
+ else if (ret == 0 && err != 0)
+ {
+ close (sock);
+ errno = err;
+ return -1;
+ }
+
+ /* The connection succeeded. Return the socket. */
+ return sock;
+}
+
+/* Open a tcp socket. */
+
+int
+net_open (struct serial *scb, const char *name)
+{
+ struct addrinfo hint;
+ struct addrinfo *ainfo;
+
+ memset (&hint, 0, sizeof (hint));
+ /* Assume no prefix will be passed, therefore we should use
+ AF_UNSPEC. */
+ hint.ai_family = AF_UNSPEC;
+ hint.ai_socktype = SOCK_STREAM;
+ hint.ai_protocol = IPPROTO_TCP;
+
+ parsed_connection_spec parsed = parse_connection_spec (name, &hint);
+
+ if (parsed.port_str.empty ())
+ error (_("Missing port on hostname '%s'"), name);
+
+ int r = getaddrinfo (parsed.host_str.c_str (),
+ parsed.port_str.c_str (),
+ &hint, &ainfo);
+
+ if (r != 0)
+ {
+ fprintf_unfiltered (gdb_stderr, _("%s: cannot resolve name: %s\n"),
+ name, gai_strerror (r));
+ errno = ENOENT;
+ return -1;
+ }
+
+ scoped_free_addrinfo free_ainfo (ainfo);
+
+ /* Flag to indicate whether we've got a connection refused. It will
+ be true if any of the connections tried was refused. */
+ bool got_connrefused;
+ /* If a connection succeeds, SUCCESS_AINFO will point to the
+ 'struct addrinfo' that succeed. */
+ struct addrinfo *success_ainfo = NULL;
+ unsigned int polls = 0;
+
+ /* Assume the worst. */
+ scb->fd = -1;
+
+ do
+ {
+ got_connrefused = false;
+
+ for (addrinfo *iter = ainfo; iter != NULL; iter = iter->ai_next)
+ {
+ /* Iterate over the list of possible addresses to connect
+ to. For each, we'll try to connect and see if it
+ succeeds. */
+ int sock = try_connect (iter, &polls);
+
+ if (sock >= 0)
+ {
+ /* We've gotten a successful connection. Save its
+ 'struct addrinfo', the socket, and break. */
+ success_ainfo = iter;
+ scb->fd = sock;
+ break;
+ }
+ else if (