*/
struct GNUNET_STREAM_IOReadHandle *read_handle;
+ /**
+ * The shutdown handle associated with this socket
+ */
+ struct GNUNET_STREAM_ShutdownHandle *shutdown_handle;
+
/**
* Buffer for storing received messages
*/
* Which operation to shutdown? SHUT_RD, SHUT_WR or SHUT_RDWR
*/
int operation;
+
+ /**
+ * Shutdown completion callback
+ */
+ GNUNET_STREAM_ShutdownCompletion completion_cb;
+
+ /**
+ * Closure for completion callback
+ */
+ void *completion_cls;
};
{
struct GNUNET_STREAM_MessageHeader *close_ack;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%x: Received CLOSE from %x\n",
+ socket->our_id,
+ socket->other_peer);
close_ack = GNUNET_malloc (sizeof (struct GNUNET_STREAM_MessageHeader));
close_ack->header.size = htons (sizeof (struct GNUNET_STREAM_MessageHeader));
close_ack->header.type = htons (GNUNET_MESSAGE_TYPE_STREAM_CLOSE_ACK);
const struct GNUNET_STREAM_MessageHeader *message,
const struct GNUNET_ATS_Information*atsi)
{
+ struct GNUNET_STREAM_ShutdownHandle *shutdown_handle;
+
+ shutdown_handle = socket->shutdown_handle;
switch (socket->state)
{
case STATE_CLOSE_WAIT:
socket->state = STATE_CLOSED;
+ if ( (NULL == shutdown_handle) ||
+ (SHUT_RDWR != shutdown_handle->operation) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%x: Received CLOSE_ACK when shutdown handle is NULL or "
+ "not for SHUT_RDWR\n",
+ socket->our_id);
+ return GNUNET_OK;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%x: Received CLOSE_ACK from %x\n",
+ socket->our_id,
+ socket->other_peer);
+ if (NULL != shutdown_handle->completion_cb) /* Shutdown completion */
+ shutdown_handle->completion_cb(shutdown_handle->completion_cls,
+ SHUT_RDWR);
+ GNUNET_free (shutdown_handle); /* Free shutdown handle */
break;
default:
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
{
struct GNUNET_STREAM_ShutdownHandle *handle;
struct GNUNET_STREAM_MessageHeader *msg;
+
+ GNUNET_assert (NULL == socket->shutdown_handle);
handle = GNUNET_malloc (sizeof (struct GNUNET_STREAM_ShutdownHandle));
handle->socket = socket;
+ handle->completion_cb = completion_cb;
+ handle->completion_cls = completion_cls;
+ socket->shutdown_handle = handle;
+
msg = GNUNET_malloc (sizeof (struct GNUNET_STREAM_MessageHeader));
msg->header.size = htons (sizeof (struct GNUNET_STREAM_MessageHeader));
switch (operation)
{
case SHUT_RD:
handle->operation = SHUT_RD;
-
+ if (NULL != socket->read_handle)
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Existing read handle should be cancelled before shutting"
+ " down reading\n");
break;
case SHUT_WR:
handle->operation = SHUT_WR;
*/
struct GNUNET_STREAM_IOReadHandle *io_read_handle;
+ /**
+ * Peer's shutdown handle
+ */
+ struct GNUNET_STREAM_ShutdownHandle *shutdown_handle;
+
/**
* Our Peer id
*/
* Check whether peers successfully shut down.
*/
static void
-shutdown_callback (void *cls, const char *emsg)
+peergroup_shutdown_callback (void *cls, const char *emsg)
{
if (emsg != NULL)
{
/**
- * Shutdown nicely
+ * Close sockets and stop testing deamons nicely
*/
static void
-do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+do_close (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
if (NULL != peer1.socket)
GNUNET_STREAM_close (peer1.socket);
GNUNET_TESTING_daemons_stop (pg,
GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_SECONDS, 5),
- &shutdown_callback,
+ &peergroup_shutdown_callback,
NULL);
}
+/**
+ * Completion callback for shutdown
+ *
+ * @param cls the closure from GNUNET_STREAM_shutdown call
+ * @param operation the operation that was shutdown (SHUT_RD, SHUT_WR,
+ * SHUT_RDWR)
+ */
+static void
+shutdown_completion (void *cls,
+ int operation)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "STREAM shutdown successful\n");
+ GNUNET_SCHEDULER_add_now (&do_close,
+ cls);
+}
+
+
+
+/**
+ * Shutdown sockets gracefully
+ */
+static void
+do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ peer1.shutdown_handle = GNUNET_STREAM_shutdown (peer1.socket,
+ SHUT_RDWR,
+ &shutdown_completion,
+ cls);
+}
+
+
/**
* Something went wrong and timed out. Kill everything and set error flag
*/
}
result = GNUNET_SYSERR;
abort_task = 0;
- do_shutdown (cls, tc);
+ do_close (cls, tc);
}
/**
else
{
writing_success = GNUNET_YES;
- if (GNUNET_YES == reading_success)
+ if (GNUNET_YES == reading_success)
GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
}
}