+/* Handles stream IO */
+
+static void silc_sftp_client_io(SilcStream stream, SilcStreamStatus status,
+ void *context)
+{
+ SilcSFTPClient sftp = context;
+
+ switch (status) {
+
+ case SILC_STREAM_CAN_WRITE:
+ if (!silc_buffer_headlen(&sftp->packet))
+ return;
+
+ SILC_LOG_DEBUG(("Writing pending data to stream"));
+
+ /* Write pending data to stream */
+ silc_buffer_push(sftp->packet, silc_buffer_headlen(sftp->packet));
+ while (silc_buffer_len(sftp->packet) > 0) {
+ ret = silc_stream_write(stream, sftp->packet->data,
+ silc_buffer_len(sftp->packet));
+ if (ret == 0) {
+ /* EOS */
+ /* XXX */
+ silc_buffer_reset(sftp->packet);
+ return;
+ }
+
+ if (i == -2) {
+ /* Error */
+ /* XXX */
+ silc_buffer_reset(sftp->packet);
+ return FALSE;
+ }
+
+ if (ret == -1) {
+ /* Cannot write now, write later. */
+ silc_buffer_pull(sftp->packet, silc_buffer_len(sftp->packet));
+ return;
+ }
+
+ /* Wrote data */
+ silc_buffer_pull(sftp->packet, ret);
+ }
+ break;
+
+ case SILC_STREAM_CAN_READ:
+ SILC_LOG_DEBUG(("Reading data from stream"));
+
+ /* Make sure we have fair amount of free space in inbuf */
+ if (silc_buffer_taillen(&ps->inbuf) < SILC_PACKET_DEFAULT_SIZE)
+ if (!silc_buffer_realloc(&ps->inbuf, silc_buffer_truelen(&ps->inbuf) +
+ SILC_PACKET_DEFAULT_SIZE * 2))
+ return;
+
+ /* Read data from stream */
+ ret = silc_stream_read(ps->stream, &ps->inbuf.tail,
+ silc_buffer_taillen(&ps->inbuf));
+
+ if (ret == 0) {
+ /* EOS */
+ SILC_PACKET_CALLBACK_EOS(ps);
+ silc_buffer_reset(&ps->inbuf);
+ return;
+ }
+
+ if (ret == -2) {
+ /* Error */
+ SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_READ);
+ silc_buffer_reset(&ps->inbuf);
+ return;
+ }
+
+ if (ret == -1) {
+ /* Cannot read now, do it later. */
+ silc_buffer_pull(&ps->inbuf, silc_buffer_len(&ps->inbuf));
+ return;
+ }
+
+ /* Read some data */
+ silc_buffer_pull_tail(&ps->inbuf, ret);
+
+ /* Now process the data */
+ silc_sftp_client_receive_process(sftp);
+ break;
+
+ default:
+ break;
+ }
+}
+
+/* Starts SFTP client and returns context for it. */