+indirecttcp_start_writing(
+ NdmpDevice *self)
+{
+ DirectTCPAddr *real_addrs, *iter;
+ int conn_sock;
+
+ /* The current state is that the other end is trying to connect to
+ * indirecttcp_sock. The mover remains IDLE, although its window is set
+ * correctly for the part we are about to write. */
+
+ g_debug("indirecttcp_start_writing, ready to accept");
+ conn_sock = accept(self->indirecttcp_sock, NULL, NULL);
+ if (conn_sock < 0) {
+ device_set_error(DEVICE(self),
+ g_strdup_printf("Could not accept indirecttcp socket: %s", strerror(errno)),
+ DEVICE_STATUS_DEVICE_ERROR);
+ return FALSE;
+ }
+ g_debug("indirecttcp_start_writing, accepted");
+
+ close(self->indirecttcp_sock);
+ self->indirecttcp_sock = -1;
+
+ /* tell mover to start listening */
+ g_assert(self->for_writing);
+ if (!ndmp_connection_mover_listen(self->ndmp,
+ NDMP4_MOVER_MODE_READ,
+ NDMP4_ADDR_TCP,
+ &real_addrs)) {
+ set_error_from_ndmp(self);
+ return FALSE;
+ }
+
+ /* format the addresses and send them down the socket */
+ for (iter = real_addrs; iter && SU_GET_FAMILY(iter) != 0; iter++) {
+ char inet[INET_ADDRSTRLEN];
+ const char *addr;
+ char *addrspec;
+
+ addr = inet_ntop(AF_INET, &iter->sin.sin_addr.s_addr, inet, INET_ADDRSTRLEN);
+
+ addrspec = g_strdup_printf("%s:%d%s", addr, SU_GET_PORT(iter),
+ SU_GET_FAMILY(iter+1) !=0? " ":"");
+ g_debug("indirecttcp_start_writing, send %s", addrspec);
+ if (full_write(conn_sock, addrspec, strlen(addrspec)) < strlen(addrspec)) {
+ device_set_error(DEVICE(self),
+ g_strdup_printf("writing to indirecttcp socket: %s", strerror(errno)),
+ DEVICE_STATUS_DEVICE_ERROR);
+ return FALSE;
+ }
+ }
+
+ /* close the socket for good. This ensures that the next call to
+ * write_from_connection_impl will not go through the mover setup process.
+ * */
+ if (close(conn_sock) < 0) {
+ device_set_error(DEVICE(self),
+ g_strdup_printf("closing indirecttcp socket: %s", strerror(errno)),
+ DEVICE_STATUS_DEVICE_ERROR);
+ return FALSE;
+ }
+ conn_sock = -1;
+
+ /* and free the listen_addrs, since we didn't free them in accept_impl */
+ if (self->listen_addrs) {
+ g_free(self->listen_addrs);
+ self->listen_addrs = NULL;
+ }
+
+ /* Now it's up to the remote end to connect to the mover and start sending
+ * data. We won't get any notification when this happens, although we could
+ * in principle poll for such a thing. */
+ return TRUE;
+}
+
+static int