/** * Functions of this signature are called whenever we transmitted a * query via a stream. * * @param cls the struct StreamHandle for which we did the write call * @param status the status of the stream at the time this function is called; * GNUNET_OK if writing to stream was completed successfully, * GNUNET_STREAM_SHUTDOWN if the stream is shutdown for writing in the * mean time. * @param size the number of bytes written */ static void query_write_continuation (void *cls, enum GNUNET_STREAM_Status status, size_t size) { struct StreamHandle *sh = cls; sh->wh = NULL; if ( (GNUNET_STREAM_OK != status) || (sizeof (struct StreamQueryMessage) != size) ) { reset_stream (sh); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successfully transmitted %u bytes via stream to %s\n", (unsigned int) size, GNUNET_i2s (&sh->target)); if (NULL == sh->rh) sh->rh = GNUNET_STREAM_read (sh->stream, GNUNET_TIME_UNIT_FOREVER_REL, &handle_stream_reply, sh); transmit_pending (sh); }
/** * We got a reply from the stream. Process it. * * @param cls the struct StreamHandle * @param status the status of the stream at the time this function is called * @param data traffic from the other side * @param size the number of bytes available in data read; will be 0 on timeout * @return number of bytes of processed from 'data' (any data remaining should be * given to the next time the read processor is called). */ static size_t handle_stream_reply (void *cls, enum GNUNET_STREAM_Status status, const void *data, size_t size) { struct StreamHandle *sh = cls; sh->rh = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %u bytes from stream to %s\n", (unsigned int) size, GNUNET_i2s (&sh->target)); if (GNUNET_SYSERR == GNUNET_SERVER_mst_receive (sh->mst, NULL, data, size, GNUNET_NO, GNUNET_NO)) { GNUNET_break_op (0); reset_stream_async (sh); return size; } sh->rh = GNUNET_STREAM_read (sh->stream, GNUNET_TIME_UNIT_FOREVER_REL, &handle_stream_reply, sh); return size; }
/** * Scheduler call back; to be executed when a new stream is connected * Called from listen connect for peer2 */ static void stream_read_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct PeerData *pdata = cls; read_task = GNUNET_SCHEDULER_NO_TASK; pdata->io_read_handle = GNUNET_STREAM_read (pdata->socket, GNUNET_TIME_UNIT_FOREVER_REL, &input_processor, pdata); GNUNET_assert (NULL != pdata->io_read_handle); }
/** * Task for calling STREAM_read * * @param cls the peer data entity * @param tc the task context */ static void stream_read_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct PeerData *peer = cls; peer->io_read_handle = GNUNET_STREAM_read (peer->socket, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5), &input_processor, peer); GNUNET_assert (NULL != peer->io_read_handle); }
/** * We're done handling a request from a client, read the next one. * * @param sc client to continue reading requests from */ static void continue_reading (struct StreamClient *sc) { int ret; ret = GNUNET_SERVER_mst_receive (sc->mst, NULL, NULL, 0, GNUNET_NO, GNUNET_YES); if (GNUNET_NO == ret) return; refresh_timeout_task (sc); sc->rh = GNUNET_STREAM_read (sc->socket, GNUNET_TIME_UNIT_FOREVER_REL, &process_request, sc); }
/** * Functions of this type are called upon new stream connection from other peers * or upon binding error which happen when the app_port given in * GNUNET_STREAM_listen() is already taken. * * @param cls the closure from GNUNET_STREAM_listen * @param socket the socket representing the stream; NULL on binding error * @param initiator the identity of the peer who wants to establish a stream * with us; NULL on binding error * @return GNUNET_OK to keep the socket open, GNUNET_SYSERR to close the * stream (the socket will be invalid after the call) */ static int accept_cb (void *cls, struct GNUNET_STREAM_Socket *socket, const struct GNUNET_PeerIdentity *initiator) { struct StreamClient *sc; if (NULL == socket) return GNUNET_SYSERR; if (sc_count >= sc_count_max) { GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# stream client connections rejected"), 1, GNUNET_NO); return GNUNET_SYSERR; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Accepting inbound stream connection from `%s'\n", GNUNET_i2s (initiator)); GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# stream connections active"), 1, GNUNET_NO); sc = GNUNET_malloc (sizeof (struct StreamClient)); sc->socket = socket; sc->mst = GNUNET_SERVER_mst_create (&request_cb, sc); sc->rh = GNUNET_STREAM_read (sc->socket, GNUNET_TIME_UNIT_FOREVER_REL, &process_request, sc); GNUNET_CONTAINER_DLL_insert (sc_head, sc_tail, sc); sc_count++; refresh_timeout_task (sc); return GNUNET_OK; }